What happens
An agent that arms a monitor, backgrounds a shell or hands work to a cloud session is
told by its CLI to end the turn and wait to be notified. The pane falls quiet, and about
a minute later Claude Code's idle notification arrives. Codeman files that as an
approval item of kind idle, and the session joins the group Codeman calls NEEDS YOU:
the heading codeman tui prints, the Needs you section on the phone overview, and the
needs you pill on a rich sidebar row. Nothing there wants anything from me. I open the
tab, read the last message, find an agent waiting for a sleep to finish, and close it
again.
Any long wait ends a turn this way — a build, a CI run, a log tail — so those rows sit
in NEEDS YOU for as long as the work runs.
Measured
Today, on a beta instance running master (1.32.0 source) so it could not touch my live
sessions. I asked a session to arm one monitor and end its turn:
curl -s -X POST http://127.0.0.1:5000/api/v1/sessions/$SID/input \
-d '{"input":"Call the Monitor tool once with command \"sleep 600\" … then end your turn.\r","useMux":true}'
| source |
what it said |
| the pane's last row |
⏵⏵ bypass permissions on · 1 monitor · ← for agents |
GET /api/sessions |
status: "idle", isWorking: false, nothing further |
| the session's row in the UI |
the yellow waiting pill, which is the NEEDS YOU tier |
Killing the monitor's own process made the CLI wake, take a turn and drop the chip from
its footer. So the CLI states the difference on screen the whole time, and Codeman reads
past it.
Why it happens
Codeman's session model has idle | busy | stopped | error and nothing between them.
The pane probe reads one thing off the screen, the working line
(_probePaneWorking, src/session.ts), which answers whether a turn is running. Both
classifiers then put any pending approval, kind idle included, in the tier that means
a human is needed: classifySession at src/tui/tui-model.ts:78 and
_mobileOverviewState at src/web/public/mobile-overview.js:104.
So a quiet pane has one meaning inside Codeman, and the CLI has two meanings for it. The
last row of the screen is where Claude Code says which one this is, and it names the kind
and the count: 1 monitor, 2 shells, 1 cloud session, 4 background tasks.
Why it matters
- NEEDS YOU is the group I act on, and entries that need nothing are what teach me to
stop trusting it.
- The Approvals Inbox counts those rows as pending items when it is on, so its bell
carries a number that overstates what is waiting.
- Anything reading
/api/sessions inherits the blind spot. My own board tool files the
same sessions as waiting on me, because Codeman is where it gets its facts.
What I have built, and did not send
I have this working on a branch and I have not opened a PR, because CONTRIBUTING asks
for a nod on anything bigger than a small fix. It is one commit, the gate is green, and
I verified it end to end on the beta instance above. Its shape:
- The CLI registry carries the footer row as an optional
capabilities.workDetect.watchingLine, beside the workingLine it already holds, and
it goes through compileVersionRegex() like every other regex that comes from config.
_confirmIdle() already captures the pane at the moment a turn ends. That same capture
now also yields the label, through a pure helper in session-activity.ts that searches
the last few lines only, so a session that prints the words "1 monitor" is not read as
running one.
- The label lands on
Session.watching and rides toLightDetailedState() out to every
session payload.
- The phone overview, the desktop home rail and the rich sidebar rows wear it as a
watching badge in the accent colour, beside the state pill rather than instead of it.
- Tests cover the pattern against verbatim pane captures, the session field through a
real idle transition, and each surface's row model.
Questions before I send anything
- The screen, or a hook? A
PostToolUse matcher on Monitor would report the
arming precisely, with the description and the timeout, but Claude Code fires nothing
when a monitor ends, so the end has to be inferred. The footer row is right in both
directions and covers backgrounded shells and cloud sessions as well. It also couples
to a CLI's UI string, which is what the registry exists to hold, so I read it as the
registry's kind of problem rather than a new one. Do you agree?
- A badge, or a state of its own? I kept the state pill deciding the group, because
an agent can arm a monitor and ask me a question in the same breath, and only the pill
knows which. A fifth state would be tidier and would get that case wrong.
- Should the idle alert stand down while a session is watching? That is the deeper
version of this fix and it touches the Approvals Inbox rather than the pane probe. I
have not written it, and I would rather ask than assume.
- Which surfaces? The badge shows where a state pill already shows. The header tab
strip and the plain sidebar have no pill at all, and codeman tui rows have their own
vocabulary. Say the word and I will cover either.
- What shape on the wire? Today
watching is the CLI's own words as a string. A
{ kind, count } object would survive a CLI rewording its footer, at the cost of a
mapping table per CLI.
Environment
- Ubuntu 22.04.5 on WSL2, Node 22.22.3, tmux 3.2a
- Codeman 1.30.0 installed with
install.sh into ~/.codeman/app; measured above on
master at 1.32.0
- Claude Code 2.1.278, browser Firefox
What happens
An agent that arms a monitor, backgrounds a shell or hands work to a cloud session is
told by its CLI to end the turn and wait to be notified. The pane falls quiet, and about
a minute later Claude Code's idle notification arrives. Codeman files that as an
approval item of kind
idle, and the session joins the group Codeman calls NEEDS YOU:the heading
codeman tuiprints, theNeeds yousection on the phone overview, and theneeds youpill on a rich sidebar row. Nothing there wants anything from me. I open thetab, read the last message, find an agent waiting for a
sleepto finish, and close itagain.
Any long wait ends a turn this way — a build, a CI run, a log tail — so those rows sit
in NEEDS YOU for as long as the work runs.
Measured
Today, on a beta instance running master (1.32.0 source) so it could not touch my live
sessions. I asked a session to arm one monitor and end its turn:
⏵⏵ bypass permissions on · 1 monitor · ← for agentsGET /api/sessionsstatus: "idle",isWorking: false, nothing furtherwaitingpill, which is the NEEDS YOU tierKilling the monitor's own process made the CLI wake, take a turn and drop the chip from
its footer. So the CLI states the difference on screen the whole time, and Codeman reads
past it.
Why it happens
Codeman's session model has
idle | busy | stopped | errorand nothing between them.The pane probe reads one thing off the screen, the working line
(
_probePaneWorking,src/session.ts), which answers whether a turn is running. Bothclassifiers then put any pending approval, kind
idleincluded, in the tier that meansa human is needed:
classifySessionatsrc/tui/tui-model.ts:78and_mobileOverviewStateatsrc/web/public/mobile-overview.js:104.So a quiet pane has one meaning inside Codeman, and the CLI has two meanings for it. The
last row of the screen is where Claude Code says which one this is, and it names the kind
and the count:
1 monitor,2 shells,1 cloud session,4 background tasks.Why it matters
stop trusting it.
carries a number that overstates what is waiting.
/api/sessionsinherits the blind spot. My own board tool files thesame sessions as waiting on me, because Codeman is where it gets its facts.
What I have built, and did not send
I have this working on a branch and I have not opened a PR, because CONTRIBUTING asks
for a nod on anything bigger than a small fix. It is one commit, the gate is green, and
I verified it end to end on the beta instance above. Its shape:
capabilities.workDetect.watchingLine, beside theworkingLineit already holds, andit goes through
compileVersionRegex()like every other regex that comes from config._confirmIdle()already captures the pane at the moment a turn ends. That same capturenow also yields the label, through a pure helper in
session-activity.tsthat searchesthe last few lines only, so a session that prints the words "1 monitor" is not read as
running one.
Session.watchingand ridestoLightDetailedState()out to everysession payload.
watchingbadge in the accent colour, beside the state pill rather than instead of it.real idle transition, and each surface's row model.
Questions before I send anything
PostToolUsematcher onMonitorwould report thearming precisely, with the description and the timeout, but Claude Code fires nothing
when a monitor ends, so the end has to be inferred. The footer row is right in both
directions and covers backgrounded shells and cloud sessions as well. It also couples
to a CLI's UI string, which is what the registry exists to hold, so I read it as the
registry's kind of problem rather than a new one. Do you agree?
an agent can arm a monitor and ask me a question in the same breath, and only the pill
knows which. A fifth state would be tidier and would get that case wrong.
version of this fix and it touches the Approvals Inbox rather than the pane probe. I
have not written it, and I would rather ask than assume.
strip and the plain sidebar have no pill at all, and
codeman tuirows have their ownvocabulary. Say the word and I will cover either.
watchingis the CLI's own words as a string. A{ kind, count }object would survive a CLI rewording its footer, at the cost of amapping table per CLI.
Environment
install.shinto~/.codeman/app; measured above onmaster at 1.32.0