fix(terminal): read the colour env from the registry on every local spawn path

buildClaudeEnv(), the direct-PTY fallback taken when mux creation fails, now
reads getCli('claude').env and applies its unset and exports lists. It used to
delete COLORTERM and CLAUDECODE from a hand-maintained list of its own, which
left it contradicting the registry entry that the tmux pane and the attach
client both read. An engine value needing a mux name has nothing to resolve
against on this path, so it is skipped rather than guessed.

Claude no longer unsets NO_COLOR. The invisible-background bug does not need
it, and unsetting it overrides a preference the user set deliberately, so a
user who exports NO_COLOR globally keeps monochrome panes. The other seven
truecolor CLIs still unset it; that inconsistency is intentional and the
comment on the entry says so.

The invariants doc gains a Terminal colour env paragraph under Session launch
modes, where a reader looking up Claude will find it — the previous sentence
sat under a heading that lists only the non-Claude CLIs. It now says the lists
are the stock catalog and a clis.json override replaces them wholesale, and
that the declarations reach the tmux pane, its attach client and the direct
PTY but not a remote pane, whose command carries no env exports at all. Docker
hands COLORTERM=truecolor to every mode, including the two the registry says
must unset it.

The changeset named six peer CLIs and there are seven: deepseek also exports
truecolor. A test beside the existing OpenCode assertion pins the new
behaviour, so a future registry edit cannot make the backgrounds vanish again
in silence.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Michael Grundberg
2026-09-13 14:42:30 +02:00
co-authored by Claude Opus 5
parent 7767b16d4f
commit dae2ac580f
5 changed files with 43 additions and 9 deletions
+4 -2
View File
@@ -174,17 +174,19 @@ const CLAUDE: CliEntry = {
legacyConfigAliases: { resumeId: 'resumeSessionId' },
},
env: {
// Claude joins the truecolor list with COLORTERM=truecolor and NO_COLOR unset.
// Claude asks for truecolor, like every CLI here except `shell` and `opencode`.
// tmux hands the pane TERM=screen, which supports-color reads as 16 colors, and
// Claude then quantizes every RGB color its theme asks for down to that palette.
// Each dark background lands on ESC[40m, the terminal's own black, so the block
// Claude draws behind the user's own messages renders invisible. PR #3 unset
// COLORTERM here against xterm.js#484, which xterm.js had already closed in 2019,
// and Codeman now ships @xterm/xterm 6 and sets `terminal-overrides *:Tc` itself.
// The other truecolor CLIs also unset NO_COLOR. Claude does not, so a user who
// exports NO_COLOR globally keeps the monochrome panes they asked for.
// CLAUDECODE stays unset, because Claude reads it as a signal that it is running
// nested inside itself.
exports: [{ name: 'COLORTERM', value: 'truecolor' }],
unset: ['CLAUDECODE', 'NO_COLOR'],
unset: ['CLAUDECODE'],
tmuxSetenvKeys: [],
dockerExecEnvNames: [],
allowedPrefixes: ['CLAUDE_CODE_'],