shell-integration: fix ssh-env SetEnv clobbering user SSH config (#11518)

## Problem

Ghostty's `ssh-env` shell integration uses `-o "SetEnv
COLORTERM=truecolor"` when wrapping SSH commands. OpenSSH treats
command-line `-o SetEnv` options as **replacements** for all `SetEnv`
entries in `~/.ssh/config`, not additions. This silently drops any
user-configured `SetEnv` variables.

For example, a user with this in their SSH config:
```
Host myserver
  SetEnv MY_VAR=hello
```
...would find `MY_VAR` empty after SSHing through Ghostty with `ssh-env`
enabled.

Reference: https://github.com/ghostty-org/ghostty/discussions/10871

## Fix

Replace `-o "SetEnv COLORTERM=truecolor"` with the additive pattern: set
`COLORTERM=truecolor` locally before the SSH call and forward it via
`SendEnv`.

`SendEnv` is additive — it does not clobber `SetEnv` entries in
`~/.ssh/config`.

**Trade-off:** `SendEnv` requires `AcceptEnv COLORTERM` on the remote
server (unlike `SetEnv`). But this was already the case for
`TERM_PROGRAM`/`TERM_PROGRAM_VERSION`, so it's a consistent and
acceptable approach.

## Changes

All 5 shell integration files updated with the same pattern:

- `SetEnv COLORTERM=truecolor` option removed
- `COLORTERM` added to the existing `SendEnv` option
- `COLORTERM=truecolor` set as a local env var on the execute line (so
`SendEnv` has something to forward)

## Test plan

- [ ] Enable `ssh-env` in Ghostty config: `shell-integration-features =
ssh-env`
- [ ] Add `SetEnv MY_VAR=hello` under a host in `~/.ssh/config` and
`AcceptEnv MY_VAR` in `/etc/ssh/sshd_config` on the remote
- [ ] SSH to that host — `echo $MY_VAR` should return `hello` (was empty
before this fix)
- [ ] `echo $COLORTERM` returns `truecolor` (requires `AcceptEnv
COLORTERM`)
- [ ] `echo $TERM_PROGRAM` still propagates (same `AcceptEnv`
requirement as before)
This commit is contained in:
Jon Parise
2026-03-16 08:01:33 -04:00
committed by GitHub
5 changed files with 10 additions and 14 deletions

View File

@@ -123,8 +123,7 @@ if [[ "$GHOSTTY_SHELL_FEATURES" == *ssh-* ]]; then
# Configure environment variables for remote session
if [[ "$GHOSTTY_SHELL_FEATURES" == *ssh-env* ]]; then
ssh_opts+=(-o "SetEnv COLORTERM=truecolor")
ssh_opts+=(-o "SendEnv TERM_PROGRAM TERM_PROGRAM_VERSION")
ssh_opts+=(-o "SendEnv COLORTERM TERM_PROGRAM TERM_PROGRAM_VERSION")
fi
# Install terminfo on remote host if needed
@@ -180,7 +179,7 @@ if [[ "$GHOSTTY_SHELL_FEATURES" == *ssh-* ]]; then
fi
# Execute SSH with TERM environment variable
TERM="$ssh_term" builtin command ssh "${ssh_opts[@]}" "$@"
TERM="$ssh_term" COLORTERM=truecolor builtin command ssh "${ssh_opts[@]}" "$@"
}
fi

View File

@@ -83,8 +83,7 @@
# Configure environment variables for remote session
if (has-value $features ssh-env) {
set ssh-opts = (conj $ssh-opts ^
-o "SetEnv COLORTERM=truecolor" ^
-o "SendEnv TERM_PROGRAM TERM_PROGRAM_VERSION")
-o "SendEnv COLORTERM TERM_PROGRAM TERM_PROGRAM_VERSION")
}
if (has-value $features ssh-terminfo) {
@@ -148,7 +147,7 @@
}
}
with [E:TERM = $ssh-term] {
with [E:TERM = $ssh-term E:COLORTERM = truecolor] {
(external ssh) $@ssh-opts $@args
}
}

View File

@@ -129,8 +129,7 @@ function __ghostty_setup --on-event fish_prompt -d "Setup ghostty integration"
# Configure environment variables for remote session
if contains ssh-env $features
set -a ssh_opts -o "SetEnv COLORTERM=truecolor"
set -a ssh_opts -o "SendEnv TERM_PROGRAM TERM_PROGRAM_VERSION"
set -a ssh_opts -o "SendEnv COLORTERM TERM_PROGRAM TERM_PROGRAM_VERSION"
end
# Install terminfo on remote host if needed
@@ -198,7 +197,7 @@ function __ghostty_setup --on-event fish_prompt -d "Setup ghostty integration"
end
# Execute SSH with TERM environment variable
TERM="$ssh_term" command ssh $ssh_opts $argv
TERM="$ssh_term" COLORTERM=truecolor command ssh $ssh_opts $argv
end
end

View File

@@ -12,9 +12,9 @@ export module ghostty {
# `ssh-env`: use xterm-256color and propagate COLORTERM/TERM_PROGRAM vars
if (has_feature "ssh-env") {
$ssh_env.TERM = "xterm-256color"
$ssh_env.COLORTERM = "truecolor"
$ssh_opts = [
"-o" "SetEnv COLORTERM=truecolor"
"-o" "SendEnv TERM_PROGRAM TERM_PROGRAM_VERSION"
"-o" "SendEnv COLORTERM TERM_PROGRAM TERM_PROGRAM_VERSION"
]
}

View File

@@ -325,8 +325,7 @@ _ghostty_deferred_init() {
# Configure environment variables for remote session
if [[ "$GHOSTTY_SHELL_FEATURES" == *ssh-env* ]]; then
ssh_opts+=(-o "SetEnv COLORTERM=truecolor")
ssh_opts+=(-o "SendEnv TERM_PROGRAM TERM_PROGRAM_VERSION")
ssh_opts+=(-o "SendEnv COLORTERM TERM_PROGRAM TERM_PROGRAM_VERSION")
fi
# Install terminfo on remote host if needed
@@ -382,7 +381,7 @@ _ghostty_deferred_init() {
fi
# Execute SSH with TERM environment variable
TERM="$ssh_term" command ssh "${ssh_opts[@]}" "$@"
TERM="$ssh_term" COLORTERM=truecolor command ssh "${ssh_opts[@]}" "$@"
}
fi