40 Commits

Author SHA1 Message Date
Jason Rayne
bbb02a8392 test: update shell integration tests for SSH flags
Add ssh-env and ssh-terminfo fields to existing setupFeatures tests.
2025-06-25 15:46:18 -07:00
Jason Rayne
e73313ed40 change: migrate SSH integration from standalone option to shell-integration-features flags
- Add ssh_env and ssh_terminfo flags to ShellIntegrationFeatures
- Remove SSHIntegration enum and ssh-integration config option
- Update setupFeatures to handle new flags via reflection
- Remove setupSSHIntegration function and all references

Integrates SSH functionality into existing shell-integration-features
system for better consistency and user control.
2025-06-25 15:46:18 -07:00
Jason Rayne
142e07c502 feat: add SSH integration wrapper for shell integration
- Implements opt-in SSH wrapper following sudo pattern
- Supports term_only, basic, and full integration levels
- Fixes xterm-ghostty TERM compatibility on remote systems
- Propagates shell integration environment variables
- Allows for automatic installation of terminfo if desired
- Addresses GitHub discussions #5892 and #4156
2025-06-25 15:43:32 -07:00
Jon Parise
37974dba06 bash: explicitly request a login shell
Prior to #7044, on macOS, our shell integrated command line would be
executed under `exec -l`, which caused bash to be started as a login
shell. Now that we're using direct command execution, add `--login` to
our bash command's arguments on macOS to get that same behavior.
2025-05-05 10:26:37 -04:00
Mitchell Hashimoto
722d41a359 config: allow commands to specify whether they shell expand or not
This introduces a syntax for `command` and `initial-command` that allows
the user to specify whether it should be run via `/bin/sh -c` or not.
The syntax is a prefix `direct:` or `shell:` prior to the command,
with no prefix implying a default behavior as documented.

Previously, we unconditionally ran commands via `/bin/sh -c`, primarily
to avoid having to do any shell expansion ourselves. We also leaned on
it as a crutch for PATH-expansion but this is an easy problem compared
to shell expansion.

For the principle of least surprise, this worked well for configurations
specified via the config file, and is still the default. However, these
configurations are also set via the `-e` special flag to the CLI, and it
is very much not the principle of least surprise to have the command run via
`/bin/sh -c` in that scenario since a shell has already expanded all the
arguments and given them to us in a nice separated format. But we had no
way to toggle this behavior.

This commit introduces the ability to do this, and changes the defaults
so that `-e` doesn't shell expand. Further, we also do PATH lookups
ourselves for the non-shell expanded case because thats easy (using
execvpe style extensions but implemented as part of the Zig stdlib). We don't
do path expansion (e.g. `~/`) because thats a shell expansion.

So to be clear, there are no two polar opposite behavioes here with
clear semantics:

  1. Direct commands are passed to `execvpe` directly, space separated.
     This will not handle quoted strings, environment variables, path
     expansion (e.g. `~/`), command expansion (e.g. `$()`), etc.

  2. Shell commands are passed to `/bin/sh -c` and will be shell expanded
     as per the shell's rules. This will handle everything that `sh`
     supports.

In doing this work, I also stumbled upon a variety of smaller
improvements that could be made:

  - A number of allocations have been removed from the startup path that
    only existed to add a null terminator to various strings. We now
    have null terminators from the beginning since we are almost always
    on a system that's going to need it anyways.

  - For bash shell integration, we no longer wrap the new bash command
    in a shell since we've formed a full parsed command line.

  - The process of creating the command to execute by termio is now unit
    tested, so we can test the various complex cases particularly on
    macOS of wrapping commands in the login command.

  - `xdg-terminal-exec` on Linux uses the `direct:` method by default
    since it is also assumed to be executed via a shell environment.
2025-04-10 13:15:14 -07:00
Jon Parise
cd6b850758 shell-integration: minor documentation updates 2025-03-22 15:57:55 -04:00
Jon Parise
0caba3e19f shell-integration: comptime buffer capacity 2025-03-22 15:56:05 -04:00
Jon Parise
314d52ac3a shell-integration: switch to $GHOSTTY_SHELL_FEATURES
This change consolidates all three opt-out shell integration environment
variables into a single opt-in $GHOSTTY_SHELL_FEATURES variable. Its
value is a comma-delimited list of the enabled shell feature names (e.g.
"cursor,title").

$GHOSTTY_SHELL_FEATURES is set at runtime and automatically added to the
shell environment. Its value is based on the shell-integration-features
configuration option.

