Compaction & Branch Summarization
LLMs have finite context windows. Atomic reduces transcript context with verbatim line compaction while preserving an exact count of recent context-visible messages as ordinary messages. Branch summarization is a separate, intentionally lossy feature used only when navigating away from a branch. Compaction runs entirely locally with the active session model; no external compaction service is involved. The model only selects which lines to delete — Atomic reconstructs the retained text mechanically, so surviving lines are never rewritten.Overview
There is one context-compaction door:
compact.
Verbatim Line Compaction
What “verbatim” means
Atomic serializes the compactable part of the conversation into role-tagged lines:N→content and returns only one-based, inclusive line ranges as bare records:
start,end — unsigned decimal integers, one comma, no brackets or prose. Atomic safety-normalizes endpoints by swapping reversed pairs, clamping to the transcript, sorting, merging overlap/adjacency, and splitting around explicit protected spans. It then reconstructs from the original input lines. The model never writes, summarizes, reorders, or normalizes retained text. Every retained non-marker line is byte-identical to an input line and remains in input order.
Markers and repeated compaction
Each deleted span is replaced on its own line with exactly:(filtered 1 lines). When a later compaction swallows an earlier marker, Atomic adds the earlier marker’s count to the new marker. Adjacent old markers are folded too, so counts remain cumulative across repeated compactions. On repeated compaction, the planner receives the prior durable verbatim summary plus every currently active ordinary message except the exact protected tail.
Protected structure
Role-header lines such as[User]: and [Assistant]: are ordinary ranked lines and may be deleted. Explicit protected spans, including blank lines, are never deleted. The configured number of newest context-visible messages remains outside the classifier request entirely; all preceding active transcript content is included.
Images in the compactable region become the literal line [image]; images in the protected recent tail remain normal image content. Tool-result text remains capped at 16,000 characters before becoming durable compaction text, with an explicit truncation marker for the remainder.
Parameters
The effective parameters appear in extension events and successful results:preserve_recent counts context-visible messages without aligning the boundary to a user turn. An assistant message or tool result may therefore begin the kept tail. A value of 0 protects no messages and makes the entire active transcript compactable. If query is absent, Atomic derives it from the last visible user message.
Configure defaults in ~/.atomic/agent/settings.json or .atomic/settings.json:
reserveTokens controls the automatic threshold that decides when compaction runs; it is not converted into a classifier line ratio. Manual calls can pass parameter overrides through the SDK.
When compaction runs
- Manual:
/compact,ctx.compact(),session.compact(), or RPC{ "type": "compact" }. - Threshold: automatic compaction starts when estimated context usage exceeds the effective input budget minus
reserveTokens. Atomic checks both completed responses and the prospective next-turn context after tool results have been appended. A post-tool crossing is compacted before the active Pi tool loop sends its follow-up provider request. - Overflow: an actual provider context overflow compacts and then retries the interrupted turn.
compact request is still pending instead of waiting behind it. Atomic writes a backup snapshot immediately before appending a compaction boundary.
The post-tool check stays inside the active Pi loop: it runs at most one ordinary verbatim compaction attempt for that completed tool turn, returns the rebuilt context to the loop, and never calls or schedules agent.continue(). Normal context reconstruction preserves provider tool-call/result protocol validity. Below-threshold tool turns follow the unchanged request path. Because the same active run resumes without emitting another agent_start, the interactive TUI replaces the compaction loader with its working spinner as soon as successful mid-turn compaction ends; streaming feedback therefore resumes immediately without waiting for another user interaction.
One-pass planning and failure behavior
Atomic asks the active session model, at the active reasoning level and through the normal session stream/provider wrapper, to rank every eligible line in one global pass and apply one threshold. The entire compactable region is sent in exactly one classifier request; it is never split into chunks. Manual, threshold, and overflow compaction all calculate the line target directly from the preparedcompression_ratio. Explicit protected lines form a hard keep floor.
The request uses the same provider path and failure handling as pi’s summary compaction. Provider/API errors, overflow, abort, malformed output, or empty/unusable safe ranges fail after that one request. These failures write no compaction entry and schedule no continuation. During the post-tool preflight, failure or cancellation also stops the active loop before its follow-up provider request, is surfaced through the normal compaction lifecycle, and is not admitted to ordinary provider retry or model fallback. There is no semantic retry, critical rung, deterministic fallback, or deterministic target correction.
A syntactically valid usable result is accepted once after safety-only normalization, even when it deletes fewer lines or tokens than requested. Atomic never adds or restores model-selected deletions to force a target. During overflow recovery, the existing one-shot compact-and-retry continuation may therefore surface unresolved overflow naturally. During a post-tool preflight, Atomic likewise does not add a second compaction strategy or attempt; if the rebuilt context is still known to exceed the provider’s hard input limit, it refuses to send the follow-up request and reports the limit failure clearly.
Length-truncated response recovery
When the planner model’s output is truncated bymax_tokens (indicated by stopReason: "length"), Atomic silently recovers complete newline-terminated deletion records from the truncated response. A deterministic line parser validates each completed line (those followed by a newline) against the strict start,end grammar. The final fragment after the last newline is always discarded — even if it looks syntactically complete — because EOF may have cut a multi-digit integer (e.g. 300,30 could have intended 300,305). If any completed line has invalid syntax or zero usable records survive validation, recovery fails and the normal RangePlanError path applies.
Example of truncated output:
120,180 and 6,40; discards 300, without guessing. The planner prompt instructs the model to emit ranges in descending deletion confidence (lowest continuation value first) so the most important deletions appear earliest and survive truncation.
Successful partial recovery is an ordinary successful compaction: no warning, banner, toast, or special status copy appears. The UI shows the normal spinner then ✻ Context compacted.
For operational observability, a private recovery diagnostic sidecar is written beside persisted sessions with 0600 permissions. It records the full raw response, stop reason, usage, request maxTokens, model metadata, recovered range count, and recovery category. The sidecar path is never surfaced in the success UI, error messages, or user-visible status. In-memory sessions and sidecar write failures do not affect the successful recovery.
Planner failure diagnostics
For a persisted session, a failed planner call writes a JSON sidecar beside the session JSONL and includes its path in theRangePlanError, for example:
0600 permissions where supported and records the full planner response text, stop reason, provider error, usage, request maxTokens, timestamp, failure category, and non-secret model metadata. It does not record API keys, request headers, the planner prompt, or the numbered transcript request. The raw response itself may contain sensitive text if the model echoed input, so treat the sidecar with the same care as its adjacent session file.
Diagnostic categories distinguish malformed output, valid output with no usable ranges, provider errors, and stream failures. In-memory sessions do not create sidecars. If the diagnostic write fails, Atomic preserves the original error and classification rather than replacing the planner failure.
Interactive main chat and attached workflow stage chat treat compaction_end as the authority for cancellation and failure UI. A failed or cancelled /compact stops its spinner, shows the event-provided status or diagnostic path without a duplicate stack trace, writes no boundary, and leaves the session usable for another /compact attempt or a normal follow-up turn.
Context thresholds and persisted token-reduction statistics use API-aware normalized usage. OpenAI Responses, Codex Responses, and OpenAI Completions sum uncached input plus cache-read/cache-write partitions. Anthropic Messages alone applies the mirrored-cache guard needed by compatible endpoints that duplicate the same prompt tokens across input and cache fields.
Persistence and resume
A successful run appends the existing pi-styletype:"compaction" entry shape:
compaction entry is active only when details.strategy === "verbatim-lines". On rebuild, Atomic emits a visible custom-role boundary message containing the durable summary, followed by the original messages beginning at firstKeptEntryId. When no pre-boundary context-visible message is retained—such as with preserve_recent: 0—firstKeptEntryId is null. Messages appended after the boundary are always replayed. The boundary is converted to a user-role provider message and shown in the TUI as a collapsible compaction card.
Resume does not rerun planning or re-derive deletions: the exact compacted string and nullable tail boundary are already in JSONL. Existing records with a string firstKeptEntryId keep their original resume behavior. Legacy context_compaction logical-deletion records and old compaction summary records without the discriminator are inert archival data. Their historical omissions are not reapplied when an old session resumes.
Extension hooks
session_before_compact
Extensions may cancel or provide a complete replacement for the prepared region:
preparation is a deep-frozen clone. An override changes only the compacted region text; Atomic retains the prepared boundary and persists the supplied text verbatim. Empty/whitespace text is rejected. The override path does not require provider credentials.
session_compact
After persistence, Atomic emits an observe-only event:
Branch Summarization
When It Triggers
When you use/tree to navigate to a different branch, Atomic offers to summarize the work you’re leaving. This injects context from the left branch into the new branch.
Branch summarization is a separate mechanism from context compaction. It generates a summary of the abandoned branch path and injects it into the new branch position. This is appropriate here because the alternative (losing branch context entirely on navigation) is worse than a lossy summary.
How It Works
- Find common ancestor: Deepest node shared by old and new positions
- Collect entries: Walk from old leaf back to common ancestor
- Prepare with budget: Include messages up to token budget (newest first)
- Generate summary: Call LLM with structured format
- Append entry: Save
BranchSummaryEntryat navigation point
Cumulative File Tracking
Branch summarization tracks files cumulatively. When generating a summary, Atomic extracts file operations from:- Tool calls in the messages being summarized
- Previous branch summary
details(if any)
BranchSummaryEntry Structure
Defined insession-manager.ts:
details.
See collectEntriesForBranchSummary(), prepareBranchEntries(), and generateBranchSummary() for the implementation.
Branch Summary Format
Branch summarization uses a structured format:Message Serialization for Branch Summaries
Before branch summarization, messages are serialized to text viaserializeConversation():
Extension Hooks for Branch Summarization
session_before_tree
Fired before/tree navigation. Always fires regardless of whether user chose to summarize. Can cancel navigation or provide custom summary.
SessionBeforeTreeEvent and TreePreparation in the types file.
Settings
Configure compaction in~/.atomic/agent/settings.json or <project-dir>/.atomic/settings.json (legacy .pi paths are also supported):
Disable auto-compaction with
"enabled": false. You can still compact manually with /compact.
Historical formats
Two old formats remain parseable but inactive:type:"context_compaction"records store logical entry/content-block deletion targets from older versions. Those records are inert, so content they once hid can re-enter context when an old session resumes.type:"compaction"withoutdetails.strategy: "verbatim-lines"stored generated summary prose. Those records also remain inert.
details on the shared CompactionEntry shape; the session format version is the same for all of them.