|
| 1 | +--- |
| 2 | +title: SSH |
| 3 | +description: |- |
| 4 | + Ghostty's `+ssh` CLI action is a drop-in `ssh` wrapper that prepares |
| 5 | + the remote session for Ghostty before exec'ing the real `ssh` |
| 6 | + binary. |
| 7 | +--- |
| 8 | + |
| 9 | +`ghostty +ssh` is a drop-in `ssh` wrapper. It prepares the remote |
| 10 | +session for Ghostty, then exec's the real `ssh` binary with your |
| 11 | +arguments forwarded verbatim: |
| 12 | + |
| 13 | +```sh |
| 14 | +ghostty +ssh -- user@example.com |
| 15 | +``` |
| 16 | + |
| 17 | +You can use it as an alias so that every `ssh` invocation in your |
| 18 | +shell goes through `+ssh`: |
| 19 | + |
| 20 | +```bash |
| 21 | +alias ssh='ghostty +ssh --' |
| 22 | +``` |
| 23 | + |
| 24 | +Or you can let Ghostty's [shell integration](#shell-integration) wrap |
| 25 | +`ssh` for you automatically. |
| 26 | + |
| 27 | +Run `ghostty +ssh --help` for the full flag reference. |
| 28 | + |
| 29 | +## Features |
| 30 | + |
| 31 | +### Environment Forwarding |
| 32 | + |
| 33 | +The `--forward-env` flag (default `true`) requests `SendEnv` |
| 34 | +forwarding of `COLORTERM`, `TERM_PROGRAM`, and `TERM_PROGRAM_VERSION` |
| 35 | +so the remote shell can detect that it's running inside Ghostty. |
| 36 | + |
| 37 | +For the forwarded variables to reach the remote session, the remote |
| 38 | +`sshd` must list them in its `AcceptEnv` directive. See |
| 39 | +[Remote `sshd` Configuration](#remote-sshd-configuration) below. |
| 40 | + |
| 41 | +Disable with `--forward-env=false`. |
| 42 | + |
| 43 | +### Terminfo Install |
| 44 | + |
| 45 | +Ghostty uses `xterm-ghostty` as its `TERM` value, but most remote |
| 46 | +hosts don't yet ship Ghostty's terminfo entry. See |
| 47 | +[Terminfo](/docs/help/terminfo#ssh) for more information. |
| 48 | + |
| 49 | +The `--terminfo` flag (default `true`) installs Ghostty's terminfo |
| 50 | +entry on the remote host the first time you connect, using `tic` on |
| 51 | +the remote. When the install succeeds (or the host is already cached), |
| 52 | +`TERM` is set to `xterm-ghostty` for the remote session. |
| 53 | + |
| 54 | +If the install fails (for example, `tic` isn't available on the |
| 55 | +remote), `+ssh` logs a warning and falls back to `TERM=xterm-256color`, |
| 56 | +which is a widely-supported entry that preserves color and most |
| 57 | +terminal capabilities on the remote. |
| 58 | + |
| 59 | +Disable with `--terminfo=false`. |
| 60 | + |
| 61 | +### Install Cache |
| 62 | + |
| 63 | +Successful terminfo installs are recorded in a local cache, keyed by |
| 64 | +`user@hostname`, so subsequent connections to the same host skip the |
| 65 | +install step. The cache is managed by the |
| 66 | +[`+ssh-cache`](#the-+ssh-cache-cli-action) action. |
| 67 | + |
| 68 | +Passing `--cache=false` to `+ssh` bypasses both the read and the |
| 69 | +write for a single invocation, without touching the cache. This is |
| 70 | +useful for scripting ("always reinstall") and for debugging issues. |
| 71 | + |
| 72 | +### Alternate `ssh` Executable |
| 73 | + |
| 74 | +By default `+ssh` exec's the first `ssh` on your `PATH`. The |
| 75 | +`--ssh=PATH` flag points it at a specific client instead: |
| 76 | + |
| 77 | +```sh |
| 78 | +ghostty +ssh --ssh=/opt/homebrew/bin/ssh -- user@example.com |
| 79 | +``` |
| 80 | + |
| 81 | +This is useful when you have an alternate OpenSSH build or wrapper |
| 82 | +client that you want `+ssh` to use. The path must resolve to an |
| 83 | +executable; if it doesn't, `+ssh` fails rather than silently falling |
| 84 | +back to the `PATH` `ssh`. |
| 85 | + |
| 86 | +## The `+ssh-cache` CLI Action |
| 87 | + |
| 88 | +`ghostty +ssh-cache` manages the terminfo cache used by `+ssh`: |
| 89 | + |
| 90 | +```sh |
| 91 | +# List every cached host. |
| 92 | +ghostty +ssh-cache |
| 93 | + |
| 94 | +# Check whether a single host is cached. |
| 95 | +ghostty +ssh-cache --host=user@example.com |
| 96 | + |
| 97 | +# Manually mark a host as cached (e.g. after installing terminfo by hand). |
| 98 | +ghostty +ssh-cache --add=user@example.com |
| 99 | + |
| 100 | +# Force the next connection to reinstall terminfo on a host. |
| 101 | +ghostty +ssh-cache --remove=user@example.com |
| 102 | + |
| 103 | +# Clear the entire cache. |
| 104 | +ghostty +ssh-cache --clear |
| 105 | + |
| 106 | +# Set the cache expiration period (default: entries never expire). |
| 107 | +ghostty +ssh-cache --expire-days=30 |
| 108 | +``` |
| 109 | + |
| 110 | +`--remove` is the recommended way to force a reinstall on a single |
| 111 | +host: drop the cache entry, and the next successful connection |
| 112 | +re-populates it. Use `+ssh --cache=false` when you want to bypass the |
| 113 | +cache entirely. |
| 114 | + |
| 115 | +Cache entries are always keyed as `user@hostname`, where `user` is the |
| 116 | +ssh user (defaulting to your local `$USER`) and `hostname` is the |
| 117 | +resolved remote host (post-`HostName`, post-`ProxyJump`) rather than |
| 118 | +an alias from `~/.ssh/config`. |
| 119 | + |
| 120 | +Run `ghostty +ssh-cache --help` for the full flag reference. |
| 121 | + |
| 122 | +## Shell Integration |
| 123 | + |
| 124 | +Ghostty's [shell integration](/docs/features/shell-integration) can |
| 125 | +wrap `ssh` in your interactive shell so that `ghostty +ssh` is invoked |
| 126 | +transparently. This is disabled by default and can be enabled via |
| 127 | +[`shell-integration-features`](/docs/config/reference#shell-integration-features): |
| 128 | + |
| 129 | +```ini |
| 130 | +shell-integration-features = ssh-env,ssh-terminfo |
| 131 | +``` |
| 132 | + |
| 133 | +- **`ssh-env`** enables environment forwarding (passes |
| 134 | + `--forward-env=true` to `+ssh`). |
| 135 | +- **`ssh-terminfo`** enables the remote terminfo install (passes |
| 136 | + `--terminfo=true` to `+ssh`). |
| 137 | + |
| 138 | +The wrapper is a small shell function named `ssh` that translates |
| 139 | +these feature flags into the right `+ssh` command-line options and |
| 140 | +then forwards your args. |
| 141 | + |
| 142 | +### Limitations |
| 143 | + |
| 144 | +Because the wrapper is a shell function, it **is not inherited by |
| 145 | +child processes**. The wrapper will _not_ be used in the following |
| 146 | +cases: |
| 147 | + |
| 148 | +- **Scripts run as `./script.sh` or `sh script.sh`.** Each script runs |
| 149 | + in a new non-interactive shell that does not inherit the function. |
| 150 | + Source the script into your current shell instead (e.g. |
| 151 | + `source script.sh` or `. script.sh`) so it runs in the same shell |
| 152 | + process where the function is defined. |
| 153 | +- **Wrapper tools that spawn `ssh` themselves**, such as |
| 154 | + `aws ec2-instance-connect ssh`, `gcloud compute ssh`, `mosh`, |
| 155 | + `rsync -e ssh`, `git` over `ssh`, `scp`, and `sftp`. These invoke |
| 156 | + `ssh` (or an `ssh`-like binary) directly and never consult your |
| 157 | + shell's function table. |
| 158 | +- **Non-interactive shells and subshells** more generally, including |
| 159 | + `Makefile` recipes, `cron` jobs, and command substitutions in other |
| 160 | + programs. |
| 161 | + |
| 162 | +For these cases, invoke `ghostty +ssh` directly, or configure |
| 163 | +`~/.ssh/config` as described below. |
| 164 | + |
| 165 | +## Manual `~/.ssh/config` Configuration |
| 166 | + |
| 167 | +For cases the shell wrapper can't cover, you can configure `SetEnv` |
| 168 | +and `SendEnv` directly in `~/.ssh/config`, which applies to every |
| 169 | +`ssh` invocation regardless of how it was launched: |
| 170 | + |
| 171 | +```ssh-config |
| 172 | +# ~/.ssh/config |
| 173 | +Host example.com |
| 174 | + SetEnv TERM=xterm-256color |
| 175 | + SendEnv COLORTERM TERM_PROGRAM TERM_PROGRAM_VERSION |
| 176 | +``` |
| 177 | + |
| 178 | +<Note> |
| 179 | + `SetEnv` requires OpenSSH 8.7 or newer. See |
| 180 | + [Terminfo](/docs/help/terminfo#ssh) for how to copy Ghostty's terminfo entry |
| 181 | + to a remote host manually. |
| 182 | +</Note> |
| 183 | + |
| 184 | +<Note> |
| 185 | + If the remote host already has the `xterm-ghostty` terminfo entry installed, a |
| 186 | + `SetEnv TERM=xterm-256color` stanza will unnecessarily downgrade `TERM`. Only |
| 187 | + use this for hosts that lack the terminfo entry. |
| 188 | +</Note> |
| 189 | + |
| 190 | +## Remote `sshd` Configuration |
| 191 | + |
| 192 | +Environment forwarding uses `SendEnv`, which is only a _request_. The |
| 193 | +remote `sshd` will silently drop any variable that isn't listed in its |
| 194 | +`AcceptEnv` directive. If you want `COLORTERM`, `TERM_PROGRAM`, and |
| 195 | +`TERM_PROGRAM_VERSION` to reach the remote session, the remote |
| 196 | +`sshd_config` needs something like: |
| 197 | + |
| 198 | +```sshd-config |
| 199 | +# /etc/ssh/sshd_config on the remote host |
| 200 | +AcceptEnv COLORTERM TERM_PROGRAM TERM_PROGRAM_VERSION |
| 201 | +``` |
| 202 | + |
| 203 | +This is a property of the remote host, not Ghostty, and many managed |
| 204 | +or hardened servers will not have it configured. `TERM` itself is |
| 205 | +always forwarded by `ssh` and is not affected by `AcceptEnv`. |
0 commit comments