dsh-readprune
Save tokens in a DeepSeek Harness session by keeping content out of the context in the first place.
A Host plugin that prunes input at the source rather than compressing it afterwards: read any file by line range or symbol mention instead of whole, and bound oversized tool results at the boundary while keeping a recovery path.
What makes this different
Most token-saving plugins work on content that has already entered the context: they summarize it, fold it, or trim it after the fact. This one tries to keep the expensive content out in the first place:
- A question about one function no longer costs a whole file.
- A 177,000-character docs page no longer costs a whole page.
Nothing is rewritten by a model, and nothing is lost: every pruned body is archived and readable again by offset.
Three deferred-loaded tools
| Tool | What it does |
|---|---|
read_range |
Reads only the lines asked for: a line window, every mention of a symbol with context, or a structural outline. Hard-capped output. |
tool_catalog |
One-line inventory of the tools this session can call, so a deferred toolset stays discoverable. |
fetch_recall |
Reads any slice of a pruned result by absolute character offset. |
Two result-shaping passes
Scoped by tool name through tools/post-execute:
- Web pages — a bounded prose head (starting at the page's content landmark when it marks one) plus a digest of the page's headings.
- Shell output — head and tail. Diagnostics live at the end, and the host's own byte cap otherwise drops them.
Measured
Session level (the number that matters)
A tool result is re-sent on every step after it enters, so its real cost is
size x (steps remaining). Modeling a 30-step session with four file reads:
| Prompt tokens | |
|---|---|
| Whole-file reads | 667,776 |
| Pruned reads | 374,512 |
| Saving | 293,264 (43.9%) |
The saving grows with session length: 33.6% at 10 steps, 43.9% at 30, 47.8% at 100. It is capped below 50% because a fixed prompt baseline (opening message, system prompt, tool schemas) is paid on every step and is not touched here.
Reproduce it yourself:
npm run measure:session
Per operation
Same question, only the read strategy changed:
| File | Lines | Whole read | read_range |
Saved |
|---|---|---|---|---|
| index.js | 464 | 4,661 tok | 188 tok | 96.0% |
| client.js | 710 | 9,389 tok | 274 tok | 97.1% |
| bench/index.js | 875 | 8,999 tok | 513 tok | 94.3% |
Oversized results:
| Body | Raw | Pruned | Saved |
|---|---|---|---|
| docs page (live fetch) | 46,582 tok | 583 tok | 98.7% |
| shell output (2.8M chars, host-capped) | 16,842 tok | 1,515 tok | 91.0% |
The per-operation figures are large because one operation can replace a whole file. They are not whole-session savings — use the session table for that.
Token counts use a deterministic approximation of the harness token rule (CJK about 1.7 chars/token, code about 3.8 chars/token). They compare strategies; they do not predict a bill.
Install
dsh plugin install dsh-readprune
The row id stays token-diet across renames, so a config override in your own
cordis.patch.yml keeps applying.
Config
| Key | Default | Meaning |
|---|---|---|
guide |
true |
Inject the "prefer read_range" prompt section. Without it the tools exist but a model keeps dumping whole files. Costs ~162 tokens per turn. |
exposeCatalog |
true |
Register tool_catalog. |
slim |
true |
Prune oversized results via tools/post-execute. |
slimWebTools |
["web_fetch"] |
Web-shaped results: prose head + heading digest. |
slimShellTools |
["pwsh","bash","wsl","tty_run"] |
Shell-shaped results: head + tail. post-execute is a global waterfall, so only listed tools are touched. |
maxInlineChars |
8000 |
Above this size a result is pruned. |
headChars |
1500 |
Web mode: characters kept inline. |
shellHeadLines / shellTailLines |
60 / 60 |
Shell mode: lines kept from each end. |
durableArchive |
true |
Archive pruned bodies under ~/.dsh/token-diet/archive so locators survive a restart. Falls back to memory if the disk refuses. |
maxArchiveFiles |
200 |
Oldest archived bodies are pruned past this count. |
Tests
npm test # five suites, no network
npm run measure:reads # the per-operation table
npm run measure:page # the web page figure (fetches docs.python.org)
npm run measure:session # the session table
npm test covers tool invocation end to end, the pruning passes on an offline
fixture, the post-execute wiring (including proof that read/grep/edit
are untouched), and the durable archive.
Honest limits
- It cannot shrink other plugins' tool schemas. There is no service or event
to mark another plugin's
ToolSchemaasdeferLoading; only this plugin's own tools are deferred. On a heavily loaded profile the fixed per-turn schema cost remains. symbolmode is textual, not semantic. It matches substrings, sosavealso hitssavesSelection. Usemode: outlinewhen the identifier is unknown.readis untouched. The upstream file tools keep working, so a model can always fall back — which means savings appear only when it actually choosesread_range.- Archived bodies are plain files under
~/.dsh/token-diet/archive, readable by anything running as you. Do not enable this on shared machines if fetched content may be sensitive. spillStoreis not used. Its runtime availability could not be confirmed, and a hard dependency on it would disable pruning entirely if absent.
Licence
MIT. Icon is original artwork drawn for this plugin.
No comments yet. Be the first to write one.