SLOPSHOPPER

subagent-models

Status line shows which model each running subagent is using

newguardstatuspromptagents
A shopper browsing a rack in a slop shop
README

subagent-models

Shows which model each subagent is running on, in the status line under the prompt.

What it does

When Claude starts subagents, the status line shows one entry per subagent:

agents: haiku-4-5, sonnet-5-5

When a subagent finishes, its entry gets a check mark and stays visible until your next prompt, so a short run can't flash past:

agents: haiku-4-5 ✓, sonnet-5-5

If several subagents ran in one turn, they all stay listed. Submitting a prompt clears the line.

Why

The built-in subagent list doesn't say what model each one is using. A default subagent model set in your settings, or a subagent picking its own, can make that a surprise.

Install and run

claude --plugin-dir /path/to/claude-code-mods/subagent-models

To load it in every session, see Install.

Try it: ask Claude to "use the Explore agent to list the files in this folder, then reply done."

Notes

  • No tokens: it only reads which model each subagent resolved to.
  • A subagent that started before the mod loaded shows ? for its model.
  • The name is the model Claude Code resolved, so an alias like sonnet appears as its full name, for example sonnet-5-5. A default subagent model set in your settings (CLAUDE_CODE_SUBAGENT_MODEL) overrides what Claude chooses.

How it works

Hooks on agent.spawn (records the model each subagent started with), turn.complete and tool.call (refresh which are still running), and prompt.submit (clears). It writes through $.ui.status.

Source 1 files
hooks/register.ts 55 lines
1import type { EngineInterface, Register } from 'claude-code'
2
3// Models of the subagents started since the last prompt, by agent id.
4const models = new Map<string, string>()
5
6const short = (model: string) => model.replace(/^claude-/, '')
7
8async function refresh($: EngineInterface) {
9  if (models.size === 0) {
10    $.ui.status(undefined)
11    return
12  }
13
14  const running = new Set(
15    (await $.agent.list()).filter(a => a.status === 'running').map(a => a.id),
16  )
17  const label = [...models].map(
18    ([id, model]) => `${short(model)}${running.has(id) ? '' : ' ✓'}`,
19  )
20
21  $.ui.status(`agents: ${label.join(', ')}`)
22}
23
24export const register: Register = on => {
25  on('prompt.submit', async ($, e, next) => {
26    models.clear()
27    await refresh($)
28    return next(e)
29  })
30
31  on('agent.spawn', async ($, e, next) => {
32    const started = await next(e)
33
34    if (!started.deny && started.agentId) {
35      models.set(started.agentId, started.model)
36      await refresh($)
37    }
38
39    return started
40  })
41
42  // Subagents finish with a turn.complete; tool calls catch the rest.
43  on('turn.complete', async ($, e, next) => {
44    const done = await next(e)
45    await refresh($)
46    return done
47  })
48
49  on('tool.call', async ($, e, next) => {
50    const ran = await next(e)
51    await refresh($)
52    return ran
53  })
54}
55