Browse documentation

Technical documentation / Reference

Sessions, context, and cache

Feature docs index ยท Repository README

Resume work, shorten provider context without losing local history, export a session, or remove old sessions. Paths use ~/.magi-code by default; MC_HOME relocates that directory.

Resume or start fresh

Use magi-code --continue for the latest eligible session, --resume <SESSION_ID> for a specific session, or /new for a fresh one. --no-session disables persistence and cannot be combined with attachment flags.

Sessions are JSONL files under ~/.magi-code/sessions. They store prompts, responses, diagnostics, tool calls/results, context/cache events, rewind events, and subagent summaries. Slash-command errors become diagnostics when a session is active.

Provider requests replay the ordered conversation until a valid compaction checkpoint. User turns, assistant text, provider response items, tool calls, and results remain distinct. Failed or cancelled partial assistant text remains provider-visible. Replay includes all entries, but historical tool outputs over 24,000 characters keep only their first and last 6,000 characters with omission markers. Failed-turn recovery may use bounded summaries instead of exact structured replay. Raw durable history remains unchanged.

Local-only events (hook_diagnostic, hook_lifecycle, context_cache, session_title, and diagnostic) stay out of provider replay. Hook lifecycle records preserve sanitized start/success/failure history for local audit and TUI replay without rerunning hooks. They also stay out of recent-context helpers, budget accounting, and cache keys.

Provider cache affinity and diagnostics

Codex requests send stable session-id and thread-id values for each conversation. Child sessions have separate identities. A bounded server-issued x-codex-turn-state value persists only within one execution turn, including tool continuations and retries. New turns and account changes do not inherit it. This improves routing consistency but does not guarantee cache hits.

Codex provider_stream_trace records include request_sequence and response_identity.cache: attempt timing, turn identifier, salted fingerprints of instructions/tools/input/configuration, routing-header presence, and whether the previous attempt preserved its complete input prefix and configuration. Fingerprints are comparable only within that turn. Salts and raw routing values are never saved. These diagnostics remain local-only. Join sequence data to finalized usage from the same run to separate prefix changes from unexplained cache losses. Retries count as attempts, not extra successful requests.

Compact a long session

Run /compact [custom instructions] to summarize an active persisted session. It uses the active provider/model unless both agent.compaction.provider and agent.compaction.model are nonblank. A partial or blank override, missing session, disabled persistence, auth/config failure, or oversized request fails without creating a checkpoint.

Instructions come from bundled prompts/compact.md or $MC_HOME/prompts/compact.md. The request contains current structured replay, including historical tool calls/results, but no tools or tool definitions.

After success, compaction copies current JSONL byte-for-byte to an immutable .history/<session-id>/ generation. It then atomically replaces the active file with a checkpoint plus events appended after the bounded snapshot. Future requests use only the latest valid summary and later provider-visible events. Archives keep raw audit history but do not supply normal replay, listing, or title reads. Repeated compaction rotates the active generation; /new starts a separate session.

Compaction separately checkpoints structured execution_effects. Dispatched tool results record bounded mutation-path evidence, including partial edits. Counters and call/path samples survive restores and repeated compaction. Summarizers and resumed agents receive a recorded-evidence note: a clean working tree does not prove no edits occurred. This is an audit record, not permission enforcement or a filesystem sandbox. Shell calls are counted, but their side effects and complete reversal are not independently verified. Invalid evidence is marked incomplete, never treated as proof of no mutations. Full tool-call/result records remain in .history.

Configure automatic compaction

Automatic compaction is enabled by default, including when agent.compaction.auto is absent. It triggers at 80% of the active model's context window, with no fixed token threshold. Set agent.compaction.auto.enabled to false to disable it. The defaults are:

{
  "agent": { "compaction": {
    "auto": {
      "enabled": true,
      "max_compactions_per_run": 4,
      "threshold_percent": 80,
      "threshold_tokens": null
    }
  } }
}
SettingRule
threshold_percentDefault 80; 1 to 100, projected next-request tokens as a percentage of the active model maximum. null disables this trigger.
threshold_tokensDefault null (unset); accepts a positive fixed projected token count.
max_compactions_per_run0 to 255, default 4; 0 removes only the per-run count cap, not provider, tool, context, or cancellation bounds.

