npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@omri1100/opencode-dcp

v3.1.19

Published

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

Readme

Dynamic Context Pruning Plugin

ko-fi npm version

Automatically reduces token usage in OpenCode by managing conversation context.

DCP in action

Installation

Install from the CLI:

opencode plugin @tarquinen/opencode-dcp@latest --global

This installs the package and adds it to your global OpenCode config.

Project Status

Development on DCP has slowed because most new context-management work has moved to Sleev and the sleev CLI. Sleev is a local proxy for Claude Code, Codex, and OpenCode that builds on DCP's core ideas with newer context-management features and will work with any harness/client.

DCP remains available for OpenCode plugin users, but new features are landing in Sleev first. If you are starting fresh, we recommend trying Sleev:

npm i -g sleev
sleev

How It Works

DCP reduces context size through a compress tool and automatic cleanup. Your session history is never modified — DCP replaces pruned content with placeholders before sending requests to your LLM.

Compress

Compress is a tool exposed to your model that replaces closed, stale conversation content with high-fidelity technical summaries. You can think of this as a much smarter version of Opencode's compaction process. Instead of triggering statically when your session reaches its maximum context and on the entire coding session, Compress allows the model to pick when to activate based on task completion, and to only compress the specific messages that are no longer needed verbatim.

DCP supports two compression modes:

  • range mode compresses contiguous spans of conversation into one or more summaries.
  • message mode (experimental) compresses individual raw messages independently, letting the model manage context much more surgically.

In range mode, when a new compression overlaps an earlier one, the earlier summary is nested inside the new one so information is preserved through layers of compression rather than diluted away. In both modes, protected tool outputs (such as subagents and skills) and protected file patterns are kept in compression summaries, ensuring that the most important information is never lost. You can also enable protectUserMessages to preserve your messages verbatim during compression, though note that large prompts (e.g. copy-pasting log files in the prompt) will then never be compressed away.

Deduplication

Identifies repeated tool calls (same tool, same arguments) and keeps only the most recent output. Recalculated when the compress tool runs, so prompt cache is only impacted alongside compression.

Purge Errors

Prunes inputs from errored tool calls after a configurable number of turns (default: 4). Error messages are preserved; only the potentially large input content is removed. Recalculated on compress tool use.

Configuration

DCP uses its own config file, searched in order:

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

Each level overrides the previous, so project settings take priority over global. Restart OpenCode after making config changes.

[!NOTE] If you use models with smaller context windows, such as GitHub Copilot models or local models, lower compress.minContextLimit and compress.maxContextLimit in your configuration to match the available context.

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

