500 Commits

Author SHA1 Message Date
Mitchell Hashimoto
8ab3010bb8 cli: rewrite ssh-cache diskcache and test IO 2025-07-09 09:20:14 -07:00
Jason Rayne
f242c6b5c4 Merge branch 'main' into ssh-integration 2025-07-05 14:54:31 -07:00
Mitchell Hashimoto
fb9c52ecf4 Nuke GLFW from Orbit
This deletes the GLFW apprt from the Ghostty codebase.

The GLFW apprt was the original apprt used by Ghostty (well, before
Ghostty even had the concept of an "apprt" -- it was all just a single
application then). It let me iterate on the core terminal features,
rendering, etc. without bothering about the UI. It was a good way to get
started. But it has long since outlived its usefulness.

We've had a stable GTK apprt for Linux (and Windows via WSL) and a
native macOS app via libghostty for awhile now. The GLFW apprt only
remained within the tree for a few reasons:

  1. Primarily, it provided a faster feedback loop on macOS because
     building the macOS app historically required us to hop out of the
     zig build system and into Xcode, which is slow and cumbersome.

  2. It was a convenient way to narrow whether a bug was in the
     core Ghostty codebase or in the apprt itself. If a bug was in both
     the glfw and macOS app then it was likely in the core.

  3. It provided us a way on macOS to test OpenGL.

All of these reasons are no longer valid. Respectively:

  1. Our Zig build scripts now execute the `xcodebuild` CLI directly and
     can open the resulting app, stream logs, etc. This is the same
     experience we have on Linux. (Xcode has always been a dependency of
     building on macOS in general, so this is not cumbersome.)

  2. We have a healthy group of maintainers, many of which have access
     to both macOS and Linux, so we can quickly narrow down bugs
     regardless of the apprt.

  3. Our OpenGL renderer hasn't been compatible with macOS for some time
     now, so this is no longer a useful feature.

At this point, the GLFW apprt is just a burden. It adds complexity
across the board, and some people try to run Ghostty with it in the real
world and get confused when it doesn't work (it's always been lacking in
features and buggy compared to the other apprts).

So, it's time to say goodbye. Its bittersweet because it is a big part
of Ghostty's history, but we've grown up now and it's time to move on.
Thank you, goodbye.

(NOTE: If you are a user of the GLFW apprt, then please fork the project
prior to this commit or start a new project based on it. We've warned
against using it for a very, very long time now.)
2025-07-04 14:12:18 -07:00
Jason Rayne
1bdcbac96c Merge branch 'main' into ssh-integration 2025-07-03 22:41:29 -07:00
Mitchell Hashimoto
e494d94fb3 Handle exec failures more gracefully
Fixes #7792

Our error handling for `exec` failing within the forked process never
actually worked! It triggered all sorts of issues. We didn't catch this
before because it used to be exceptionally hard to fail an exec because
we used to wrap ALL commands in a `/bin/sh -c`.

However, we now support direction execution, most notably when you do
`ghostty -e <command>` but also via the `direct:` prefix on configured
commands.

This fixes up our exec failure handling by printing a useful error
message and avoiding any errdefers in the child which was causing the
double-close.
2025-07-03 21:31:03 -07:00
Mitchell Hashimoto
465ac5b1b7 clean up some of the color usage, use exhaustive switches 2025-07-03 09:25:56 -07:00
Daniel
9e341a3d60 Created tagged union for selection colors, enabled parsing
Implemented cell color for Metal

Removed use of selection-invert-fg-bg

Mirrored feature to OpenGL

Added tests for SelectionColor

Fixed selection on inverted cell behavior

Implemented cell colors for cursor-text

Implemented cell colors for cursor-color, removed uses of cursor-invert-fg-bg during rendering

Updated docs for dynamically colored options

Updated docstrings, cleaned up awkward formatting, and moved style computation to avoid unnecssary invocations

Bump version in docstrings
2025-07-03 07:14:37 -07:00
Basil Crow
182f8ddd1a Do not resolve the symbolic link for the initial working directory 2025-07-03 07:09:24 -07:00
Mitchell Hashimoto
81cef6e63b various cleanups around scroll timers 2025-06-30 09:40:49 -07:00
moni-dz
f73c90bf5d surface: add timer-based scrolling during selection 2025-06-30 09:17:20 -07:00
moni-dz
c00b8740aa termio: add selection scrolling callback 2025-06-30 09:15:53 -07:00
James Holderness
7f0778bcf2 termio: indicate support for OSC 52 in primary DA report
This is an extension agreed upon by modern terminals to indicate that
they support copying to the clipboard with XTerm's OSC 52 sequence. It
is only reported when writing to the clipboard is actually allowed.
2025-06-29 15:32:17 +01:00
Mitchell Hashimoto
591ef0f40f Move child exit handling logic to apprt thread
Fixes #7500
Supersedes #7582

This commit moves the child exit handling logic from the IO thead to the
apprt thread. The IO thread now only sends a `child_exited` message to
the apprt thread with metadata about the exit conditions (exit code,
runtime).