$GHOSTTY_SHELL_FEATURES is only set when at least one shell feature is
enabled. It won't be set when 'shell-integration-features = false'.

$GHOSTTY_SHELL_FEATURES lists only the enabled shell feature names. We
could have alternatively gone in the opposite direction and listed the
disabled features, letting the scripts assume each feature is on by
default like we did before, but I think this explicit approach is a
little safer and easier to reason about / debug.

It also doesn't support the "no-" negation prefix used by the config
system (e.g. "cursor,no-title"). This simplifies the implementation
requirements of our (multiple) shell integration scripts, and because
$GHOSTTY_SHELL_FEATURES is derived from shell-integration-features,
the user-facing configuration interface retains that expressiveness.

$GHOSTTY_SHELL_FEATURES is intended to primarily be an internal concern:
an interface between the runtime and our shell integration scripts. It
could be used by people with particular use cases who want to manually
source those scripts, but that isn't the intended audience.

... and because the previous $GHOSTTY_SHELL_INTEGRATION_NO_* variables
were also meant to be an internal concern, this change does not include
backwards compatibility support for those names.

One last advantage of a using a single $GHOSTTY_SHELL_FEATURES variable
is that it can be easily forwarded to e.g. ssh sessions or other shell
environments.
2025-03-22 10:16:59 -04:00
Mitchell Hashimoto
0f4d2bb237 Lots of 0.14 changes 2025-03-12 09:55:52 -07:00
Jon Parise
a2018d7b20 bash: handle additional command arguments
A '-' or '--' argument signals the end of bash's own options. All
remaining arguments are treated as filenames and arguments. We shouldn't
perform any additional argument processing once we see this signal.

We could also assume a non-interactive shell session in this case unless
the '-i' (interactive) shell option has been explicitly specified, but
let's wait on that until we know that doing so would solve a real user
problem (and avoid any false negatives).
2025-01-23 10:43:36 -05:00
Bryan Lee
ccd6fd26ec Ensure setup_features runs even when shell detection fails 2025-01-18 05:12:45 +08:00
Bryan Lee
9c1edb5449 Add tests for setup shell integration features 2025-01-18 05:12:44 +08:00
Bryan Lee
8ee4deddb4 Fix shell-integration-features being ignored when shell-integration is none 2025-01-18 05:12:44 +08:00
Jon Parise
1b91a667fb bash: drop automatic shell integration with --posix
'--posix' starts bash in POSIX mode (like /bin/sh). This is rarely used
for interactive shells, and removing automatic shell integration support
for this option allows us to simply/remove some exceptional code paths.

Users are still able to manually source the shell integration script.

Also fix an issue where we would still inject GHOSTTY_BASH_RCFILE if we
aborted the automatic shell integration path _after_ seeing an --rcfile
or --init-file argument.
2025-01-07 16:09:03 -05:00
Jon Parise
f141f4b2b0 os: add prependEnv(), like appendEnv()
We can use this function in setupXdgDataDirs() to simplify the
XDG_DATA_DIRS environment variable code in a more standardized way.
2024-12-16 10:56:27 -05:00
Jon Parise
a0ce70651a bash: re-enable automatic bash shell detection
Bash shell detection was originally disabled in #1823 due to problems
with /bin/bash on macOS.

Apple distributes their own patched version of Bash 3.2 on macOS that
disables the POSIX-style $ENV-based startup path:

e5397a7e74/bash-3.2/shell.c (L1112-L1114)

This means we're unable to perform our automatic shell integration
sequence in this specific environment. Standard Bash 3.2 works fine.

Knowing this, we can re-enable bash shell detection by default unless
we're running "/bin/bash" on Darwin. We can safely assume that's the
unsupported Bash executable because /bin is non-writable on modern macOS
installations due to System Integrity Protection.

