031. The Claude pid file names the wait and a background shell
- Date
- 2026-10-30
- Agents
- Claude Code
- Measured on
- real machine
Measured
2026-10-30, Claude Code 2.1.314 with --model haiku, on Linux (Debian 13,
x64), in a private tmux server with a throwaway HOME and a copied login.
The scenarios scenarios/claude/dialog-states.sh (three runs) and
scenarios/claude/plan-and-resume.sh (one run) read
~/.claude/sessions/<pid>.json every 1 s while each wait lasted. They
kept one copy of the file for each status and recorded every hook payload.
Measured on: real machine.
What was measured
-
The
statusfield and awaitingForfield had these values:Wait statuswaitingForThe input box waits for a prompt idlenot in the file A turn runs busynot in the file A question from the agent ( AskUserQuestion)waitinginput neededA Bash command dialog waitingpermission promptA plan approval ( ExitPlanMode)waitingpermission promptThe turn ended, and a background shell runs shellnot in the file statusstayedwaitingfor each read of the wait: 10 reads in 10 s for each dialog. ThewaitingForfield is in the file only whilestatusiswaiting. -
The prompt "Run the command sleep 30 with your Bash tool in the background ..." gave this order of
statusvalues, read every 1 s:busyfor 2 to 4 s,shellfor 26 to 27 s,busyfor 2 s, thenidle. This order was the same in the three runs. Withsleep 3,shelllasted 1 to 2 s. Soshellmeans: no turn runs, and a background shell of the session still runs. This explains theshellvalue of fact 023. -
When the background shell ends, Claude Code starts a new turn by itself. That is the second
busy. The hooks for that turn areUserPromptSubmit, whosepromptstarts with<task-notification>, and thenStop. No key was sent for that turn. -
The
Stoppayload has abackground_taskslist. At the end of the turn that started the shell, it had one item with the keysid,type(shell),status(running),descriptionandcommand. Theidis thebackgroundTaskIdof thePostToolUsetool_responseof that Bash call. At the end of the turn that the task notification started, the list was empty.Stopalso hassession_crons(an empty list in each run) andstop_hook_active(false). -
After "1." on the plan approval,
statuswaswaitingfor one more read (1 s), thenbusy, thenidle. -
The other fields of the file in 2.1.314:
peerProtocol,peerFeatures,pidDomain,asksForConvertedSkills,nameSourceandnameSince, next to the fields of fact 023.
Mechanism
A reader can tell a question from a permission dialog with no screen:
waitingFor is input needed for a question, and permission prompt
for a tool dialog or a plan approval. The reader cannot tell a plan
approval from a tool dialog by the pid file.
A reader must not show shell as a wait for the operator. The agent
starts its next turn by itself when the shell ends. A reader that wants
the task list reads background_tasks from Stop.
Incident
None. tg-bridge and aw asked which dialog waits, and what shell means.
Screens
None.
Not measured
- An MCP dialog, a question wizard of more than one question, and a dialog of a subagent.
- A background shell that runs while a turn also runs.
- A background shell that the operator stops, and a shell that fails.
- Whether
waitingForhas other values. - Other models, macOS and Windows.