Smart Compaction
Smart Compaction for OpenCode 2: structured six-section checkpoints with protected identifiers and exact file and worktree state.
0
651
34 in 7 days
37.0
Multi-signal model
11 days ago
2026-10-09
Install and configure
opencode.jsonWrites to this project's opencode.json — applies to this repository only.
opencode.json
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-smart-compaction@0.3.0"]
}Writes to ~/.config/opencode/opencode.json — applies to every project.
~/.config/opencode/opencode.json
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-smart-compaction@0.3.0"]
}If you want to modify the plugin locally, install it into the project and reference the local path.
shell
pnpm add -D opencode-smart-compactionOpenCode loads npm dependencies through its embedded runtime on startup and caches them locally — no manual global install needed.
Smart Compaction for OpenCode 2. When OpenCode compacts a long session, this plugin writes the checkpoint itself: a structured six-section summary that keeps the identifiers it must not lose and ends with the exact file and worktree state.
It started as a port of the Smart Compaction extension in shariq-pi-extensions and is now developed for OpenCode on its own.
What a checkpoint contains
The model writes six sections:
- Primary goal and constraints, including every "never do X" rule the user stated.
- Progress ledger: done, in progress (with batch counts), and blocked.
- Code changes with short verbatim snippets of in-flight work.
- Errors, root causes, and fixes.
- Key decisions and discarded approaches.
- Resume anchor and the next concrete step.
The plugin then adds two things the model doesn't write:
- Retained identifiers. Commit SHAs, UUIDs, URLs, and IPv4 addresses from your messages or the previous checkpoint are protected. Any the summary dropped are appended verbatim under
### Retained Identifiers. - File and worktree state. Files the session read or changed through tools, accumulated across compactions and capped to the 40 read and 60 changed files used most recently; the files git reports as dirty; lockfile and generated-asset changes; background shells the session still has running, so the next turn doesn't start a duplicate dev server; background subagents that haven't reported back, so the next turn waits for them instead of polling or launching them again; and a bounded diff of uncommitted work, including previews of untracked files. Untracked symlinks are never followed.
The conversation goes to the model in a bounded form: long tool output keeps its beginning and end, failures and the newest messages get more room, large tool arguments such as file contents are shortened, and terminal escape codes and repeated lines are removed. Session history itself is never changed.
A summary is accepted only when it has all six sections. Otherwise the plugin retries the same model with its default settings (no variant), then the session's model when compaction uses a different one. Authentication, permission, and quota errors stop the retries.
On the next compaction, the previous checkpoint goes back to the model as <previous-summary> and is merged with the new turns. Recent conversation from older, unmarked checkpoints is included too; recent turns already covered by a plugin checkpoint aren't summarized twice. The appended state is regenerated each time.
OpenCode still stores the most recent conversation (compaction.keep.tokens) verbatim beside the checkpoint. After a long autonomous run, OpenCode can keep much more than that setting because it moves the boundary back to a user turn. The plugin summarizes those kept turns too, then limits the recent-context block sent on subsequent requests to about 40,000 tokens by default. Only checkpoints marked as covering those turns are shortened; stored history is untouched, and the cut is deterministic for prompt caching.
Install
Add the package to plugins in ~/.config/opencode/opencode.json or a project's opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"plugins": ["opencode-smart-compaction"]
}
OpenCode installs it from npm on the next start. It needs OpenCode 2.0.26 or later. OpenCode checks unpinned plugins for new versions but doesn't install them on its own; run opencode plugin update to upgrade.
Configure
Compaction triggers at whichever comes first: 95% of the model's context window or 600,000 tokens. After each model step, the plugin compares the context that step used with that threshold and, once it is reached, requests a compaction, which OpenCode runs before the next step. Change it with plugin options:
{
"plugins": [
{
"package": "opencode-smart-compaction",
"options": { "thresholdMode": "hybrid", "thresholdPercent": 95, "hardLimitTokens": 600000 }
}
]
}
thresholdMode:hybrid(default, whichever comes first),percent,hard, oroffto leave timing to OpenCode alone.thresholdPercent(default95) andhardLimitTokens(default600000).maxRecentTokens(default40000): maximum recent-context size in each request, estimated as characters divided by four. Keeps the newest turns, with an omission note, and prefers a turn boundary; a single oversized turn is shortened at a line boundary when possible. Set0to disable both trimming and the extra summary coverage of kept turns. This bounds the recent block, not the entire request.
OpenCode's own automatic compaction still runs at the model window minus compaction.buffer (10% of the window by default), and it fires first when that is lower than the plugin's threshold. For the 95% threshold to apply, set compaction.buffer below 5% of your smallest model window; 8000 works for windows of 200,000 tokens and up. OpenCode's own trigger then remains a backstop. Other compaction settings:
compaction.auto(defaulttrue) turns OpenCode's automatic compaction and overflow recovery on or off;/compactruns it on demand.compaction.keep.tokens(default15000) sets OpenCode's target for recent conversation kept verbatim beside the checkpoint; its user-turn boundary can make the actual amount larger.maxRecentTokensis the plugin's separate request-side ceiling.
The checkpoint is written by the session's model with its selected variant, so reasoning settings carry over. To use another model, set agents.compaction.model (for example "provider/model#variant"); OpenCode passes that model to the plugin instead. Models set to provider-native compaction (settings.compaction.type: "native") don't call the hook, so the checkpoint format doesn't apply to them; the threshold still does.
Limits
- Fails open. If no attempt produces a complete checkpoint, the plugin logs a warning and OpenCode compacts with its own prompt. A session never blocks on the plugin. Pi's Smart Compaction cancels compaction instead.
- No timeout or thinking-off retry. OpenCode's generation API takes only a prompt and a model, so an attempt can't be cancelled after a time limit and the retry uses the model's default settings rather than turning reasoning off.
- Compaction cost isn't recorded. The same API returns no token usage, so the summary request doesn't appear in OpenCode's session cost.
- Background shells after a restart. Running shells are learned from OpenCode's events, so shells started before the OpenCode service last restarted aren't listed.
- Conservative recent-context trimming. Checkpoints without a reliable kept-turn boundary or with unsupported content, such as user attachments, are left untrimmed. If session context can't be read, previously recorded subagents are retained, but newly launched or completed children can't be discovered on that compaction.
Documentation
- Architecture: the hook, the request it builds, and how the summary is completed.
- Development: commands, tests, and releases.
License
Similar plugins
Context Pruner
opencode-context-pruner
Continuous verbatim context pruning for OpenCode, powered by TypeSafe Jev. Port of fast-jev-compaction adapted to OpenCode's context hook.
Autocompact
@hacky.software/opencode-autocompact
Claude Code-style autocompact for OpenCode V2 with a per-session threshold: /autocompact 500k compacts a session and its children once the live context reaches that many tokens.
Jev Compaction
opencode-jev-compaction
opencode plugins that shrink context by deleting provably-stale tool calls and truncating the rest, deterministically first, with an optional local Laya backend.