From there, the apprt thread can handle the exit situation however is
necessary. This commit doesn't change the behavior but it does fix the
issue #7500. The behavior is: exit immediately, show abnormal exit
message, wait for user input, etc.

This also gets us closer to #7649.
2025-06-27 10:36:23 -07:00
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
Mitchell Hashimoto
0b5092bf3a pwd: fix hostname resolution on macos (#7029)
## Description

Yet another edge case in #2484 

When macOS's "Private WiFi address" feature is enabled it'll change the
hostname to a mac address. Mac addresses look like URIs with a hostname
and port component, e.g. `12:34:56:78:90:12` where `:12` looks like port
`12`. However, mac addresses use hex numbers and as such can also
contain letters `a` through `f`. So, a mac address like
`ab💿ef🆎cd:ef` is valid, but will not be parsed as a URI, because
`:ef` is not a valid port.

This commit attempts to fix that by checking if the hostname is a valid
mac address when `std.Uri.parse()` fails and constructing a new
`std.Uri` struct using that information.

It's not perfect, but is equally compliant with the URI spec as
`std.Uri` currently is. Meaning not at all compliant 😅

## Testing instructions

### Unit tests

> [!IMPORTANT]
> I don't know if these tests are run in CI or if they're picked up by
`zig build test`. I get an unrelated crash that mentions `minidump` and
an invalid OSC command when I try to run `zig build test` on my mac.

1. Make sure `zig test src/os/hostname.zig` is passing.

### Manual testing instructions

#### Setup - Enable the "Private WiFi address" setting

> [!IMPORTANT]
> You must be connected to WiFi to be able to test this.

1. Open your mac's "System Settings".
2. Go to Network &rarr; Wi-Fi &rarr; Details.

<img width="710" alt="image"
src="https://github.com/user-attachments/assets/fe30cfe7-8e77-4421-8b36-2f7aab0918dd"
/>

3. Set the "Private Wi-Fi address" setting to `Rotating`.

<img width="710" alt="image"
src="https://github.com/user-attachments/assets/bd695c20-106c-46bd-8862-cbdce55fed6f"
/>

> [!IMPORTANT]
> Now you wait. The private Wi-Fi address will eventually rotate to a
mac address that ends with a non-digit, e.g. `0a`, `ff`, `e2`, etc.
You'll notice this when your shell integration stops working, e.g. you
open a new tab in Ghostty and the shell is in your home directory
instead of whichever directory you had open in your previous tab.

#### Testing the changes

1. Open Ghostty.
3. `cd` to any directory that isn't the default (usually `$HOME`)
directory, e.g. `cd Documents`.
4. Open a new tab (<kbd>Cmd+T</kbd>) or split (<kbd>Cmd+D</kbd>).
5. Assuming the setup steps have been followed you should:
    * On `main`:  land in `$HOME` in the new tab or split.
* On this branch: land in the same working directory as the original tab
or split.
2025-06-24 07:40:14 -04:00
Mitchell Hashimoto
1947afade9 input configuration to pass input as stdin on startup
This adds a new configuration `input` that allows passing either raw
text or file contents as stdin when starting the terminal.

The input is sent byte-for-byte to the terminal, so control characters
such as `\n` will be interpreted by the shell and can be used to run
programs in the context of the loaded shell.

Example: `ghostty --input="hello, world\n"` will start the your default
shell, run `echo hello, world`, and then show the prompt.
2025-06-22 18:18:16 -04:00
Qwerasd
7cfc906c60 debug: properly set thread names on macOS 2025-06-20 15:18:41 -06:00
Mitchell Hashimoto
57cd5ef085 feat: implement mode 1048 for saving/restoring cursor position (#7553)
Implements mode 1048 for saving/restoring cursor position.

This is the same as mode 1049 but only saves cursor position without
touching the alternate screen.

**save/restore cursor position:**
- `ESC[?1048h` - save cursor position  
- `ESC[?1048l` - restore cursor position

**Quick test:**
```bash
printf '\e[5;10H[SAVED HERE]'
printf '\e[?1048h'                # save position
printf '\e[15;1HMoved somewhere else...'
printf '\e[?1048l'                # restore 
printf ' RESTORED!'           # should appear next to [SAVED HERE]
```

Fixes #7473
2025-06-09 07:14:59 -07:00
Alex Straight
59bc980250 feat: implement mode 1048 for saving/restoring cursor position 2025-06-09 06:55:38 -07:00
Mitchell Hashimoto
a87c68d49a termio: unconditionally show "process exited" message
We previously only showed this message if the user had
`wait-after-command` set to true, since if its false the surface would
close anyways.

With the latest undo feature on macOS, this is no longer the case; a
exited process can be undone and reopened. I considered disallowing
undoing an exited surface, but I think there is value in being able to
go back and recapture output in scrollback if you wanted to.
2025-06-09 06:51:17 -07:00
Kristófer R
e0655a7f75 Move url parsing helper to os/hostname
Also adds a test to verify that the function is working as intended.
2025-06-07 22:07:18 -04:00
Kristófer R
ffe7f0d8bf extract url parsing into its own function 2025-06-07 22:07:18 -04:00
Kristófer R
64bfaf23f9 take kitty-shell-cwd scheme into account 2025-06-07 22:07:17 -04:00
Kristófer R
b66368b4d6 extract mac address validity check to function 2025-06-07 22:07:17 -04:00
Kristófer R
19ca1bfb1c Fix modulo operation and custom Uri struct init 2025-06-07 22:07:17 -04:00
Kristófer R
0e74b8027a pwd: fix hostname resolution on macos
When macOS's "Private WiFi address" feature is enabled it'll change the
hostname to a mac address. Mac addresses look like URIs with a hostname
and port component, e.g. 12:34:56:78:90:12 where `:12` looks like port
12. However, mac addresses can also contain letters a through f, so a
valid mac address like ab💿ef🆎cd:ef is valid, but will not be parsed
as a URI, because `:ef` is not a valid port.

This commit attempts to fix that by checking if the hostname is a valid
mac address when `std.Uri.parse()` fails and constructing a new std.Uri
struct using that information.

It's not perfect, but is equally compliant with the URI spec as std.Uri
currently is.
2025-06-07 22:07:17 -04:00
Mitchell Hashimoto
2ad86cde69 OSC: allow multiple set/reset/report operations per OSC (#7429) 2025-05-30 13:16:57 -07:00
Mitchell Hashimoto
c5e5d61438 terminal: bring alt screen behaviors much closer in line with xterm
This brings the behavior of mode 47, 1047, and 1049 much closer to
xterm's behavior. I found that our prior implementation had many
deficiencies.

For example, we weren't properly copying the cursor state back to the
primary screen from the alternate screen for modes 47 and 1047. And we
weren't saving/restoring cursor state unconditionally for mode 1049 even
if we were already in the alternate screen.

These are weird, edgy behaviors that I don't think anyone expected
(evidence by there being no bug reports about them), but they are bugs
nontheless.

Many tests added.
2025-05-29 15:43:27 -07:00
Jeffrey C. Ollie
bcf4d55dad OSC: nest ColorOperation-related structs 2025-05-29 11:37:08 -05:00
Jeffrey C. Ollie
35384670c4 OSC: fix typo 2025-05-29 11:37:08 -05:00
Jeffrey C. Ollie
e0ddc7a2fa OSC: clean up color_operation handling 2025-05-29 11:37:08 -05:00
Jeffrey C. Ollie
479fa9f809 OSC: use std.SegmentedList instead of custom data structure 2025-05-29 11:37:07 -05:00
Jeffrey C. Ollie
1d9d253e4d OSC: fix bug with buffer disappearing 2025-05-29 11:37:07 -05:00
Jeffrey C. Ollie
1288296fdc OSC: add a datastructure to prevent some (most?) allocations 2025-05-29 11:37:06 -05:00
Jeffrey C. Ollie
5bb7492955 OSC: convert OSC 110, 111, and 112 and add more tests 2025-05-29 11:37:06 -05:00
Jeffrey C. Ollie
9c1abf487e OSC: start adding structure to allow multiple color operations per OSC 2025-05-29 11:37:06 -05:00
Jonatan Borkowski
21c97aa9d6 add support for buffer switching with CSI ? 47 h/l 2025-05-27 11:48:14 -07:00
Leorize
b6f120a749 termio, flatpak: support spawning terminals in cwd
Implements path access testing for Flatpak via test spawning. This is
required since Flatpak reserves certain paths from being accessible
regardless of permissions.

Ref: https://docs.flatpak.org/en/latest/sandbox-permissions.html#reserved-paths
2025-05-06 13:42:14 -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
c23b389cf1 gtk: implement bell (#7087)
This PR implements a more lightweight alternative to #5326 that contains
features that I personally think Just Make Sense for the bell.

No configs, no GStreamer stuff, just sane defaults to get us started.
2025-04-14 11:19:19 -07:00
Leah Amelia Chen
a0760cabd6 gtk: implement bell
Co-authored-by: Jeffrey C. Ollie <jeff@ocjtech.us>
2025-04-14 23:44:13 +08: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
Leorize
009b53c45e termio, flatpak: implement process watcher with xev
This allows `termio.Exec` to track processes spawned via
`FlatpakHostCommand`, finally allowing Ghostty to function as a
Flatpak.

Alongside this is a few bug fixes:

* Don't add ghostty to PATH when running in flatpak mode since it's
  unreachable.
* Correctly handle exit status returned by Flatpak. Previously this was
  not processed and contains extra status bits.
* Use correct type for PID returned by Flatpak.
2025-03-15 07:29:13 -07:00
Mitchell Hashimoto
0f4d2bb237 Lots of 0.14 changes 2025-03-12 09:55:52 -07:00
Mitchell Hashimoto
7e2286eb8c Zig 0.14 2025-03-11 14:39:04 -07:00