Skip to content
Conduit

skill

cachefit

Fit prompt-cache TTL and auto-compaction settings to your own Claude Code and Codex history.

Jubii100/cachefitcommunitylistedunreviewed

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

Skills do not use an MCP config. Follow the steps in the README below.

README

synced Oct 26, 2026

cachefit

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 HASH writes only the plan you previewed, a backup goes to ~/.local/state/cachefit, and cachefit revert undoes 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

WhereCommandWhat you get
Claude Code pluginclaude plugin marketplace add Jubii100/cachefitclaude plugin install cachefit@cachefitthe /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/cachefitthe cachefit skill: the agent runs the CLI, explains the advice and applies it on your yes. Install the CLI too (pipx).
Command linepipx install git+https://github.com/Jubii100/cachefit or pip install . in a clonethe cachefit command
A clone, no install./bin/cachefit analyzethe 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

ToolSettingHow
Claude CodeCLAUDE_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, autoCompactWindowwritten
Claude Code, opt-in --restrainCLAUDE_CODE_WORKFLOW_MAX_CONCURRENT_AGENTS, CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTSwritten only with --restrain
Codexmodel_auto_compact_token_limit in config.toml (where Claude Code compacts for the measured window)written
Gemini CLImodel.compressionThreshold (the same point, as a fraction of the context window)written
OpenCode, Cursor, GitHub Copilotnone documented for the thresholdadvice 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.

MeasureValue
History analysed14 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 cache5m; 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 cache5m; 1h costs 16.2 % more (16.0 % to 16.3 % across the assumptions; 16.2 % over the 14 days)
Auto-compaction window200k, 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 / peak2 / 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 files16 of 3,577 reads, about 0.02 % of input (estimate); guard: leave off
Confidencemedium (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.

↑↓ navigate openesc close