Skip to main content

ctxprune

Cut big tool outputs, logs and documents in half before your LLM reads them, without mangling IDs. A 140M-parameter model deletes the least useful words; everything it keeps is passed on byte for byte. Runs on CPU in about 0.1 s per 500 tokens. Apache-2.0.

ctxprune on a failing pytest run: struck-through words are deleted, IDs and code stay intact

At 50% of tokens kept, a reader LLM answers 51.5% of SQuAD v2 + HotpotQA questions exactly from ctxprune's output vs 36.5% from headroom's Kompress-v2 (400 questions, 95% CI of the gap +10.5 to +19.5), and 68.8% vs 53.4% for LLMLingua-2-large on our agent-text set. Try it in your browser (nothing is uploaded).

Quick start

pip install ctxprune
ctxprune build.log --keep 0.5          # or: some_command | ctxprune --keep 0.33 --protect
import ctxprune
short = ctxprune.prune(tool_output, keep=0.5)    # protect=True never drops IDs, numbers or paths

Which one do I use?

You want to... Use
Shrink big Bash/MCP outputs inside Claude Code ctxprune install claude-code or the plugin: /plugin install ctxprune --marketplace riceharvest/ctxprune
Compress a file or a pipe from the shell ctxprune FILE --keep 0.5 --protect, --stats, reads stdin
Call it from Python ctxprune.prune(text, keep=0.5) Compressor for batching and options
Call it from another language / avoid the model load ctxprune serve POST localhost:8787/compress {"text": ...}
Compress retrieved documents in LangChain CtxpruneDocumentCompressor see below
Compress retrieved nodes in LlamaIndex CtxpruneNodePostprocessor see below
Use it inside LLMLingua PromptCompressor(model_name="darioooooo0o/ctxprune-small", use_llmlingua2=True) needs LLMLingua#261
Run the raw model (ONNX / transformers / transformers.js) model card label 1 = keep

Agents setting this up for a user: see AGENTS.md.

Claude Code

pip install ctxprune && ctxprune install claude-code     # undo: ctxprune uninstall claude-code

This adds a PostToolUse hook. Bash and MCP outputs over 6,000 characters are compressed to about half before Claude reads them, with identifiers, numbers and paths always kept. Claude gets a one-line note saying so, and the full output is saved under ~/.cache/ctxprune/outputs/ so it can grep the original if a detail is missing. Commands that print files Claude may edit (cat, head, sed -n, git diff/show) and the Read/Grep tools are never touched, and a command containing CTXPRUNE_OFF=1 is passed through. If anything fails, Claude gets the original output. Settings: CTXPRUNE_RATE (0.5), CTXPRUNE_MIN_CHARS (6000). Each compressed call loads the model (~2 s); run ctxprune serve in the background and the hook uses it instead.

As a plugin, without touching settings files (needs ctxprune on PATH, or uv so it can run via uvx): /plugin install ctxprune --marketplace riceharvest/ctxprune.

LangChain and LlamaIndex

from ctxprune.integrations import CtxpruneDocumentCompressor    # LangChain
retriever = ContextualCompressionRetriever(base_compressor=CtxpruneDocumentCompressor(rate=0.5),
                                           base_retriever=base_retriever)

from ctxprune.integrations import CtxpruneNodePostprocessor     # LlamaIndex
engine = index.as_query_engine(node_postprocessors=[CtxpruneNodePostprocessor(rate=0.5)])

How good is it, honestly

  • Compression loses information. On our agent set, QA accuracy goes from 91.8% uncompressed to 68.8% at 50% kept. Use it where the token savings are worth that, e.g. long logs, test output, search results, retrieved docs.
  • Weak spots: source code (the teacher rarely deleted code, so the model keeps most of it) and non-English web prose, where LLMLingua-2-large still does better.
  • Our 378-question set is from our own training distribution, so the neutral SQuAD/HotpotQA comparison above is the fairer number. Per-source tables and caveats: model card.

By @imdariotoo.


Reproducing the model

Why: LLMLingua-2 (Microsoft, Mar 2024) was trained only on meeting transcripts under CC BY-NC-SA labels. On agent tool outputs it loses or mangles about half of all identifiers (UUIDs, IPs, paths, versions) and breaks JSON.

Pipeline

step script where notes
corpus scripts/build_corpus.py CPU, ~2 min ranged parquet reads from 8 permissive sources; split per repo/server/site
labels scripts/label.py teacher LLM (scripts/teacher_up.sh) deletion-only compression, LCS-aligned to atoms; cached
train scripts/train.py any torch device (we used an Intel Arc Pro B70) or CPU token classifier, label 1 = keep (LLMLingua-2 convention)
quick eval scripts/eval_quick.py CPU identifiers lost, JSON validity, char ratio vs LLMLingua-2
QA eval scripts/eval_qa.py questions/answer teacher LLM can a reader still answer from the compressed text

scripts/run_v1.sh runs corpus and labels; scripts/after_label.sh runs everything after them.

Data sources (all permissive)

SWE-smith trajectories (MIT), SWE-rebench OpenHands trajectories (CC BY 4.0), Toucan-1.5M MCP tool calls (Apache-2.0), github-code-clean filtered to MIT/Apache/BSD/ISC files, FineWeb-Edu and FineWeb-2 (ODC-BY), oasst2 (Apache-2.0). Every chunk records its dataset, license and source reference. Teacher: Qwen3.8-27B GPTQ (Apache-2.0 outputs).

Training more after an eval

Nothing has to be redone:

  1. More data, same mix. Rerun build_corpus.py into the same directory with a larger --total. Sampling is deterministic, and dataset revisions are pinned in chunks/revisions.json, so every source file becomes a superset of the old one. To weight a domain up, add --mix toucan_mcp=0.3.
  2. Label only the new chunks. Rerun label.py. The teacher cache is keyed by (prompt version, model, text), so old chunks come back from disk.
  3. Continue training from the previous model: train.py --data <dir> --init-from runs/v1-mmbert-small/final --out runs/v2-... (or --resume to continue an interrupted run from its checkpoint). --data accepts several directories, to mix label sets.
  4. Re-run evals. Question and answer caches mean only new contexts cost LLM calls.

Changing the teacher prompt bumps PROMPT_VERSION in ctxprune/teacher.py, which invalidates the cache on purpose.

Tests

uv run pytest: atom round-trips, identifier atoms, CJK handling, LCS alignment, chunk budgets, split stability and cache resume.

Metadata

Release files for ctxprune 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ctxprune 0.2.0
File Size Uploaded
ctxprune-0.2.0.tar.gz 34.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ctxprune 0.2.0
File Interpreter ABI Platform
ctxprune-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 69.9 kB

Release files / ctxprune-0.2.0.tar.gz

Download URL ctxprune-0.2.0.tar.gz
Size 34.0 kB
Tags Source
SHA-256 checksum
How to use checksums
12bb2f304cac05127901baab70a820314f487a5d9a2c059905464488850b3f43
BLAKE2b-256 checksum
How to use checksums
6d8898a20197548bdfd90dc5f3bb65c02b73df2de36b6992e424176418c1d7fa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release files / ctxprune-0.2.0-py3-none-any.whl

Download URL ctxprune-0.2.0-py3-none-any.whl
Size 35.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ea606084f1adc4a1be338970275580fe968d1399d2f4b34dc18d9c6ff721433d
BLAKE2b-256 checksum
How to use checksums
ec8d80034a1e1f129215feb9ceddd452aa3b634f5798c05953ae1ebf26e03836
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.1

2 release files

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page