teammateMode "tmux" silently falls back to in-process since ~v2.1.50+
Environment
- Claude Code version: 2.1.62
- OS: macOS Darwin 25.4.0
- tmux: 3.6a
$TMUX: set (/private/tmp/tmux-501/default,30374,3)- Config:
"teammateMode": "tmux"in~/.claude/settings.json CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS:1
Bug Description
All teammates spawn with backendType: "in-process" and no tmux panes are created, despite "teammateMode": "tmux" being explicitly set in settings. This worked correctly on earlier versions (~Feb 8-9, 2026) but broke silently around Feb 19.
Expected Behavior
With "teammateMode": "tmux", agents should spawn in tmux split-panes (or new windows), producing real pane IDs like %1, %8, %25, etc.
Actual Behavior
All agents spawn in-process. Team config files show "tmuxPaneId": "in-process" and "backendType": "in-process" for every teammate. No tmux panes are created.
Evidence
Working teams (Feb 8-9, earlier Claude Code version):
| Team | Pane IDs | Backend |
|------|----------|---------|
| tidy-conjuring-axolotl | %1, %2, %3 | tmux |
| fluffy-wishing-duckling | %6, %7 | tmux |
| game-polish | %8 | tmux |
| word-survivor-audit | %9, %16 | tmux |
| word-survivor-v2 | %25 | tmux |
| v2-playable | %39 | tmux |
Broken teams (Feb 19+, Claude Code ~2.1.50+):
| Team | Pane IDs | Backend |
|------|----------|---------|
| sim-fix | all in-process | in-process |
| animation-prototypes | all in-process | in-process |
| delightful-v2 | all in-process | in-process |
| polymarket-refactor | all in-process | in-process |
| great | all in-process | in-process |
| life-audit | all in-process | in-process |
| motion-system | all in-process | in-process |
Root Cause Analysis
From the compiled binary, the teammate spawn decision flows through a gatekeeper function (deobfuscated as cv() / isInProcessEnabled):
// Decision function — called before any spawn
function cv() {
// CHECK 1: Non-interactive session (process.stdin.isTTY)
if (F_()) // ← If stdin is not a TTY, returns true immediately
return true; // → FORCE IN-PROCESS, skip config check
// CHECK 2: Read teammateMode from config
let T = U28(); // reads captured teammate mode
if (T === "in-process") return true;
else if (T === "tmux") return false;
else /* "auto" */ return !WwR();
}
The spawn entry point:
async function k28(T, R) {
if (cv()) // ← If true, config is never consulted
return b28(T, R); // → in-process spawn (hardcoded)
if (T.use_splitpane !== false)
return P28(T, R); // → tmux split-pane spawn
return y28(T, R); // → tmux new-window spawn
}
The problem: The non-interactive TTY check (F_(), which checks process.stdin.isTTY) runs before the config check. If process.stdin.isTTY returns false (even inside a real terminal session), it short-circuits to in-process mode and the "teammateMode": "tmux" setting is never consulted.
The binary contains the log message "[BackendRegistry] isInProcessEnabled: true (non-interactive session)" on this code path, confirming this is the bypass route.
Suggested Fix
- When
teammateModeis explicitly"tmux", the non-interactive TTY check should not override it. The user has explicitly opted in to tmux mode — that should be respected regardless of TTY state. - If a fallback from tmux to in-process does occur, emit a visible warning/log rather than silently degrading. Something like:
"[BackendRegistry] Warning: teammateMode is 'tmux' but falling back to in-process because stdin is not a TTY"
Reproduction
- Be inside a tmux session with
$TMUXset - Set
"teammateMode": "tmux"in~/.claude/settings.json - Set
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 - Create a team and spawn teammates
- Check
~/.claude/teams/<team-name>/config.json— all members havebackendType: "in-process"instead of"tmux"
11 Comments
Found 1 possible duplicate issue:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Same problem, different reasons.
Related: #26244
Same root cause —
isInProcessEnabled()checksisTTY/isInteractivebefore consultingteammateMode, so an explicit"tmux"setting gets silently overridden. Both issues propose the same fix (checkteammateMode === "tmux"first).The difference is why
isTTYis falsy: here it's a macOS regression introduced around v2.1.50, while #26244 hits it on Windows where Bun SFE'sprocess.stdout.isTTYis alwaysundefined. A fix for the shared code path should resolve both.the same behaviour happens when using the flag --teammate-mode tmux as well
Also happening here, it's a black box, can't see what they're doing.
I'm on macOS Sequoia using Ghostty.
@danielpiva the agent view requires the iTerm2 plugin for tmux, so it's not a feature available for Ghostty in general :( devastating I know.
this is resolved
<img width="1109" height="919" alt="Image" src="https://github.com/user-attachments/assets/e4d1e7d8-caaa-476d-8e77-c3d397778d49" />
@kylesnav
it doesnt work on ghostty? previously it did...
version - 2.1.63
<img width="2028" height="835" alt="Image" src="https://github.com/user-attachments/assets/e7a5c479-821b-485c-9303-e0702d70023c" />
It pretty much worked ~fine with Ghostty until not so long ago :(
It's sad, really. Not to mention that the flickering is back for me.
@MrAshRhodes I thought I was being insane, but yes it pretty much worked fine with Ghostty + tmux just a few days ago on 2.1.69!
<img width="3680" height="2384" alt="Image" src="https://github.com/user-attachments/assets/2caca902-c015-46f5-bb98-69c6c91aa75b" />
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.