At least one trigger is required while enabled. With both, the first threshold reached applies: min(ceil(max_tokens * percent / 100), threshold_tokens). For only a fixed threshold, set threshold_percent to null. This differs from the hard usable budget (max_tokens - reserve_tokens), though scheduling still requires context budgeting.

Automatic compaction applies to persisted primary and child sessions at successful completed-turn or settled tool-continuation boundaries, after required writes and cancellation checks. It excludes active tools, incomplete-stream/reasoning-only/TTSR recovery, cancelled/failed/partial runs, unsafe tool-progress recovery, --no-session, title/vision/tool-internal jobs, and compaction requests. Child compaction changes only that child's file in sessions/subagents/.

At tool boundaries, runtime projects the pending continuation, including observed steering for that primary or child run without acknowledging it. At completed turns, it projects pending steering or literal lowercase continue. At or above cutoff, it compacts before the next request under manual compaction rules, then confirms the compacted request falls below the same cutoff. Another compaction requires new provider-visible growth and remaining count allowance. Hard-budget preflight counts toward a finite cap.

After compaction, pending steering for that run takes precedence and is submitted in collapsed order. Otherwise runtime appends and sends continue with origin: "automatic_compaction"; CLI/TUI shows you [automatic]: continue. Manual /compact does not add this continuation merely because auto mode is enabled.

Failure stops continuation. Before checkpoint commit, the old active file remains authoritative; afterward, the new checkpoint does. No request is sent without durable continuation input, and steering is acknowledged only after append succeeds. Fix the bounded, sanitized error, then retry primary input or child task. /compact and /new recover primary sessions, not child sessions.

Selected-subagent steering in Mission Control uses the same child session and continuation path. Unpersisted input remains recallable after failure or cancellation but is not durable until appended. The in-memory control registry holds up to 64 active or pending child entries and refuses new controls rather than dropping accepted input. Completed children reject new steering, but Alt-C can recall pending input in the viewer. Pending child input must be recalled before a new primary run.

Compaction visibility and authority

Mission Control shows one primary transcript card per compaction: progress becomes the sanitized checkpoint summary. Child compaction activity retains the same summary with bounded display/truncation metadata. Reopening a session rebuilds the summary card from its checkpoint. Cancellation or a later continuation failure does not discard a committed checkpoint.

Handle context limits

SettingDefault
agent.context.enabledtrue
agent.context.max_tokens128000
agent.context.reserve_tokens16384
agent.context.keep_recent_tokens20000; only bounded non-provider helpers, not active replay

Budget resolution starts with global/default context settings, uses cached model-catalog context-window metadata when available, then applies exact agent.context.model_overrides["provider/model"]. Overrides affect normal runs, context display, and compaction fit checks. They cannot increase the provider's actual limit.

Counting is local: tiktoken-rs uses embedded o200k_base/cl100k_base tables selected by model family, without a provider round-trip. Catalog budgets use explicit context/input metadata only, never output-token limits.

If the full request exceeds max_tokens - reserve_tokens, eligible persisted primary/child runs can automatically compact before recording or sending the current input, independently of the post-turn trigger. This preflight preserves expanded prompt injections, checks fit, and sends the original input once without an automatic continue. It requires enabled auto compaction, a session, no active cancellation, and input plus static request content that fits without history. Child preflight rotates only that child's session.

If preflight cannot help, use /compact for a primary session, choose a larger compaction model/context override, shorten the input, or use /new.

Recover an incomplete stream

Primary and child loops allow one ephemeral continuation for recoverable partial assistant text or parser-only partial tool-call progress, provided no completed tool call or provider function-response item entered agent state. This includes transport/body failures. Incomplete arguments are abandoned, never executed or reconstructed.

Recovery adds available partial assistant text plus Continue only to in-memory replay and emits AutomaticUserPrompt; it does not persist synthetic user_input. Completed tool/protocol items, cancellation, or a second failure remain terminal.

Export a session

/export creates $MC_HOME/exports/<session-id>-<UTC>[-N].zip for the active persisted session on Unix. It accepts no arguments or custom destination, never overwrites, and provides no import command. It does not change the session or call a provider.

