Status and triage
Sessions classify themselves from their own output. Nothing is configured, no wrapper script is installed, and the shell is a normal shell — Saggar reads the same things you would read if you were looking at it, which is the only reason it works on the agent you started by hand.
The four bands
| Status | Means |
|---|---|
| Needs you | An agent is blocked on a question, or the shell rang a bell. This is the only state that wants a human, and it is the one the menu, the dock badge, the notifications, and the remote companion are all built around. |
| Working | Output is moving. Nothing to do. |
| Idle | A prompt is sitting there, quiet. Often an agent that stopped short and would carry on if nudged. |
| Finished | The command exited. A non-zero code says so, and reads as failed rather than done. |
What it reads
Six signals feed the classifier, and no single one of them is trusted alone:
| Signal | Source | Feeds |
|---|---|---|
| Interaction cues | a scan of the transcript tail | needs you |
| Output activity | the pty's own data callback, not polling | working / idle |
| Bell |
| needs you |
| Exit code | process termination | finished / failed |
| Terminal title | what the agent writes there | session name |
| Process tree | a walk of the shell's children | agent presence |
The cue vocabulary is deliberately verb-agnostic — any Do you want to… or Would you like to… counts — so every flavor of approval prompt is caught rather than the three or four somebody remembered to enumerate. A bell-raised needs-you clears itself when output resumes or you type.
Where an agent handshake is installed, it outranks all of this: a permission prompt raises needs you by contract, with no transcript scan involved.
How it asks for you
Everything above would be worth little if it only tinted a dot. Status drives five surfaces:
- The menu
A dot per session, and a rollup per project — a folded project shows the tally of what is inside it.
- The attention cards
Blocked sessions stack over the menu's bottom-left corner. The top card shows the waiting question with the prompt's own options as buttons, so it can be answered without opening the terminal at all; the cards behind peek out with the queue depth. The dock icon badges with the same count.
- Sounds
Each state change speaks in its own voice — one tone for a new waiter, another for a failed exit, another for a clean finish. One tone per beat, loudest wins, so several sessions turning at once never stack into noise. And it reads the room: a cue that lands while you are mid-keystroke in another session is held and delivered as a single catch-up once you pause. A decision request should never yank you out of thought.
- Notifications
A Notification Center banner posts when Saggar isn't the app you are looking at — a session waiting on you, or a shell that just finished or failed. Tap it to raise Saggar on that terminal. On by default, suppressed while Saggar is frontmost, because the menu already told you. A waiting prompt is not a one-shot edge, so it is handled separately from an exit: the reminder fires when Saggar stops being frontmost and nudges again on an interval while a prompt keeps sitting unseen. Leaving the app is exactly what surfaces the waiter.
- Your phone
The same events, over remote control, if you have armed it.
Triage — ⌘J
One key walks every terminal with a claim on you, loudest first. The order is fixed, and it is the app's opinion about what a claim actually is:
- Blocked on a prompt
- Failed
- Finished with uncommitted work
- Finished clean
Within a class, longest-waiting first. Each press selects the next stop, raising its window if it has been popped out. With nothing left waiting, the key lands on a quiet 0 waiting card instead — the app's whole question answered with no one, which is a better end to the walk than the key going dead.
⌘↩ answers the terminal in front of you:
it types a waiting prompt's default answer, or marks a bell-only
needs-you as seen, and falls through to the shell whenever there is
nothing to answer. The palette has bulk versions of the same idea —
accept every waiting prompt, tell every idle agent to continue, close
all the idle ones.