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

@davecodes/pi-dcp

v0.2.0

Published

Dynamic Context Pruning for Pi — port of opencode-dcp. Deduplication, error-input purge, and an LLM-callable compress tool to keep long sessions cheap.

Readme

Pi-Dynamic-Context-Pruning

Cut LLM token spend in long Pi sessions, automatically. Dedup redundant tool calls, strip errored payloads, and let the model summarize closed work-streams — all without ever modifying your session history.

A faithful port of @tarquinen/opencode-dcp tailored to pi's extension API. Zero npm dependencies at runtime.

License: AGPL-3.0-or-later. Tests: 55 passing on Node 22 and 24.

Contents

Why

A long agentic loop in Pi typically wastes tokens on:

  • Repeated lookups — the same grep or read re-issued five turns later
  • Failed payloads — a 4-KB bash command that errored, sent back to the model on every subsequent turn
  • Closed work-streams — initial repo scans, abandoned approaches, resolved retry loops whose raw output is no longer useful

pi-dcp prunes all three before the request hits the model. The on-disk session is never touched — pruning is applied to the request payload only, so /tree, /compact, fork, and resume all keep the originals intact.

How it works

A context event fires on every outbound LLM request. pi-dcp hooks that event, rewrites the request payload in-place, and lets it continue to the provider. The on-disk session is never mutated.

Three independent mechanisms run on the outbound request:

| Mechanism | What it does | When | |---|---|---| | Deduplication | Same toolName + canonical(args) keeps the newest result and replaces older copies with a [pruned by pi-dcp: duplicate ... call] marker. | Every LLM call (auto) | | Errored input purge | Failed tool calls have their arguments stripped after N turns. Error message is preserved. | Every LLM call (auto) | | compress tool | LLM-callable. Replaces a span of tool results with a lossless technical summary. Two modes: message (per-id list) or range (start and end span). | When the model decides |

Plus three nudge surfaces that bias the model toward compressing:

  • Soft or strong in-system-prompt nudge when usage crosses minContextLimit
  • Hard nudge above maxContextLimit
  • Iteration nudge after N non-user messages without a user reply

Install

Three ways. Pick one:

npm (recommended — versioned, easy to update):

pi install npm:@davecodes/pi-dcp

git (always tracks main):

pi install git:github.com/Davidcreador/pi-dcp

manual clone (for hacking on the code):

git clone [email protected]:Davidcreador/pi-dcp.git ~/.pi/agent/extensions/pi-dcp

All three paths produce the same runtime behavior. Pi auto-discovers the extension via its pi.extensions package.json entry.

User state always lives at ~/.pi-dcp/, not next to the code. That directory holds:

~/.pi-dcp/
  config.json              your settings (written on first run from defaults)
  prompts/
    defaults/              regenerated each launch (read-only reference)
    overrides/             drop *.md files here to customize the LLM prompts
  dcp.log                  debug log (when config.debug is true)
  stats.json               lifetime savings counters

To update:

pi update npm:@davecodes/pi-dcp

Quick start

After install, run pi normally. Verify the extension is live:

pi -p "do you have a tool called 'compress'? answer yes/no"

Expected output: yes.

Open a long session as usual. Check savings any time with:

/dcp context     # this session
/dcp stats       # lifetime, across sessions

To bias the model toward compressing more aggressively, edit ~/.pi-dcp/config.json:

{
  "compress": {
    "minContextLimit": "30%",
    "maxContextLimit": "60%",
    "nudgeForce": "strong"
  }
}

minContextLimit is the soft-nudge floor. maxContextLimit is the hard-nudge ceiling. Restart pi after config changes.

Slash commands

| Command | What it does | |---|---| | /dcp | Show this command list | | /dcp context | Current session: token usage, DCP savings, active compressions | | /dcp stats | Lifetime savings across all pi sessions | | /dcp sweep [n] | Stage a compression over the last n tool results (default: since last user message). Use to nuke unwanted output. | | /dcp manual on/off/toggle/status | Runtime manual mode — stops the LLM from auto-compressing. Edit config.json to persist. | | /dcp decompress <id> | Temporarily restore a stored compression's original tool outputs | | /dcp recompress <id> | Re-apply a previously decompressed entry |

Slash commands work in interactive pi mode only — pi -p (print mode) does not dispatch them. The compress tool and auto strategies work in both modes.

