subagent-ledger
You fan a task out to five subagents, and afterwards /cost gives one total: which agent read the whole repository, and which one ran for four minutes, stays hidden. This mod shows what each subagent of the session spent: its turns, its wall-clock time and its tokens, one row per agent, the costliest first.
What it does
The mod hooks
agent.spawn, which names what the subagent is: its agent type (Explore,general-purpose, a plugin's agent,fork) and the one-line description of its task. It keeps that against the agent id the spawn answers with, together with the model the spawn resolved, and draws the row as running at once.It hooks
turn.completeof every subagent loop. That turn is the subagent's answer, so it ends the run:donewhen the turn ended with an answer,stoppedwhen it was interrupted, refused or ended on an API error. Each of those turns adds one turn, itsdurationMs, and its tokens: the input, the output, the cache reads and the cache writes the engine reports for that turn. The turn also names the model that answered it, which replaces the spawn's model, drawn without the vendor prefix and without the date of a full id, soclaude-haiku-4-5-20251001reads ashaiku-4-5. A main-loop turn is not counted.It hooks
turn.step, one model request, to draw a subagent as running again when its loop runs after it answered, as it does when SendMessage resumes it. A main-loop step is not read.While the sidebar is open, the ledger is one
subagentssection that stays for the session and is rewritten at each spawn, at each subagent turn and when a subagent runs again:subagents port the config loader to the new schem… · opus-5 · 7 turn · 4m 10s · T 260k · I 5k · O 9k · CR 210k · CW 36k · running find the parser · haiku-4-5 · 3 turn · 42s · T 81k · I 2k · O 1k · CR 70k · CW 8k · done read the tests · haiku-4-5 · 1 turn · 9s · T 30k · I 1k · O 500 · CR 24k · CW 5k · stopped 2 more · 150kA row's name is the description of its task, cut at 40 characters; a spawn that named no description shows its agent type there instead. Its tokens read as
Tthe total,Ithe input the cache did not serve,Othe output,CRthe cache reads andCWthe cache writes; the last four add up toT. A row ends with its status word:runningyellow while its subagent runs,donegreen once it answered, andstoppedfaint when its run ended without an answer. The model is coloured by family (opus red, fable yellow, sonnet green, haiku faint). TheTtotal is yellow from 80% of the limit (200k tokens by default) and red once the subagent reached it, in every status. The label, the turns, the time and the tokens by kind stay in the default colour. The rows past the third are one faint line with their tokens added up, so a fan-out of twenty agents still holds four rows.With the sidebar closed, or without that mod installed, the totals go to the status line instead:
subagent-ledger: 4 subagent · 12 turn · 3m 10s · 210k/subagent-ledgerprints the totals and every subagent of the session, the costliest first, whatever the sidebar shows.
Command
/subagent-ledger on or off, the limit, the totals and every subagent
/subagent-ledger on | off on by default
/subagent-ledger limit 500 a subagent over 500k tokens is drawn red; 1 to 10000, 200 by default, stored across sessions
Install
claude plugin marketplace add KilimcininKorOglu/claude-code-mods
claude plugin install subagent-ledger@kilimcininkoroglu-mods
Function hooks are early access. Claude Code 2.1.288 and later load them by default, so there is nothing to switch on.
After installing
- Restart Claude Code.
- Install the sidebar mod for the per-agent rows. Without it the mod shows the totals on the status line.
What it can reach
Validated with claude plugin validate on Claude Code 2.1.283:
❯ ./register.ts hooks: session.start, command.run{command=subagent-ledger}, agent.spawn, turn.step, turn.complete
❯ ./register.ts calls: $.command.register, $.sidebar.clear (via clearShown), $.sidebar.set (via show), $.store.get (via readLimit, readSettings), $.store.set (via setEnabled, setLimit), $.ui.status (via clearShown, show)
Reach L0, draws and remembers.
1. Reads: each spawn's agent type, description and resolved model, each subagent turn's id, duration, end reason, model and token counts, and the agent id of each model request. It reads no prompt, no answer, no file and no tool result.
2. Runs: nothing
3. Sends: nothing to the model; the rows and the status line are for the person only
4. Persists: in $.store, the on/off setting and the limit; the ledger itself lives in memory and ends with the session
5. Hostile input: the only text drawn is the agent type, the spawn's own description, cut to 40 characters, and the model id the engine reports
Limits
- The ledger counts turns as they end. A subagent still running is in the rows, yellow, with what it has spent so far.
- A run ends in the ledger only at the subagent's
turn.complete. A subagent whose run ends without one stays yellow. Whether every kind of end (aTaskStop, a killed background agent) raises that event is not measured. - A subagent whose spawn this mod did not see (one started before it loaded) is counted under the label
agent, because only the spawn names the type. Its model is empty until one of its turns names one, and a row without a model draws without that field. - The tokens are the engine's own per-turn counts. A turn that got no response carries none and adds zero.
- Tokens are not dollars. What a cache read costs against a subscription's limits is not documented.
- The ledger is per session. A restart starts empty, and the counts are not written to disk.
Development
make install # eslint, typescript-eslint, typescript
make lint # complexity limit 10, the build fails above it
make typecheck # needs .claude/types/ from /plugin-types
make validate
make test # claude plugin test