Agent teams: teammates die immediately — harness spawns claude without a pty, causing stdin/print mode failure

Resolved 💬 4 comments Opened May 20, 2026 by MarkAWard Closed Jun 23, 2026

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

  1. Enable agent teams: set CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 in ~/.claude/settings.json.
  2. In a Claude Code session, call TeamCreate then Agent(team_name="test", name="worker", prompt="hello", run_in_background=true).
  3. The tool returns "Spawned successfully".
  4. 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
``

  1. 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 if script is unavailable.

The fix should be applied to the tmux backend spawn path (and likely any other backend spawn paths for consistency).

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