mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-04 22:49:41 +02:00
COD-115 fix: scrub TMUX/TMUX_PANE so tmux-backed sessions don't crash-loop
When the web server is launched from inside a tmux pane it inherits TMUX/
TMUX_PANE. tmux's nesting guard then makes every new attach-bridge PTY
(`tmux attach-session`, used by codex/opencode/gemini and mux-wrapped claude)
exit code 1; the respawn controller recreates the dead bridge → infinite loop.
The existing guard in buildMuxAttachEnv() used `TMUX: undefined` on a
{...process.env} spread, which leaves the KEY present with value undefined —
node-pty serializes it as the literal string "TMUX=undefined", still tripping
the guard. (The working create path in tmux-manager.ts uses `delete`.)
Fix:
- Primary: delete process.env.TMUX / TMUX_PANE at web bootstrap (src/index.ts)
so every downstream {...process.env} spread is clean regardless of launch
context. `delete`, not `= undefined`.
- buildMuxAttachEnv(): build a copy and `delete` TMUX/TMUX_PANE/CLAUDECODE
(and COLORTERM when not truecolor) instead of `: undefined` — same node-pty
quirk affected all of them.
- Test: assert the keys are genuinely ABSENT (`'TMUX' in env === false`), not
merely undefined — the prior test only checked `toBeUndefined()`, which is
why the bug slipped through. Red→green confirmed.
Verified on isolated beta launched from inside tmux (inherited the poisonous
TMUX=codeman,980,7): created a codex session + triggered interactive attach —
the bridge `tmux -L codeman-beta attach-session` spawned with NO TMUX in its
env, attached successfully, zero "exited with code: 1", server healthy.
Circuit-breaker for repeated non-zero bridge exits (AC bullet 4, optional)
split to a follow-up. Deploy-pending (substrate): never auto-deployed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
1fa88cd187
commit
3c0e6286f6
@@ -124,17 +124,32 @@ export function buildClaudeEnv(sessionId: string): Record<string, string | undef
|
||||
* Lighter than buildClaudeEnv — no PATH augmentation or Codeman vars needed
|
||||
* since the mux session already has those set.
|
||||
*
|
||||
* @param truecolorEnabled - When true, set COLORTERM=truecolor (COD-75 opt-in);
|
||||
* otherwise leave COLORTERM unset. Mirrors buildEnvExports() so both paths agree.
|
||||
* @returns Environment variables object for pty.spawn
|
||||
*/
|
||||
export function buildMuxAttachEnv(): Record<string, string | undefined> {
|
||||
return {
|
||||
export function buildMuxAttachEnv(truecolorEnabled?: boolean): Record<string, string | undefined> {
|
||||
const env: Record<string, string | undefined> = {
|
||||
...process.env,
|
||||
LANG: 'en_US.UTF-8',
|
||||
LC_ALL: 'en_US.UTF-8',
|
||||
TERM: 'xterm-256color',
|
||||
COLORTERM: undefined,
|
||||
CLAUDECODE: undefined,
|
||||
};
|
||||
// COD-115: keys to UNSET must be `delete`d, NOT set to `undefined`. On a
|
||||
// `{...process.env}` spread the key stays present with value undefined, and node-pty
|
||||
// serializes it as the literal string "TMUX=undefined" — a non-empty value that still
|
||||
// trips tmux's nesting guard, killing the attach-bridge PTY (exit 1 → respawn loop).
|
||||
// The server can be launched from inside tmux; attach clients must never inherit that
|
||||
// parent tmux context. (Same fix the working create path uses in tmux-manager.ts.)
|
||||
delete env.TMUX;
|
||||
delete env.TMUX_PANE;
|
||||
delete env.CLAUDECODE;
|
||||
if (truecolorEnabled) {
|
||||
env.COLORTERM = 'truecolor';
|
||||
} else {
|
||||
delete env.COLORTERM; // COD-75: unset for non-truecolor (was `: undefined`, same node-pty quirk)
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user