The expensive thing in a long Claude Code session is not what you ask, it is how long you have been asking.
The whole conversation is resent on every single call. A session that runs for 900 calls pays for everything accumulated so far, 900 times over. The cost grows with the square of the length, and nothing in the interface tells you this is happening until the bill does.
This kit puts it in the status bar and tells you when to act.
myproject Opus 5 1M 15% ctx (150K) alice team 30% wk ~$18
myproject Opus 5 1M 24% ctx (242K) -> /handoff and /compact alice team 30% wk
myproject Opus 5 1M 85% ctx (850K) -> /handoff + /compact NOW 70% wk ~$18
It warns at 55% of the window, and separately at 200K tokens whatever the window size. That second threshold matters more than it looks: on a 1M context model, 200K tokens is only 20%, a number that reads as "plenty of room" while the session is already larger than a standard context window can hold. The token count is shown next to the percentage for the same reason, because a percentage against a very large denominator hides how big the conversation actually got.
At 85% it stops suggesting and starts insisting. It never compacts for you: it puts the decision where you will see it.
It also blocks one specific thing: taking a screenshot of something you have not edited since the last one. That image is byte-for-byte identical to one already in the context, and it will be resent on every call for the rest of the session.
Measured on one real session before any of this was in place:
| Tool calls in a single conversation | 973 |
| Transcript on disk | 51 MB |
| Screenshots | 157 |
| Screenshots of a node that had not changed | 87 (55%) |
| Worst single node | captured 20 times |
The length is the headline. The screenshots are what made the slope steeper: each one leaves roughly 112 KB in the context permanently, so a session heavy on images gets there faster. A long session with no images at all still gets there.
The rules against all of this were already written down, in the config file that gets loaded every session. They were being read. They did not survive contact with a task in progress, which is why most of this kit reports rather than reminds, and why exactly one part of it blocks.
| File | Event | What it does |
|---|---|---|
statusline-context.sh |
statusLine | Context %, quota, cost, active account |
stop-compact-nudge.sh |
Stop | Says out loud, once per tier, that it is time to compact |
paper-shot-guard.sh |
PreToolUse | Blocks a 4th screenshot of an unedited node |
session-size-warn.sh |
PostToolUse | Counts calls, screenshots and per-node captures |
context-weight.sh |
PostToolUse | Real bytes per tool, so you know what filled the context |
compact-reset.sh |
UserPromptSubmit | Resets the counters on /compact |
Plus a handoff skill that writes decisions and dead ends to disk before you
compact.
Every number comes from the JSON Claude Code already passes on stdin:
context_window.used_percentage, rate_limits.seven_day, cost.total_cost_usd.
Nothing is estimated. Screenshot and byte counters only appear once they are a
problem, so a clean session stays quiet.
Two details worth knowing:
The dollar figure is a shadow price on a subscription. Claude Code reports
what the work would have cost on the API. On Max, Pro or a Team seat you are not
billed per token, so the kit dims it and prefixes ~. On a flat plan the number
that can actually stop you is the quota, which is why % wk sits ahead of it.
The account label (alice max, alice team) appears when a credential is
readable, and follows /login. If you switch between a work and a
personal account, the statusline rereads the live credential on every redraw. If
two credential files disagree and were touched within a minute of each other, it
shows account? in amber rather than asserting one that might be wrong.
This is the only piece that blocks rather than warns, and the reasoning is narrow: taking the same screenshot of a node you have not edited is not a judgement call the user should keep making, it is a mistake. If the node did not change, the image is identical.
Three captures of the same node pass. The fourth is denied with a reason. Any
edit to that node resets the counter, so the normal edit-then-look loop is
untouched. Escape hatch: PAPER_SHOT_GUARD=off.
It matches mcp__paper__get_screenshot, so it is only useful with
Paper. Adapt the matcher for another MCP that returns
images.
Warns at 55% of the context window, then every 15 points. Reads the real token usage from the transcript rather than counting calls: one call can weigh 900 bytes or 700 KB, so counting them is a poor proxy.
It never compacts for you. It writes the suggestion where you will read it and stops.
The order it suggests is deliberate: /handoff first, /compact second.
Compacting first destroys exactly the decisions and dead ends worth keeping.
Compacting is lossy. It keeps a summary and drops the rest, and what it drops first is usually the reasoning: why you rejected the other approach, which three things you already tried that did not work.
/handoff writes that to a file before you compact: the next step first,
executable as written, then state, decisions and why, and traps. The traps
section is the one that earns its keep, because a dead end is recorded nowhere
else. The code only shows what worked.
Version 2 added the lessons from using it in anger: full rewrite instead of appending (a handoff that accumulates sessions becomes a changelog nobody can resume from), a ~40-line cap, a routing table so durable rules and traps land in docs or memory instead of piling up here, and a pointer left where your sessions always look first, so the file actually gets read on resume.
Hence the order the kit suggests, handoff first and compact second. Doing it the other way round destroys exactly what you were about to write down.
This is also the one part of the kit that is not really an invention. Dumping state to markdown and starting fresh is the most widely agreed-on answer to this problem: Anthropic calls it structured note-taking, and it comes up independently in threads where people compare notes and in write-ups from people running agents unattended.
git clone https://github.com/dsaltaren/claude-context-kit
cd claude-context-kit
./install.shThen merge the printed snippet into settings.json. The installer deliberately
does not edit that file for you.
Requires bash and Python 3 (both present on macOS by default). Verified against Claude Code 2.1.237.
- Thresholds assume you would rather compact early than late. The absolute 200K trigger fires at 20% of a 1M window, which some people will find noisy. Both thresholds are one edit away at the top of each file.
- The guard is Paper-specific as written.
context-weight.shis partly redundant now that the native%exists. It is kept because it is the only piece that reports which tool consumed the context, which the native field does not.- Nothing here is a substitute for delegating to a subagent. A subagent's screenshots live in its context, not yours. That is the only lever that actually breaks the drag; this kit just makes the drag visible.
- Since v2.1.198, subagents inherit the session model.
Exploreandgeneral-purposeare no longer free Haiku. SetCLAUDE_CODE_SUBAGENT_MODEL=sonnet(orhaiku) if you assumed otherwise. - Nothing here helps across sessions. The kit measures one conversation; it has no memory of the last one. What covers that gap is a file-based memory, one fact per markdown file plus a small index loaded every session, so the model starts informed instead of being taught the same things again. Different problem, separate repo, coming shortly.
Nothing here was designed in a vacuum. What other people had already worked out:
- Effective context engineering for AI agents (Anthropic) makes
the case for structured note-taking and for subagent architectures where the
orchestrator only receives condensed summaries. The
handoffskill is that idea, nothing more. - Statusline reference (Claude Code docs) lists the fields
passed on stdin. Worth reading before building anything:
used_percentage,cost.total_cost_usdandrate_limitsall arrive pre-computed. I estimated several of these by hand before noticing. - ccstatusline is the established option in this space, far more configurable than what is here. If you want a statusline rather than a cost tripwire, start there.
- "When I have to compact a 2 day long 900k context session" (r/ClaudeAI) is where the cache-cost numbers get argued out in public, and where the disagreement below comes from.
- "What I learned running 25+ agents in a loop, unattended" (r/ClaudeCode) calls durable markdown memory "by far the single highest-leverage thing I learned".
- "Subagents inherit your session model now" (r/ClaudeCode) is the source of the last caveat above, and the one finding here that is a plain fact rather than a preference.
An open disagreement, since this kit quietly takes a side. One camp keeps long sessions alive deliberately, on the grounds that a cache read is far cheaper than rebuilding a cold context, and that letting the cache expire costs more than staying warm. The other starts fresh per task, on the grounds that quality degrades well before the window fills. Both positions have support and neither has produced a number that settles it. This kit assumes the second, which is a preference, not a proven result. If you hold the first, the thresholds are one edit away.
MIT