112 Commits

Author SHA1 Message Date
Jason Rayne
f95476b181 refactor: apply maintainer feedback to SSH integration scripts across all shells
- Update Bash script (baseline): Simplify cache checking logic, clarify
"xterm-ghostty terminfo" message, remove unnecessary ssh_opts from
terminfo installation, remove extra success message
- Align ZSH/Fish/Elvish with updated Bash: Remove extra success
messages, adopt simplified cache checking, standardize setup messages
- Apply Elvish improvements: Remove unnecessary try/catch blocks, use
idiomatic error handling patterns
- Apply Fish improvements: Replace string pattern matching with
efficient `contains` checks on split features list
2025-07-08 10:45:42 -07:00
Jason Rayne
f279937377 refactor: simplify terminfo handling and remove base64 dependency
- Default ssh_term to xterm-256color to eliminate fallback assignments
- Remove base64 and replace infocmp -Q2 with standard -0 -x options for
compatibility
- Use process substitution instead of intermediate ssh_config variable
- Always set TERM explicitly since ssh_term is always defined
2025-07-07 11:33:26 -07:00
Jason Rayne
c3b14dff71 refactor: simplify SSH terminfo and environment handling
- Simplify feature detection to use single wildcard check
- Replace ssh_env array with simple ssh_term string variable
- Use TERM environment prefix instead of save/restore pattern
- Remove unnecessary backgrounded subshell for cache operations
2025-07-07 10:00:56 -07:00
Jason Rayne
08db61e27e refactor: simplify SSH environment variable handling
- Remove complex ssh_exported_vars tracking and local environment
modification in favor of trusting Ghostty's local environment
- Replace regex patterns with glob-based feature detection for better
performance
- Fix local variable declaration consistency throughout
- Streamline logic while maintaining all functionality
2025-07-07 09:06:15 -07:00
Jason Rayne
2d2df4b99f Merge branch 'main' into ssh-integration 2025-07-05 13:34:47 -07:00
Jason Rayne
a22074a85c fix: optimize SSH integration and improve error handling
- Replace dual-loop SSH config parsing with efficient single-pass case
statement
- Remove overly cautious timeout logic from cache checks for simplicity
- Add base64 availability check with xterm-256color fallback when
missing
- Include hostname in terminfo setup messages for better UX
- Maintain SendEnv/SetEnv dual approach for maximum OpenSSH
compatibility (relying on SetEnv alone seems to drop some vars during my
tests, despite them being explicitly included in AcceptEnv on the remote
host)
2025-07-05 13:24:59 -07:00
Jon Parise
b8931dd1db bash: stop using PS0 for the 'cursor' feature
Our use of PS0 (which bash runs before command execution) was causing
raw command sequences to be printed between multiple commands in a
sequence.

    $ alias garbage='echo start
    > echo end'

    $ garbage
    start
    �\���dend

I wasn't able to definitely track down all of the reasons for why this
only happens in the command sequence case, but I suspect it's related to
the way that __ghostty_preexec runs from within the bash DEBUG trap (by
way of bash-preexec).

This problem occurs when PS0 is set to _any_ string (even "") inside of
__ghostty_preexec, which also rules out most/any Ghostty-specific code.
PS1 and PS2 appear to be safe to (re)set in this context.