Configuration reference

Defaults are written to ~/.pi-dcp/config.json on first run. Per-project overrides at <repo>/.pi/dcp.json shallow-merge on top. Restart pi after edits.

The shipped defaults are tuned for real-world long sessions — see config.example.json in this repo for the exact reference shape and inline comments.

{
  "enabled": true,
  "debug": false,
  "pruneNotification": "minimal",

  "experimental": {
    "customPrompts": false
  },

  "manualMode": {
    "enabled": false,
    "automaticStrategies": true
  },

  "turnProtection": {
    "enabled": true,
    "turns": 3
  },

  "compress": {
    "mode": "range",
    "permission": "allow",
    "minContextLimit": 30000,
    "maxContextLimit": 70000,
    "modelMinLimits": {
      "anthropic/claude-opus-4-7": 35000
    },
    "modelMaxLimits": {
      "anthropic/claude-opus-4-7": 85000
    },
    "nudgeEveryTurns": 5,
    "nudgeFrequency": 3,
    "iterationNudgeThreshold": 8,
    "nudgeForce": "strong",
    "protectedTools": []
  },

  "strategies": {
    "deduplication": {
      "enabled": true,
      "protectedTools": []
    },
    "purgeErrors": {
      "enabled": true,
      "turns": 2,
      "protectedTools": []
    }
  }
}

