diff --git a/docs/features/shell-integration.mdx b/docs/features/shell-integration.mdx index 81ab5705..a9b5eaa3 100644 --- a/docs/features/shell-integration.mdx +++ b/docs/features/shell-integration.mdx @@ -23,9 +23,9 @@ description: |- while at a prompt. - `sudo` can be automatically wrapped to preserve Ghostty terminfo (disabled by default) -- `ssh` can be automatically wrapped to either transmit the Ghostty - terminfo or set the `TERM` environment variable to `xterm-256color` - to maximize compatibility (disabled by default) +- `ssh` can be automatically wrapped to set up the remote terminal + environment correctly. See [SSH](/docs/features/ssh) for details + (disabled by default). ## Shell Integration Injection @@ -156,105 +156,10 @@ the Ghostty shell-specific code as shown in the previous section. ## SSH Integration -Ghostty uses `xterm-ghostty` as its `TERM` value, but most remote hosts -don't yet ship Ghostty's terminfo entry. See -[Terminfo](/docs/help/terminfo#ssh) for background on the problem and -the manual remedies. +The `ssh-env` and `ssh-terminfo` shell integration features wrap `ssh` +in your interactive shell so that Ghostty's [`+ssh`](/docs/features/ssh) +CLI action is invoked transparently. This sets up the remote terminal +environment so applications running over `ssh` work correctly. -The `ssh-env` and `ssh-terminfo` shell integration features attempt to -address this automatically. Both are disabled by default and can be -enabled via -[`shell-integration-features`](/docs/config/reference#shell-integration-features): - -```ini -shell-integration-features = ssh-env,ssh-terminfo -``` - -- **`ssh-env`** sets `TERM=xterm-256color` for the remote session and - forwards `COLORTERM`, `TERM_PROGRAM`, and `TERM_PROGRAM_VERSION` via - `SendEnv` so the remote shell can still detect that it's running inside - Ghostty. -- **`ssh-terminfo`** attempts to install Ghostty's terminfo entry on the - remote host the first time you connect, using `infocmp` locally and - `tic` remotely. Successful installations are cached locally so subsequent - connections skip the install step. The cache can be inspected and - managed with the `ghostty +ssh-cache` CLI action. - -When both features are enabled, Ghostty tries to install the terminfo -entry first and falls back to `xterm-256color` if installation fails. - -### How It Works - -Both features work by defining a shell function named `ssh` that wraps -the real `ssh` binary. When you type `ssh` in your interactive shell, -this function runs first, configures `TERM` and any other environment or -`ssh` options that are needed, and then invokes the real `ssh` binary -on your behalf. - -This mechanism is simple and requires no changes to your `~/.ssh/config`, -but it has an important limitation: **shell functions are not inherited -by child processes.** The `ssh` wrapper only applies to `ssh` invocations -made directly from your interactive shell. - -### Limitations - -The `ssh` shell function will _not_ be used in the following cases: - -- **Scripts run as `./script.sh` or `sh script.sh`.** Each script runs - in a new non-interactive shell that does not inherit the function. - Source the script into your current shell instead (e.g. - `source script.sh` or `. script.sh`) so it runs in the same shell - process where the function is defined. -- **Wrapper tools that spawn `ssh` themselves**, such as - `aws ec2-instance-connect ssh`, `gcloud compute ssh`, `mosh`, - `rsync -e ssh`, `git` over `ssh`, `scp`, and `sftp`. These invoke - `ssh` (or an `ssh`-like binary) directly and never consult your - shell's function table. -- **Non-interactive shells and subshells** more generally, including - `Makefile` recipes, `cron` jobs, and command substitutions in other - programs. - -### Manual `~/.ssh/config` Configuration - -If you need `TERM` and environment forwarding for cases the shell wrapper -can't cover (see above), you can configure `SetEnv` and `SendEnv` -directly in `~/.ssh/config`, which applies to every `ssh` invocation -regardless of how it was launched: - -```ssh-config -# ~/.ssh/config -Host example.com - SetEnv TERM=xterm-256color - SendEnv COLORTERM TERM_PROGRAM TERM_PROGRAM_VERSION -``` - - - `SetEnv` requires OpenSSH 8.7 or newer. See - [Terminfo](/docs/help/terminfo#ssh) for more on the terminfo side of this - problem, including how to copy Ghostty's terminfo entry to a remote host - manually. - - - - If the remote host already has the `xterm-ghostty` terminfo entry - installed, a `SetEnv TERM=xterm-256color` stanza will unnecessarily - downgrade `TERM`. Only use this for hosts that lack the terminfo entry. - - -### Remote `sshd` Configuration - -The `ssh-env` feature uses `SendEnv` to forward `COLORTERM`, -`TERM_PROGRAM`, and `TERM_PROGRAM_VERSION` to the remote host, but -`SendEnv` is only a _request_. The remote `sshd` will silently drop any -variable that isn't listed in its `AcceptEnv` directive. If you want -these variables to reach the remote session, the remote `sshd_config` -needs something like: - -```sshd-config -# /etc/ssh/sshd_config on the remote host -AcceptEnv COLORTERM TERM_PROGRAM TERM_PROGRAM_VERSION -``` - -This is a property of the remote host, not Ghostty, and many managed or -hardened servers will not have it configured. `TERM` itself is always -forwarded by `ssh` and is not affected by `AcceptEnv`. +See [SSH](/docs/features/ssh) for full details, including how to use +`+ssh` directly outside of an interactive shell. diff --git a/docs/features/ssh.mdx b/docs/features/ssh.mdx new file mode 100644 index 00000000..eb1e64c8 --- /dev/null +++ b/docs/features/ssh.mdx @@ -0,0 +1,205 @@ +--- +title: SSH +description: |- + Ghostty's `+ssh` CLI action is a drop-in `ssh` wrapper that prepares + the remote session for Ghostty before exec'ing the real `ssh` + binary. +--- + +`ghostty +ssh` is a drop-in `ssh` wrapper. It prepares the remote +session for Ghostty, then exec's the real `ssh` binary with your +arguments forwarded verbatim: + +```sh +ghostty +ssh -- user@example.com +``` + +You can use it as an alias so that every `ssh` invocation in your +shell goes through `+ssh`: + +```bash +alias ssh='ghostty +ssh --' +``` + +Or you can let Ghostty's [shell integration](#shell-integration) wrap +`ssh` for you automatically. + +Run `ghostty +ssh --help` for the full flag reference. + +## Features + +### Environment Forwarding + +The `--forward-env` flag (default `true`) requests `SendEnv` +forwarding of `COLORTERM`, `TERM_PROGRAM`, and `TERM_PROGRAM_VERSION` +so the remote shell can detect that it's running inside Ghostty. + +For the forwarded variables to reach the remote session, the remote +`sshd` must list them in its `AcceptEnv` directive. See +[Remote `sshd` Configuration](#remote-sshd-configuration) below. + +Disable with `--forward-env=false`. + +### Terminfo Install + +Ghostty uses `xterm-ghostty` as its `TERM` value, but most remote +hosts don't yet ship Ghostty's terminfo entry. See +[Terminfo](/docs/help/terminfo#ssh) for more information. + +The `--terminfo` flag (default `true`) installs Ghostty's terminfo +entry on the remote host the first time you connect, using `tic` on +the remote. When the install succeeds (or the host is already cached), +`TERM` is set to `xterm-ghostty` for the remote session. + +If the install fails (for example, `tic` isn't available on the +remote), `+ssh` logs a warning and falls back to `TERM=xterm-256color`, +which is a widely-supported entry that preserves color and most +terminal capabilities on the remote. + +Disable with `--terminfo=false`. + +### Install Cache + +Successful terminfo installs are recorded in a local cache, keyed by +`user@hostname`, so subsequent connections to the same host skip the +install step. The cache is managed by the +[`+ssh-cache`](#the-+ssh-cache-cli-action) action. + +Passing `--cache=false` to `+ssh` bypasses both the read and the +write for a single invocation, without touching the cache. This is +useful for scripting ("always reinstall") and for debugging issues. + +### Alternate `ssh` Executable + +By default `+ssh` exec's the first `ssh` on your `PATH`. The +`--ssh=PATH` flag points it at a specific client instead: + +```sh +ghostty +ssh --ssh=/opt/homebrew/bin/ssh -- user@example.com +``` + +This is useful when you have an alternate OpenSSH build or wrapper +client that you want `+ssh` to use. The path must resolve to an +executable; if it doesn't, `+ssh` fails rather than silently falling +back to the `PATH` `ssh`. + +## The `+ssh-cache` CLI Action + +`ghostty +ssh-cache` manages the terminfo cache used by `+ssh`: + +```sh +# List every cached host. +ghostty +ssh-cache + +# Check whether a single host is cached. +ghostty +ssh-cache --host=user@example.com + +# Manually mark a host as cached (e.g. after installing terminfo by hand). +ghostty +ssh-cache --add=user@example.com + +# Force the next connection to reinstall terminfo on a host. +ghostty +ssh-cache --remove=user@example.com + +# Clear the entire cache. +ghostty +ssh-cache --clear + +# Set the cache expiration period (default: entries never expire). +ghostty +ssh-cache --expire-days=30 +``` + +`--remove` is the recommended way to force a reinstall on a single +host: drop the cache entry, and the next successful connection +re-populates it. Use `+ssh --cache=false` when you want to bypass the +cache entirely. + +Cache entries are always keyed as `user@hostname`, where `user` is the +ssh user (defaulting to your local `$USER`) and `hostname` is the +resolved remote host (post-`HostName`, post-`ProxyJump`) rather than +an alias from `~/.ssh/config`. + +Run `ghostty +ssh-cache --help` for the full flag reference. + +## Shell Integration + +Ghostty's [shell integration](/docs/features/shell-integration) can +wrap `ssh` in your interactive shell so that `ghostty +ssh` is invoked +transparently. This is disabled by default and can be enabled via +[`shell-integration-features`](/docs/config/reference#shell-integration-features): + +```ini +shell-integration-features = ssh-env,ssh-terminfo +``` + +- **`ssh-env`** enables environment forwarding (passes + `--forward-env=true` to `+ssh`). +- **`ssh-terminfo`** enables the remote terminfo install (passes + `--terminfo=true` to `+ssh`). + +The wrapper is a small shell function named `ssh` that translates +these feature flags into the right `+ssh` command-line options and +then forwards your args. + +### Limitations + +Because the wrapper is a shell function, it **is not inherited by +child processes**. The wrapper will _not_ be used in the following +cases: + +- **Scripts run as `./script.sh` or `sh script.sh`.** Each script runs + in a new non-interactive shell that does not inherit the function. + Source the script into your current shell instead (e.g. + `source script.sh` or `. script.sh`) so it runs in the same shell + process where the function is defined. +- **Wrapper tools that spawn `ssh` themselves**, such as + `aws ec2-instance-connect ssh`, `gcloud compute ssh`, `mosh`, + `rsync -e ssh`, `git` over `ssh`, `scp`, and `sftp`. These invoke + `ssh` (or an `ssh`-like binary) directly and never consult your + shell's function table. +- **Non-interactive shells and subshells** more generally, including + `Makefile` recipes, `cron` jobs, and command substitutions in other + programs. + +For these cases, invoke `ghostty +ssh` directly, or configure +`~/.ssh/config` as described below. + +## Manual `~/.ssh/config` Configuration + +For cases the shell wrapper can't cover, you can configure `SetEnv` +and `SendEnv` directly in `~/.ssh/config`, which applies to every +`ssh` invocation regardless of how it was launched: + +```ssh-config +# ~/.ssh/config +Host example.com + SetEnv TERM=xterm-256color + SendEnv COLORTERM TERM_PROGRAM TERM_PROGRAM_VERSION +``` + + + `SetEnv` requires OpenSSH 8.7 or newer. See + [Terminfo](/docs/help/terminfo#ssh) for how to copy Ghostty's terminfo entry + to a remote host manually. + + + + If the remote host already has the `xterm-ghostty` terminfo entry installed, a + `SetEnv TERM=xterm-256color` stanza will unnecessarily downgrade `TERM`. Only + use this for hosts that lack the terminfo entry. + + +## Remote `sshd` Configuration + +Environment forwarding uses `SendEnv`, which is only a _request_. The +remote `sshd` will silently drop any variable that isn't listed in its +`AcceptEnv` directive. If you want `COLORTERM`, `TERM_PROGRAM`, and +`TERM_PROGRAM_VERSION` to reach the remote session, the remote +`sshd_config` needs something like: + +```sshd-config +# /etc/ssh/sshd_config on the remote host +AcceptEnv COLORTERM TERM_PROGRAM TERM_PROGRAM_VERSION +``` + +This is a property of the remote host, not Ghostty, and many managed +or hardened servers will not have it configured. `TERM` itself is +always forwarded by `ssh` and is not affected by `AcceptEnv`. diff --git a/docs/help/terminfo.mdx b/docs/help/terminfo.mdx index f9a41bde..09355036 100644 --- a/docs/help/terminfo.mdx +++ b/docs/help/terminfo.mdx @@ -72,11 +72,10 @@ everywhere, but in the meantime there are two ways to resolve the situation: SetEnv TERM=xterm-256color ``` -Both variants can be automated by Ghostty's shell integration via the -`ssh-terminfo` and `ssh-env` features. See -[SSH Integration](/docs/features/shell-integration#ssh-integration) for -details, including important limitations around when the automation -applies. +Ghostty can automate both variants. See [SSH](/docs/features/ssh) for +details on the `ghostty +ssh` CLI action and the `ssh-env` / +`ssh-terminfo` shell integration features, including important +limitations around when the automation applies. The `tic` command on the server may give the warning `"", line 2, diff --git a/docs/nav.json b/docs/nav.json index 445d9eef..e91e9327 100644 --- a/docs/nav.json +++ b/docs/nav.json @@ -175,6 +175,11 @@ "path": "/shell-integration", "title": "Shell Integration" }, + { + "type": "link", + "path": "/ssh", + "title": "SSH" + }, { "type": "link", "path": "/applescript",