Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Sessions

Sessions persist your conversation so you can resume later. Each session is identified by a UUID and stored in a SQLite database.

How Sessions Work

  • A session is not created when meka starts. It is created lazily when you send the first message.
  • When a session is created, its UUID is printed to stderr.
  • When you exit meka (Ctrl+D), the session UUID is printed again so you can note it for later.
  • Sessions include the full conversation: your inputs, the agent’s responses, and tool call results.

Resuming a Session

Continue Last Session

meka -c

This resumes the most recently updated session.

By UUID

meka -c 550e8400-e29b-41d4-a716-446655440000

The agent loads the previous conversation and continues from where you left off.

By UUID Prefix

If the value isn’t a valid UUID, meka treats it as a leading prefix and looks up sessions whose ID starts with it. This avoids having to copy the entire UUID:

meka -c 550e            # works if exactly one session starts with `550e`
meka -c 5               # likely ambiguous; meka lists matching IDs and exits

When a prefix matches multiple sessions, meka prints the matching IDs (most-recent first) so you can disambiguate. Type a few more characters until the prefix is unique.

Session Locking

Only one meka instance can be attached to a session at a time. This prevents race conditions from concurrent writes.

  • If you try to resume a session that is locked by a running meka process, you will get an error.
  • If the locking process has exited (crashed or was killed), meka detects this and allows you to take over the lock.
  • Under ACP (meka acp), the lock is released as soon as the editor disconnects: closing the connection (stdin EOF) or sending SIGTERM/Ctrl-C makes meka acp exit, so the session can be reopened immediately.

Storage Location

Sessions are stored in a SQLite database at a platform-specific location:

PlatformPath
Linux~/.local/share/meka/meka.db ($XDG_DATA_HOME/meka/meka.db)
macOS~/Library/Application Support/meka/meka.db
Windows%APPDATA%\meka\meka.db

Database Schema

The database has three tables:

sessions, one row per session:

ColumnTypeDescription
idTEXT (UUID)Primary key
created_atTEXT (RFC 3339)When the session was created
updated_atTEXT (RFC 3339)When the session was last updated
locked_byTEXT (PID)PID of the process holding the lock, or NULL
metadataTEXTReserved for future use

messages, one row per message in a session:

ColumnTypeDescription
idINTEGERAuto-incrementing primary key
session_idTEXT (UUID)Foreign key to sessions.id
roleTEXTuser, assistant, or tool_results
contentTEXTMessage content (plain text or JSON)
created_atTEXT (RFC 3339)When the message was saved

tool_outputs, scratchpad entries, one row per entry:

ColumnTypeDescription
session_idTEXT (UUID)Part of composite primary key
nameTEXTPart of composite primary key
contentTEXTThe stored content
created_atTEXT (RFC 3339)When the entry was created

Scratchpad entries are scoped to a session. Two sessions can have entries with the same name. Entries are preserved across compaction but deleted when a session is deleted.

History Retention

meka automatically manages session storage on startup with sensible defaults:

  • retention_days (default: 90): deletes sessions whose updated_at is older than this many days.
  • max_storage_bytes (default: 52428800 / 50 MB): when total message content exceeds this limit, the oldest sessions are deleted until the total is under the limit.

You can override these defaults in the config file under [session]:

[session]
retention_days = 30          # delete sessions not used in 30 days
max_storage_bytes = 10485760 # cap total storage at ~10 MB

See Config File for details.

Context Window Limiting

Long sessions can exceed the LLM’s context window or become expensive. The context_messages setting (default: 200) limits how many recent messages are sent to the API:

[session]
context_messages = 100

The full history remains in SQLite for resumption. Only the API payload is truncated. The truncation preserves tool call chains (it never splits a tool use from its result).

Compacting a Session

If a session becomes too long, you can use the /compact command to have the LLM summarize the conversation and replace older messages with a structured summary. A token-budgeted tail of the most recent messages is preserved verbatim (snapped to a clean user-turn boundary so tool calls aren’t split). The structured summary captures the primary task and current state, key files and decisions, errors and fixes, every distinct user request, the next step (quoted verbatim to avoid drift), and any security-relevant constraints the user stated (preserved verbatim so they keep applying after compaction).

