Skip to content

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

Merged
jparise merged 1 commit into
ghostty-org:mainfrom
j0hnm4r5:fix/ssh-env-setenv-override
Mar 16, 2026
Merged

jparise merged 1 commit into
ghostty-org:mainfrom
j0hnm4r5:fix/ssh-env-setenv-override

Conversation

@j0hnm4r5

@j0hnm4r5 j0hnm4r5 commented Mar 15, 2026 •

Copy link
Copy Markdown
Contributor

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: #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)

@ghostty-vouch

ghostty-vouch Bot commented Mar 15, 2026

Copy link
Copy Markdown
Contributor

Hi @j0hnm4r5, thanks for your interest in contributing!

This project requires that pull request authors are vouched, and you are not in the list of vouched users.

This PR will be closed automatically. See https://github.com/ghostty-org/ghostty/blob/main/CONTRIBUTING.md for more details.

@ghostty-vouch ghostty-vouch Bot closed this Mar 15, 2026
@jparise

jparise commented Mar 15, 2026

Copy link
Copy Markdown
Contributor

!vouch

@jparise jparise reopened this Mar 15, 2026
ghostty-vouch Bot pushed a commit that referenced this pull request Mar 15, 2026
@ghostty-vouch ghostty-vouch Bot mentioned this pull request Mar 15, 2026
ghostty-vouch Bot added a commit that referenced this pull request Mar 15, 2026
Triggered by
[comment](#11518 (comment))
from @jparise.

Vouch: @j0hnm4r5

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

@jparise jparise left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This make sense to me and is a good overall improvement. Thanks!

@jparise

jparise commented Mar 15, 2026

Copy link
Copy Markdown
Contributor

@j0hnm4r5 was there more you wanted to iterate on before marking this as "Ready for review"?

@j0hnm4r5

Copy link
Copy Markdown
Contributor Author

Sorry, I wasn't expecting this to get seen/vouched so quickly! I just double checked the code and a few SSH connections and I think we're good; I'll mark it as ready.

@j0hnm4r5
j0hnm4r5 marked this pull request as ready for review March 16, 2026 05:27
@j0hnm4r5
j0hnm4r5 requested a review from a team as a code owner March 16, 2026 05:27
@jparise
jparise merged commit 925992a into ghostty-org:main Mar 16, 2026
66 checks passed
@jparise jparise added this to the 1.3.2 milestone Mar 16, 2026
rjwittams pushed a commit to rjwittams/ghostty that referenced this pull request Apr 1, 2026
Triggered by
[comment](ghostty-org#11518 (comment))
from @jparise.

Vouch: @j0hnm4r5

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
christmic pushed a commit to christmic/Sylvander that referenced this pull request Aug 12, 2026
Triggered by
[comment](ghostty-org/ghostty#11518 (comment))
from @jparise.

Vouch: @j0hnm4r5

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@mitchellh mitchellh modified the milestones: 1.3.2, 1.4.0 Oct 13, 2026
mitchellh added a commit that referenced this pull request Oct 26, 2026
`+ssh` passed `-o SetEnv=TERM=...` to ssh. ssh only uses the first
SetEnv it finds, so the one on the command line replaced every SetEnv
entry in the user's ssh config. This brings back the bug that #11518
fixed in the old shell integration wrapper, now in `+ssh` (#12582).

`TERM` was also only set with `--forward-env`, so `--forward-env=false`
(what `ssh-terminfo`-only users get) left the inherited
`TERM=xterm-ghostty` in place even when the terminfo install failed.

ssh sends the SetEnv entries in the user's ssh config again, and a
failed terminfo install falls back to `xterm-256color` like it did in
1.3.1, no matter which `ssh-*` features are enabled.

`TERM` is now set in the environment of the ssh process instead of with
SetEnv, the same way the 1.3.1 wrapper did. ssh sends `TERM` on its own
when it opens a remote terminal, so the server doesn't need `AcceptEnv
TERM`. This happens whenever `--forward-env` or `--terminfo` is enabled.
With both disabled, ssh runs with the user's environment unchanged. The
`+ssh` help is updated to explain how `TERM` is chosen.

Docs: https://man.openbsd.org/ssh_config#SetEnv
jcollie pushed a commit to jcollie/ghostty that referenced this pull request Oct 26, 2026
`+ssh` passed `-o SetEnv=TERM=...` to ssh. ssh only uses the first
SetEnv it finds, so the one on the command line replaced every SetEnv
entry in the user's ssh config. This brings back the bug that ghostty-org#11518
fixed in the old shell integration wrapper, now in `+ssh` (ghostty-org#12582).

`TERM` was also only set with `--forward-env`, so `--forward-env=false`
(what `ssh-terminfo`-only users get) left the inherited
`TERM=xterm-ghostty` in place even when the terminfo install failed.

ssh sends the SetEnv entries in the user's ssh config again, and
a failed terminfo install falls back to `xterm-256color` like it
did in 1.3.1, no matter which `ssh-*` features are enabled.

`TERM` is now set in the environment of the ssh process instead of
with SetEnv, the same way the 1.3.1 wrapper did. ssh sends `TERM` on
its own when it opens a remote terminal, so the server doesn't need
`AcceptEnv TERM`. This happens whenever `--forward-env` or
`--terminfo` is enabled. With both disabled, ssh runs with the user's
environment unchanged. The `+ssh` help is updated to explain how
`TERM` is chosen.

Docs: https://man.openbsd.org/ssh_config#SetEnv
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants