kumo
Guides

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 idle

Lifecycle 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 signals
  • claude β€” approval forms, permission prompts, OSC-title spinner
  • codex Β· 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-detection

A 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, inside any-of or not

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):

MatcherMeaning
containsASCII case-insensitive substring
contains-anyfirst matching pattern of the list
prefixtrimmed text starts with (idle OSC title, e.g. ✳)
spinner"braille" / "half-circle" first glyph of the OSC title
spinner-lineshort line holding a dingbat glyph (working prompt box)
btw-overlaythe /btw reasoning overlay (header + esc to close)
yes-no-linea 1. yes / 2. no option line
braille-inany 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.

On this page