Desired UX
For a project running an agent in the main pane:
- while the agent is coding / executing / waiting on subagents or tools: show the running spinner next to the project name,
- when the agent returns to the command input prompt and is no longer working: show the green checkmark (
done) until the user acknowledges it by visiting the window,
- after acknowledgement, clear back to idle.
Concrete current case:
- Project:
nomadamas-code
- Window:
nmux-linux:3
- Main pane:
%277, title π: nomadamas-code
- Main pane process tree contains:
gjc --resume 019f4e18-3b38-7000-87e7-e18fccd4570a
During inspection the pane was not at a finished command prompt; it was actively waiting on an architect subagent:
Await Architect pass-2 review.
A 3-second sample showed the gjc process burning CPU:
gjc delta after 3s: 93 ticks
So this should be classified as running, not idle.
Why it does not work today
There are two separate problems.
1. gjc is not registered as an agent binary
The watcher status pipeline is gated by AGENT_BINS:
const AGENT_BINS = new Set(['claude', 'codex', 'omx', 'gemini', 'aider', 'continue', 'cursor']);
Because gjc is absent, the watcher sees the main pane process tree but classifies it as having no agent:
PANE %277 root 3565692 title π: nomadamas-code detected_agents []
gjc_desc [('1302720', 'gjc --resume 019f4e18-3b38-7000-87e7-e18fccd4570a')]
Once agents=[], the watcher does not sample gjc CPU as agent work and also skips PTY/output activity attribution, because the PTY path is guarded by if (agents.length).
Result: @nmuxlinux_status=running is never refreshed for gjc, and the sidebar shows idle.
This overlaps with issue #23, but it is only the first layer.
2. The current state machine detects activity, not "returned to command prompt"
Even after adding gjc to AGENT_BINS, the current watcher cannot reliably implement the desired UX because it does not know whether the agent has returned to its command prompt.
Current watcher semantics are heuristic:
// active if CPU delta on any known agent pid >= CPU_ACTIVE_THRESHOLD
// OR pane PTY mtime advanced this tick
const CPU_ACTIVE_THRESHOLD = 60;
const QUIET_TICKS_TO_DONE = 4; // about 12 seconds
Then:
if (active) {
setWindowStatus(target, 'running', ...);
} else if (curStatus === 'running' && quietTicks >= QUIET_TICKS_TO_DONE) {
setWindowStatus(target, 'done', ...);
}
That means done currently means "the watcher saw no attributed CPU/output for about 12 seconds after a previous running state." It does not mean "the agent returned to the command input prompt."
This distinction matters:
- A long model call can be genuinely running but produce no PTY output for more than 12 seconds.
- A tool/subagent await can be genuinely running with intermittent output or CPU.
- A daemon-like agent can stay alive after returning to prompt.
- A process can be quiet for reasons unrelated to completion.
- If the row is already
idle because the agent was never recognized, the quiet path does not promote it to done; it only transitions running -> done.
So the desired transition is prompt-state based, but the implementation is silence/activity based.
Hook/integration gap
nmux-linux has a hook-based path for some tools:
nmux-linux notify-current --status running|done|failed|need-input
The Claude hook installer currently wires:
UserPromptSubmit -> running
Notification -> need-input
SubagentStop -> done
Stop -> done
But there is no equivalent gjc integration that emits:
- work started / prompt submitted ->
running,
- command finished and prompt is back ->
done,
- user input needed ->
need-input,
- failure ->
failed.
Without either native gjc hooks or a prompt-state detector, nmux-linux can only infer status from CPU and PTY quietness.
Expected behavior
For gjc in the main pane:
- When the user submits a prompt or
gjc starts executing work, project status becomes running.
- While
gjc is actively working, awaiting a subagent, awaiting a tool, or streaming output, status stays running.
- When
gjc returns to its command input prompt (Type your message...) and no work is in flight, status becomes done.
- Visiting the project window acknowledges the checkmark and clears status back to
idle.
- Sub panes do not need to drive this indicator.
Suggested implementation direction
Implement this as a real agent-state integration, not only as a process-existence check.
Minimum fixes:
- Add
gjc to the shared agent binary registry so watcher attribution works:
const AGENT_BINS = new Set(['gjc', 'claude', 'codex', 'omx', 'gemini', 'aider', 'continue', 'cursor']);
- Add a
gjc-specific completion signal or prompt-state detector. Possible approaches:
- preferred: wire
gjc lifecycle hooks, if available, to call nmux-linux notify-current,
- alternatively: detect the main pane prompt state from pane content, e.g. visible
Type your message... with no active task/subagent markers,
- alternatively: support an explicit
gjc status file/socket/event stream if GJC exposes one.
- Keep CPU/PTY watcher as a fallback, but do not treat quietness as equivalent to prompt-ready completion when a stronger agent signal exists.
Acceptance criteria
- Main-pane
gjc / gjc --resume <id> is recognized as an agent.
- While
gjc is awaiting subagents/tools or otherwise executing, sidebar shows the running spinner.
- When
gjc returns to command input prompt, sidebar shows done / green checkmark.
- Visiting the window clears the checkmark back to idle.
- A long silent model call does not falsely become
done merely because there was no PTY output for 12 seconds.
- Sub panes do not drive this status.
- Existing stale-running protection remains intact for crashed watcher / abandoned tmux options.
Desired UX
For a project running an agent in the main pane:
done) until the user acknowledges it by visiting the window,Concrete current case:
nomadamas-codenmux-linux:3%277, titleπ: nomadamas-codeDuring inspection the pane was not at a finished command prompt; it was actively waiting on an architect subagent:
A 3-second sample showed the
gjcprocess burning CPU:So this should be classified as
running, notidle.Why it does not work today
There are two separate problems.
1.
gjcis not registered as an agent binaryThe watcher status pipeline is gated by
AGENT_BINS:Because
gjcis absent, the watcher sees the main pane process tree but classifies it as having no agent:Once
agents=[], the watcher does not samplegjcCPU as agent work and also skips PTY/output activity attribution, because the PTY path is guarded byif (agents.length).Result:
@nmuxlinux_status=runningis never refreshed forgjc, and the sidebar shows idle.This overlaps with issue #23, but it is only the first layer.
2. The current state machine detects activity, not "returned to command prompt"
Even after adding
gjctoAGENT_BINS, the current watcher cannot reliably implement the desired UX because it does not know whether the agent has returned to its command prompt.Current watcher semantics are heuristic:
Then:
That means
donecurrently means "the watcher saw no attributed CPU/output for about 12 seconds after a previous running state." It does not mean "the agent returned to the command input prompt."This distinction matters:
idlebecause the agent was never recognized, the quiet path does not promote it todone; it only transitionsrunning -> done.So the desired transition is prompt-state based, but the implementation is silence/activity based.
Hook/integration gap
nmux-linuxhas a hook-based path for some tools:The Claude hook installer currently wires:
But there is no equivalent
gjcintegration that emits:running,done,need-input,failed.Without either native
gjchooks or a prompt-state detector,nmux-linuxcan only infer status from CPU and PTY quietness.Expected behavior
For
gjcin the main pane:gjcstarts executing work, project status becomesrunning.gjcis actively working, awaiting a subagent, awaiting a tool, or streaming output, status staysrunning.gjcreturns to its command input prompt (Type your message...) and no work is in flight, status becomesdone.idle.Suggested implementation direction
Implement this as a real agent-state integration, not only as a process-existence check.
Minimum fixes:
gjcto the shared agent binary registry so watcher attribution works:gjc-specific completion signal or prompt-state detector. Possible approaches:gjclifecycle hooks, if available, to callnmux-linux notify-current,Type your message...with no active task/subagent markers,gjcstatus file/socket/event stream if GJC exposes one.Acceptance criteria
gjc/gjc --resume <id>is recognized as an agent.gjcis awaiting subagents/tools or otherwise executing, sidebar shows the running spinner.gjcreturns to command input prompt, sidebar showsdone/ green checkmark.donemerely because there was no PTY output for 12 seconds.