Your main Claude Code session can't see how full each subagent's context is. These hooks tell it — and warn it before it hands more work to an agent with degraded performance.
When a Claude session runs subagents (background agents, teammates, review panels), nothing reports how much context each one has used. So the main session routinely says "one more round" to an agent sitting at 350k+ tokens. Agents that full get worse: recall drops, they lean on their own earlier conclusions, they churn more, and reviews may rubber-stamp. This plugin gives the dispatcher context awareness, configurable.
Three small hooks.
-
Observer (
SubagentStop) — when a subagent stops, reads its context size from its transcript (current, peak, and whether it was ever compacted) and saves the numbers. -
Drain (
PostToolUse) — on the orchestrator's next tool call, slips any new reports into its context:[subagent-context] research-worker (claude-opus-5): ~383k tokens — OVER THRESHOLD: prefer spawning a fresh agent over re-tasking this one; long-context agents degrade. -
Guard (
PreToolUseonSendMessage) — catches the moment before the main session sends more work to a full agent. Pastwarn_tokensit adds a warning to that tool call. Pastblock_tokens(350k by default) it also asks you to confirm. You can always say yes.
This costs you nothing other than a few tokens on an existing message: no extra model calls.
Reports go to whatever session spawned the agent. The root session gets reports for its own spawns, teammates, and Workflow-tool agents (labeled with the run id); a subagent that spawns its own subagents gets their reports in its own context, and the same warn logic applies when it re-tasks them.
As a plugin:
/plugin marketplace add msshives-gif/subagent-context
/plugin install subagent-context@subagent-context
Manual (no plugin system):
git clone https://github.com/msshives-gif/subagent-context
cd subagent-context && ./scripts/install.sh # merges into ~/.claude/settings.json, with backupEither way, restart any running Claude Code sessions — hooks are read
at startup. ./scripts/uninstall.sh reverses the manual install.
Requirements
- Python 3.9 or newer, on PATH as
python3orpython. No other dependencies. - A Claude Code version that includes
agent_idandagent_transcript_pathin theSubagentStophook payload. To check: spawn any subagent, then runpython3 scripts/status.py. If it lists the agent, you're set. - Developed and tested on Linux; macOS runs the same code paths.
Windows should work (portable locking,
pythonfallback) but hasn't been tested on a real Windows machine — reports welcome. On Windows, install as a plugin (install.shis a bash script).
Every knob works as an environment variable (SUBAGENT_CONTEXT_<NAME>)
or a key in ~/.claude/subagent-context.json (env wins; point
SUBAGENT_CONTEXT_CONFIG at a different config path if you want one):
| Knob | Default | Meaning |
|---|---|---|
warn_tokens |
250000 |
Above this, reports carry an OVER-THRESHOLD warning and the guard starts firing. |
block_tokens |
350000 |
Above this, messaging the agent needs your confirmation. 0 turns this off. |
report_min_tokens |
0 |
Only report agents at least this big. 0 = report every stop. |
models |
{} |
Per-model overrides for the three knobs above — see below. |
system_message |
true |
Also show each report to you in the UI. |
drain_batch_max |
20 |
Max reports delivered per tool call. |
flush_grace_ms |
4000 |
How long to wait for a stopping agent's transcript to finish being written. |
state_dir |
~/.claude/subagent-context |
Where recorded numbers live. |
ledger / ledger_max_bytes |
true / 5MB |
Keep an audit log of every observation, rotated at the size limit. |
state_ttl_days |
7 |
Old sessions' records get cleaned up after this. |
The defaults assume long-context models. A model with a 200k window compacts before reaching 250k — compaction is itself reported and guarded, but if you mix model families, give each its own thresholds. The confirmation prompt can't be answered in a headless run, so there the block acts as a refusal.
models maps a model-ID substring to overrides for warn_tokens,
block_tokens, and report_min_tokens. In
~/.claude/subagent-context.json:
{
"warn_tokens": 250000,
"models": {
"claude-fable-5": { "warn_tokens": 400000, "block_tokens": 700000 },
"opus": { "warn_tokens": 250000, "block_tokens": 350000 },
"haiku": { "warn_tokens": 150000 }
}
}A pattern matches when it appears anywhere in the agent's model ID
(case-insensitive); the longest matching pattern wins, so
claude-opus-4-8 can be more specific than opus. Knobs a match
doesn't set fall back to the global values, and agents whose model is
unknown always use the globals. As an environment variable,
SUBAGENT_CONTEXT_MODELS takes the same mapping as a JSON string.
Reports arrive on their own. To look at the current numbers any time:
python3 scripts/status.py # all sessions, newest first
python3 scripts/status.py --session 02ff # prefix matchInstalled as a plugin, you won't have a clone of the repo. Run the
script from the plugin's own directory — /plugin shows you the path.
- Built on undocumented internals. Context is measured from Claude Code's subagent transcript files, whose format is not a public interface. If a Claude Code update changes those formats, this plugin stops producing reports. It will not break your session. Built and verified against Claude Code as of 2026-08-02.
- Numbers are minimums. Reports are taken when an agent stops. In
practice that's often —
SubagentStopfires every time an agent goes idle, not only when it finishes for good (that's what we observed; it isn't documented) — but an agent that's mid-task has already grown past its last report. - Compaction is treated as a warning sign. After auto-compaction an
agent's current context looks small again. Reports show the peak and
a
COMPACTED xNflag, and the guard still fires for it. - The guard watches
SendMessage. That's how existing agents get more work in current Claude Code. FreshAgentspawns start empty and need no guard. NoSendMessagetool in your setup? The guard never fires; reports still work. - Privacy. Recorded state stays on your machine, under
state_dir: agent names, models, session IDs, token counts, transcript paths. Nothing goes over the network. - Install one way, not both. Plugin install and
install.shtogether would run every hook twice and duplicate reports.
Plugin: /plugin uninstall subagent-context. Manual:
./scripts/uninstall.sh. Then delete ~/.claude/subagent-context/.
python3 -m unittest discover testsDesign rationale, the verified hook-channel behavior this depends on, and rejected alternatives: docs/DESIGN.md.
MIT.