Shell Integration
Some Ghostty features require integrating with your shell. Ghostty can automatically inject shell integration for bash, elvish, fish, nushell, and zsh.
- Do not confirm close for terminals where the cursor is at a prompt.
- New terminals start in the working directory of the previously focused terminal.
- Complex prompts resize correctly by allowing the shell to redraw -- rather than reflow -- the prompt line.
- Triple-click while holding control (Linux) or command (macOS) to select the output of a command.
- The cursor at the prompt is turned into a bar to represent more typical text editing.
- The
jump_to_promptkeybinding can be used to scroll the terminal window forward and back through prompts. - Alt+click (option+click on macOS) moves the cursor to the click location while at a prompt.
sudocan be automatically wrapped to preserve Ghostty terminfo (disabled by default)sshcan be automatically wrapped to either transmit the Ghostty terminfo or set theTERMenvironment variable toxterm-256colorto maximize compatibility (disabled by default)
Ghostty will automatically inject the shell integration code for bash,
elvish, fish, nushell, and zsh.
Note
The version of Bash distributed with macOS (
/bin/bash) does not support automatic shell integration. You'll need to manually source the shell integration script (as shown below). You can also install a standard version of Bash from Homebrew or elsewhere and set it as your shell.
Other shells do not have shell integration code written, but they will function fine within Ghostty, although some or all of the above-mentioned shell integration features may be unavailable.
Nushell provides many of these features
itself (such as title and cursor handling), so its Ghostty integration
focuses on Ghostty-specific features like sudo, ssh-env, and
ssh-terminfo. Similarly, newer versions of Fish (4.0+) have built-in
support for prompt marking so jump_to_prompt, prompt resizing, and
prompt selection will work without shell integration.
Ghostty detects your shell using a simple string match on the
basename of the command to execute. If you are using a supported
shell with a different name, you can force the shell integration
by setting the shell-integration configuration option:
shell-integration = fish
If you want to disable automatic shell integration:
shell-integration = none
To verify shell integration is working, look for the following log lines:
info(io_exec): using Ghostty resources dir from env var: /Applications/Ghostty.app/Contents/Resources
info(io_exec): shell integration automatically injected shell=termio.shell_integration.Shell.fish
If you see any of the following, something is not working correctly.
The main culprit is usually that GHOSTTY_RESOURCES_DIR is not pointing
to the right place.
ghostty terminfo not found, using xterm-256color
shell could not be detected, no automatic shell integration will be injected
For the automatic shell integration to work Ghostty must either be run
from the macOS app bundle or be installed in a location where the contents of
zig-out/share are available somewhere above the directory where Ghostty
is running from.
On Linux, this should automatically work if you run from the zig-out
directory tree structure (a standard FHS-style tree) or run from a
properly installed location via -p (see
build from source).
You may also manually set the GHOSTTY_RESOURCES_DIR to point to the
zig-out/share/ghostty contents. To validate this directory the file
$GHOSTTY_RESOURCES_DIR/../terminfo/ghostty.terminfo should exist.
Setting this environment variable manually is a red flag that something
else is wrong, though, and you should investigate further.
Shell integration can also be manually sourced in your shell configuration. This ensures that shell integration works in more scenarios (such as when you switch shells within Ghostty).
Ghostty will automatically set the GHOSTTY_RESOURCES_DIR environment
variable when it starts, so you can use this to (1) detect your shell
is launched within Ghostty and (2) to find the shell-integration.
For example, for bash, you'd put this at the top of your ~/.bashrc:
# Ghostty shell integration for Bash. This should be at the top of your bashrc!
if [ -n "${GHOSTTY_RESOURCES_DIR}" ]; then
builtin source "${GHOSTTY_RESOURCES_DIR}/shell-integration/bash/ghostty.bash"
fi
Note
Technically, the bash shell integration script could be sourced from anywhere, but some bash configurations may interfere with the shell integration. To avoid this, we recommend sourcing the script as early as possible in your shell configuration.
Each shell integration's installation instructions are documented inline:
| Shell | Integration |
|---|---|
bash | ${GHOSTTY_RESOURCES_DIR}/shell-integration/bash/ghostty.bash |
elvish | ${GHOSTTY_RESOURCES_DIR}/shell-integration/elvish/lib/ghostty-integration.elv |
fish | "$GHOSTTY_RESOURCES_DIR"/shell-integration/fish/vendor_conf.d/ghostty-shell-integration.fish |
nushell | $GHOSTTY_RESOURCES_DIR/shell-integration/nushell/vendor/autoload/ghostty.nu |
zsh | ${GHOSTTY_RESOURCES_DIR}/shell-integration/zsh/ghostty-integration |
For shell-specific details see shell-integration/README.md.
Automatic shell integration as described in the previous section only works for the initially launched shell when Ghostty is started.
If you switch shells within Ghostty, i.e. you manually run bash or
you use a command like nix-shell, the shell integration will be
lost in that shell (it will keep working in the original shell process).
To make shell integration work in these cases, you must manually source the Ghostty shell-specific code as shown in the previous section.
Ghostty uses xterm-ghostty as its TERM value, but most remote hosts
don't yet ship Ghostty's terminfo entry. See
Terminfo for background on the problem and
the manual remedies.
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:
shell-integration-features = ssh-env,ssh-terminfo
ssh-envsetsTERM=xterm-256colorfor the remote session and forwardsCOLORTERM,TERM_PROGRAM, andTERM_PROGRAM_VERSIONviaSendEnvso the remote shell can still detect that it's running inside Ghostty.ssh-terminfoattempts to install Ghostty's terminfo entry on the remote host the first time you connect, usinginfocmplocally andticremotely. Successful installations are cached locally so subsequent connections skip the install step. The cache can be inspected and managed with theghostty +ssh-cacheCLI action.
When both features are enabled, Ghostty tries to install the terminfo
entry first and falls back to xterm-256color if installation fails.
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.
The ssh shell function will not be used in the following cases:
- Scripts run as
./script.shorsh 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.shor. script.sh) so it runs in the same shell process where the function is defined. - Wrapper tools that spawn
sshthemselves, such asaws ec2-instance-connect ssh,gcloud compute ssh,mosh,rsync -e ssh,gitoverssh,scp, andsftp. These invokessh(or anssh-like binary) directly and never consult your shell's function table. - Non-interactive shells and subshells more generally, including
Makefilerecipes,cronjobs, and command substitutions in other programs.
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
Host example.com
SetEnv TERM=xterm-256color
SendEnv COLORTERM TERM_PROGRAM TERM_PROGRAM_VERSION
Note
SetEnvrequires OpenSSH 8.7 or newer. See Terminfo for more on the terminfo side of this problem, including how to copy Ghostty's terminfo entry to a remote host manually.
Note
If the remote host already has the
xterm-ghosttyterminfo entry installed, aSetEnv TERM=xterm-256colorstanza will unnecessarily downgradeTERM. Only use this for hosts that lack the terminfo entry.
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:
# /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.