Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
0d8147e
WIP: dev stash changes
Tarquinen Jan 24, 2026
cd77e3d
feat: add squash tool and combo prompt variants
Tarquinen Jan 25, 2026
278f862
refactor: use ulid for synthetic message ID generation
Tarquinen Jan 26, 2026
6ce83d6
refactor: move squashSummaries to top-level state
Tarquinen Jan 26, 2026
41a7c08
refactor: move squash utility functions to tools/utils.ts
Tarquinen Jan 26, 2026
adfdd71
fix: add secure mode authentication support
Tarquinen Jan 27, 2026
ca972e0
refactor: append context info to existing assistant messages instead …
Tarquinen Jan 28, 2026
8e57d9d
fix: improve discard/extract robustness and fix missing cache sync (D…
Tarquinen Jan 28, 2026
db08fc3
v1.3.0-beta.1 - Bump beta version
Tarquinen Jan 28, 2026
0e803ea
docs: sync schema and README with implementation of protected tools
Tarquinen Jan 28, 2026
80f1a7e
docs: add ko-fi badge to README
Tarquinen Jan 28, 2026
a39c766
swap readme buttons
Tarquinen Jan 28, 2026
ff132f1
validate extraction is array
Tarquinen Jan 28, 2026
3470c06
improve squash tool error messages to specify which boundary string f…
Tarquinen Jan 28, 2026
d3cbf5d
revert prompt style to dev branch format with semantic improvements
Tarquinen Jan 28, 2026
74cdce5
v1.3.1-beta.0 - Bump version
Tarquinen Jan 28, 2026
286b309
docs: move demo images to assets/images directory
Tarquinen Jan 28, 2026
ce86682
fix: ensure tool count accuracy in context breakdown using unique cal…
Tarquinen Jan 29, 2026
2255691
cleanup
Tarquinen Jan 29, 2026
0a381d8
refactor: inject assistant text parts instead of tool parts
Tarquinen Jan 29, 2026
f963d8a
refactor: hybrid injection strategy for DeepSeek/Kimi models
Tarquinen Jan 29, 2026
e1f5312
injection guide comments
Tarquinen Jan 29, 2026
a74cb8b
refactor: new prompt structure and dx cli
spoons-and-mirrors Jan 29, 2026
0bcec1d
inline tags to avoid unwanted linebreak
spoons-and-mirrors Jan 29, 2026
c645e69
nudge
spoons-and-mirrors Jan 29, 2026
06ce131
gitignore
spoons-and-mirrors Jan 29, 2026
53e2c15
DCP: Distill Compress Prune
spoons-and-mirrors Jan 29, 2026
5863a1d
reorder tool registering
spoons-and-mirrors Jan 29, 2026
3d9e4df
Merge pull request #327 from Opencode-DCP/prompt/refactor
Tarquinen Jan 30, 2026
efead8f
fix: generate .ts from .md at build time for bundler compatibility
Tarquinen Jan 30, 2026
cdb5862
refactor: consolidate cli/ into scripts/
Tarquinen Jan 30, 2026
f123eb3
Fix context summary output to handle cases where only tools or only m…
Tarquinen Jan 30, 2026
2cd85fc
revert: show cooldown for errored tools to prevent loop behavior
Tarquinen Jan 30, 2026
866bdc1
spell check
Tarquinen Jan 30, 2026
d66a6c2
docs: standardize DCP tool order to distill, compress, prune
Tarquinen Jan 30, 2026
22f5848
Rename compress tool config from showSummary to showCompression
Tarquinen Jan 30, 2026
9ad912c
chore: bump version to 1.3.1-beta.2
Tarquinen Jan 30, 2026
fbf3bd8
Merge pull request #331 from Opencode-DCP/beta
Tarquinen Jan 31, 2026
d71f5c6
stuff
Tarquinen Jan 31, 2026
4bd1fb8
maybe
Tarquinen Jan 31, 2026
85b0aeb
cc cache readme stuff
Tarquinen Jan 31, 2026
b8d7486
cleanup
Tarquinen Jan 31, 2026
0fc988a
cleanup tool cache logic
Tarquinen Jan 31, 2026
a8b2551
update dependencies and migrate to v2 sdk
Tarquinen Jan 31, 2026
a21285a
feat: add full tool pruning for edit and write tools
Tarquinen Jan 31, 2026
dc104e2
fix: move schema validation to execute() for better error messages
Tarquinen Jan 31, 2026
7453ed4
v1.3.2-beta.0 - Bump version
Tarquinen Jan 31, 2026
4e03a4b
refactor: use Set for prune ID storage
Tarquinen Feb 1, 2026
b3d9e5b
feat: support toast notifications via notificationType config option
essinghigh Feb 1, 2026
8f469ad
prettier
essinghigh Feb 1, 2026
7e3a43c
Merge branch 'dev' into notification-toast-dev
Tarquinen Feb 1, 2026
e96796d
Merge pull request #340 from essinghigh/notification-toast-dev
Tarquinen Feb 1, 2026
6148868
refactor: revert to simpler tool part injection for all models
Tarquinen Feb 1, 2026
698392e
fix: restore Gemini thoughtSignature bypass for synthetic tool parts
Tarquinen Feb 1, 2026
0bcacfb
refactor: rename prunedCount to prunedToolCount for clarity
Tarquinen Feb 1, 2026
e595928
docs: add pruneNotificationType to README config example
Tarquinen Feb 1, 2026
e82ed4d
feat: add message count tracking to stats display
Tarquinen Feb 1, 2026
1d93287
v1.3.3-beta.0 - Bump version
Tarquinen Feb 1, 2026
5166df3
refactor: inject context as text part in existing user message
Tarquinen Feb 2, 2026
3a1bfd6
feat: use synthetic assistant messages for non-DeepSeek/Kimi injection
Tarquinen Feb 2, 2026
0467654
refactor: use tool parts for all non-user-message injections
Tarquinen Feb 3, 2026
7e44bd7
chore: track tests/, gitignore tests/results/
Tarquinen Feb 3, 2026
5df9e01
feat: add session analysis utility scripts
Tarquinen Feb 3, 2026
16c8f25
test: add DCP cache testing script
Tarquinen Feb 3, 2026
1a3b7f3
refactor: simplify context injection to use tool parts universally
Tarquinen Feb 3, 2026
cbbf60a
chore: remove unused variant variable from inject.ts
Tarquinen Feb 3, 2026
e5b2038
feat: add token counting for prunable tools
Tarquinen Feb 3, 2026
7304f0a
feat: add context usage info to prunable tools list
Tarquinen Feb 3, 2026
b5a4d05
refactor: use userInfo consistently in synthetic part creation
Tarquinen Feb 3, 2026
e76a8ce
readme update
Tarquinen Feb 3, 2026
19484ca
Relicense to AGPL-3.0 and add Contributor License Agreement (CLA)
Tarquinen Feb 4, 2026
3828d47
Add PR template and update CONTRIBUTING.md with official CLA info
Tarquinen Feb 4, 2026
2f036c6
Clarify CLA process and reference SAP template in CONTRIBUTING.md
Tarquinen Feb 4, 2026
ed112b0
docs: add test file for CLA verification
Tarquinen Feb 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
### Summary
<!-- Provide a brief description of the changes in this PR -->

### Checklist
- [ ] I have read the [CONTRIBUTING.md](https://github.com/Opencode-DCP/opencode-dynamic-context-pruning/blob/dev/CONTRIBUTING.md)
- [ ] I have signed the CLA via the CLA Assistant bot (check the bot comment below after opening the PR)
- [ ] My changes follow the project's coding style
- [ ] I have added tests to cover my changes (if applicable)
9 changes: 7 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,16 @@ Thumbs.db
# OpenCode
.opencode/

# Tests (local development only)
tests/
# Generated prompt files (from scripts/generate-prompts.ts)
lib/prompts/*.generated.ts

# Tests
tests/results/
notes/
test-update.ts

# Documentation (local development only)
docs/
SCHEMA_NOTES.md

repomix-output.xml
9 changes: 9 additions & 0 deletions .repomixignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.github/
.logs/
.opencode/
dist/
.repomixignore
repomix-output.xml
bun.lock
package-lock.jsonc
LICENCE
21 changes: 21 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Contributing to DCP

Thank you for your interest in contributing to Dynamic Context Pruning (DCP)!

## License and Contributor License Agreement (CLA)

This project uses the **GNU Affero General Public License v3.0 (AGPL-3.0)**.

To maintain the project's sustainability, we require contributors to sign a **Contributor License Agreement (CLA)**. We use the standard **SAP Individual Contributor License Agreement**, which allows us to keep the project open-source while preserving the ability to offer commercial licenses to organizations that cannot comply with the AGPL-3.0.

When you open a Pull Request, the **[CLA Assistant](https://cla-assistant.io/)** bot will automatically ask you to sign the agreement if you haven't already.

## Getting Started

1. Fork the repository.
2. Create a feature branch.
3. Implement your changes and add tests if applicable.
4. Ensure all tests pass and the code is formatted.
5. Submit a Pull Request.

We look forward to your contributions!
640 changes: 619 additions & 21 deletions LICENSE

Large diffs are not rendered by default.

185 changes: 97 additions & 88 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# Dynamic Context Pruning Plugin

[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/dansmolsky)
[![npm version](https://img.shields.io/npm/v/@tarquinen/opencode-dcp.svg)](https://www.npmjs.com/package/@tarquinen/opencode-dcp)

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

![DCP in action](dcp-demo5.png)
![DCP in action](assets/images/dcp-demo5.png)

## Installation

Expand All @@ -27,15 +28,17 @@ DCP uses multiple tools and strategies to reduce context size:

### Tools

**Discard** — Exposes a `discard` tool that the AI can call to remove completed or noisy tool content from context.
**Distill** — Exposes a `distill` tool that the AI can call to distill valuable context into concise summaries before removing the tool content.

**Extract** — Exposes an `extract` tool that the AI can call to distill valuable context into concise summaries before removing the tool content.
**Compress** — Exposes a `compress` tool that the AI can call to collapse a large section of conversation (messages and tools) into a single summary.

**Prune** — Exposes a `prune` tool that the AI can call to remove completed or noisy tool content from context.

### 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** — Prunes write tool inputs 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.
**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.

Expand All @@ -47,90 +50,100 @@ LLM providers like Anthropic and OpenAI cache prompts based on exact prefix matc

**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 65% with DCP enabled vs 85% without.
> **Note:** In testing, cache hit rates were approximately 80% with DCP enabled vs 85% without for most providers.

**Best use case:** Providers that count usage in requests, such as Github Copilot and Google Antigravity, have no negative price impact.

**Best use case:** Providers that count usage in requests, such as Github Copilot and Google Antigravity have no negative price impact.
**Claude Subscriptions:** Anthropic subscription users (who receive "free" caching) may experience faster limit depletion than hit-rate ratios suggest due to the higher relative cost of cache misses. See [Claude Cache Limits](https://she-llac.com/claude-limits) for details.

## 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

<details>
<summary><strong>Default Configuration</strong> (click to expand)</summary>

```jsonc
{
"$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",
// Slash commands configuration
"commands": {
"enabled": true,
// Additional tools to protect from pruning via commands (e.g., /dcp sweep)
"protectedTools": [],
},
// Protect from pruning for <turns> message turns
"turnProtection": {
"enabled": false,
"turns": 4,
},
// Protect file operations from pruning via glob patterns
// Patterns match tool parameters.filePath (e.g. read/write/edit)
"protectedFilePatterns": [],
// LLM-driven context pruning tools
"tools": {
// Shared settings for all prune tools
"settings": {
// Nudge the LLM to use prune tools (every <nudgeFrequency> tool results)
"nudgeEnabled": true,
"nudgeFrequency": 10,
// Additional tools to protect from pruning
"protectedTools": [],
},
// Removes tool content from context without preservation (for completed tasks or noise)
"discard": {
"enabled": true,
},
// Distills key findings into preserved knowledge before removing raw content
"extract": {
"enabled": true,
// Show distillation content as an ignored message notification
"showDistillation": 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 write tool inputs when the file has been subsequently read
"supersedeWrites": {
"enabled": false,
},
// 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": [],
},
},
}
```

</details>
- Project: `.opencode/dcp.jsonc` (or `dcp.json`) in your project's `.opencode` directory

> <details>
> <summary><strong>Default Configuration</strong> (click to expand)</summary>
>
> ```jsonc
> {
> "$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": [],
> },
> // Protect from pruning for <turns> message turns past tool invocation
> "turnProtection": {
> "enabled": false,
> "turns": 4,
> },
> // Protect file operations from pruning via glob patterns
> // Patterns match tool parameters.filePath (e.g. read/write/edit)
> "protectedFilePatterns": [],
> // LLM-driven context pruning tools
> "tools": {
> // Shared settings for all prune tools
> "settings": {
> // Nudge the LLM to use prune tools (every <nudgeFrequency> tool results)
> "nudgeEnabled": true,
> "nudgeFrequency": 10,
> // Additional tools to protect from pruning
> "protectedTools": [],
> },
> // Removes tool content from context without preservation (for completed tasks or noise)
> "prune": {
> "enabled": true,
> },
> // Distills key findings into preserved knowledge before removing raw content
> "distill": {
> "enabled": true,
> // Show distillation content as an ignored message notification
> "showDistillation": false,
> },
> // Collapses a range of conversation content into a single summary
> "compress": {
> "enabled": true,
> // Show summary content as an ignored message notification
> "showCompression": true,
> },
> },
> // 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": [],
> },
> },
> }
> ```
>
> </details>

### Commands

Expand All @@ -141,14 +154,10 @@ DCP provides a `/dcp` slash command:
- `/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`.

### Turn Protection

When enabled, turn protection prevents tool outputs from being pruned for a configurable number of message turns. This gives the AI time to reference recent tool outputs before they become prunable. Applies to both `discard` and `extract` tools, as well as automatic strategies.

### Protected Tools

By default, these tools are always protected from pruning across all strategies:
`task`, `todowrite`, `todoread`, `discard`, `extract`, `batch`, `write`, `edit`
By default, these tools are always protected from pruning:
`task`, `todowrite`, `todoread`, `distill`, `compress`, `prune`, `batch`, `plan_enter`, `plan_exit`

The `protectedTools` arrays in each section add to this default list.

Expand All @@ -166,4 +175,4 @@ Restart OpenCode after making config changes.

## License

MIT
AGPL-3.0-or-later
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
1 change: 1 addition & 0 deletions cla-test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This is a test file to verify the CLA Assistant bot.
Loading
Loading