Skip to content

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

@MarkAWard

Description

@MarkAWard

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:
    PANE=$(jq -r '.members[]|select(.name=="worker").tmuxPaneId' ~/.claude/teams/test/config.json)
    tmux capture-pane -t "$PANE" -p | tail -5
  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 if script is unavailable.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:agentsbugSomething isn't workinghas reproHas detailed reproduction stepsplatform:macosIssue specifically occurs on macOS

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions