MadoHub Docs

Agent Detection

How MadoHub identifies which AI agent is running and tracks its state.

MadoHub monitors terminal output in real-time to detect which AI agent is running and what state it's in. This powers the visual indicators on tile title bars and triggers routing connections.

Supported agents

Claude Code

Detected by Unicode markers in terminal output:

MarkerMeaning
❯ (U+2770)Claude Code prompt
✽ (U+273D)Thinking/spinner
⏺ (U+23FA)Tool use indicator

Also matches the literal string "Claude Code" in output.

OpenAI Codex CLI

Detected by these patterns:

  • OpenAI Codex — Branding line
  • codex> — TUI prompt
  • openai/codex — Package reference
  • codex v[0-9] — Version string
  • > _ OpenAI Codex — Startup banner
  • codex --dangerously — Sandbox-bypass flag (case-insensitive)
  • codex ... fast — Fast-model invocation (case-insensitive)
  • gpt-[0-9.]+ x?high — Model info

Amp and OpenCode

Amp and OpenCode are also recognized as agent kinds, but not by the frontend terminal-text sniffer above — it only classifies Claude Code, Codex, and generic shell. Amp and OpenCode sessions are identified separately, by a backend process-tree scan that walks the terminal's descendant processes looking for their executables.

Generic shell

If no agent markers are detected, the terminal is treated as a standard shell session.

Agent states

MadoHub tracks seven states for each terminal:

StateDetectionVisual
Working"esc to interrupt" in status bar, or ✽/⏺ with ellipsisGreen pulsing border
Idle"? for shortcuts" in status barNo indicator
Waiting"Allow once" / "Allow always" / "Deny" / "Do you want to proceed?" / "(y/n)" / "requires approval" dialogsOrange border
StoppedCompletion keyword detected via terminal scraping (ambiguous — task may have finished successfully or not)Red indicator
CompletedConfirmed successful finish, parsed from the agent's JSONL/DB session log (e.g. Codex task_complete)Green indicator
FailedConfirmed failure, parsed from the agent's JSONL/DB session log (e.g. Codex turn_aborted / error)Red indicator
ExitedThe underlying PTY process is gone (terminal state)Gray/dim indicator

Each state carries a stateSource tag of either pty-scrape or jsonl-watcher, so the UI (and any routing logic) can tell a live terminal-scraping guess apart from a verdict confirmed by reading the agent's own session transcript. "Stopped" is always pty-scrape and inherently ambiguous; "Completed" and "Failed" come from jsonl-watcher and are treated as authoritative.

Completion detection

MadoHub detects when an agent finishes a task by matching a shape, not a fixed word list: a line-start spinner glyph, followed by a capitalized past-tense verb, followed by " for " and a duration.

The regex pattern:

/(?:^\s*[✶✽✳✢·∗*]\s*([A-Z][a-zé]+(?:ed|t))|\b(Saut[ée]*d|Cogitated))\s+for\s+(?:\d+\s*[hm]\s*)*\d+\s*[hms]\b/

Claude Code rotates the verb across releases (Worked, Churned, Sautéed, Cogitated, and others), so the verb itself is deliberately not enumerable — matching relies on the shape instead. A realistic match looks like:

✽ Worked for 2m 30s

The line-start glyph anchor (one of ✶✽✳✢·∗*) is what prevents false positives from ordinary prose such as "Retried for 3s". Sautéed and Cogitated survive in the pattern only as a glyph-less legacy fallback for older CLI output that predates the glyph-anchored format.

When a completion is detected, the agent state changes to "stopped" and any connected routing triggers may fire.

On this page