| @@ -54,7 +54,7 @@ would break your Claude Code login. |
| 54 | 54 | |
| 55 | 55 | Useful flags: `-model`, `-effort low|medium|high|xhigh|max`, `-max-turns`, |
| 56 | 56 | `-resume latest`, `-no-stream`, `-no-cache`, `-v`, `-yolo`, `-no-tui`, `-no-skills`, |
| 57 | | - `-no-claude-code-auth`. |
| 57 | + `-no-agents`, `-no-claude-code-auth`. |
| 58 | 58 | |
| 59 | 59 | ## The TUI |
| 60 | 60 | |
| @@ -101,13 +101,14 @@ to six lines. |
| 101 | 101 | | `$` | the same, through `python3` | |
| 102 | 102 | | `ctrl+j` | newline without sending | |
| 103 | 103 | | `shift+tab` | cycle the approval mode | |
| 104 | + | `ctrl+b` | open the agents sidebar — see below | |
| 104 | 105 | | `ctrl+r` | expand elided tool output | |
| 105 | 106 | | `pgup`/`pgdn` | scroll the transcript | |
| 106 | 107 | | `esc` | interrupt the turn | |
| 107 | 108 | | `ctrl+c` | interrupt the turn; again when idle to exit | |
| 108 | 109 | |
| 109 | 110 | Commands: `/allowed`, `/clear`, `/effort`, `/exit`, `/help`, `/model`, |
| 110 | | - `/setup`, `/skills`, and one per discovered skill. |
| 111 | + `/mouse`, `/setup`, `/skills`, and one per discovered skill. |
| 111 | 112 | |
| 112 | 113 | A slash at the start of an empty prompt opens the command menu, which filters |
| 113 | 114 | as you type — a name that starts with what you typed before one that merely |
| @@ -232,6 +233,168 @@ The TUI is skipped automatically when stdin or stdout is not a terminal, and by |
| 232 | 233 | consume the same `agent.Event` stream, so neither can show something the other |
| 233 | 234 | cannot. |
| 234 | 235 | |
| 236 | + ## Subagents |
| 237 | + |
| 238 | + The agent can start other agents. `spawn_agent(preset, task)` returns |
| 239 | + immediately with a short id — `a1`, `a2`, … — and that agent runs in the |
| 240 | + background on its own goroutine while the main agent carries on with whatever |
| 241 | + it was doing. `agent_wait(id)` blocks until that one finishes, for the times |
| 242 | + the parent genuinely cannot proceed without the answer. |
| 243 | + |
| 244 | + A subagent is a whole agent, not a subroutine: its own conversation, its own |
| 245 | + context window, its own model, its own turn loop. The parent never sees its |
| 246 | + turns — only the report it ends with. That is the point. Work that would have |
| 247 | + filled the parent's window with file listings fills the child's instead, and |
| 248 | + comes back a paragraph long. |
| 249 | + |
| 250 | + Three presets, compiled in rather than configurable, because a preset the model |
| 251 | + can invent is a blast radius the model can invent: |
| 252 | + |
| 253 | + | Preset | For | Turn cap | |
| 254 | + | --- | --- | --- | |
| 255 | + | `explore` | finding things, and reporting paths and line numbers | 20 | |
| 256 | + | `plan` | working out how a change should be made, without making it | 30 | |
| 257 | + | `general` | a self-contained piece of work, edits and tests included | 40 | |
| 258 | + |
| 259 | + All three get the full tool set — read, glob, grep, edit, write, bash, skill — |
| 260 | + and none of them gets `spawn_agent`, so subagents cannot spawn subagents. |
| 261 | + |
| 262 | + **A preset pins no model and no effort level.** Both are arguments to |
| 263 | + `spawn_agent`, because what to spend is a judgement about the job and the agent |
| 264 | + holding the task is the one making it: `model` picks what runs it — a small |
| 265 | + fast model for mechanical search, a strong one for work that has to be right — |
| 266 | + and `effort` picks how hard it thinks, `low` through `max`. Omit either and it |
| 267 | + inherits the session's. A pinned id here would be a guess about someone else's |
| 268 | + endpoint as well as about the job: point the harness at a gateway that serves |
| 269 | + neither, and every spawn of that preset fails before its first turn. |
| 270 | + |
| 271 | + The models it may choose between are in its own system prompt: the harness asks |
| 272 | + the endpoint what it serves at startup — `GET /v1/models`, the same route the |
| 273 | + picker uses — and lists them newest first, with the rule that the newest is the |
| 274 | + one to reach for unless you asked for another or it has already failed this |
| 275 | + session. An endpoint that does not answer that route simply gets no listing, |
| 276 | + and the agent is told that naming no model runs the subagent on whatever the |
| 277 | + session is using. The list is read once, because it sits in the cached prefix |
| 278 | + and a prompt that changes mid-session throws the cache away. Subagents do not |
| 279 | + get this paragraph — they have no such choice to make. |
| 280 | + |
| 281 | + `output_config.effort` is a per-model capability, not a universal parameter. |
| 282 | + Haiku 4.5 rejects a request carrying it, and `xhigh` did not exist before Opus |
| 283 | + 4.7 — so a request for a level its model does not take goes out without it, |
| 284 | + rather than failing with a 400 that reads like a bug in the harness. Where that |
| 285 | + happens to a subagent the answer says so outright (`claude-haiku-4-5 takes no |
| 286 | + effort level, so "low" was not applied`) instead of letting the parent believe |
| 287 | + it got what it asked for, and the effort pill in the status line reads `not on |
| 288 | + Haiku` rather than claiming a setting that is not in force. |
| 289 | + |
| 290 | + A model this build has never heard of — a gateway serving something else, a |
| 291 | + family released after it — is treated the same way: the level is left off. The |
| 292 | + two mistakes are not symmetric. Sending effort to a model that lacks it is a |
| 293 | + 400 that ends the run before any work happens; omitting it costs the level and |
| 294 | + says so in the pill. Gateway decoration is seen past first, so |
| 295 | + `anthropic.claude-opus-5`, `openrouter/anthropic/claude-opus-5` and |
| 296 | + `claude-opus-5@20260401` are all recognised as the model they name — for |
| 297 | + pricing and for the thinking parameter too. |
| 298 | + |
| 299 | + Every spawn goes through the ordinary approval box, which shows the preset, the |
| 300 | + model and the task. It is not rememberable per task — the task text differs |
| 301 | + every time, so "always this exact one" would never match twice — but "always |
| 302 | + allow this tool" still applies, for anyone who has decided to trust spawning as |
| 303 | + such. A subagent's own tool calls go through the same policy, and the box says |
| 304 | + which agent is asking. |
| 305 | + |
| 306 | + Four run at once; further spawns queue. Two agents editing one file is not a |
| 307 | + special case: `edit_file` already refuses a file whose mtime moved since that |
| 308 | + agent read it, so the second one is told to read it again rather than |
| 309 | + clobbering the first. |
| 310 | + |
| 311 | + A report reaches the parent exactly once, whichever way it gets there. Both |
| 312 | + paths — `agent_wait` returning it as a tool result, and the front end putting |
| 313 | + it into the conversation as a message — claim it from the supervisor first, and |
| 314 | + only one claim wins. Without that, an agent that finished before its |
| 315 | + `agent_wait` call was even emitted was handed over twice: once as the result, |
| 316 | + once as a message a turn later, which is the context cost the whole feature |
| 317 | + exists to avoid. A wait that loses the claim answers with a line saying where |
| 318 | + to find the report instead of repeating it. |
| 319 | + |
| 320 | + **The report comes back on its own.** When a subagent finishes, its report is |
| 321 | + appended to the main conversation as a user message and the main agent starts a |
| 322 | + turn on it — you do not have to type anything. It is held back only while a |
| 323 | + turn is already running, while an approval is on screen, while a `!` or `$` |
| 324 | + command is running, or while you have text in the prompt box: a turn starting |
| 325 | + under your fingers would blur the input and eat what you were typing. It goes |
| 326 | + up the moment that clears. A failed or killed agent is reported the same way, |
| 327 | + so the parent is never left waiting on a result that is not coming. |
| 328 | + |
| 329 | + ### The agents sidebar |
| 330 | + |
| 331 | + `ctrl+b` opens a 30-column pane on the right and gives it the keyboard; the |
| 332 | + transcript reflows into what is left rather than being covered by it. |
| 333 | + |
| 334 | + Open and focused are separate things. The pane answers every key while it has |
| 335 | + focus — that is what lets `k` be a kill rather than a letter — so **click the |
| 336 | + prompt to type again**, and the pane stays where it is. Click a row to hand the |
| 337 | + keys back. `ctrl+b` always moves towards the pane: it opens a closed one, |
| 338 | + focuses an open one, and only closes a pane that already has the keys. Which |
| 339 | + one is live is visible in two places: the heading carries the accent and the |
| 340 | + prompt frame goes dim, or the other way round. |
| 341 | + |
| 342 | + ``` |
| 343 | + ⏺ Two of those are independent, so I will farm │ Agents 2 ⏵ |
| 344 | + them out. │ |
| 345 | + │ ❯ ✳ a1 plan $0.23 |
| 346 | + ⏺ SpawnAgent(preset=explore, task=…) │ Opus · 2m04s · 6 turns |
| 347 | + ⎿ started a2 (explore) on claude-haiku-4-5, s…│ ● a2 explore |
| 348 | + │ Haiku · waiting · 1 turn |
| 349 | + │ |
| 350 | + │ ↑↓ move · enter open |
| 351 | + ✢ Deliberating… (8s · turn 5 · esc to interrup…│ p pause · k kill · esc back |
| 352 | + ╭──────────────────────────────────────────────╮│ |
| 353 | + │ › ask for a change, /help, ! for a shell ││ |
| 354 | + ╰──────────────────────────────────────────────╯│ |
| 355 | + joni ✳ Opus 5 ⏵ 2 agents │ |
| 356 | + ⏵ approvals on (shift+tab to cycle) · ctrl+b a…│ |
| 357 | + ``` |
| 358 | + |
| 359 | + Each agent is two lines: the status glyph, the id and the preset, with the cost |
| 360 | + at the right, and under it the model, how long it has been going and how many |
| 361 | + turns it has taken. The model is the family alone — thirty columns will not |
| 362 | + hold `claude-haiku-4-5` as well as the numbers — and the full id is in the |
| 363 | + header of the thread, one keystroke away. |
| 364 | + |
| 365 | + | Key | Does | |
| 366 | + | --- | --- | |
| 367 | + | `↑`/`↓` | move | |
| 368 | + | `enter` | open that agent's thread in the main pane | |
| 369 | + | `esc` | back to your own thread; again to close the pane | |
| 370 | + | `p` | pause or resume | |
| 371 | + | `k` | stop it | |
| 372 | + | click the prompt | type again, leaving the pane open | |
| 373 | + |
| 374 | + The statuses are queued, running, waiting — blocked on an approval of yours — |
| 375 | + paused, done, failed and killed. Pause is checked between turns: the model call |
| 376 | + and the tool calls in flight finish, and it holds before the next request, so |
| 377 | + the conversation is never left with a `tool_use` whose `tool_result` never |
| 378 | + came. Kill cancels immediately, and what the agent already did to the tree |
| 379 | + stays done — this ends an agent, it does not undo one. |
| 380 | + |
| 381 | + Mouse reporting is on, so clicking the agents pill in the status line toggles |
| 382 | + the pane and clicking a row selects it. `/mouse` turns reporting off and on |
| 383 | + again, because while it is on the terminal's own text selection is not. |
| 384 | + |
| 385 | + A child's usage is priced at the child's model and rolled into the session |
| 386 | + total, so a haiku agent spawned from an opus session is not billed at opus |
| 387 | + rates. Every metrics event a child writes carries its agent id, so |
| 388 | + `.harness/events.jsonl` can be split per agent afterwards. |
| 389 | + |
| 390 | + Subagent transcripts last as long as the session does: `-resume` brings back |
| 391 | + your conversation, not theirs. |
| 392 | + |
| 393 | + Subagents belong to the TUI: their reports come back as messages the front end |
| 394 | + puts into the conversation, and the line-based REPL has nowhere to show four |
| 395 | + agents at once. `-p` and `-no-tui` runs are not offered the tools at all, and |
| 396 | + `-no-agents` turns them off for a TUI run too. |
| 397 | + |
| 235 | 398 | ## Setup |
| 236 | 399 | |
| 237 | 400 | The first run on a terminal opens a full-screen wizard instead of the chat: the |