{
    "$schema": "https://raw.githubusercontent.com/Opencode-DCP/opencode-dynamic-context-pruning/master/dcp.schema.json",
    // Enable or disable the plugin
    "enabled": true,
    // Automatically update npm-installed DCP when a newer npm latest is available.
    // Version-locked plugin specs are not updated.
    "autoUpdate": 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 cleanup (deduplication, purgeErrors)
        // still runs 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,
        // Enable user-editable prompt overrides under dcp-prompts directories
        // When false (default), prompt override files/directories are ignored
        "customPrompts": 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": {
        // Compression mode: "range" (compress spans into block summaries)
        // or experimental "message" (compress individual raw messages)
        "mode": "range",
        // Permission mode: "allow" (no prompt), "ask" (prompt), "deny" (tool not registered)
        "permission": "allow",
        // Show compression content in a chat notification
        "showCompression": false,
        // Let active summary tokens extend the effective maxContextLimit
        "summaryBuffer": true,
        // 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": 50000,
        // 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": 50000,
        //     "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": [],
        // Preserve text wrapped in <protect>...</protect> when compressed
        "protectTags": false,
        // Preserve your messages during compression.
        // Warning: large copy-pasted prompts will never be compressed away
        "protectUserMessages": false,
    },
    // Automatic pruning strategies
    "strategies": {
        // Remove duplicate tool calls (same tool with same arguments)
        "deduplication": {
            "enabled": true,
            // Additional tools to protect from pruning
            "protectedTools": [],
        },
        // 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 TUI panel and one prompt-producing slash command:

  • /dcp — Opens the DCP panel with context, stats, and manual-mode controls.
  • /dcp-compress [focus] — Asks the model to run one compression pass. Optional focus text directs what content to compress, following the active compress.mode.

Prompt Overrides

DCP exposes six editable prompts:

  • system
  • compress-range
  • compress-message
  • context-limit-nudge
  • turn-nudge
  • iteration-nudge

This feature is disabled by default. Set experimental.customPrompts to true in your DCP config to activate it.

When enabled, managed defaults are written to ~/.config/opencode/dcp-prompts/defaults/ as plain-text prompt files. A single README.md in that directory explains each prompt and how to create overrides.

To customize behavior, add a file with the same name under an overrides directory and edit it as plain text.

To reset an override, delete the matching file from your overrides directory.

Protected Tools

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

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. By default it includes task, skill, todowrite, and todoread.

Archived task report digests (fork, opt-in)

Set "compress": { "taskReportDigests": true } in DCP configuration and restart OpenCode to enable optional report digests in the existing compression call:

{
    "topic": "Reader investigation",
    "content": [
        {
            "startId": "b4",
            "endId": "m0080",
            "summary": "(b4)\nCurrent implementation decisions and working notes...",
            "taskReports": [
                {
                    "taskId": "ses_helper_session_id",
                    "digest": "Relevant findings, latest requirements/decisions, constraints, open issues, resolved issues, and evidence/file paths...",
                },
            ],
        },
    ],
}

This is off by default and independent of observability and its policy. The main agent writes the digest; DCP makes no extra AI calls. Only completed protected task reports are eligible. Skills, user messages, working notes and other tool outputs keep their existing preservation behavior. A missing/empty digest, ambiguous report identity, failed archive write or unreadable archive keeps the full report. Digests that would not shorten the report also keep it intact.

When enabled, eligible visible reports receive a short guidance tag with their helper session IDs, original byte sizes, and a concrete taskReports example. This also covers exact reports still retained inside old blocks. Guidance is attached to the report or its containing block, rather than a changing list in an older system prompt. Adding an unrelated helper report leaves earlier guidance unchanged. At most eight candidates per block are shown; originals remain intact. These hints do not request an extra compression, helper task, or model call.

With observability enabled, each successful compression call also records one count-only task-reports event, including calls with zero eligible reports. It counts eligible/ineligible reports, requested IDs, requests matching eligible reports, replacements, retained reports and unmatched requests. Retention reasons include missing/invalid/duplicate digests, ambiguous identity, a digest that is not shorter, or archive failure. Before/after byte and token estimates include the digest's archive link. Identical originals are counted once per selected entry; a batch sums its entries. No report text, helper IDs, archive paths or digest text are included in these events. Existing observability retention and enable/disable settings apply. Events carry the recording plugin version; backfilled usage still keeps its original request timestamp.

dcp-report shows adoption among eligible calls, retained reasons, net report token estimates and median reduction across eligible calls (including missed opportunities). Calls from older logs without these counters are marked untracked, not assumed to have zero reports. Use the next 20 eligible calls to check adoption and whether median report-payload reduction reaches 50%, while retaining exact originals and preserving requirements. This is a report-level estimate, not total-context reduction, causal savings or subscription quota.

Before replacement, DCP saves the exact original report in $XDG_DATA_HOME/opencode/storage/plugin/dcp/task-reports/<sha256>.txt (normally under ~/.local/share/). These are local content archives, separate from the count-only observations, with no automatic retention cleanup. The digest includes an absolute file path the agent can read to recover details. Existing archives are verified before reuse and are never overwritten. Keep these files when moving a session to another machine.

Reports already embedded in selected old blocks can also be shortened during a merge. DCP requires the complete exact output from history and an uninterrupted protected-tools section matched to those outputs. It stops at working notes or unknown content. Missing original history, ambiguous boundaries and unrecognized formats keep the full report; report-shaped text is never used to infer a partial original. Old blocks are expanded normally; only identified reports change. Compact successful-replacement receipts are recorded in the compression tool result so historical recovery uses the same choices, including when this option is later disabled. Normal state reload keeps the saved summary and archive references as-is.

Impact on Prompt Caching

LLM providers cache prompts based on exact prefix matching. When DCP prunes content, it changes messages, which invalidates cached prefixes from that point forward.

Trade-off: You lose some cache reads but gain token savings from reduced context size and fewer hallucinations from stale context. In most cases, especially in long sessions, the savings outweigh the cache miss cost.

[!NOTE] In testing, cache hit rates were approximately 85% with DCP vs 90% without.

No impact for:

  • Request-based billing — Providers like GitHub Copilot that charge per request, not tokens.
  • Uniform token pricing — Providers like Cerebras that bill cached and uncached tokens at the same rate.

License

AGPL-3.0-or-later

Local usage observations (fork)

Enable count-only tracking in ~/.config/opencode/dcp.jsonc, then restart OpenCode:

{
    "observability": {
        "enabled": true,
        "retentionDays": 14,
        "detailedDiagnostics": false,
    },
}

Tracking is off by default and independent of debug. These options can also be set in project DCP configuration. The allowed retention is 1–365 days. Files live under $XDG_DATA_HOME/opencode/storage/plugin/dcp/observability/ (normally ~/.local/share/opencode/storage/plugin/dcp/observability/), with daily rotation and retention cleanup on the first observation of each UTC day. Disabling tracking stops writes and cleanup; existing files remain local.

Logs contain request/session/block identifiers, model/variant, token counts, compression outcomes, timestamps and the first changed message position. They do not contain conversation text, summaries, reasoning text, tool arguments, tool outputs, error text, or file paths. Prefix comparisons use in-memory hashes that are never written to disk. Tracking makes no AI or network calls and does not change prompts, compression rules, or model settings. Optional detailedDiagnostics also estimates transformed message tokens locally, including reasoning; it adds tokenization work and is normally unnecessary.

Observation-only compression policy

To measure a candidate rule, add this inside observability and restart OpenCode:

"policy": {
    "enabled": true,
    "minReductionPercent": 10,
    "emergencyContextPercent": 90,
}

The policy is off by default and requires observability.enabled; it does not require detailedDiagnostics. Every compression still runs normally. Each successful call records whether the candidate would allow, defer, or be unknown. It would allow an estimated whole-context reduction of at least 10%, or an estimated context at least 90% of the actual model context limit. A small reduction with no known model limit is unknown, rather than assumed safe to defer. Both percentages are configurable, greater than 0 and at most 100.

Before automatic tool pruning and after the complete compression batch, the policy counts copies of the visible messages through DCP's real replacement path. This includes existing summaries, protected content, reasoning and native-cleared tool output placeholders. Hidden raw history is not counted again. System/tool overhead is estimated from cached system counts and the latest provider usage and held constant. Message IDs, nudges, provider serialization and newer-model tokenization are not reproduced exactly, so these are predictions, not provider token counts. The comparison adds local tokenization work twice per compression call; it adds no AI requests, retries or model instructions. Failed compressions have no prediction.

The report joins predictions with the following request's observed context drop and cache reads/writes. It displays decision counts and prediction error; use --json to inspect each pair. Gaps, model changes, missing usage and multiple compression calls in the same request prevent a clean paired comparison. New work and generated tokens can still affect the observed drop. Older events without policy predictions remain readable. There is no enforcement or cooldown in this mode.

Generate a weekly report with the published package:

npm exec --package=@omri1100/[email protected] -- dcp-report --days 7

Use --json for per-compression observations or --dir PATH for an alternate log directory. In a checkout, run npm run report -- --days 7. The report itself runs locally; npm exec may download the package on its first use.

The report deduplicates request observations across restarts, groups batched ranges into one compression call, and separates fresh blocks from merged blocks. Paired comparisons flag missing usage, gaps over five minutes, and model/variant changes. It shows observed context drops, not net savings or subscription-quota usage: intervening work, native pruning and provider cache behavior can affect the same requests. Recorded provider cost may be zero under a subscription. Resuming a session can backfill usage and completed/failed tool attempts already in its history; compression position and summary counts are recorded only for live compressions with tracking enabled. Prefix comparisons start fresh after restart.

Summary recovery

Historical range reconstruction now uses the same placeholder expansion, boundary-block preservation, missing-block appending and protected-content steps as live compression. This keeps earlier summaries visible when a fork or native compaction requires rebuilding DCP state. Recovery uses the current protection settings and available history. Existing saved DCP state is not automatically rebuilt by this release.

Release installation check

npm run check:package also packs the release and installs that tarball in an empty temporary project using normal npm dependency resolution (no --force or --legacy-peer-deps). It initializes the installed server, verifies local usage and detailed diagnostic records, and launches the installed report executable. This check requires registry access and does not touch your OpenCode installation.

The runtime tool-helper SDK is a direct dependency pinned to the build-tested version rather than an unrestricted peer that can pull in incompatible UI packages. Terminal UI peers are optional for server/report installation; their existing compatibility ranges are unchanged.