Compaction preserves scratchpad entries and the todo list, and re-injects environment context so the agent isn’t disoriented after compaction. The summary message ends with a directive to resume the work directly rather than narrate the summary. Tools that the model loaded via load_tool before compaction stay loaded after; the deferred-tool active set is snapshotted into the compaction boundary, so resumed sessions don’t re-issue load_tool for tools they already used. If a detail was dropped, the model can recall / recall_read the full pre-compaction history, which stays on disk.

Internally, compaction does not delete pre-compaction rows from the database. It appends a compact_boundary row to the messages table; the materialized view is reconstructed from the event log, so the persisted log itself stays append-only.

Auto-Compact

When auto_compact is enabled (default: true), meka automatically compacts the conversation when the input token count exceeds 80% of the context window. This runs between turns, not during tool loops. The check is both reactive (the previous turn’s reported usage) and proactive (an estimate of the next request, so a turn whose own input jumps over the window is compacted before it is sent). As a last resort, if the provider still rejects a request for exceeding the context window, meka compacts once and retries the turn instead of failing.

[session]
auto_compact = true
context_window = 200000  # optional override

Listing Sessions

To see past sessions:

meka session list

This shows a table with each session’s ID, last update time, and a preview of the first message:

ID                                    Updated              Preview
550e8400-e29b-41d4-a716-446655440000  2026-03-14 12:00:00  How do I implement a binary search tree?
a1b2c3d4-e5f6-7890-abcd-ef1234567890  2026-03-13 09:30:00  Fix the login page CSS

By default the 20 most recent sessions are shown. Use -n to change:

meka session list -n 50

Exporting a Session

You can export any session as a Markdown file:

meka session export 550e8400-e29b-41d4-a716-446655440000

This writes session-550e8400-e29b-41d4-a716-446655440000.md in the current directory with the full conversation. User and assistant messages are rendered as Markdown sections, while tool calls and results are wrapped in collapsible <details> blocks. The export always covers the entire session, including turns that were later hidden from the model by compaction (each compaction point is marked with its summary).

To write to a specific file:

meka session export 550e8400-e29b-41d4-a716-446655440000 -o conversation.md

To print to stdout (for piping):

meka session export 550e8400-e29b-41d4-a716-446655440000 -o -

JSON (structured, round-trippable)

Pass --format json for a structured export instead of rendered Markdown:

meka session export 550e8400-e29b-41d4-a716-446655440000 --format json

This writes session-<id>.json, a lossless dump of the session’s event log (including input images and compaction boundaries), its cumulative stats, and scratchpad entries. Unlike Markdown, a JSON export also includes any sub-agent child sessions spawned during the conversation, and it can be re-imported with meka session import. It deliberately contains no credentials: API keys and OAuth tokens live in separate tables and are never part of an export.

Importing a Session

Recreate a session from a JSON export:

meka session import session-550e8400-e29b-41d4-a716-446655440000.json

meka assigns the imported session (and any sub-agent children) new UUIDs so they can’t collide with existing sessions, then prints the new root session ID. Resume it like any other session:

meka -c <new-id>

Read from stdin with -:

cat session.json | meka session import -

The import preserves the full conversation, per-message timestamps, cumulative stats, and scratchpad entries. Because the provider and model are chosen at run time (not stored per session), a resumed import uses your currently-active provider.

Deleting Sessions

Delete specific sessions by UUID:

meka session delete 550e8400-e29b-41d4-a716-446655440000

Delete multiple sessions at once:

meka session delete 550e8400-e29b-41d4-a716-446655440000 a1b2c3d4-e5f6-7890-abcd-ef1234567890

Delete all sessions:

meka session delete --all

Input History

Separate from your saved conversations, meka keeps a rolling history of the prompts you type at the REPL, so Up-arrow recall and Ctrl+R reverse-search work across runs (shell-style). This is distinct from a session (a stored conversation) and from the /history slash command (which reprints the current conversation).

List recent input-history entries (oldest first; -n 0 shows all):

meka history list
meka history list -n 100

Clear it entirely:

meka history clear

Managing Sessions via SQLite

You can also manage sessions directly through the SQLite database. For example, to list all sessions:

sqlite3 ~/.local/share/meka/meka.db \
  "SELECT id, created_at, updated_at FROM sessions ORDER BY updated_at DESC;"