The ZIP contains byte-for-byte session JSONL, optional primary metadata, immutable compaction generations, referenced child JSONL/metadata/history, and manifest.json with sizes, SHA-256 digests, child relationships, and completeness warnings. Missing or unsafe optional descendants are omitted with bounded warnings; missing or unsafe primary data aborts. Session locks remain held through publication.

The unencrypted archive contains raw, potentially sensitive session, project, and tool data. Owner-private permissions do not make sharing safe. Mission Control exports off the UI loop while idle; see TUI export behavior.

Delete old sessions

/prune-sessions uses 30 days; /prune-sessions 7 uses seven. The argument must be a positive integer. Deletion is permanent for resume purposes. Mission Control rejects pruning during an active prompt/tool run.

Manual pruning considers only regular top-level *.jsonl files with valid IDs. Age comes from the latest valid event timestamp, or mtime when valid timestamps are unavailable. Files at or newer than the cutoff and live writer leases stay. It ignores directories, nested files, symlinks, other extensions, caches, auth/settings, and non-session data.

After deleting primary data, pruning attempts its metadata sidecar, validated .history archive, checkpoint ledger, and unreferenced checkpoint blobs. Other ledgers' blobs stay. It continues after individual failures, reporting deleted/skipped-active/failed counts with bounded categories such as permission_denied or not_found, never raw paths, content, or OS error chains.

Background cleanup uses sessions.retention_days; see Configuration to set or disable it. It runs before TUI entry on an unjoined thread, may overlap startup, and never blocks readiness or fails startup. It reuses manual primary pruning, then removes expired subagent JSONL and associated artifacts. Fresh sessions, the active primary, and live writers stay; filesystem cleanup is best effort.

Repair permissions

magi-code sessions repair-permissions --dry-run
magi-code sessions repair-permissions

The command resolves MC_HOME first. Default mode prompts on a TTY; --yes applies non-interactively and conflicts with --dry-run. It repairs only recognized session objects, never recurses or follows links, and fails closed on unknown or unsafe entries. Inspect those manually. Windows permission repair is unsupported.

On Unix, session roots must be non-symlink, owner-private directories (0700 or stricter). Primary JSONL and metadata must be owner-private regular files (0600 or stricter) named from validated IDs. Opens use no-follow protection and bind objects to expected paths; unsafe owners, permissions, links, directories, or replacements are rejected rather than followed.

File checkpoints

/changes reads per-session ledgers under ~/.magi-code/checkpoints. File rewind records sanitized target turns, relative paths, statuses, and counts, without file bytes, diffs, blob hashes, secret-looking paths, or denied paths. See restore controls and limits.

Conversation rewind writes a new JSONL session containing the prefix before the selected prompt; it never truncates the source. A local diagnostic records the source session and selected prompt for restoring the unsent draft on load. These fields are excluded from provider replay. Earlier checkpoint references are copied to the fork, sharing existing blobs. Session history and its usage records before the target are inherited; no provider request is made. If checkpoint copying or result recording fails, the error identifies the preserved fork; do not assume files were restored. Ordinary retention rules apply to both sessions.

Each ledger is ordered JSONL with serialized durable appends. Blobs synchronize before their records; complete records flush and synchronize before success, including the directory on first creation. A final sync failure after visible bytes reports committed-but-undurable, avoiding blind retries. Readers retain valid records before an incomplete final record and report that tail; malformed committed middle records are corruption. Pruning shares the checkpoint mutation lock and cannot pass an in-progress blob/record publication.

Local diagnostics and cache

OpenAI Responses keeps bounded local metadata per HTTP attempt: requested model, optional reported response.model and x-request-id, attempt sequence, and outcome. It is excluded from replay, recent-context text, and cache keys. A normal first-attempt success is silent. Successful retry recovery emits one informational diagnostic, or one warning if any attempt reported a model mismatch; it is also persisted. Failed requests display only the terminal provider error. Reported models may be absent or differ across attempts and are not proof of routing correctness.

Normal runs keep token counting and replay reuse in memory rather than writing diagnostic conversation snapshots under ~/.magi-code/cache. This is separate from provider-side prompt caching, whose hits remain opportunistic.

Codex and custom-provider catalogs live at cache/model-catalog/<provider>.json. They contain sanitized model IDs/display metadata, never API keys, OAuth tokens, bearer headers, account IDs, or raw provider responses.

Edit this page on GitHub โ†—