Fortunately, we can avoid using PS0 entirely by instead printing the
cursor reset escape sequence directly from __ghostty_precmd because it
also runs just before command execution.
2025-07-04 20:06:06 -04:00
Jason Rayne
75c703071a feat(ssh): rewrite SSH cache system in native Zig
- Eliminates standalone bash dependency
- Consolidates `+list-ssh-cache` and `+clear-ssh-cache` actions into
single `+ssh-cache` action with args
- Structured cache format with timestamps and expiration support
- Memory-safe entry handling with proper file locking
- Comprehensive hostname validation (IPv4/IPv6/domains)
- Atomic updates via temp file + rename
- Updated shell integrations for improved cross-platform support and
reliability
- Cache operations are now unit-testable
2025-07-03 20:11:45 -07:00
Jason Rayne
e25aa9f424 docs: update to reflect changes after porting terminfo host caching to Zig
- Minor tweak to Config.zig to show the new action.
- Rolled back README.md to remove reference to the now non-existent
'shared' subdir and bash-based cache script.
2025-07-03 16:22:57 -07:00
Jason Rayne
076f742dd4 fix: replace non-existent GHOSTTY_VERSION with TERM_PROGRAM_VERSION in shell integration
GHOSTTY_VERSION was mistakenly referenced but is never set. Use
TERM_PROGRAM_VERSION which is actually provided by Exec.zig from
build_config.version_string.
2025-06-25 17:50:15 -07:00
Jason Rayne
1873add697 docs: call out bash dependency 2025-06-25 17:00:17 -07:00
Jason Rayne
59229d7681 style: revert fish_indent quote removal
forgot to disable autoformat for this buffer (again)
2025-06-25 16:36:08 -07:00
Jason Rayne
0565ed3954 refactor: replace ghostty wrapper with proper CLI actions for terminfo cache management
- Add +list-ssh-cache and +clear-ssh-cache CLI actions
- Remove ghostty() wrapper functions from all shell integrations
- Improve variable naming in shell scripts for readability

Addresses @00-kat's feedback about CLI discoverability and naming
consistency. The new CLI actions follow established Ghostty patterns
and are discoverable via `ghostty --help`, while maintaining clean
separation of concerns between shell logic and cache management.
2025-06-25 15:46:18 -07:00
Jason Rayne
6789b7fb6e docs: add shared directory section to shell-integration README 2025-06-25 15:46:18 -07:00
Jason Rayne
8a2fa6485e refactor: extract SSH cache functionality to shared script
Addresses feedback about separation of concerns in shell integration
scripts.

Extracts host caching logic to
`src/shell-integration/shared/ghostty-ssh-cache` and updates all four
shell integrations to use the shared script. The `shared/` subdirectory
preserves the existing organizational pattern where all shell-specific
code lives in subdirectories. This cleanly separates SSH transport logic
from cache management while reducing code duplication by ~25%.

All existing SSH integration behavior remains identical.
2025-06-25 15:46:18 -07:00
Jason Rayne
81641e56b1 ssh-integration: replace levels with flags, optimize implementation
Rewrote shell functions to support the two new flags for
shell-integration-features:
- ssh-env: TERM compatibility + best effort environment variable
propagation (anything beyond TERM will depend on what the remote host
allows)
- ssh-terminfo: automatic terminfo installation with control socket
orchestration
- Flags work independently or combined

Implementation optimizations:
- ~65% code reduction through unified execution path
- Eliminated GHOSTTY_SSH_INTEGRATION environment variable system
- Replaced complex function dispatch with direct flag detection
- Consolidated 4 cache helper functions into single _ghst_cache()
utility
- Simplified control socket management (removed multi-step
orchestration)
- Subsequent connections to cached hosts are now directly executed and
more reliable

New additions:
- If ssh-terminfo is enabled, ghostty will be wrapped to provide users
with convenient commands to invoke either of the two utility functions:
`ghostty ssh-cache-list` and `ghostty ssh-cache-clear`
2025-06-25 15:46:18 -07:00
Jason Rayne
ddd3da487e fix: update cache file location 2025-06-25 15:46:18 -07:00
Jason Rayne
30683979bc fix: catch up to current state 2025-06-25 15:46:18 -07:00
Jason Rayne
f206e76841 ssh-integration: improve host caching, new method for "full" integration
Need a sanity check on this new approach for "full" to help determine if
it's worth additional iteration/refinement.

