AI Agents
AI CLI panes, status detection, toasts, and audible alerts.
Kumo auto-detects any AI CLI running inside a pane and lists it in the sidebar's AGENTS tab with its workspace and CLI name.
New: orchestration primitives
Kumo 0.7.0 adds server-owned waits β kumo agent wait, agent prompt --wait, agent read, and pane wait-output β so agents (and you) can drive any pane and wait for the result without polling. See the full Orchestration guide for the ADE primitives, dev-server/test-suite patterns, and the AI skill prompt.
Spawning an agent
leader+a spawns a dedicated AI pane running your configured CLI
(ai-cmd, default opencode). Or just run opencode, claude, codex, β¦
inside any shell pane β kumo detects the process automatically.
Status at a glance
Each agent shows a status dot, detected from the live terminal buffer (not just the viewport), so it stays accurate even while you scroll:
- π΅ Blue β working (actively producing output)
- π Orange β blocked, waiting for your approval
- βͺ Gray β idle (quiet, ready)
- π’ Green β done (finished while you weren't looking; focusing the pane marks it seen β idle)
- β Dim β unknown (recognized agent whose classification failed β idle was not proven)
The full five-state model is working Β· blocked Β· idle Β· done Β· unknown. done is the same transition that fires the corner toast on workingβidle while unfocused; unknown means the daemon saw the agent process but no idle/working/blocked signal matched. Both are first-class wait targets: kumo agent wait -p 42 --until done.
When an agent blocks or finishes, kumo raises a transient toast in
the corner of every attached viewer (click it to jump to the agent's pane)
and plays an audible chime β a distinct sound per event. Blocked agents also
float to the top of the AGENTS list with a filled β dot and a Β· blocked
hint, and their pane glows orange even without focus.
Agent inbox
leader+i moves the keyboard into the agent panel. j/k (or the
arrows) move between the agents that need attention β blocked Β· done Β·
running β and Enter jumps straight to the chosen pane (switching
session and tab as needed). Esc or q leaves the inbox.
The sidebar defaults to the project layout: a single projects list with
β find at the top. Each worktree shows its session name with the AI status
dot on the left (where βΈ used to be) and branch dimmed underneath. The
active worktree is expanded β branch + every agent underneath, all sharing a
subtle block highlight β while inactive worktrees stay minimized to one line.
Hover a worktree for a faint highlight; the focused agent gets a slightly
brighter agent block so you always know where the cursor is. Drag the
right-edge separator to resize the sidebar (20β50 cols, live, kumo reload
honors width).
Press leader+f (or click β find) to open the workspace finder
β a centered palette over sessions + tabs, contains filtered, starts_with
ranked, Enter jumps (SessionFocus/TabFocus). The finder lives on the
project layout; in other layouts leader+f is still bindable via
workspace-finder. The classic layouts remain one config line away:
[sidebar]
layout = "project" # project | divided | tabs β explorer/navigator alias project
width = 28 # only for project, draggable live 20..50[notifications]
position = "top-right" # top-left | bottom-right | bottom-left | center | off
sound = true # audible chime on blocked/finished transitions
blocked = true # toast when an agent blocks
finished = true # toast when an agent finishes / goes idleLifecycle detection
Process detection (name + workspace) works for every agent below; lifecycle detection (working / blocked / idle) is per-agent:
Bundled lifecycle rules
opencodeβ permission dialogs, question prompt, prompt-footer signalsclaudeβ approval forms, permission prompts, OSC-title spinnercodexΒ·geminiΒ·qwenΒ·aiderΒ·codyΒ·sweΒ·coco
When none of an agent's explicit markers match, it reads unknown, never a
fabricated idle state. Use kumo agent explain and a user override to tune a
CLI version whose terminal chrome has changed.
Custom detection rules (agent-detection/<agent>.toml)
The lifecycle classifiers are data-driven (0.7.0): kumo ships rule
manifests for every supported agent above (built into the binary), and reads
per-agent overrides from your config dir:
~/.config/kumo/agent-detection/<agent>.toml # $KUMO_CONFIG_DIR/agent-detectionA file for an agent kumo already knows replaces its bundled rules; a file
for any other agent id adds it. Rules load at daemon start and are re-read
automatically when the file changes (or explicitly with kumo reload). Invalid
files (bad id charset, unknown region, test with
more than one matcher) are warned about and skipped β detection never crashes
and keeps the bundled defaults.
# ~/.config/kumo/agent-detection/my-agent.toml
[agent]
id = "my-agent" # [a-z0-9-]+ β must match the filename stem
[[blocked]]
tests = [
{ region = "screen", contains = "do you want to proceed?" },
{ region = "form", yes-no-line = true },
]
[[working]]
tests = [{ region = "title", spinner = "braille" }]
[[idle]]
tests = [{ region = "screen", contains = "ask anything" }]A signal is an OR of [[signal]] groups; a group is an AND of its tests.
Tests may nest:
any-of = [...]β at least one branch matches (branches may be nested groups)not = [...]β succeeds when the AND of the listed entries does not match (used to keep a question dialog from reading as idle)tests = [...]β a nested AND group, insideany-ofornot
Each leaf test binds one matcher to one evidence region β screen (buffer
tail), form (below the last rule), footer (pinned prompt footer), title
(OSC window title):
| Matcher | Meaning |
|---|---|
contains | ASCII case-insensitive substring |
contains-any | first matching pattern of the list |
prefix | trimmed text starts with (idle OSC title, e.g. β³) |
spinner | "braille" / "half-circle" first glyph of the OSC title |
spinner-line | short line holding a dingbat glyph (working prompt box) |
btw-overlay | the /btw reasoning overlay (header + esc to close) |
yes-no-line | a 1. yes / 2. no option line |
braille-in | any braille glyph in the region |
Adding a new agent: run it in a pane, watch the markers via
kumo agent explain <pane>, write the file, then kumo reload until the
status is right β exactly what we did for the built-ins
(app/kumo/src/daemon/agents/rules/).
Agents live in the daemon
Lifecycle detection, status, and audible alerts run server-side, so they are
visible in the sidebar of any attached terminal β and kumo agent status
(list / ls) surfaces each agent's status and pane id from outside the
TUI, so a blocked agent is noticeable even when you are not attached.
Orchestration: wait, prompt, read, broadcast
Agents (and you) can drive any pane over the same socket the TUI uses β no polling, pinned to the pane's OS pid, with bracketed-paste-aware injection. The primitives are agent wait --until, agent prompt [--wait], agent read --source, pane wait-output --regex, agent start/rename/broadcast. For the complete reference, recipes (dev server, verify loop, agent-to-agent handoff, parallel workers), error codes, and the copy-paste skill prompt for AIs running inside kumo, see the Orchestration guide.
kumo agent wait -p 42 --until idle --timeout 30s
kumo agent prompt -p 42 "fix the test" --wait idle
kumo agent read -p 42 --source recent
kumo pane wait-output -p 12 --regex "passed|failed"Debugging status: kumo agent explain
Detection is heuristic, so kumo can explain on demand why any pane reads the status it does β evaluated live by the running daemon against the pane's terminal buffer:
kumo agent status # who runs, and where (e.g. pane 42 Β· work:t1:p2)
kumo pane list # every pane id + s/t/p position (optional -t filter)
kumo agent explain 42 # or by position: s1:t2:p1, work:t2:p1 (with -s: t2:p1)Both the id and the composite position ([s:]t[:p], 1-based) are accepted β
positions are friendly for interactive use, ids stay stable for scripts.
The cpu/mem line covers the agent's whole process tree (children
included) with CPU measured over a sliding ~6 s window, so a bursty agent
reads a truthful average instead of flat 0%.
The report shows the matched markers for every agent with rules (bundled
or your own) and the evidence region where each was found β screen
(buffer tail), form (below the last rule β Claude's live prompt), footer
(opencode's prompt footer), or title (OSC window title) β the
precedence that decided the winner (blocked > working > idle > unknown),
and the reason chain behind an idle verdict: explicit idle markers,
unseen-finish hold (done until focused), seen-after-focus, dead pane, the
not-an-AI-CLI default, or the no-signal fallback (unknown). Raw vs.
displayed status differ when the done/seen rule is active, which the report
makes explicit.