JSPM

  • Created
  • Published
  • Downloads 8919
  • Score
    100M100P100Q152268F
  • License AGPL-3.0-or-later

OpenCode plugin that optimizes token usage by pruning obsolete tool outputs from conversation context

Package Exports

  • @tarquinen/opencode-dcp
  • @tarquinen/opencode-dcp/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@tarquinen/opencode-dcp) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Dynamic Context Pruning Plugin

ko-fi npm version

Automatically reduces token usage in OpenCode by removing obsolete content from conversation history.

DCP in action

Installation

Add to your OpenCode config:

// opencode.jsonc
{
    "plugin": ["@tarquinen/opencode-dcp@latest"],
}

Using @latest ensures you always get the newest version automatically when OpenCode starts.

Restart OpenCode. The plugin will automatically start optimizing your sessions.

Beta Notice (v2.2.7-beta0)

  • Strategy shift to a single user-facing context tool: compress.
  • Context management is now less surgical and more focused on preserving high-signal work grouped by task.

How Pruning Works

DCP uses one user-facing tool and strategies to reduce context size:

For model-facing behavior (prompts and tool calls), this capability is always addressed as compress.

Tool

Compress — Exposes a compress tool that will select a conversation range and replace it with a technical summary.

The model can use compress at different scales: tiny ranges for noise cleanup, focused ranges for preserving key findings, and full chapters for completed work. The model will choose the best moment to compress based on session context size and opportunity.

Strategies

Deduplication — Identifies repeated tool calls (e.g., reading the same file multiple times) and keeps only the most recent output. Runs automatically on every request with zero LLM cost.

Supersede Writes — Removes write tool calls for files that have subsequently been read. When a file is written and later read, the original write content becomes redundant since the current file state is captured in the read result. Runs automatically on every request with zero LLM cost.

Purge Errors — Prunes tool inputs for tools that returned errors after a configurable number of turns (default: 4). Error messages are preserved for context, but the potentially large input content is removed. Runs automatically on every request with zero LLM cost.

Your session history is never modified—DCP replaces pruned content with placeholders before sending requests to your LLM.

Impact on Prompt Caching

LLM providers like Anthropic and OpenAI cache prompts based on exact prefix matching. When DCP prunes a tool output, it changes the message content, which invalidates cached prefixes from that point forward.

Trade-off: You lose some cache read benefits but gain larger token savings from reduced context size and performance improvements through reduced context poisoning. In most cases, the token savings outweigh the cache miss cost—especially in long sessions where context bloat becomes significant.

Note: In testing, cache hit rates were approximately 85% with DCP enabled vs 90% without for most providers.

Best use cases:

  • Request-based billing — Providers that count usage in requests, such as Github Copilot have no negative price impact.
  • Uniform token pricing — Providers that bill cached tokens at the same rate as regular input tokens, such as Cerebras, see pure savings with no cache-miss penalty.

Configuration

DCP uses its own config file:

  • Global: ~/.config/opencode/dcp.jsonc (or dcp.json), created automatically on first run
  • Custom config directory: $OPENCODE_CONFIG_DIR/dcp.jsonc (or dcp.json), if OPENCODE_CONFIG_DIR is set
  • Project: .opencode/dcp.jsonc (or dcp.json) in your project's .opencode directory

[!IMPORTANT] Defaults are applied automatically. Expand this if you want to review or override settings.

