skill
cachefit
Fit prompt-cache TTL and auto-compaction settings to your own Claude Code and Codex history.
Set up
Skills are installed by placing their folder where your agent loads skills.
The download comes from github.com/Jubii100/cachefit 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, 2026cachefit
Cache and context settings learned from YOUR history, not from a default.
Coding agents ship one-size defaults for the settings that decide what your input tokens cost: how long the prompt cache lives (5 minutes or 1 hour), when the conversation is compacted, and how many agents run at once. The right values depend on how you work: how long you pause between turns, how long your sessions run, how many subagents you fan out. cachefit reads your own Claude Code transcripts on your machine, replays them under each choice and recommends the cache TTL that would have cost least and the cheapest compaction window under a quality cap. Then it shows you the change as a diff and writes it only when you say yes.
It works on the input side. Caveman makes the agent say less; cachefit sets what the context you keep re-sending costs: how long it stays cached and when it is compacted. They stack.
- Python 3.9 or newer, standard library only, no network calls.
- Writes Claude Code, Codex and Gemini CLI settings; advice only for OpenCode, Cursor and GitHub Copilot.
- Every write is a dry-run diff first, then
--yes:--expect HASHwrites only the plan you previewed, a backup goes to~/.local/state/cachefit, andcachefit revertundoes it, touching only cachefit's own keys if you have edited the file since.
Quickstart
pipx install git+https://github.com/Jubii100/cachefit
cachefit analyze
cachefit apply --platform claude-code # prints the diff; run it again with --yes to write
cachefit analyze --json gives the same advice as data. Exit codes: 0 ok, 2 usage, 3 nothing to analyse or cannot.
Install
| Where | Command | What you get |
|---|---|---|
| Claude Code plugin | claude plugin marketplace add Jubii100/cachefitclaude plugin install cachefit@cachefit | the /cachefit skill, the /cachefit:tune command, cachefit on the Bash tool's PATH, the read guard hook (it does nothing until cachefit guard on) |
| Agent Skill (Claude Code, Codex, Gemini CLI, OpenCode, Cursor, GitHub Copilot) | npx skills add Jubii100/cachefit | the cachefit skill: the agent runs the CLI, explains the advice and applies it on your yes. Install the CLI too (pipx). |
| Command line | pipx install git+https://github.com/Jubii100/cachefit or pip install . in a clone | the cachefit command |
| A clone, no install | ./bin/cachefit analyze | the same command, run from the checkout |
Per-tool details, including what is automatic, what is advice only and what is not supported: Claude Code · Codex · Gemini CLI · OpenCode · Cursor · GitHub Copilot.
What it sets
| Tool | Setting | How |
|---|---|---|
| Claude Code | CLAUDE_CODE_PROMPT_CACHE_TTL, CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL (5m or 1h) and CLAUDE_CODE_AUTO_COMPACT_WINDOW, in the settings file's env block, with the matching keys promptCacheTtl, subagentPromptCacheTtl, autoCompactWindow | written |
Claude Code, opt-in --restrain | CLAUDE_CODE_WORKFLOW_MAX_CONCURRENT_AGENTS, CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS | written only with --restrain |
| Codex | model_auto_compact_token_limit in config.toml (where Claude Code compacts for the measured window) | written |
| Gemini CLI | model.compressionThreshold (the same point, as a fraction of the context window) | written |
| OpenCode, Cursor, GitHub Copilot | none documented for the threshold | advice only |
Scopes: --scope user (default), project, local (Claude Code's .claude/settings.local.json) and managed
(cachefit prints the merged managed file and the admin command; it never writes it).
How each decision is made
Cache TTL: counterfactual replay. Claude Code keeps two cache buckets: the main conversation (interactive, -p
and SDK turns) and everything else (subagents, workflows, compaction, session titles). For each bucket cachefit
replays every request of your history twice. Under each TTL every cache write is priced at that TTL's write price
(1.25x base input for 5 minutes, 2x for 1 hour), and a gap between two requests of a stream that is longer than the
TTL means the cache expired, so the prefix it carried is written again. The 1-hour cache doubles the price of every
fresh write, so it wins only when enough of your pauses fall between 5 minutes and an hour. A difference within 1 % is
a tie, and a tie picks 5m.
Two things keep the replay honest. First, a consistency check: replayed at the TTL you actually ran, it must give back the cost your transcripts report. That checks its arithmetic, not the counterfactual, which no history can show; a miss above 1 % drops the confidence to low. Second, the transcripts do not show which cached prefix another session kept warm, so each bucket is replayed under three assumptions: the sharing that was observed (the pick), more (any same-model stream within the TTL shares its prefix) and less (an observed warm read counts only if another stream ran within the TTL). The advice prints the range, and the confidence drops to medium when the pick changes inside it.
Auto-compaction window: the cost curve under a quality cap. For each window W, cachefit models the cost per
useful request of your sessions: a small window compacts often, and each compaction re-writes the cache; a large one
re-reads a longer context on every turn. In Claude Code, compaction was measured to fire about 33k tokens below W
(inferred from transcripts, not documented). On the author's history the curve was flat between 200k and 250k and
steep below 150k. cachefit takes the upper end of the range within 2 % of the minimum (as cheap, with fewer
compactions), then applies a quality cap, 200k by default (--quality-cap N, 100000 to 1000000). The cap exists because no quality-vs-context
curve for the current Claude models is published, while Anthropic's own system cards report agentic evals that
compact at 100k to 200k, and the API's default compaction trigger is 150k.
Agents at once: concurrency percentiles. A stream (one transcript) counts as active from each request to its
next one, or for 90 seconds when the next comes later or never. Percentiles are taken over active time and
weighted 0.5 for the last day, 0.3 for the last 3 days and 0.2 for the last 14 (so the weighted "peak" is a blend
of three peaks, not one observed moment). The gap sets the level: on the author's history a 300-second gap read one
to three more agents at each percentile than 90 seconds, while an independent count on a 10-second grid (active only
between requests at most 300 seconds apart) read the same p50, p90 and p99 and a peak one lower. Only Claude Code
requests count. Each cap is set from the quantity it limits, weighted the same way and rounded up, at least 2 and never
above the documented default: CLAUDE_CODE_WORKFLOW_MAX_CONCURRENT_AGENTS (16) from the most agents one workflow run
had going at once, CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS (20) from the most subagents one session had going at once.
CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY limits parallel tool calls within one turn, which stream counts do not measure,
so cachefit never sets it. The caps are opt-in and are not offered at low confidence: concurrency is a usage question,
not a cache one. No cap on cache entries per seat is documented and cache reads do not count toward
input-tokens-per-minute limits.
Read guard: your read share. cachefit counts the Read calls that loaded a large file (over 500 lines or 96 KB) whole, estimates their tokens (characters / 4) and counts each result again on every later request it rode along with until the next compaction. When that is a material share of all input processed (5 % by default), it recommends the guard; otherwise it says leave it off.
Dollar figures are API-equivalent at list prices from the bundled price table (--prices FILE is merged over it). A
subscription's usage pool weighs cache reads and writes in a way that is not published, so on a subscription the
figures are a proxy for which choice uses less of it.
Evidence from the author's machine
Counts and percentages only, from cachefit analyze on one developer's history.
| Measure | Value |
|---|---|
| History analysed | 14 days, 108,193 Claude Code requests in 1,512 agent streams |
| Consistency check (the replay at the TTL actually used vs the cost reported) | within 0.08 % |
| Main conversation cache | 5m; 1h costs 1.6 % more (recency-weighted 1d/3d/14d; 1.3 % to 4.1 % across the three sharing assumptions; 4.2 % over the 14 days) |
| Subagent and workflow cache | 5m; 1h costs 16.2 % more (16.0 % to 16.3 % across the assumptions; 16.2 % over the 14 days) |
| Auto-compaction window | 200k, set by the quality cap: the cheapest window was 220k, and 200k to 250k were within 2 % of it; the 1M default costs about 80 % more per request at the 5m pick. The window replay comes within 5 % of the cost per request reported |
| Agents at once, weighted p50 / p90 / p99 / peak | 2 / 5.5 / 11.3 / 19.6 (last day alone: 2 / 6 / 10 / 17); at most 10.3 agents at once in one workflow run and 5.4 subagents in one session (weighted) |
| Whole reads of large files | 16 of 3,577 reads, about 0.02 % of input (estimate); guard: leave off |
| Confidence | medium (the window replay's 5 % miss) |
Your numbers will differ: that is the point.
Privacy
cachefit runs on your machine and sends nothing anywhere. It reads the transcripts under ~/.claude/projects and
~/.codex/sessions (or --claude-root, --codex-root, CLAUDE_CONFIG_DIR, CODEX_HOME), and it prints, stores or
returns from them only counts, sizes, timestamps, model names and opaque hashes: never message text, prompts, file
paths, project names or raw ids. The diffs it prints mask every string value in the settings file that is not its
own, so a token in a neighbouring env entry never reaches the terminal. The read guard and cachefit ask read the
one file the agent asked for, locally, and make no model call.
Read guard (optional, off by default)
The read guard is a PreToolUse hook. When it is on, it refuses a Read that would load a large file whole, or a bare
shell read of one (cat FILE, less FILE, ...), and tells the agent which lines to read instead, with an outline of
the file and the cachefit ask FILE --need "..." command that finds the lines answering a question (a local keyword
search, no model call). The outline shows names only (headings, definitions, keys), never a value, and a file type
without a known pattern gets none.
The guard as packaged has not been measured. The evidence is thin and comes from an earlier, unpublished version run by the author: in an A/B of 120 headless runs (one model, six tasks per kind, one run each) it never fired when grep was available; when it fired it saved 17-20 % on targeted questions and cost 5-16 % on whole-file work. So it is off by default and the analyzer recommends it only when your own history shows whole large reads as a material share of input.
cachefit guard status
cachefit guard on # off: cachefit guard off
The guard's settings live in $CACHEFIT_CONFIG or ~/.config/cachefit/config.json:
{"guard": {"enabled": false, "min_lines": 500, "min_bytes": 98304, "exempt": [".env*"]}}
Key, certificate and credential files are always left to Claude Code's own permission rules, whatever exempt says:
.env*, *.pem, *.key, *.p12, *.pfx, *.jks, *.keystore, id_rsa* and the other SSH key names, .netrc,
.pgpass, .npmrc, .pypirc, and any name containing secret, credential or password.
The guard acts only where its hook is installed. The Claude Code plugin installs it. Without the plugin, add this to
your Claude Code settings file (hooks merges with what is there):
{"hooks": {"PreToolUse": [{"matcher": "Read|Bash", "hooks": [{"type": "command", "command": "cachefit guard hook"}]}]}}
Any internal error, a missing interpreter included, allows the read: the guard never blocks work. For Codex, which reads files through shell commands, see platforms/codex.md.
Commands
cachefit analyze [--days 14] [--json] [--claude-root P] [--codex-root P] [--prices F] [--quality-cap N]
cachefit apply [--platform claude-code|codex|gemini-cli|opencode|all] [--scope user|project|local|managed]
[--project DIR] [--restrain] [--yes [--expect HASH]]
cachefit revert [--platform ...] [--scope ...] [--project DIR] [--yes]
cachefit monitor [--interval 30] [--once]
cachefit ask PATH --need TEXT [--find NAME]...
cachefit guard hook|status|on|off
apply and revert are dry runs until --yes. The dry run of apply prints a plan hash; --yes --expect HASH
writes only if the history and the settings file still give that plan, and refuses (exit 3) otherwise. Each write keeps
a backup and a record of the keys it set in $XDG_STATE_HOME/cachefit (default ~/.local/state/cachefit, a folder
made private to you), never beside the settings file, where a project's git could pick it up. revert restores the file byte for byte
if it is still as cachefit left it; otherwise it restores only the keys that still hold cachefit's value and leaves
every other change, yours included, as it is. bin/cachefit runs the package from a checkout or the plugin
directory; CACHEFIT_PYTHON picks the interpreter (default python3).
Limits
- The replay prices what your transcripts record. It cannot see a request that a different setting would have caused or avoided, such as a compaction that would have happened at another window.
- The Codex and Gemini CLI thresholds are transferred from the Claude Code measurement (the point where Claude Code compacts for the measured window): Codex and Gemini models are not in the price table and their history is not replayed.
- Gemini CLI's threshold is a fraction of the model's window; cachefit assumes a 1M window and says so in the advice.
- The compaction trigger offset (W minus about 33k) is measured, not documented, and may change with Claude Code.
- Start a new session after applying (Gemini CLI needs a restart). A shell export or a higher-precedence setting can
still win; the apply output names the ones it can see, such as
FORCE_PROMPT_CACHING_5M.
License
MIT. See LICENSE and CHANGELOG.md.