live splits into Agents and Commanders, and the payload says which is which

A commander is a chat by every mechanism it uses, so it turned up in Live beside the conversations
somebody is actually having. With one deploy commander that is untidy. With a watcher armed per repo it
is a list where the thing you are looking for is outnumbered.

Two tabs inside Live, counts always shown. That last part differs from the badge on the Live tab above it,
which hides at zero because a standing `0` there says nothing. These two say a lot at zero:
`Commanders (0)` is how you find out the watcher is not running, which is usually why you looked.

The flag is derived server-side from the cwd, not from a `command_hq_sessions` lookup — every commander
shares one directory, so the directory IS the answer, it costs no query, and it is already right during a
commander's first turn, before any row exists.

It has to be in the payload rather than computed in the panel, and that is the point of the change: the
iPhone app swipes between LIVE chats and has no room for tabs. Filtering there needs the server to name
them. A deploy commander appearing in that swipe order is precisely what must not happen.

A commander row also now opens Command HQ instead of /chat. Same transcript either way, but /chat renders
it with nothing that makes it a commander legible — no category, no cost, no watcher state, and no way to
disarm it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-21 19:25:17 +00:00
co-authored by Claude Opus 5
parent 6dae3e7a14
commit ebfa09e067
5 changed files with 134 additions and 18 deletions
@@ -26,6 +26,14 @@ export type LiveSession = {
*/
title: string | null;
cwd: string | null;
/**
* A commander rather than an ordinary chat, derived server-side from the cwd.
*
* Every consumer of this list needs it, and one of them cannot work around its absence. The sessions
* panel splits Live into two tabs; the iPhone app swipes between live chats, has no tabs, and so can only
* keep a deploy commander out of that swipe order if the payload names it.
*/
isCommander: boolean;
};
const LIVE_KEY = 'CHAT_LIVE_SESSIONS';