skill
scrim
The cloth between the tool and the model — tool-output thinning and cost observability for Claude Code and Codex. Fail-open hooks, nothing lost.
Set up
Skills are installed by placing their folder where your agent loads skills.
The download comes from github.com/nikshepsvn/scrim itself, not from our server, so what you get is exactly what its author published.
Install instructions come from the README
README
synced Oct 26, 2026In a theater, a scrim hangs in front of the lamp. The scene stays lit. The bulb never hits your eyes.
Coding agents don't have one. They read every passing test, the full ls -R, and six Chrome screenshots — then you pay (or compact) for the glare. Scrim hangs in front of the tool result:
Three things it will never do: touch Read or Edit, break your session (hooks fail open — on any error the agent sees the original result), or switch your model.
Install
git clone git@github.com:nikshepsvn/scrim.git
claude --plugin-dir "$(cd scrim && pwd)"
Or from the marketplace:
/plugin marketplace add nikshepsvn/scrim
/plugin install scrim@scrim
Restart Claude Code. Run a tool. Then /scrim:
Scrim
Usage (list prices, not Stripe)
$1,204 API-eq turns 412 cache-read 41,236,801 (96%) cache-write 3,102,455 out 81,340
claude-opus-5 $980 300 turns
claude-fable-5 $210 112 turns
Tools (this plugin)
142 calls 4.20 MB in → 0.31 MB out 3.89 MB thinned (61 calls)
mcp__claude-in-chrome__browser_batch n=2 3.80 MB
stashed originals 12 (scrim get <id>)
compactions 2 (each one = a window that overflowed)
Those dollars are list prices (Fable at Fable rates, Opus at Opus rates). Max/Ultra is a subscription — you are looking at quota shape, not a card charge.
If nothing shows up: python3 scripts/scrim.py doctor. Tests are hermetic, stdlib only: make test.
Four jobs
How it hangs
What gets through
| Kind | Policy |
|---|---|
| Tests / lint | FAIL, Error, traceback with its stack frames, tail |
| Logs | Drain-lite templates + counts, plus the raw last lines (the crash is usually at the end) |
Grep / rg | Head + tail; FAIL/Error hits in the omitted middle appended anyway |
ls / Glob | Head + omitted count |
| Chrome / Playwright | Images dropped, leftover text capped |
| Web | 16 KB cap |
| Other fat bash | Signal lines, else head+tail |
Read / Edit | Untouched |
scrim get | Untouched — retrieval never re-thins the blob you asked to recover |
If the rewrite would not actually be smaller, the original goes through. PreToolUse caps only pure listings — pipes, redirects, and mutating find (-exec, -delete) are never rewritten, and find inside a string argument doesn't count.
gzip does not reduce tokens. The model has to read text.
Nothing is lost
To tune it, copy config.example.json → ~/.scrim/config.json. "shrink": false logs only. Every key: docs/config.md. Old ~/.sift / ~/.spend directories are renamed on first run.
The CLI
python3 scripts/scrim.py --today # local calendar day (add --json for machines)
python3 scripts/scrim.py days # 7-day trend: claude $, codex $, turns, tool MB
python3 scripts/scrim.py --backfill # lifetime, retries deduped
python3 scripts/scrim.py get <id> 118-130 # slice of an omitted original
python3 scripts/scrim.py stashes # what's retrievable
python3 scripts/scrim.py kinds # where the MB went, by kind
python3 scripts/scrim.py doctor # is the chain healthy
python3 scripts/scrim.py prune # trim old metrics + stash
python3 scripts/scrim.py --config # effective config + warnings
days takes a count (days 30) and covers both agents:
last 7 days (list prices, not Stripe)
day claude $ codex $ turns tool MB in→out
2026-08-18 382 0 1,266 4.20 → 0.31
2026-08-17 129 0 306 -
Statusline
Live numbers in every turn instead of a post-hoc report — wire scrim statusline into Claude Code's statusLine slot in ~/.claude/settings.json:
"statusLine": { "type": "command", "command": "python3 /ABS/PATH/TO/scrim/scripts/scrim.py statusline" }
Fable · ctx 42% · $1.23 · tools 4.2→0.3 MB · 3.9 thinned · compacted ×1
Codex
Codex CLI 0.146+ runs the same hooks.json format — verified live, not assumed:
| on Codex | |
|---|---|
See — tracking, stash, Stop report, days | ✅ verified live |
Usage $ — parsed from ~/.codex/sessions rollouts | ✅ its own block in /scrim |
| Prevent — PreToolUse input caps | ⚠️ Code Mode exec skips PreToolUse (#23411) |
| Thin — neutral output rewrite | ❌ not shipped (#34895); opt-in codex_block_thin uses the decision:"block" lever instead |
make codex-hooks # install, then trust once via /hooks in the Codex TUI
Optional: extract with a model
inception/mercury-2 was the only model in our bake-off that behaved like a reducer at hook latency. Use ≥4096 completion tokens.
export OPENROUTER_API_KEY=sk-or-...
{
"reducer": "openrouter",
"reducer_model": "inception/mercury-2",
"reducer_max_tokens": 4096,
"reducer_timeout_sec": 20
}
The macOS Claude app often ignores shell env. You can set reducer_api_key in ~/.scrim/config.json. Do not commit that file.
Do not use Morph or Inkling as the reducer. Morph reprints the dump. Inkling spends the budget on hidden reasoning. Notes: docs/eval.md. Backup: google/gemini-2.5-flash.
Privacy
Default path: nothing extra leaves the machine. Metrics are counts and tool names.
Reducer on: a truncated dump is sent to OpenRouter or Anthropic. Cache lives in ~/.scrim/reducer-cache/.
Docs
| How it works | Hook pipeline |
| Config | Every key |
| Eval | Measured save rates and model bake-off |
| Codex | Verified compatibility matrix |
| Security | Fail-open and what leaves the machine |