Agent teams: teammates die immediately — harness spawns claude without a pty, causing stdin/print mode failure
Summary
When using the experimental agent teams feature (CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1), every teammate spawned via TeamCreate + Agent(team_name=..., name=...) dies immediately with:
Error: Input must be provided either through stdin or as a prompt argument when using --print
The Agent tool returns "Spawned successfully" — the failure happens inside the subprocess after the tool returns, so there is no indication of failure from the tool result itself. The spawned process cannot be communicated with; any SendMessage calls go into an inbox that no one is reading.
Versions confirmed affected: 2.1.141, 2.1.143, 2.1.145
Platform: macOS (Darwin 25.4.0), zsh, tmux
---
Root Cause
The harness builds a spawn command that does not allocate a pty for the child process's stdin:
env CLAUDECODE=1 CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 \
SSL_CERT_FILE=... REQUESTS_CA_BUNDLE=... \
/Users/<user>/.local/share/claude/versions/2.1.145 \
--agent-id <name>@<team> --agent-name <name> --team-name <team> \
--agent-color blue --parent-session-id <uuid> \
--agent-type general-purpose --permission-mode auto --model claude-opus-4-7
When claude is invoked this way, isatty(stdin) returns false. The binary interprets this as a non-interactive (CI/script) context, automatically enters --print mode, then exits with the above error because there is no stdin data and no --prompt argument.
This was verified with a controlled test: both the harness-pinned and latest claude binaries fail identically when spawned without a pty. Prepending script -q /dev/null to the spawn command fixes the issue completely — the spawned claude enters interactive mode, reads its inbox file, and operates normally.
---
Steps to Reproduce
- Enable agent teams: set
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1in~/.claude/settings.json. - In a Claude Code session, call
TeamCreatethenAgent(team_name="test", name="worker", prompt="hello", run_in_background=true). - The tool returns
"Spawned successfully". - Wait 5 seconds. Capture the teammate's tmux pane:
``bash``
PANE=$(jq -r '.members[]|select(.name=="worker").tmuxPaneId' ~/.claude/teams/test/config.json)
tmux capture-pane -t "$PANE" -p | tail -5
- Observe:
Error: Input must be provided either through stdin or as a prompt argument when using --print
---
Expected Behavior
Spawned teammate enters interactive mode and reads its prompt from ~/.claude/teams/<team>/inboxes/<name>.json (which the harness correctly pre-writes before spawning).
---
Actual Behavior
Teammate exits immediately with the --print mode error. The harness reports success because the spawn intent was dispatched; the binary crash is invisible to the caller.
---
Workaround
Wrap the spawn binary in script -q /dev/null to interpose a pty:
env CLAUDECODE=1 CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 \
script -q /dev/null /path/to/claude \
--agent-id <name>@<team> ... [all original flags]
We have shipped a project-level helper script that automates this recovery loop — it extracts the harness's original command from the dead pane's scrollback, injects the script wrapper, and re-runs. It works reliably but is a workaround for what should be fixed in the spawn command builder.
---
Suggested Fix
In the harness's teammate spawn command builder, allocate a pty for the child process before exec. Options (in order of preference):
node-pty— cleanest fix; allocates a proper pty pair in Node, no external process needed.script -q /dev/null <cmd>— works on macOS and modern Linux (util-linux ≥ 2.28); zero dependencies.socat PTY,raw <cmd>— alternative ifscriptis unavailable.
The fix should be applied to the tmux backend spawn path (and likely any other backend spawn paths for consistency).
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