It solves the double auth issue, successfully propagates env vars, and
avoids output noise for connections that happen after terminfo is
installed. The only issue I don't have time to fix tonight is the fact
that it drops the MOTD for cached (re)connections.
2025-06-25 15:46:18 -07:00
Jason Rayne
69f9976394 fix: manual formatting pass to ensure consistency with existing patterns 2025-06-25 15:46:18 -07:00
Jason Rayne
4cebee5c8e fix: add client-side caching to eliminate redundant terminfo installations
- Cache known hosts with terminfo in
$GHOSTTY_RESOURCES_DIR/terminfo_hosts
- Skip installation step for cached hosts (single connection instead of
two)
- Use secure file permissions (600) and atomic writes
- Extract SSH target safely from command arguments
- Maintains full functionality while improving user experience on
repeated connections
2025-06-25 15:46:18 -07:00
Jason Rayne
b6bb9abfbc fix: address comprehensive shell integration code review issues
- Fix elvish function name mismatch and use conj for list operations
- Simplify terminfo installation command per ghostty docs (tic -x -)
- Fix conditional structure to ensure error messages always print
- Remove redundant checks and optimize array initialization
- Use consistent patterns across bash, fish, elvish, and zsh
implementations
2025-06-25 15:46:18 -07:00
Jason Rayne
995fb09813 fix: add builtin prefix for safety and consistency 2025-06-25 15:46:18 -07:00
Jason Rayne
2ddcf2fffe fix: remove resources_dir var, add builtin prefix for consistency 2025-06-25 15:46:18 -07:00
Jason Rayne
fb8f6c77dd fix: remove dangling resources_dir var 2025-06-25 15:46:18 -07:00
Jason Rayne
80475e1d17 fix: critical elvish syntax errors for environment variables 2025-06-25 15:46:18 -07:00
Jason Rayne
4206ab1210 fix: use idiomatic Fish shell syntax in SSH integration
- Use `set --append` for array operations
- Use `type -q` for command existence checks
2025-06-25 15:46:18 -07:00
Jason Rayne
2e9a0e92db fix: clean up SSH environment variable propagation 2025-06-25 15:46:18 -07:00
Jason Rayne
b07b3e4608 fish: revert all formatting changes
Keeps only functional additions for SSH integration wrapper,
preserving original line breaks and indentation to minimize
diff noise per maintainer feedback.
2025-06-25 15:46:18 -07:00
Jason Rayne
c70643404c bash: revert all formatting changes
Keeps only functional additions for SSH integration wrapper,
preserving original line breaks and indentation to minimize
diff noise per maintainer feedback.
2025-06-25 15:46:18 -07:00
Jason Rayne
842ced9212 bash: preserve mixed indentation in SSH integration changes
Preserves existing mixed indentation in ghostty.bash to minimize
diff noise per maintainer feedback.
2025-06-25 15:46:18 -07:00
Jason Rayne
2babdb458f refactor: simplify ssh integration environment variable checks 2025-06-25 15:46:18 -07:00
Jason Rayne
8f93d8fe03 fix: use kebab-case for ssh-integration enum values 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
b629f3337a bash: remove dependency on $GHOSTTY_RESOURCES_DIR
We were depending on $GHOSTTY_RESOURCES_DIR for two reasons:

1. To locate our script-adjacent bash-preexec.sh script
2. To restrict our script's execution to environments in which
   $GHOSTTY_RESOURCES_DIR is available (i.e. Ghostty-only shells)

For (1), we can instead determine our directory using $BASH_SOURCE[0].
This is slightly differently than our previous behavior, where we'd
always load bash-preexec.sh from the $GHOSTTY_RESOURCES_DIR hierarchy,
even if ghostty.bash from source from somewhere else on the file system
... but we never relied on that behavior, even in development.

For (2), there's no harm in source'ing this script outside of Ghostty,
and if that does become a concern, we can restore this condition or use
something more targeted based on those specific cases.

Historically, I believe (2) was in place to enable (1), so addressing
(1) removes the need for (2).

And lastly, none of the other shell integration scripts depend on
$GHOSTTY_RESOURCES_DIR.
2025-06-16 19:54:27 -04:00
Jon Parise
5b4976f6ef elvish: fix platform:hostname function call syntax 2025-04-08 10:54:26 -04:00
Jon Parise
b213c157f0 elvish: use kitty-shell-cwd:// to report pwd
OSC 7's standard body is a percent-encoded file:// URL. There isn't an
easy way for us to percent-encode the path ($pwd) component here without
implementing a custom function.

Instead, switch to the kitty-shell-cwd:// scheme, which Kitty introduced
to ease this implementation challenge in shell scripts. It accepts the
path string verbatim, without an encoding.