Default Configuration (click to expand)
{
    "$schema": "https://raw.githubusercontent.com/Opencode-DCP/opencode-dynamic-context-pruning/master/dcp.schema.json",
    // Enable or disable the plugin
    "enabled": true,
    // Enable debug logging to ~/.config/opencode/logs/dcp/
    "debug": false,
    // Notification display: "off", "minimal", or "detailed"
    "pruneNotification": "detailed",
    // Notification type: "chat" (in-conversation) or "toast" (system toast)
    "pruneNotificationType": "chat",
    // Slash commands configuration
    "commands": {
        "enabled": true,
        // Additional tools to protect from pruning via commands (e.g., /dcp sweep)
        "protectedTools": [],
    },
    // Manual mode: disables autonomous context management,
    // tools only run when explicitly triggered via /dcp commands
    "manualMode": {
        "enabled": false,
        // When true, automatic strategies (deduplication, supersedeWrites, purgeErrors)
        // still run even in manual mode
        "automaticStrategies": true,
    },
    // Protect from pruning for <turns> message turns past tool invocation
    "turnProtection": {
        "enabled": false,
        "turns": 4,
    },
    // Experimental settings
    "experimental": {
        // Allow DCP processing in subagent sessions
        "allowSubAgents": false,
    },
    // Protect file operations from pruning via glob patterns
    // Patterns match tool parameters.filePath (e.g. read/write/edit)
    "protectedFilePatterns": [],
    // Unified context compression tool and behavior settings
    "compress": {
        // Permission mode: "allow" (no prompt), "ask" (prompt), "deny" (tool not registered)
        "permission": "allow",
        // Show compression content in a chat notification
        "showCompression": false,
        // Soft upper threshold: above this, DCP keeps injecting strong
        // compression nudges (based on nudgeFrequency), so compression is
        // much more likely. Accepts: number or "X%" of model context window.
        "maxContextLimit": 100000,
        // Soft lower threshold for reminder nudges: below this, turn/iteration
        // reminders are off (compression less likely). At/above this, reminders
        // are on. Accepts: number or "X%" of model context window.
        "minContextLimit": 30000,
        // Optional per-model override for maxContextLimit by providerID/modelID.
        // If present, this wins over the global maxContextLimit.
        // Accepts: number or "X%".
        // Example:
        // "modelMaxLimits": {
        //     "openai/gpt-5.3-codex": 120000,
        //     "anthropic/claude-sonnet-4.6": "80%"
        // },
        // Optional per-model override for minContextLimit.
        // If present, this wins over the global minContextLimit.
        // "modelMinLimits": {
        //     "openai/gpt-5.3-codex": 30000,
        //     "anthropic/claude-sonnet-4.6": "25%"
        // },
        // How often the context-limit nudge fires (1 = every fetch, 5 = every 5th)
        "nudgeFrequency": 5,
        // Start adding compression reminders after this many
        // messages have happened since the last user message
        "iterationNudgeThreshold": 15,
        // Controls how likely compression is after user messages
        // ("strong" = more likely, "soft" = less likely)
        "nudgeForce": "soft",
        // Tool names whose completed outputs are appended to the compression
        "protectedTools": [],
    },
    // Automatic pruning strategies
    "strategies": {
        // Remove duplicate tool calls (same tool with same arguments)
        "deduplication": {
            "enabled": true,
            // Additional tools to protect from pruning
            "protectedTools": [],
        },
        // Prune write tool inputs when the file has been subsequently read
        "supersedeWrites": {
            "enabled": true,
        },
        // Prune tool inputs for errored tools after X turns
        "purgeErrors": {
            "enabled": true,
            // Number of turns before errored tool inputs are pruned
            "turns": 4,
            // Additional tools to protect from pruning
            "protectedTools": [],
        },
    },
}

Commands

DCP provides a /dcp slash command:

  • /dcp — Shows available DCP commands

  • /dcp context — Shows a breakdown of your current session's token usage by category (system, user, assistant, tools, etc.) and how much has been saved through pruning.

  • /dcp stats — Shows cumulative pruning statistics across all sessions.

  • /dcp sweep — Prunes all tools since the last user message. Accepts an optional count: /dcp sweep 10 prunes the last 10 tools. Respects commands.protectedTools.

  • /dcp manual [on|off] — Toggle manual mode or set explicit state. When on, the AI will not autonomously use context management tools.

  • /dcp compress [focus] — Trigger a single compress tool execution. Optional focus text directs what range to compress.

Protected Tools

By default, these tools are always protected from pruning: task, todowrite, todoread, compress, batch, plan_enter, plan_exit

The protectedTools arrays in commands and strategies add to this default list.

For the compress tool, compress.protectedTools ensures specific tool outputs are appended to the compressed summary. It defaults to an empty array [] but always inherently protects task, todowrite, and todoread.

Config Precedence

Settings are merged in order: Defaults → Global (~/.config/opencode/dcp.jsonc) → Config Dir ($OPENCODE_CONFIG_DIR/dcp.jsonc) → Project (.opencode/dcp.jsonc). Each level overrides the previous, so project settings take priority over config-dir and global, which take priority over defaults.

Restart OpenCode after making config changes.

Limitations

Subagents — DCP is disabled for subagents by default. Subagents are not designed to be token efficient; what matters is that the final message returned to the main agent is a concise summary of findings. DCP's pruning could interfere with this summarization behavior.

You can opt in experimentally with experimental.allowSubAgents: true.

License

AGPL-3.0-or-later