feat: add GHOSTTY_BIN_DIR to path via shell integration (#8976)

Closes #8956

Elvish written by Copilot, the rest was written by me with AI
documentation.
This commit is contained in:
Mitchell Hashimoto
2025-10-01 07:52:12 -07:00
parent ee82baadde
commit 3184187f2d
6 changed files with 34 additions and 4 deletions

View File

@@ -2350,6 +2350,11 @@ keybind: Keybinds = .{},
/// cache manually using various arguments.
/// (Available since: 1.2.0)
///
/// * `path` - Add Ghostty's binary directory to PATH. This ensures the `ghostty`
/// command is available in the shell even if shell init scripts reset PATH.
/// This is particularly useful on macOS where PATH is often overridden by
/// system scripts. The directory is only added if not already present.
///
/// SSH features work independently and can be combined for optimal experience:
/// when both `ssh-env` and `ssh-terminfo` are enabled, Ghostty will install its
/// terminfo on remote hosts and use `xterm-ghostty` as TERM, falling back to
@@ -6985,6 +6990,7 @@ pub const ShellIntegrationFeatures = packed struct {
title: bool = true,
@"ssh-env": bool = false,
@"ssh-terminfo": bool = false,
path: bool = true,
};
pub const RepeatableCommand = struct {

View File

@@ -73,6 +73,13 @@ if [ -n "$GHOSTTY_BASH_INJECT" ]; then
builtin unset GHOSTTY_BASH_RCFILE
fi
# Add Ghostty binary to PATH if the path feature is enabled
if [[ "$GHOSTTY_SHELL_FEATURES" == *"path"* && -n "$GHOSTTY_BIN_DIR" ]]; then
if [[ ":$PATH:" != *":$GHOSTTY_BIN_DIR:"* ]]; then
export PATH="$PATH:$GHOSTTY_BIN_DIR"
fi
fi
# Sudo
if [[ "$GHOSTTY_SHELL_FEATURES" == *"sudo"* && -n "$TERMINFO" ]]; then
# Wrap `sudo` command to ensure Ghostty terminfo is preserved.

View File

@@ -196,6 +196,11 @@
set edit:before-readline = (conj $edit:before-readline $beam~)
set edit:after-readline = (conj $edit:after-readline {|_| block })
}
if (and (has-value $features path) (has-env GHOSTTY_BIN_DIR)) {
if (not (has-value $paths $E:GHOSTTY_BIN_DIR)) {
set paths = [$@paths $E:GHOSTTY_BIN_DIR]
}
}
if (and (has-value $features sudo) (not-eq "" $E:TERMINFO) (has-external sudo)) {
edit:add-var sudo~ $sudo-with-terminfo~
}

View File

@@ -61,6 +61,11 @@ function __ghostty_setup --on-event fish_prompt -d "Setup ghostty integration"
end
end
# Add Ghostty binary to PATH if the path feature is enabled
if contains path $features; and test -n "$GHOSTTY_BIN_DIR"
fish_add_path --append "$GHOSTTY_BIN_DIR"
end
# When using sudo shell integration feature, ensure $TERMINFO is set
# and `sudo` is not already a function or alias
if contains sudo $features; and test -n "$TERMINFO"; and test "file" = (type -t sudo 2> /dev/null; or echo "x")

View File

@@ -220,6 +220,13 @@ _ghostty_deferred_init() {
builtin print -rnu $_ghostty_fd \$'\\e[0 q'"
fi
# Add Ghostty binary to PATH if the path feature is enabled
if [[ "$GHOSTTY_SHELL_FEATURES" == *"path"* ]] && [[ -n "$GHOSTTY_BIN_DIR" ]]; then
if [[ ":$PATH:" != *":$GHOSTTY_BIN_DIR:"* ]]; then
builtin export PATH="$PATH:$GHOSTTY_BIN_DIR"
fi
fi
# Sudo
if [[ "$GHOSTTY_SHELL_FEATURES" == *"sudo"* ]] && [[ -n "$TERMINFO" ]]; then
# Wrap `sudo` command to ensure Ghostty terminfo is preserved

View File

@@ -219,8 +219,8 @@ test "setup features" {
var env = EnvMap.init(alloc);
defer env.deinit();
try setupFeatures(&env, .{ .cursor = true, .sudo = true, .title = true, .@"ssh-env" = true, .@"ssh-terminfo" = true });
try testing.expectEqualStrings("cursor,ssh-env,ssh-terminfo,sudo,title", env.get("GHOSTTY_SHELL_FEATURES").?);
try setupFeatures(&env, .{ .cursor = true, .sudo = true, .title = true, .@"ssh-env" = true, .@"ssh-terminfo" = true, .path = true });
try testing.expectEqualStrings("cursor,path,ssh-env,ssh-terminfo,sudo,title", env.get("GHOSTTY_SHELL_FEATURES").?);
}
// Test: all features disabled
@@ -228,7 +228,7 @@ test "setup features" {
var env = EnvMap.init(alloc);
defer env.deinit();
try setupFeatures(&env, .{ .cursor = false, .sudo = false, .title = false, .@"ssh-env" = false, .@"ssh-terminfo" = false });
try setupFeatures(&env, .{ .cursor = false, .sudo = false, .title = false, .@"ssh-env" = false, .@"ssh-terminfo" = false, .path = false });
try testing.expect(env.get("GHOSTTY_SHELL_FEATURES") == null);
}
@@ -237,7 +237,7 @@ test "setup features" {
var env = EnvMap.init(alloc);
defer env.deinit();
try setupFeatures(&env, .{ .cursor = false, .sudo = true, .title = false, .@"ssh-env" = true, .@"ssh-terminfo" = false });
try setupFeatures(&env, .{ .cursor = false, .sudo = true, .title = false, .@"ssh-env" = true, .@"ssh-terminfo" = false, .path = false });
try testing.expectEqualStrings("ssh-env,sudo", env.get("GHOSTTY_SHELL_FEATURES").?);
}
}