feat(cli): port ghostty +action CLI commands

Ports ZIG/src/cli into ghostty-cli: action detection/dispatch with
per-action --help, and the actions help, version, list-actions,
list-colors, list-keybinds, list-themes (plain listing plus an
interactive ratatui browser mirroring Ghostty's libvaxis UI),
show-config, validate-config, edit-config, crash-report (listing),
ssh-cache and boo (235 embedded frames).

Verified byte-for-byte against the installed Ghostty 1.3.1 for stdout,
stderr and exit codes of most actions, incl. tty output in a pty at
widths 20-200. Known differences: +list-colors --plain prints all 782
colors (Ghostty truncates at 617 because it never flushes), +version
has placeholder build info until build_info::set is wired up.

Deferred: list-fonts, show-face (need font discovery integration) and
new-window (needs GTK IPC); they return NotYetAvailable for now.

Test Plan:
- cargo test -p ghostty-cli (86 tests)
- cargo run -p ghostty-cli --example cli -- +list-keybinds --plain
  and diff against `ghostty +list-keybinds --plain`
This commit is contained in:
ddidderr committed 2026-10-11 22:22:01 +02:00
1 parent 5462bd8e3e
commit f2c4b40062
46 files changed
+7135 -6

No files matched your search

@@ -0,0 +1,62 @@
The `new-window` will use native platform IPC to open up a new window in a
running instance of Ghostty.
If the `--class` flag is not set, the `new-window` command will try and
connect to a running instance of Ghostty based on what optimizations the
Ghostty CLI was compiled with. Otherwise the `new-window` command will try
and contact a running Ghostty instance that was configured with the same
`class` as was given on the command line.
All of the arguments after the `+new-window` argument (except for the
`--class` flag) will be sent to the remote Ghostty instance and will be
parsed as command line flags. These flags will override certain settings
when creating the first surface in the new window. Currently, only
`--working-directory`, `--command`, and `--title` are supported. `-e` will
also work as an alias for `--command`, except that if `-e` is found on the
command line all following arguments will become part of the command and no
more arguments will be parsed for configuration settings.
If `--working-directory` is found on the command line and is a relative
path (i.e. doesn't start with `/`) it will be resolved to an absolute path
relative to the current working directory that the `ghostty +new-window`
command is run from. `~/` prefixes will also be expanded to the user's home
directory.
If `--working-directory` is _not_ found on the command line, the working
directory that `ghostty +new-window` is run from will be passed to Ghostty.
GTK uses an application ID to identify instances of applications. If Ghostty
is compiled with release optimizations, the default application ID will be
`com.mitchellh.ghostty`. If Ghostty is compiled with debug optimizations,
the default application ID will be `com.mitchellh.ghostty-debug`. The
`class` configuration entry can be used to set up a custom application
ID. The class name must follow the requirements defined [in the GTK
documentation](https://docs.gtk.org/gio/type_func.Application.id_is_valid.html)
or it will be ignored and Ghostty will use the default as defined above.
On GTK, D-Bus activation must be properly configured. Ghostty does not need
to be running for this to open a new window, making it suitable for binding
to keys in your window manager (if other methods for configuring global
shortcuts are unavailable). D-Bus will handle launching a new instance
of Ghostty if it is not already running. See the Ghostty website for
information on properly configuring D-Bus activation.
Only supported on GTK.
Flags:
* `--class=<class>`: If set, open up a new window in a custom instance of
Ghostty. The class must be a valid GTK application ID.
* `--command`: The command to be executed in the first surface of the new window.
* `--working-directory=<directory>`: The working directory to pass to Ghostty.
* `--title`: A title that will override the title of the first surface in
the new window. The title override may be edited or removed later.
* `-e`: Any arguments after this will be interpreted as a command to
execute inside the first surface of the new window instead of the
default command.
Available since: 1.2.0