Skip to content
Simran's Writing Room
Menu
  • Blogs
  • Books
  • About
Menu

Context Is RAM: How OpenCode’s DCP Prunes Better Than Claude Code and Codex

Posted on by Simran Chawla

Ninety minutes into a debugging session, your agent forgets the file it renamed an hour ago. The one fact the whole task hinges on. It didn’t get distracted — its context got garbage-collected.


What is context compression?

A long agent session piles up tokens: file reads, tool outputs, stack traces, whole failed attempts. Eventually it closes in on the model’s context window, and something has to give — old content gets summarized or dropped so the session can keep going. That’s context compression.

The concept is universal. The interesting parts are when it fires, who decides, and what gets thrown away. Every tool answers those differently.


What is DCP?

DCP — Dynamic Context Pruning — is an OpenCode plugin, not a model feature. It sits between your session history and the LLM request, deciding what actually gets sent to the model. That placement sounds mundane; it’s the whole point.


What DCP does

  • Never mutates the actual session; swaps in placeholders/summaries only at request time, so the transcript on disk stays complete for auditing or replay.
  • Three separate strategies, not one blunt mechanism:
    • compress — model-invoked tool, summarizes closed/stale spans (or individual messages in experimental mode)
    • deduplication — drops repeated identical tool calls, keeps latest
    • purgeErrors — strips inputs from failed tool calls after N turns, keeps the error text
fig. 1 — where DCP sits between session history and the LLM request

Usecases

A session makes the strategies concrete — and shows what they do to the token bill:

token count per turn, with and without DCP
turn actionwithout DCPwith DCP strategy
1 read auth.py (~1.4K)1.4K1.4K—
2 read auth.py again2.8K1.4Kdedup
3 read auth.py again4.2K1.4K—
5 pytest fails ×3, tracebacks9.6K6.8K—
7 4 turns past the failures11.0K5.6KpurgeErrors — inputs gone, errors kept
9 “fix imports” wraps up15.2K6.1Kcompress — model nudged via exposed tool; 8 turns → a ~300-token summary
15 pytest green, more edits23.4K9.0K—
20 session still going31.8K11.6K—

Numbers are illustrative — file sizes and tracebacks vary — but the shape is the point: at this rate the raw history crosses ~190K around turn 120 and hits panic compaction, while the pruned view stays lean because compress keeps folding closed spans. Each mechanism fired for a different reason: repetition, staleness, task closure. None of them waited for a threshold.

The nudge, and when there isn’t one

Those three strategies split into two kinds of work:

  • Rules — no nudge. Dedup and purgeErrors are deterministic. Identical repeated call? Drop the older copies. Failed input four turns stale? Strip it. They fire on every request whether the model is thinking about memory or not — no model involvement, no permission asked.
  • Judgment — nudge. Compress is the only strategy that needs taste: is this span actually finished? A plugin can’t know that. So DCP nudges: a hint travels with the request, telling the model the compress tool exists and when it fits. The model reads it and decides.
fig. 2 — rules run unconditionally; only compress waits on the model

Nudged, not forced — and that’s the deliberate trade. Forcing would mean gating the model’s work on a memory call it might disagree with, so DCP accepts the “model forgot to compress” failure mode instead.


vs Claude Code auto-compact

  • Trigger: fixed token/% threshold (currently ~95%, historically inconsistent — buffer size changed silently between versions).
  • Mechanism: one-shot, whole-transcript summarize-and-replace when it fires.
  • Control: /compact [instructions], CLAUDE.md compact section — and for years no true off switch; documented env-var attempts to disable were silently ignored through 2025–26. Working switches only arrived recently, and that era is why people stopped trusting them.

vs Codex CLI

  • Trigger: model_auto_compact_token_limit, similarly threshold-based, capped at 90% — can’t be raised further.
  • Mechanism: for OpenAI-hosted models, compaction is a server-side encrypted blob (type=compaction, encrypted_content) — opaque even to the client, explicitly “not intended to be human-interpretable.” Local models get plaintext LLM summarization instead.
  • On repeated compaction, prior summaries get discarded and replaced, not nested — each pass is built from the previous summary, so you lose fidelity every round.

The interesting bit

Both incumbents treat compaction as an infrastructure event: a threshold trips, the system yanks the whole transcript and replaces it with a summary, regardless of whether anything meaningful just finished. DCP inverts that — pruning tied to task completion semantics the model itself judges.

fig. 3 — one big replace at a threshold, versus many small folds at task boundaries
Axis
Claude Code / Codex
DCP
Trigger
token/% threshold (systems-level)
model decides via exposed tool call, nudged not forced
Granularity
whole transcript, one-shot
per-span or per-message, surgical
Repeated compaction
flat replace → lossy compounding
nested summaries → layered, not diluted
Cheap wins
none — everything funnels through summarization
dedup/error-purge run continuously, separate from summarization
Opacity
Codex: encrypted, uninspectable blob. Claude Code: buffer size changed w/o changelog entry
fully local, jsonc-configurable, inspectable

That’s a genuinely different failure mode to guard against. Instead of “ran out of room, panic-summarize everything,” it’s “model forgot to call compress, context grows unchecked.” Both are real; they’re duals, and each design picks one for you.

context-is-ram · agent memory management
© 2026 Simran's Writing Room