macOS users can either manually source our shell integration script
(which otherwise works fine with Apple's Bash) or install a standard
version of Bash from Homebrew or elsewhere.
2024-12-14 17:31:28 -05:00
Mitchell Hashimoto
70cc2d9793 termio: copy input command to avoid memory corruption
Fixes #2779
2024-11-23 09:40:18 -08:00
Mitchell Hashimoto
3e971f2837 termio: tweaks to xdg data dir handling (no logic changes) 2024-11-17 09:48:42 -08:00
notcancername
8e736aa4eb Append the default value of XDG_DATA_DIRS when setting up shell integration 2024-11-17 15:28:41 +01:00
Łukasz Niemier
f9be02a20f chore: clean up typos 2024-08-05 13:56:57 +02:00
multifred
72c672adb7 Fix multiple deprecated names for zig lib/std 2024-07-22 00:07:17 +02:00
Jon Parise
7d7fa46b0c shell-integration: bash must be explicitly enabled
For now, bash integration must be explicitly enabled (by setting
`shell-integration = bash`). Our automatic shell integration requires
bash version 4 or later, and systems like macOS continue to ship bash
version 3 by default. This approach avoids the cost of performing a
runtime version check.
2024-06-03 20:34:29 -04:00
Mitchell Hashimoto
66a9b1b99f rename env var 2024-05-27 16:18:51 -07:00
ilk
7377ca8917 refactor(shell-integration): refactor to make cases alphabetical
also refactors elvish file to evade unobvious returns
and tries to fix some build errors
2024-05-27 16:15:12 -07:00
ilk
1fa830cc73 feat(shell-integration): add automatic integration for Elvish
Fish automatic integration taken as an example.
Just like fish, Elvish checks `XDG_DATA_DIRS` for its modules.
Thus, Fish integration in zig is reused, and integration in
Elvish now removes `GHOSTTY_FISH_XDG_DIR` environment variable
on launch.
2024-05-27 16:15:01 -07:00
Jon Parise
016c58cfe4 shell-integration: handle 'bash -c command'
When the -c option is present, then commands are read from the first
non-option argument command string. Our simple implementation assumes
that if we see at least the '-c' option, a command string was given, and
the shell is always considered to be non-interactive - even if the '-i'
(interactive) option is also given.
2024-05-14 11:01:49 -07:00
Jon Parise
054e01eaaf shell-integration: expand bash HISTFILE value
bash reads HISTFILE at startup to locate its history file, but this is
apparently too early for it to be able to expand home-relative paths. We
now manually expand the full path and add that to the environment.
2024-05-08 07:49:46 -07:00
Mitchell Hashimoto
d64fa6d9db termio: shell integration uses arena 2024-05-07 19:57:26 -07:00
Jon Parise
861edc722f shell-integration: revise ShellIntegration.command comment 2024-05-05 14:03:31 -07:00
Jon Parise
73b3560e62 shell-integration: automatic bash integration
This change adds automatic bash shell detection and integration.

Unlike our other shell integrations, bash doesn't provide a built-in
mechanism for injecting our ghostty.bash script into the new shell
environment.

Instead, we start bash in POSIX mode and use the ENV environment
variable to load our integration script, and the rest of the bash
startup sequence becomes the responsibility of our script to emulate
(along with disabling POSIX mode).
2024-05-05 13:59:52 -07:00
Jon Parise
54f6abf1cf termio: pass full command to shell integration
This will allow the shell integration code to inspect the full command
string rather than just the first component (shell binary).
2024-04-21 09:53:27 -07:00
Jon Parise
5ea99d3626 termio: fix "forced" shell integration
When a shell is forced, we would supply its /-prefixed executable name
to mimic a path location. The rest of the integration detection logic
assumes just a base executable name. Fix the forced names accordingly.

Also add a unit test for this "force shell" behavior.
2024-04-20 11:37:34 -07:00
Marius Svechla
e34b373426 shell-integration: implement no-title option
This adds a new option to the shell integration feature set, `no-title`.
If this option is set, the shell integration will not automatically
update the window title.
2024-04-03 22:00:42 +02:00
Atanas Pepechkov
ee1366a0a8 add sudo wrapper as optional shell integration feature 2024-01-13 18:56:21 +02:00
Mitchell Hashimoto
48f316ebd2 termio: support XDG data dirs greater than 4k for fish shell integration
Fixes #1228
2024-01-05 14:27:12 -08:00
Mitchell Hashimoto
18c852d47c config: switch shell-integration-features 2023-11-07 17:05:09 -08:00
Mitchell Hashimoto
8239f09d9d allow configuring shell integration injection 2023-07-06 18:04:12 -07:00
Mitchell Hashimoto
80e2cd4e78 zsh integration 2023-07-06 17:46:54 -07:00
Mitchell Hashimoto
ad62e3ac1b fish shell integration 2023-07-06 16:10:30 -07:00
Mitchell Hashimoto
ae206b2f89 termio: fish shell integration injection 2023-07-06 14:14:55 -07:00