Your coding agent reads a 5,000-line test log to find 2 failures. Lelouch commands that output to obey — only the signal reaches the model.
Lelouch (名: the power to command) — a local-first plugin that compresses noisy command output after it runs but before your AI coding agent sees it, so the model spends its context window on signal, not on 300 lines of
✓ passed.No cloud. No API keys. Nothing leaves your machine.
Your agent runs npm test, gets 300 passing tests and 2 failures, and the
entire 3,000-token log is pasted into its context. It only needed the 2
failures and the summary line. Multiply that across a session and you burn
tokens — and precious context budget — on noise.
✓ test case 1 passed
✓ test case 2 passed
… 298 more lines …
✕ test 301 FAILED: expected 2 got 3
Tests: 1 failed, 300 passed, 301 total
becomes
✕ test 301 FAILED: expected 2 got 3
Error: assertion failed at foo.js:42
Tests: 1 failed, 300 passed, 301 total
… (300 more passing-test lines elided by lelouch)
Failures, errors, and summaries are never dropped. Only redundant, predictable noise is. And the full original is stashed locally so you can pull it back on demand (see The memory store).
From npm run bench on synthetic fixtures — estimates (≈4 chars/token) on
made-up inputs. Real workloads vary. Run it yourself:
| Fixture | Before | After | Saved |
|---|---|---|---|
| test log (300 pass, 2 fail) | 3,173 | 65 | 98% |
| npm install (200 warnings) | 2,852 | 1,708 | 40% |
| git status (80 modified) | 609 | 53 | 91% |
| Total | 6,634 | 1,826 | 72% |
⚠️ Honesty note: the "80%+ savings" you may see quoted elsewhere is a ceiling on favorable inputs, not a guarantee. A log that's already dense compresses very little. We ship a reproducible benchmark instead of a hero number.
/plugin install lelouch
Or test locally before publishing:
git clone https://github.com/zulfff/lelouch
claude --plugin-dir ./lelouch
It runs automatically on Bash output via a PostToolUse hook, ships an MCP
retrieval server, and installs a PreCompact digest hook.
npm install -g lelouchDrop a plugin file in .opencode/plugins/ (project) or
~/.config/opencode/plugins/ (global):
// .opencode/plugins/lelouch.js
export { LelouchPlugin } from "lelouch/adapters/opencode.js";Verified against the
@opencode-ai/pluginv1.18.x type contract (tool.execute.aftermutatingoutput.outputin place) and unit-tested. The adapter is defensive — any surprise leaves output untouched. If your OpenCode version differs, open an issue.
No output-rewriting hook API → you wrap commands. Wrap mode runs the command, compresses combined output, and preserves the exit code:
npm install -g lelouch
lelouch wrap -- npm test
alias ll='lelouch wrap --' # then: ll npm testnpm test 2>&1 | lelouch --command "npm test" --statsWhen output is very large (>~2,000 tokens), Lelouch stashes the full
original in a local append-only store (~/.cache/lelouch/memory.jsonl) and
tells the model its reference id. A bundled MCP server exposes:
memory_get({ id })— full uncompressed textmemory_search({ query, id? })— keyword search (AND per line) with line numbers
So nothing is truly lost — just deferred until the model asks.
Honesty note: this is keyword search, not semantic/vector search — fast and predictable, but it won't match paraphrases. See
src/store.js.
A PreCompact hook builds a deterministic preservation digest before your
context is compacted — extracting file paths, error/exit codes, stored mem_*
ids, and TODO/FIXME markers, then re-injecting them so they aren't summarized
away. It calls no model and does not block compaction. See
hooks/pre-compact.js.
Bash runs → PostToolUse hook → DLP redaction → compressor → updatedToolOutput → model
│
(large?) stash full → mem_N ──► MCP retrieval
Claude Code's PostToolUse hook can replace a tool's result via
hookSpecificOutput.updatedToolOutput. Lelouch hooks Bash, routes output to a
strategy (test log / git status / directory listing / generic
repeat-collapse + head-tail), and hands back the smaller version.
Design guarantees:
- Never changes execution. Only what the model sees — exit codes, stderr, and result structure are preserved.
- Fail-safe. Any unexpected input → the hook emits nothing and the original passes through untouched. Saving tokens is never worth corrupting a result.
- Secrets redacted first. A regex DLP pass strips AWS/GitHub/OpenAI keys,
JWTs, private keys, and
*_SECRET=values before anything is stored or shown. Best-effort, not a guarantee — seesrc/dlp.js.
| Module | Status |
|---|---|
| Output compressor (test/git/ls/generic) | ✅ built + tested |
PostToolUse hook (updatedToolOutput) |
✅ built + tested |
| DLP secret redaction | ✅ built + tested |
CLI + wrap mode |
✅ built + tested |
| Memory store + MCP retrieval | ✅ built + tested |
| PreCompact preservation digest | ✅ built + tested |
| OpenCode adapter | ✅ built + tested (verified vs @opencode-ai/plugin v1.18.x) |
| Codex / Gemini | ✅ via wrap (shell-level, not native) |
| LLM history summarizer | ❌ deliberately omitted — needs network/model, breaks local-first. The deterministic digest is the alternative. |
npm test # 22 tests, zero dependencies
npm run bench # reproduce the savings table
claude --plugin-dir .Contributions welcome — see CONTRIBUTING.md. Security policy: SECURITY.md.
MIT © zulfff