// guides

Live status for every AI agent session with lifecycle hooks

· 6 min read

Run more than two or three agent sessions at once and they turn opaque. Each terminal looks busy, but “busy” hides the difference between an agent grinding through a task and an agent that has been sitting on a question for ten minutes. So you do one of two bad things: alt-tab through every window on a loop, or miss the exact moment a session got blocked and wonder later why nothing moved.

The fix is not more discipline. It is a status signal that comes from the agents themselves, collected into one place you can watch. This post covers where that signal comes from, the one command that wires it up, and the two ways to consume it — a live table for you and a JSON feed for your scripts.

Four states, straight from the agent

Every session sits in one of four states: working, needs-input, done, or error. The important detail is where those come from. They are not scraped off the screen by watching the terminal for prompts — screen-scraping is fragile and lies the moment an agent’s output format shifts. Instead they come from the agents’ own lifecycle hooks: the events Claude Code and Codex already emit as they start work, pause for input, finish, or fail.

That makes the state authoritative. When a session reports needs-input, it is because the agent itself said it is waiting on you — not because a heuristic guessed from the last line of text. And it means the same four states mean the same thing in both tools, so a mixed fleet reads as one board instead of two dialects.

One command to wire the hooks

You do not configure each tool’s hooks by hand. mAgent (installed as magent) ships a setup step that wires the lifecycle hooks into Claude Code and hands you the one-line Codex recipe, in one shot:

magent hooks install

It is idempotent and leaves your existing hooks alone. Restart your agents after it runs so they pick up the new hooks. From then on, each session reports its own state changes as they happen — no polling, no scraping, no per-project config to maintain.

The live table

With the hooks in place, magent watch renders every session in one table, sorted most-urgent first so the sessions that need you float to the top:

$ magent watch
#  project   tool     state
1  web       claude   needs-input
2  infra     codex    error
3  api       claude   working
4  worker    codex    done

The ordering is the point. You never scan the whole list — a needs-input or error row is always at the top, and a screen full of working means there is genuinely nothing for you to do. On Windows, pressing a row number jumps focus straight to that window, so acting on a blocked session is one keystroke, not a hunt through tiled terminals.

The other two states change your review rhythm just as much. A cluster of done rows is a signal to batch your diff reviews instead of interrupting yourself the instant each task finishes, and an error row that appears while you are heads-down on another window is the one thing you genuinely cannot afford to miss. Because the table encodes all four states rather than a binary busy/idle, it tells you not just that something changed but which kind of attention it wants.

On Windows you can skip the table entirely. Run pip install magent-multi-ai-agents-manager[toast] and mAgent raises a desktop toast the moment any session flips to needs-input. Leave watch closed, keep working in another app, and let the notification pull you back only when an agent is actually stuck.

Status for scripts and CI

The same signal is available as data. magent status --json prints the current state of every session in machine-readable form, and the command sets its exit code from the health of the fleet: 0 when everything is healthy, 3 when something is degraded. That pair — structured output plus a meaningful exit code — is enough to gate on:

# machine-readable snapshot of every session
magent status --json

# the exit code alone is enough to gate on
magent status || echo "fleet degraded (exit $?)"

Because the exit code carries the verdict on its own, the simplest use needs no JSON parsing at all — magent status in a script either passes or trips the degraded code, and you branch on that. When you do want detail, the JSON gives you per-session state to filter however you like.

Where this fits, and how to get set up

Live status is the connective tissue for the rest of a many-session setup. It is what makes running multiple Claude Code sessions in parallel sustainable instead of chaotic, and it is the signal that tells you to reach for your phone when you are away from the desk — see controlling your AI coding agents from your phone for how a needs-input state turns into a notification you can act on remotely.

The full walkthrough — installing magent, running the hook setup, and checking everything with magent doctor — is in the install guide. Once the hooks are wired, the table stops being a thing you build and starts being a thing you glance at. After a reboot, the same setup lets you resume a Claude Code session after a restart in every project at once, with the status table back as soon as the agents are up.

get mAgent — 2 min install ← all postsread as markdown