agentleFS
reganomikareganomika/Bullpen/skills/routing-status/SKILL.md

routing-status

Skill1 starsChanged 4 months agoMITView on GitHub

Show a table of real routing decisions and per-model token spend for the current session, straight from route-gate.log and the transcript, not relying on any per-reply report. Use this to check that the routing skill is actually working.

The file

We split this skill into the rules it gives an agent

1 rule. About 0 are common, 1 is distinctive, and 0 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Every real agent completion in this session, with its model:

    line 44

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Gather and show two sections for the current session.

1. Find the session_id and transcript

PROJDIR=~/.claude/projects/$(pwd | sed 's/[^A-Za-z0-9]/-/g')
SESSION_ID="${CLAUDE_CODE_SESSION_ID:-$(basename "$(ls -t "$PROJDIR"/*.jsonl 2>/dev/null | head -1)" .jsonl)}"
TRANSCRIPT="$PROJDIR/${SESSION_ID}.jsonl"

The directory name is pwd with every character outside A-Za-z0-9 replaced by a dash, not just the slashes. CLAUDE_CODE_SESSION_ID is documented in Claude Code's environment-variables reference: set automatically to the current session id in Bash tool subprocesses (among others), updated on /clear. The ls -t fallback covers older CLIs where it may be absent; it picks the transcript written to most recently, which can belong to a different open session of the same project.

2. Routing (route-gate.log, this session only)

awk -F'\t' -v sid="$SESSION_ID" '$2==sid' ~/.claude/hooks/state/route-gate.log

The log holds two kinds of row, and they answer different questions. Split them.

Gate decisions (allow-tier, allow-tier-*-overridden, rewrite-haiku, deny-no-model, ask-super, allow-explicit, allow-other, allow-bypass, allow-subagent) come from PreToolUse and say what the gate did about a spawn the main loop asked for. Show as a table: tier/agent_type, count, decision. This is a routing health check on its own: deny-no-model should trend to zero, rewrite-haiku above zero means the haiku auto-route is actually firing, allow-subagent means an agent spawned another agent (never gated, since no user is there to answer a dialog).

Actual starts (start, start-nested) come from SubagentStart and say which subagents really ran and on which model, including the ones the gate never sees: agents a Workflow started, and agents nested inside another agent. start-nested is the workflow and fan-out case. The model column here is the resolved model, not a requested parameter, so it is the more trustworthy of the two for cost questions. Show it as its own table: agent_type, model, count.

A spawn the main loop issues by hand appears twice, once as a decision and once as a start. That is the point: the first row is what the gate decided, the second is what actually launched. Never add the two tables together.

3. Tokens by model (this session, real numbers)

Main session, by model, straight from the transcript (no intermediate state file anymore). Claude Code writes one API response as several transcript lines, one per content block, and every line repeats the same full usage; the unique_by(.id) dedupe is what keeps the sum honest, a raw per-line sum comes out 2-3x too high:

jq -n '
[inputs | select(.type=="assistant") | .message // empty]
| unique_by(.id)
| reduce .[] as $m ({}; .[$m.model // "unknown"] += ($m.usage.output_tokens // 0))
' "$TRANSCRIPT"

Every real agent completion in this session, with its model:

jq -n '
[inputs] as $all
| [
    $all[]
    | select(.type=="assistant")
    | .message.content[]?
    | select(type=="object" and .type=="tool_use" and (.name=="Agent" or .name=="Task"))
    | {id: .id, agent_type: (.input.subagent_type // .input.agent_type // "unknown"), model: (.input.model // "")}
  ] as $agents
| [
    $all[]
    | select(.type=="user")
    | .message.content as $c
    | (if ($c|type)=="array" then $c[] else {type:"text", text:$c} end)
    | (
        if (type=="object" and .type=="tool_result") then
          ( . as $tr
            | ($tr.content | if type=="string" then . else (.. | strings) end) as $txt
            | { tuid: $tr.tool_use_id, txt: $txt } )
        elif (type=="object" and .type=="text" and (.text|type)=="string" and (.text | test("^\\s*<task-notification"))) then
          ( .text as $txt
            | ($txt | scan("<tool-use-id>([^<]+)</tool-use-id>") | .[0]) as $tuid
            | { tuid: $tuid, txt: $txt } )
        else empty
        end
      )
    | select(.txt | test("subagent_tokens"; "i"))
    | . as $entry
    | ($agents[] | select(.id == $entry.tuid)) as $a
    | ($entry.txt | [scan("subagent_tokens[^0-9]{0,3}([0-9]+)"; "i")] | first | .[0] // empty) as $tok
    | {agent_type: $a.agent_type, model: $a.model, tokens: ($tok | tonumber)}
  ]
' "$TRANSCRIPT"

The tight {0,3} window and first on the $tok line are load-bearing: the notification reads <subagent_tokens>N</subagent_tokens><tool_uses>M</tool_uses>, and a looser window lets the word subagent_tokens in the closing tag reach M, producing a second bogus record per completion with tokens equal to the tool-use count.

Add the main session and the agents into one table by final model and compute each one's share of the total. When an agent completion's model is empty, resolve it by tier: cheap → Haiku 4.5, dev → Sonnet 5, hard → Opus 5, super → Fable 5. Match the tier on the part after the last colon: a plugin install registers these agents under scoped names like bullpen:dev, a copy-into-config install under the bare names, so accept both. An explicit model in the record wins over the tier. Those four model names are what the tier aliases resolve to on the Anthropic API on a current CLI (v2.1.219 or later for opus → Opus 5); other providers and older CLIs resolve the same aliases to different models, see the provider table in FAQ.md. Name models directly: Sonnet 5, Opus 5, Haiku 4.5, Fable 5.

This transcript query finds agents the main loop spawned through Agent/Task. Agents a Workflow started do not appear there as tool calls, so cross-check the start and start-nested rows from section 2: any agent type there with no matching completion here ran inside a workflow. Report its model from the log (that column is the resolved model) and say plainly that its token count is not available, rather than leaving it out of the picture entirely.

Honest about the limits

route-gate.log doesn't store completion tokens, only the decision at spawn time: it's the source for section 2 (how many times each thing was called), not for section 3. Section 3 comes straight from the transcript, through a tool_use/tool_result pair or a <task-notification>. If an agent completion has neither an explicit model nor a known tier (for example a custom agent like claude-code-guide with no explicit model), don't invent a model: label it "unknown" and give the agent type as-is.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.