{"slug": "show-hn-lcc-compact-claude-code-sessions-without-summarizing-them", "title": "Show HN: Lcc – compact Claude Code sessions without summarizing them", "summary": "A tool called lcc, published to PyPI as version 1.2.0 by developer lucasmartins-ai, compacts Claude Code sessions by removing old tool outputs while keeping every user and assistant message byte for byte, rather than replacing the session with a model-written summary as Claude Code's built-in `/compact` does. On one 193-message session with 75 tool calls, lcc cut tokens from 57,083 to 28,807 (−49.5%) while preserving all 43 user and assistant messages and stashing 33 removed tool outputs for retrieval via a `recall` command; across 299 long sessions (100+ messages each, 36.3M tokens) the median cut was 21.8% with 0 messages lost. In a pre-registered test on 172 real requests, an agent answering from the stashed context plus `recall` matched full-context performance on file recall (+0.006, 95% CI −0.023 to +0.034) with 36.6% fewer tokens, calling `recall` for 90% of questions about removed content, while a `/compact`-style summary of the same sessions got 73% of exact values right versus 98% for full verbatim context.", "body_md": "**Compact coding-agent context without summarizing it away.**\n\nlcc cuts what the model does not need, keeps everything else byte for byte, and writes a receipt.\n\nClaude Code's `/compact` replaces your session with a summary written by a model. Summaries\ndrop the exact error, path or line the agent needs two turns later. lcc does the opposite: old\ntool outputs leave the context but stay one `recall` away, and every user and assistant message\nis kept as it was.\n\n| One real Claude Code session (193 messages, 75 tool calls) | tokens | user and assistant messages | removed tool outputs | \n|---|---|---|---|\n| before | 57,083 | 43, as written | — | \n| `/compact` | one summary | rewritten into the summary | gone | \n| **lcc** (`rules` ,`stashed` ) | **28,807 (−49.5%)** | **43 / 43 byte for byte** | 33, each one `recall` away | \n\nMeasured with `lcc measure-session` (PyPI 1.2.0, offline, exact `o200k_base` token count;\nre-run 2026-10-23). On `main`, whose stash note now states lines and size, the same session\ngives 28,983 (−49.2%). That session is one of the best cases. **Across all 299 of my long sessions** (100+ messages each,\n36.3 M tokens) the median cut was **21.8%** (middle half 15% to 31%, best 65%), with 0 messages\nlost (`python benchmarks/research/long_sessions.py`, 2026-10-23, `main`). These are all my sessions: [run it on yours](#send-us-your-numbers) and post the result.\n\nIn a pre-registered test on 172 real requests ([evidence](https://github.com/lucasmartins-ai/lcc/blob/main/docs/EVIDENCE.md)), an agent answering\nfrom the `stashed` context plus `recall` did as well as with the full context on file recall\n(+0.006, 95% CI −0.023 to +0.034) with 36.6% fewer tokens. It called `recall` for 90% of the\nquestions about removed content. A `/compact`-style summary of the same sessions got 73% of exact values\nright (our reimplementation of `/compact`, written by Opus); full and verbatim context got 98%.\n\n```\npip install \"local-context-compiler[tiktoken]\"   # the CLI is `lcc`\nlcc measure-session \"$(ls -t ~/.claude/projects/*/*.jsonl | head -1)\"   # your latest session\n```\n\nThe second line reads your most recent Claude Code session, runs every mode offline and prints counts only. Nothing is changed and nothing leaves the machine.\n\n**Claude Code plugin** (replaces the `/compact` summary). Function hooks are early access, so\nthis needs **Claude Code 2.1.274+ and the flag below**:\n\n```\nexport CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1\nclaude plugin marketplace add lucasmartins-ai/lcc\nclaude plugin install lcc@lcc --config provider=rules --config rulesMode=stashed\n```\n\nAllow `mcp__plugin_lcc_lcc__recall` so the agent can get removed outputs back. When a pass\nfails or removes too little, the plugin hands over to the built-in summary and says so in a\ntoast. Details: [Claude Code guide](https://github.com/lucasmartins-ai/lcc/blob/main/docs/CLAUDE_CODE.md).\n\n**MCP** (Claude Code, Cursor, Claude Desktop, any stdio client):\n\n```\n{\"mcpServers\": {\"lcc\": {\"command\": \"lcc\", \"args\": [\"mcp\"]}}}\n```\n\nTools: `compact`, `compact_transcript`, `recall`, `inspect`, `prepare`, `explain`, `intake`\n([MCP guide](https://github.com/lucasmartins-ai/lcc/blob/main/docs/MCP.md)).\n\n**CLI**, on a session file or any document:\n\n```\nlcc compact ~/.claude/projects/<project>/<session>.jsonl -q \"finish the parser fix\" \\\n  --mode tool-calls --provider rules --rules-mode stashed -o compacted.json -r report.json\nlcc recall <id>                                   # a removed output, hash-checked\n\nlcc compact notes.md -q \"what is wrong with the booking flow?\" \\\n  --provider mechanical -o compacted.md -r report.json\nlcc explain report.json --source notes.md         # why each block was kept or dropped\nlcc measure-session ~/.claude/projects/<project>/<session>.jsonl --markdown\n# Codex CLI rollouts are auto-detected from their session_meta record:\nlcc measure-session /path/to/rollout.jsonl --markdown\n# or a whole project directory: per-mode median and p90 reduction over its sessions\nlcc measure-session ~/.claude/projects/<project>/ --markdown\n```\n\nIt runs every mode on one of your sessions, offline, and prints **counts only**: messages, tool\ncalls, tokens before and after, messages kept, time. No text, path or tool output. For exact\ncounts, install the `tiktoken` extra and cache its tokenizer once (lcc itself never downloads):\n`python -c \"import tiktoken; tiktoken.get_encoding('o200k_base')\"`. Otherwise the report says\n`approximate` and why. Paste it in\n[Discussions → Results](https://github.com/lucasmartins-ai/lcc/discussions/categories/results).\nAdd `--input-map` to see where the session's billed input goes instead: cache reads and\nwrites, and the share taken by tool results, tool-call inputs, injected instructions and the\nfixed system prompt and tool schemas (counts only, from the usage records in the file).\nAlready compacting with lcc? `lcc share-stats` turns your local reports into the same kind of\ncounts-only summary ([SHARE_STATS.md](https://github.com/lucasmartins-ai/lcc/blob/main/docs/SHARE_STATS.md)), or use the\n[results issue form](https://github.com/lucasmartins-ai/lcc/issues/new?template=results.yml).\nEvery number from someone other than me makes the claims above less mine and more true.\n\n- **Verbatim.** Kept spans are byte-identical to the source. Nothing is summarized or rewritten.\n- **Recoverable.**`stashed` moves removed outputs to a local content-addressed store\n(`~/.cache/lcc/stash` );`recall` re-hashes on read.\nThe placeholder,`[removed: 120 lines, 4.3 KB · lcc recall <id>]` , states lines and size, not\ntokens, so it is identical on every machine.\n- **Auditable.** Every pass writes a JSON report;`lcc explain` gives the reason for every drop.\n- **Local.** The default judges run on your CPU in plain Python. No API key, no network.\n\n| Provider | Runs | When it is used | Report says | \n|---|---|---|---|\n| `specialist-v3` | local, CPU | default ( `auto` ) whenever transcript blocks are present: the Claude Code hook,`compact_transcript` ,`--mode tool-calls` | `semantic_guarantee: none` (a rank, not a judgment) | \n| `mechanical` | local, CPU | `--provider mechanical` ; plain text under`auto` (a configured TypeSafe key does not change that unless`LCC_AUTO_REMOTE=1` ) | `semantic_guarantee: none` | \n| `rules` (`lossless` ,`recoverable` ,`stashed` ) | local, no model | `provider: rules` for transcripts | `lossless` : only provable duplicates removed;`recoverable` : also outputs that can be re-read;`stashed` (recommended): removed outputs stay byte-recoverable through`recall` | \n| `jev` | remote (TypeSafe API) | opt-in: `--provider jev` /`provider: jev` , needs`TYPESAFE_API_KEY` | semantic judgment or explicit degradation | \n| `laya` | local model | deprecated; runs only when named | named model and fallback state | \n\n`specialist-v3` details and limits: [SPECIALIST.md](https://github.com/lucasmartins-ai/lcc/blob/main/docs/SPECIALIST.md). Rules modes:\n[TOOL_CALLS.md](https://github.com/lucasmartins-ai/lcc/blob/main/docs/TOOL_CALLS.md). Jev is an optional path you name explicitly\n(`--provider jev`); it sends the objective and context blocks to the TypeSafe API, and\n`LCC_DISABLE_NETWORK=1` disables it. `auto` never picks it on its own: having a key is not\nconsent to send context off-machine, so plain text under `auto` stays on `mechanical` unless\nyou set `LCC_AUTO_REMOTE=1`. `compact` writes a `relevance-compaction-1.2` report;\ncheck `provider_used` and `degraded` before trusting the output.\n\n**Real sessions (held-out, INFERIDO).** In plain words: when a ranker has to drop part of a\nsession, how often does it keep what the agent actually used next? 1.0 would be always. A\none-shot final test on 193 items from 36 of the maintainer's sessions that started after the\ntraining cutoff. Retention AUC over drop budgets of 0–60% of candidate tokens:\n\n| ranker | recall AUC | all-kept AUC | \n|---|---|---|\n| specialist-v3 | **0.899** | **0.434** | \n| mechanical | 0.829 | 0.238 | \n| recency | 0.818 | 0.306 | \n| bm25 | 0.803 | 0.270 | \n| random | 0.689 | 0.138 | \n\nThe labels are next-action evidence from one maintainer's Claude Code sessions, which favours\nv3's training target. The sessions are private; only aggregates are published\n([SPECIALIST.md](https://github.com/lucasmartins-ai/lcc/blob/main/docs/SPECIALIST.md)).\n\n**Synthetic, reproducible** (`python benchmarks/run_judge_bench.py`, about 20 s, no network).\nNine hand-written edge cases: supersession, contradiction, config change, exception rule,\npt/en mixed, prompt injection in a tool output, large git diff, old root cause, re-read.\n\n| raw ranking | specialist-v3 | mechanical | bm25 | recency | \n|---|---|---|---|---|\n| cases with every must-keep block kept at a 30 / 50 / 70% cut (of 9) | 8 / 7 / 7 | 9 / 9 / 9 | 9 / 9 / 7 | 8 / 6 / 3 | \n\n| full pass, default settings | must-keep kept | 302 blocks | 1,138 blocks | peak RSS | \n|---|---|---|---|---|\n| `specialist-v3` , tool-call mode | 9/9 | 181 ms | 3.4 s | 71 MB | \n| `rules` lossless | 9/9 | 2 ms | 16 ms | 55 MB | \n\nThese cases are lexically easy, so the lexical baselines do well; v3 misses the Portuguese\ncase. Timings are from macOS arm64 under heavy machine load. Method, every arm and the limits:\n[BENCHMARKS.md](https://github.com/lucasmartins-ai/lcc/blob/main/docs/BENCHMARKS.md). Rules modes on real sessions:\n[REAL_SESSION_BENCHMARKS.md](https://github.com/lucasmartins-ai/lcc/blob/main/docs/REAL_SESSION_BENCHMARKS.md).\n\nReduction depends on how much of a context is noise. Below a 25% gain, the report marks the pass as not worth it, and the Claude Code plugin keeps the built-in summary.\n\n- It does not check that a model will answer correctly. A structural `PASS` is not an answer\nquality result.\n- No RAG, embeddings or vector store.\n- Protection rules and bounded restoration reduce, but do not rule out, lost evidence; see the\n[safety model](https://github.com/lucasmartins-ai/lcc/blob/main/docs/adr/0014-minimum-sufficient-context.md) .\n- `specialist-v3` was trained on Claude Code transcripts. Other agents and plain documents are\nout of distribution; plain text uses`mechanical` unless you opt in to Jev.\n\n| Topic | Link | \n|---|---|\n| Five-minute tour of the CLI | [QUICKSTART.md](https://github.com/lucasmartins-ai/lcc/blob/main/docs/QUICKSTART.md) | \n| Claude Code plugin | [CLAUDE_CODE.md](https://github.com/lucasmartins-ai/lcc/blob/main/docs/CLAUDE_CODE.md) | \n| MCP server | [MCP.md](https://github.com/lucasmartins-ai/lcc/blob/main/docs/MCP.md) | \n| Tool-call compaction and rules modes | [TOOL_CALLS.md](https://github.com/lucasmartins-ai/lcc/blob/main/docs/TOOL_CALLS.md) | \n| Aider chat history as input | [AIDER.md](https://github.com/lucasmartins-ai/lcc/blob/main/docs/AIDER.md) | \n| The local ranker | [SPECIALIST.md](https://github.com/lucasmartins-ai/lcc/blob/main/docs/SPECIALIST.md) | \n| Benchmarks | [BENCHMARKS.md](https://github.com/lucasmartins-ai/lcc/blob/main/docs/BENCHMARKS.md) ,[REAL_SESSION_BENCHMARKS.md](https://github.com/lucasmartins-ai/lcc/blob/main/docs/REAL_SESSION_BENCHMARKS.md) ,[benchmarks/](https://github.com/lucasmartins-ai/lcc/blob/main/benchmarks/README.md) | \n| Python API ( `lcc.msi.compile` ) | [msi-api.md](https://github.com/lucasmartins-ai/lcc/blob/main/docs/lcc/msi-api.md) | \n| Architecture and decisions | [architecture.md](https://github.com/lucasmartins-ai/lcc/blob/main/docs/architecture.md) ,[ADR 0010](https://github.com/lucasmartins-ai/lcc/blob/main/docs/adr/0010-deterministic-first-preparation-model-assistance.md) ,[ADR index](https://github.com/lucasmartins-ai/lcc/blob/main/docs/adr/README.md) | \n| Opt-in and deprecated providers | [JEV.md](https://github.com/lucasmartins-ai/lcc/blob/main/docs/JEV.md) ,[LAYA.md](https://github.com/lucasmartins-ai/lcc/blob/main/docs/LAYA.md) | \n| Research archive | [paper.md](https://github.com/lucasmartins-ai/lcc/blob/main/research/paper.md) ,[results-master.md](https://github.com/lucasmartins-ai/lcc/blob/main/research/results-master.md) ,[TRANSCRIPT_AB.md](https://github.com/lucasmartins-ai/lcc/blob/main/benchmarks/research/TRANSCRIPT_AB.md) | \n| Privacy | [PRIVACY_POLICY.md](https://github.com/lucasmartins-ai/lcc/blob/main/docs/PRIVACY_POLICY.md) | \n\nPython 3.11+.\n\n```\npython -m pip install -e '.[dev,tiktoken]'\npytest -q && ruff check . && mypy\nnpm test                                   # Node API and hook tests\npython benchmarks/run_judge_bench.py --check --out /tmp/judge-bench\n```\n\nThe PyPI package named `lcc` is unrelated; this one is `local-context-compiler`.\nContributing: [CONTRIBUTING.md](https://github.com/lucasmartins-ai/lcc/blob/main/CONTRIBUTING.md). Security: [SECURITY.md](https://github.com/lucasmartins-ai/lcc/blob/main/SECURITY.md).\nChanges: [CHANGELOG.md](https://github.com/lucasmartins-ai/lcc/blob/main/CHANGELOG.md).\n\n[MIT](https://github.com/lucasmartins-ai/lcc/blob/main/LICENSE). The optional Laya integration carries Apache-2.0 attribution in\n[NOTICE](https://github.com/lucasmartins-ai/lcc/blob/main/NOTICE). Maintained by [LookADev](https://lookadev.com).", "url": "https://wpnews.pro/news/show-hn-lcc-compact-claude-code-sessions-without-summarizing-them", "canonical_source": "https://github.com/lucasmartins-ai/lcc", "published_at": "2026-10-23 18:44:04+00:00", "updated_at": "2026-10-23 19:13:28.531318+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "large-language-models"], "entities": ["lcc", "Claude Code", "lucasmartins-ai", "PyPI", "Cursor", "Claude Desktop", "Codex CLI", "Opus"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/show-hn-lcc-compact-claude-code-sessions-without-summarizing-them", "markdown": "https://wpnews.pro/news/show-hn-lcc-compact-claude-code-sessions-without-summarizing-them.md", "text": "https://wpnews.pro/news/show-hn-lcc-compact-claude-code-sessions-without-summarizing-them.txt", "jsonld": "https://wpnews.pro/news/show-hn-lcc-compact-claude-code-sessions-without-summarizing-them.jsonld"}}