In Ghostty, we accept both the file:// and kitty-shell-cwd:// schemes,
and we attempt to URI-decode them both, so in practice this is more
about the "correctness" of this protocol than a functional change. It's
also possible we might decide to treat these schemes differently in the
runtime, like Kitty does.
2025-04-08 10:38:57 -04:00
Hanna
a8f760c6d2 fix: undo accidental replace 2025-04-07 16:10:50 -04:00
Hanna
77f5fe2560 fix: parenthesis are unneeded around builtins 2025-04-07 16:09:43 -04:00
Hanna
9808c13796 refactor: use builtin hostname function 2025-04-07 16:02:53 -04:00
Fabian Boehm
df174a74f8 shell-integration: Fix condition for sudo
A missing ";" meant the check for $TERMINFO was never executed.
2025-04-07 21:20:21 +02:00
Jon Parise
36ff70eb7f shell-integration: use elvish's native list type
Instead of looking for individual substrings in $GHOSTTY_SHELL_FEATURES,
`str:split` it into a list of feature names and use `has-value` to
detect their presence.
2025-03-22 12:26:56 -04:00
Jon Parise
77dc5c9dd2 shell-integration: use fish's native list type
Instead of looking for individual substrings in $GHOSTTY_SHELL_FEATURES,
`string split` it into a list of feature names and use `contains` to
detect their presence.
2025-03-22 12:11:51 -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
Yappaholic
3cac06a70a Fix elvish sudo integration and update documentation 2025-02-25 23:17:00 +03:00
Mitchell Hashimoto
a4b0e6d937 Fix sudo fish shell integration (#5276)
Currently, `sudo_has_sudoedit_flags` variable is being erased when `for`
block ends.
Change its scope to `--function` to prevent this.

Fixes `sudo: you may not specify environment variables in edit mode`.
2025-01-23 16:17:51 -08:00
Anund
168dd31367 documentation: consistent format for actions help 2025-01-23 15:58:33 -08:00
m154k1
25ccdfe495 Fix sudo fish shell integration
Set sudo_has_sudoedit_flags scope to --function.
2025-01-21 17:37:28 +02:00
Jon Parise
afa23532b6 bash: revert automatic shell integration changes
The intention of #5075 was to create a less intrusive, more hermetic
environment in which to source the bash startup files. This caused
problems for multiple people, and I believe that's because the general
expectation is that these files are sourced at global (not function)
scope.

For example, when a file is sourced from within a function scope, any
variables that weren't explicitly exported into the global environment
won't be available outside of the scope of the function. Most system and
personal startup files aren't written with that constraint because it's
not how bash itself loads these files.

As a small improvement over the original code, `rcfile` has been renamed
to `__ghostty_rcfile`. Avoiding leaking this variable while sourcing
these files was a goal of #5075, and prefixing it make it much less of a
potential issue.

This change also reverts the $HOME to ~/ change. While the ~/ notation
is more concise, using $HOME is more common and easier to implement
safely with regard to quoting.
2025-01-20 10:56:47 -05:00
Mitchell Hashimoto
b4a3ca999a bash: improve prior_trap processing (#5142)
We use `trap` to bootstrap our installation function (__bp_install). We
remove our code upon first execution but need to restore any preexisting
trap calls. We previously used `sed` to process the trap string, but
that had two downsides:

1. `sed` is an external command dependency. It needs to exist on the
system, and we need to invoke it in a subshell (which has some runtime
cost).
2. The regular expression pattern was imperfect and didn't handle
trickier cases like `'` characters in the trap string:

        $ (trap "echo 'hello'" DEBUG; trap -p DEBUG)
        hello
        trap -- 'echo '\''hello'\''' DEBUG

This change removes the dependency on `sed` by locally evaluating the
trap string and extracting any prior trap. This works reliably because
we control the format our trap string, which looks like this (with
newlines expanded):

    __bp_trap_string="$(trap -p DEBUG)"
    trap - DEBUG
    __bp_install

Upstream: https://github.com/rcaloras/bash-preexec/pull/170
2025-01-16 13:04:57 -08:00