Field notes:

  • pruneNotification: off, minimal, or detailed (reserved).
  • experimental.customPrompts: when true, honors prompts/overrides/*.md.
  • manualMode.automaticStrategies: when manual mode is on, still run dedup and purge.
  • turnProtection.turns: last N user-bounded turns are immune to pruning.
  • compress.minContextLimit / maxContextLimit: number of tokens or a "X%" string of the model's context window.
  • compress.nudgeEveryTurns: per-turn soft-nudge throttle.
  • compress.nudgeFrequency: per-request soft-nudge throttle (stacks with the per-turn one).
  • compress.iterationNudgeThreshold: 0 disables; fires after N messages since the last user message.
  • compress.nudgeForce: soft or strong wording.
  • strategies.purgeErrors.turns: turns after which errored args are purged.

Always protected (never pruned, regardless of config): compress, write, edit, todo, task, skill.

Per-model context limits

compress.modelMinLimits and modelMaxLimits accept keys shaped as provider/id, matching ctx.model.provider and ctx.model.id. Examples mirroring the shipped config.json:

| Model | Window | Soft floor | Hard ceiling | Strategy | |---|---|---|---|---| | anthropic/claude-haiku-4-5 | 200k | 30k | 70k | tight — cheap fast tier | | anthropic/claude-sonnet-4-5 | 200k | 50k | 120k | workhorse band | | anthropic/claude-sonnet-4-6 | 200k | 50k | 120k | workhorse band | | anthropic/claude-opus-4-1 to 4-7 | 200k | 35k | 85k | aggressive — save expensive tokens | | openai/gpt-5.4-mini-fast | — | 25k | 50k | tightest | | openai/gpt-5.4-mini | — | 30k | 70k | tight | | openai/gpt-5.5 | — | 45k | 100k | medium |

Values accept either a number (absolute token count) or a "X%" string (percentage of the model's context window).

Recipes

Save tokens aggressively on premium models

{
  "compress": {
    "modelMinLimits": { "anthropic/claude-opus-4-7": "10%" },
    "modelMaxLimits": { "anthropic/claude-opus-4-7": "25%" },
    "nudgeForce": "strong"
  }
}

Do not auto-compress, let me drive

{
  "manualMode": { "enabled": true, "automaticStrategies": true }
}

Auto-dedup and purge still run. You drive compression via /dcp sweep.

Project-specific overrides

Drop a .pi/dcp.json in the repo root:

{
  "strategies": {
    "purgeErrors": {
      "turns": 1,
      "protectedTools": ["lint"]
    }
  }
}

Customize the nudge wording

{
  "experimental": { "customPrompts": true }
}

Then create ~/.pi-dcp/prompts/overrides/strong-nudge.md with your text. Restart pi.

Troubleshooting

The compress tool is not showing up:

  • Confirm with pi -p "list your tools" 2>&1 | grep compress. If missing, check compress.permission is not "deny".
  • Restart pi after any config change. Extensions load once at startup.

Nothing is being pruned:

  • /dcp context shows live stats. If always 0:
    • turnProtection.turns may cover your whole session (recent turns are protected).
    • strategies.*.enabled may be false.
    • You may be hitting protected tools — write and edit are never deduped.

See what is happening under the hood:

{ "debug": true }

Restart pi. Logs land at ~/.pi-dcp/dcp.log:

[2026-05-13T...] INFO pi-dcp initialized {"mode":"range",...}
[2026-05-13T...] INFO pipeline applied {"dedupPruned":2,"errorInputsPurged":1,"tokensSaved":3214}

Compress tool refuses with protected_window_overlap:

  • The model picked tool-call IDs that live inside turnProtection.turns. Either lower turnProtection.turns, disable it, or tell the model to pick older calls.

Develop

cd ~/.pi/agent/extensions/pi-dcp

# Set up dev deps (peer + typescript)
npm install --no-save typescript @earendil-works/pi-coding-agent

# Typecheck + test
npm run check
npm run test

CI on GitHub Actions runs the same on Node 22 and 24 against every push and PR.

How it differs from opencode-dcp

| Feature | opencode-dcp | pi-dcp | |---|---|---| | Tokenizer | @anthropic-ai/tokenizer | ctx.getContextUsage() (built-in) | | Auto-update | npm latest check | git pull | | Soft/hard nudges | per-request injection | before_agent_start system-prompt addendum (functionally equivalent) | | compress.mode (range, message) | both | both | | turnProtection | runtime skip | runtime skip plus upfront refusal of compress tool overlap | | modelMinLimits and modelMaxLimits | yes | yes | | iterationNudgeThreshold | yes | yes | | nudgeForce | yes | yes | | compress.nudgeFrequency | yes | yes, plus per-turn nudgeEveryTurns | | Prompt overrides | yes | yes | | manualMode.automaticStrategies | yes | yes | | Skipped in pi-dcp | — | pruneNotificationType:"toast", compress.showCompression, compress.summaryBuffer, experimental.allowSubAgents, protectedFilePatterns |

Project layout

pi-dcp/
  index.ts                          extension entry — wires hooks, tool, /dcp command
  config.json                       runtime config (auto-generated; tracked)
  lib/
    config.ts                       loader, DEFAULT_CONFIG, percent + per-model resolution
    logger.ts                       ~/.pi-dcp/dcp.log writer (gated by config.debug)
    state.ts                        per-session in-memory state
    stats.ts                        ~/.pi-dcp/stats.json lifetime counters (atomic write)
    messages.ts                     AgentMessage helpers + canonical JSON + cloneForMutation
    pipeline.ts                     orchestrates strategies + applies compressions
    nudges.ts                       soft/strong/hard/iteration system-prompt addendums
    strategies/
      deduplication.ts              drop redundant tool calls
      purge-errors.ts               strip errored tool inputs after N turns
    tools/
      compress-message.ts           LLM tool — per-id mode
      compress-range.ts             LLM tool — span mode
      shared.ts                     preflight, storeCompression, branchToolCallIds
    prompts/
      index.ts                      PromptStore + defaults + override loader
    commands/                       /dcp subcommand handlers
      help.ts
      context.ts
      stats.ts
      manual.ts
      sweep.ts
      decompress.ts                 decompress + recompress
  test/                             55 unit tests, zero external deps
    pipeline.test.ts                dedup, purge, mutation safety, idempotency
    misc.test.ts                    config percent parsing, nudge throttling, parseStrictId
    features.test.ts                range mode, prompt overrides, manual modes, nudgeFreq
    parity.test.ts                  turnProtection, modelMin/Max, iterationNudge, nudgeForce
    audit.test.ts                   edge cases (no-user, iter-refire, protected overlap)
  skills/pi-dcp/SKILL.md            documentation surface pi reads at session start
  prompts/defaults/                 regenerated on every init (read-only reference)
  prompts/overrides/                you put files here when customPrompts is true
  .github/workflows/ci.yml          Node 22/24 matrix typecheck + test
  README.md

Credits and license

Concept and prompt design ported from @tarquinen/opencode-dcp by tarquinen. Pi adaptation and tests by @Davidcreador.

License: AGPL-3.0-or-later — inherits from upstream. See LICENSE.