Collab Troubleshooting
“Agents spawn but no output / Not logged in / DNS errors”
Recurring root cause (observed 2026-05-04, 2026-05-06, 2026-05-08): The ensemble service inherits the env of the shell that started it. If you start tsx server.ts from a shell that lacks credentials (no recent claude login, no codex login, missing PATH entries), every agent spawned afterward inherits that broken env.
Symptoms in the agent panes:
- Claude:
Not logged in · Please run /login - Codex:
stream disconnected before completion: failed to lookup address information
Fix
pkill -f 'tsx server.ts'
cd ~/Documents/ensemble && nohup ./node_modules/.bin/tsx server.ts > /tmp/ensemble-server.log 2>&1 &
Then re-run /collab from the same shell where claude --print "ok" and codex login status both succeed.
On macOS you can hand the service to launchd instead, once:
./scripts/install-launchd.sh
It then starts at login, comes back after a crash, and restarts on demand with launchctl kickstart -k gui/$(id -u)/dev.ensemble.server. The agent carries the PATH of the shell that installed it, so install from a shell where the agent CLIs work. When preflight finds the service older than 24h it does the kickstart itself.
Why the preflight catches it
scripts/collab-preflight.sh runs before every team spawn, and checks only the CLIs the run actually needs (collab-preflight.sh codex,claude,grok, or COLLAB_AGENTS):
- Service health check
- Service age (>24h = likely stale env, fail loud)
- DNS resolve api.openai.com + api.anthropic.com
- tmux DNS probe: a fresh pane must be able to resolve, because a long-running tmux server caches its own resolver and children start failing while the shell still works. A stale resolver is auto-fixed with
tmux kill-server, but only if nocollab-*tmux session is currently running; killing the server would take a working team down with it - Codex:
codex login statussays “Logged in”, and a realcodex execis asked to compute a sum and answers with the result. Asking only whether codex answers is not the same as asking whether codex works: a model that the current auth mode rejects returns an ordinary error with no quota wording, which used to score healthy right before the agent went silent for the whole session - Grok (when requested):
grok modelsreports logged in, and the project-picker hint is set - Claude:
claude auth statusreports"loggedIn": true, run inside a fresh tmux pane withCLAUDECODEunset, because that is the context agents actually spawn in. Running it in the caller’s shell passed while the spawned agent was logged out
Exit codes: 0 ok, 1 service down, 2 stale service, 3 claude broken or a named agent unavailable, 4 codex broken, 5 DNS, 6 grok broken, 7 health hook reports an unavailable agent without a permitted healthy fallback.
Explicit arguments fail loudly, environment defaults allow fallback
If you pass agents as the third argument to collab-launch.sh, a broken one is a hard failure: preflight reports the broken CLI with its own exit code (3 for claude, 4 for codex, 6 for grok, 7 for an unhealthy provider) and collab-launch.sh then aborts with exit 1. COLLAB_AGENTS is the standard set and retains auto-fallback to healthy alternatives. Every swap is printed as a warning. The implicit default pair also retains auto-fallback.
Why the postcheck catches it
scripts/collab-postcheck.sh runs 30s after spawn (background):
- Reads
<runtime-dir>/sessions, the register the service writes on every successful spawn, so it only ever looks at this team’s own panes. Without that register (an older team, or one that never got a single agent spawned) it has nothing to check and exits without touching anything - Captures those tmux panes
- Greps for “Not logged in”, “stream disconnected”, “401 Unauthorized”
- If any match, or if zero messages were exchanged in the wait window: kills this team’s sessions, prints diagnosis + suggested fix
“The monitor never appears”
Inside a herdr workspace, TERM_PROGRAM still reports iTerm.app. Ensemble checks HERDR_ENV=1 first for that reason; if you are running some other terminal multiplexer that does the same thing, force the mode with COLLAB_MONITOR=herdr|tmux|iterm|none. The launcher prints which mode it picked, and the herdr path also logs to /tmp/collab-herdr-last.log (iTerm: /tmp/ensemble-iterm.err).
Bypass for advanced users
COLLAB_SKIP_PREFLIGHT=1— skip preflight (NOT recommended)COLLAB_SKIP_POSTCHECK=1— skip postcheckCOLLAB_SERVICE_MAX_AGE=48— allow older service (default 24h)