Commit Graph

15320 Commits

Author SHA1 Message Date
Mitchell Hashimoto
e01046af15 docs: extract focus encoding example into standalone project
Extract the inline code example from focus.h into a standalone
buildable example at example/c-vt-encode-focus. The header now
uses a Doxygen @snippet tag to include the code from the example
source file, so the documentation stays in sync with code that
is verified to compile and run.
2026-03-17 16:48:48 -07:00
Mitchell Hashimoto
d3bd224081 terminal/vt: extract size report encoding to its own file (#11607)
Extract size report encoding into a reusable module and expose it
through the libghostty-vt C API as `ghostty_size_report_encode()`.

Size report escape sequences (mode 2048 in-band reports, XTWINOPS CSI
14/16/18 t responses) were formatted inline in
`Termio.sizeReportLocked`, and `termio.Message` carried its own
duplicate enum for report styles. This made the encoding logic
impossible to reuse from the C library and kept the style type
unnecessarily scoped to termio.

## Example

```c
GhosttySizeReportSize size = {
    .rows = 24, .columns = 80,
    .cell_width = 9, .cell_height = 18,
};

char buf[64];
size_t written = 0;
ghostty_size_report_encode(
    GHOSTTY_SIZE_REPORT_MODE_2048, size,
    buf, sizeof(buf), &written);
// buf contains: "\x1b[48;24;80;432;720t"
```
2026-03-17 16:48:09 -07:00
Mitchell Hashimoto
7bf89740dd vt: expose size_report encoding in the C API
Add ghostty_size_report_encode() to libghostty-vt, following the
same pattern as focus encoding: a single stateless function that
writes a terminal size report escape sequence into a caller-provided
buffer.

The size_report.zig Style enum and Size struct now use lib.Enum and
lib.Struct so the types are automatically C-compatible when building
with c_abi, eliminating the need for duplicate type definitions in
the C wrapper. The C wrapper in c/size_report.zig re-exports these
types directly and provides the callconv(.c) encode entry point.

Supports mode 2048 in-band reports and XTWINOPS responses (CSI 14 t,
CSI 16 t, CSI 18 t).
2026-03-17 16:33:57 -07:00
Mitchell Hashimoto
a1d7ad9243 terminal: extract size report encoder
Size report escape sequences were previously formatted inline in
Termio.sizeReportLocked, and termio.Message carried a duplicate enum for
report styles. That made the encoding logic harder to reuse and kept
the style type scoped to termio.

Move the encoding into terminal.size_report and export it through
terminal.main. The encoder now takes renderer.Size directly and derives
grid and pixel dimensions from one source of truth. termio.Message now
aliases terminal.size_report.Style, and Termio writes reports via the
shared encoder.
2026-03-17 16:21:34 -07:00
ghostty-vouch[bot]
45ccc69a49 Update VOUCHED list (#11605)
Triggered by [discussion
comment](https://github.com/ghostty-org/ghostty/discussions/11603#discussioncomment-16184007)
from @jcollie.

Vouch: @philocalyst

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-17 21:05:51 +00:00
Mitchell Hashimoto
d9070dbee2 Fix tmux control parser premature %end/%error block termination (#11597)
Fixes [#11935.](https://github.com/ghostty-org/ghostty/issues/11395)

I’m new to Zig, so I used AI assistance (Codex) while preparing this
change. Before opening this PR, I manually reviewed every line of the
final patch and stepped through the parser in LLDB to verify the
behavior. Happy to make any changes.

To better understand the parser, I also built a small model-checker
model
[here](https://gist.github.com/wyounas/284036272ba5893b6e413cafe2fe2a24).

Separately from this fix, I think formal verification and modeling could
be useful for parser work in Ghostty. The model is written in FizzBee,
which uses a Python-like Starlark syntax and is fairly readable. If that
seems useful, I’d be happy to open a separate discussion about whether
something like that belongs in the repository as executable
documentation or an additional safety net for future parser changes.
2026-03-17 10:32:14 -07:00
ghostty-vouch[bot]
b173b2dfb7 Update VOUCHED list (#11599)
Triggered by [discussion
comment](https://github.com/ghostty-org/ghostty/discussions/11594#discussioncomment-16180979)
from @jcollie.

Vouch: @heddxh

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-17 16:46:10 +00:00
Mitchell Hashimoto
4a88f460c4 terminal/tmux: stylistic cleanups 2026-03-17 08:58:22 -07:00
ghostty-vouch[bot]
739da492b8 Update VOUCHED list (#11598)
Triggered by
[comment](https://github.com/ghostty-org/ghostty/issues/11537#issuecomment-4075954392)
from @mitchellh.

Unvouch: @cadebrown

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-17 15:42:06 +00:00
Mitchell Hashimoto
3a65bd5c4f zsh: use OSC 133;P;k=s for secondary prompts (#11596)
This is consistent with our bash prompt handling and also lets us
simplify our multiline prompt logic (because it no longer needs to work
around 133;A's fresh-line behavior).
2026-03-17 08:35:07 -07:00
Jon Parise
3e0d434e8a zsh: use OSC 133;P;k=s for secondary prompts
This is consistent with our bash prompt handling and also lets us
simplify our multiline prompt logic (because it no longer needs to work
around 133;A's fresh-line behavior).
2026-03-17 10:37:40 -04:00
Leah Amelia Chen
71d6f08e9b gtk: move audio playback into separate file, enabling reuse (#11588) 2026-03-17 04:42:51 +00:00
ghostty-vouch[bot]
9f4e42a523 Update VOUCHED list (#11587)
Triggered by [discussion
comment](https://github.com/ghostty-org/ghostty/discussions/11585#discussioncomment-16170774)
from @jcollie.

Vouch: @heaths

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-17 03:08:46 +00:00
Jeffrey C. Ollie
79162279d9 gtk: move audio playback into separate file, enabling reuse 2026-03-16 19:53:24 -05:00
Mitchell Hashimoto
5e0db1b605 build(deps): bump softprops/action-gh-release from 2.6.0 to 2.6.1 (#11582)
Bumps
[softprops/action-gh-release](https://github.com/softprops/action-gh-release)
from 2.6.0 to 2.6.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/softprops/action-gh-release/releases">softprops/action-gh-release's
releases</a>.</em></p>
<blockquote>
<h2>v2.6.1</h2>
<p><code>2.6.1</code> is a patch release focused on restoring linked
discussion thread creation when
<code>discussion_category_name</code> is set. It fixes
<code>[#764](https://github.com/softprops/action-gh-release/issues/764)</code>,
where the draft-first publish flow
stopped carrying the discussion category through the final publish
step.</p>
<p>If you still hit an issue after upgrading, please open a report with
the bug template and include a minimal repro or sanitized workflow
snippet where possible.</p>
<h2>What's Changed</h2>
<h3>Bug fixes 🐛</h3>
<ul>
<li>fix: preserve discussion category on publish by <a
href="https://github.com/chenrui333"><code>@​chenrui333</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/765">softprops/action-gh-release#765</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md">softprops/action-gh-release's
changelog</a>.</em></p>
<blockquote>
<h2>2.6.1</h2>
<p><code>2.6.1</code> is a patch release focused on restoring linked
discussion thread creation when
<code>discussion_category_name</code> is set. It fixes
<code>[#764](https://github.com/softprops/action-gh-release/issues/764)</code>,
where the draft-first publish flow
stopped carrying the discussion category through the final publish
step.</p>
<p>If you still hit an issue after upgrading, please open a report with
the bug template and include a minimal repro or sanitized workflow
snippet where possible.</p>
<h2>What's Changed</h2>
<h3>Bug fixes 🐛</h3>
<ul>
<li>fix: preserve discussion category on publish by <a
href="https://github.com/chenrui333"><code>@​chenrui333</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/765">softprops/action-gh-release#765</a></li>
</ul>
<h2>2.6.0</h2>
<p><code>2.6.0</code> is a minor release centered on
<code>previous_tag</code> support for
<code>generate_release_notes</code>,
which lets workflows pin GitHub's comparison base explicitly instead of
relying on the default range.
It also includes the recent concurrent asset upload recovery fix, a
<code>working_directory</code> docs sync,
a checked-bundle freshness guard for maintainers, and clearer
immutable-prerelease guidance where
GitHub platform behavior imposes constraints on how prerelease asset
uploads can be published.</p>
<p>If you still hit an issue after upgrading, please open a report with
the bug template and include a minimal repro or sanitized workflow
snippet where possible.</p>
<h2>What's Changed</h2>
<h3>Exciting New Features 🎉</h3>
<ul>
<li>feat: support previous_tag for generate_release_notes by <a
href="https://github.com/pocesar"><code>@​pocesar</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/372">softprops/action-gh-release#372</a></li>
</ul>
<h3>Bug fixes 🐛</h3>
<ul>
<li>fix: recover concurrent asset metadata 404s by <a
href="https://github.com/chenrui333"><code>@​chenrui333</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/760">softprops/action-gh-release#760</a></li>
</ul>
<h3>Other Changes 🔄</h3>
<ul>
<li>docs: clarify reused draft release behavior by <a
href="https://github.com/chenrui333"><code>@​chenrui333</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/759">softprops/action-gh-release#759</a></li>
<li>docs: clarify working_directory input by <a
href="https://github.com/chenrui333"><code>@​chenrui333</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/761">softprops/action-gh-release#761</a></li>
<li>ci: verify dist bundle freshness by <a
href="https://github.com/chenrui333"><code>@​chenrui333</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/762">softprops/action-gh-release#762</a></li>
<li>fix: clarify immutable prerelease uploads by <a
href="https://github.com/chenrui333"><code>@​chenrui333</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/763">softprops/action-gh-release#763</a></li>
</ul>
<h2>2.5.3</h2>
<p><code>2.5.3</code> is a patch release focused on the remaining
path-handling and release-selection bugs uncovered after
<code>2.5.2</code>.
It fixes
<code>[#639](https://github.com/softprops/action-gh-release/issues/639)</code>,
<code>[#571](https://github.com/softprops/action-gh-release/issues/571)</code>,
<code>[#280](https://github.com/softprops/action-gh-release/issues/280)</code>,
<code>[#614](https://github.com/softprops/action-gh-release/issues/614)</code>,
<code>[#311](https://github.com/softprops/action-gh-release/issues/311)</code>,
<code>[#403](https://github.com/softprops/action-gh-release/issues/403)</code>,
and
<code>[#368](https://github.com/softprops/action-gh-release/issues/368)</code>.
It also adds documentation clarifications for
<code>[#541](https://github.com/softprops/action-gh-release/issues/541)</code>,
<code>[#645](https://github.com/softprops/action-gh-release/issues/645)</code>,
<code>[#542](https://github.com/softprops/action-gh-release/issues/542)</code>,
<code>[#393](https://github.com/softprops/action-gh-release/issues/393)</code>,
and
<code>[#411](https://github.com/softprops/action-gh-release/issues/411)</code>,
where the current behavior is either usage-sensitive or constrained by
GitHub platform limits rather than an action-side runtime bug.</p>
<p>If you still hit an issue after upgrading, please open a report with
the bug template and include a minimal repro or sanitized workflow
snippet where possible.</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="153bb8e044"><code>153bb8e</code></a>
release 2.6.1</li>
<li><a
href="569deb874d"><code>569deb8</code></a>
fix: preserve discussion category when publishing releases (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/765">#765</a>)</li>
<li>See full diff in <a
href="26e8ad27a0...153bb8e044">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=softprops/action-gh-release&package-manager=github_actions&previous-version=2.6.0&new-version=2.6.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>
2026-03-16 17:14:11 -07:00
dependabot[bot]
67dcac02f9 build(deps): bump softprops/action-gh-release from 2.6.0 to 2.6.1
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.6.0 to 2.6.1.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](26e8ad27a0...153bb8e044)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-version: 2.6.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-17 00:12:48 +00:00
Jeffrey C. Ollie
f6e92b6895 gtk: refactor application id and resource path (#11580) 2026-03-16 18:43:35 -05:00
ghostty-vouch[bot]
6abed20fc8 Update VOUCHED list (#11581)
Triggered by
[comment](https://github.com/ghostty-org/ghostty/issues/11557#issuecomment-4071331120)
from @mitchellh.

Unvouch: @mvanhorn

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-16 23:39:24 +00:00
Mitchell Hashimoto
b18705c469 libghostty: expose terminal modes and DECRPM report encoding through the C API. (#11579)
Previously libghostty-vt had no way for C consumers to query, set, or
report on terminal modes. Callers that needed to respond to DECRPM
requests or inspect mode state had no public interface to do so.

This adds three layers of mode support to the C API:

- `GhosttyMode` — a 16-bit packed type with inline helpers to construct
and inspect mode tags, plus `GHOSTTY_MODE_*` macros for all supported
ANSI and DEC private modes.
- `ghostty_terminal_mode_get` / `ghostty_terminal_mode_set` — query and
set mode values on a terminal handle.
- `ghostty_mode_report_encode` — encode a DECRPM response sequence (`CSI
[?] Ps1 ; Ps2 $ y`) into a caller-provided buffer.

## Example

```c
#include <stdio.h>
#include <ghostty/vt.h>

int main() {
    char buf[32];
    size_t written = 0;

    // Query a terminal's cursor visibility and encode a DECRPM report
    GhosttyMode mode = GHOSTTY_MODE_CURSOR_VISIBLE;
    bool value = false;
    ghostty_terminal_mode_get(terminal, mode, &value);

    GhosttyModeReportState state = value
        ? GHOSTTY_MODE_REPORT_SET
        : GHOSTTY_MODE_REPORT_RESET;

    if (ghostty_mode_report_encode(mode, state, buf, sizeof(buf), &written)
            == GHOSTTY_SUCCESS) {
        // writes ESC[?25;1$y or ESC[?25;2$y
        fwrite(buf, 1, written, stdout);
    }
}
```
2026-03-16 16:34:48 -07:00
Jeffrey C. Ollie
8a40e37b86 gtk: refactor application id and resource path 2026-03-16 18:26:37 -05:00
Mitchell Hashimoto
bfaab04468 vt: rename mode tag to mode 2026-03-16 16:15:38 -07:00
Mitchell Hashimoto
a460743b2a vt: add mode report encoding to C API
Add ghostty_mode_report_encode() which encodes a DECRPM response
sequence into a caller-provided buffer. The function takes a mode
tag, a report state integer, an output buffer, and writes the
appropriate CSI sequence (with ? prefix for DEC private modes).

The Zig-side ReportState is a non-exhaustive c_int enum that uses
std.meta.intToEnum for safe conversion to the internal type,
returning GHOSTTY_INVALID_VALUE on overflow. The C header exposes
a GhosttyModeReportState enum with named constants for the five
standard DECRPM state values.
2026-03-16 16:10:25 -07:00
Mitchell Hashimoto
1c03770e2b vt: expose terminal modes to C API
Add modes.h with GhosttyModeTag (uint16_t) matching the Zig ModeTag
packed struct layout, along with inline helpers for constructing and
inspecting mode tags. Provide GHOSTTY_MODE_* macros for all 39
built-in modes (4 ANSI, 35 DEC), parenthesized for safety.

Add ghostty_terminal_mode_get and ghostty_terminal_mode_set to
terminal.h, both returning GhosttyResult so that null terminals
and unknown mode tags return GHOSTTY_INVALID_VALUE. The get function
writes its result through a bool out-parameter.

Add a note in the Zig mode entries reminding developers to update
modes.h when adding new modes.
2026-03-16 16:01:53 -07:00
Mitchell Hashimoto
25679f3ae7 vt: add C API header for terminal mode tags
Add modes.h with GhosttyModeTag, a uint16_t typedef matching the
Zig ModeTag packed struct layout (bits 0-14 for the mode value,
bit 15 for the ANSI flag). Three inline helper functions provide
construction and inspection: ghostty_mode_tag_new,
ghostty_mode_tag_value, and ghostty_mode_tag_ansi.
2026-03-16 15:48:26 -07:00
Mitchell Hashimoto
21eb30d9bc terminal: extract DECRPM mode report encoding to terminal package (#11578)
This extracts our mode reporting from being hardcoded in termio to being
reusable in the existing `terminal.modes` namespace. The goal is to
expose this via the Zig API libghostty (done) and C API (to do later).
2026-03-16 15:32:03 -07:00
Mitchell Hashimoto
d6b37ba38f terminal: extract DECRPM mode report encoding to terminal package
This extracts our mode reporting from being hardcoded in termio
to being reusable in the existing `terminal.modes` namespace. The goal
is to expose this via the Zig API libghostty (done) and C API (to do
later).
2026-03-16 15:09:26 -07:00
Mitchell Hashimoto
e90dbc9da6 vt: expose focus encoding in C and Zig APIs (#11577)
Add focus event encoding (CSI I / CSI O) to the libghostty-vt public
API, following the same patterns as key and mouse encoding.

The focus Event enum uses lib.Enum for C ABI compatibility. The C API
provides ghostty_focus_encode() which writes into a caller-provided
buffer and returns GHOSTTY_OUT_OF_SPACE with the required size when the
buffer is too small.

Also update key and mouse encoders to return GHOSTTY_OUT_OF_SPACE
instead of GHOSTTY_OUT_OF_MEMORY for buffer-too-small errors, reserving
OUT_OF_MEMORY for actual allocation failures. Update all corresponding
header documentation.
2026-03-16 15:02:03 -07:00
Mitchell Hashimoto
bed9d92f04 vt: expose focus encoding in C and Zig APIs
Add focus event encoding (CSI I / CSI O) to the libghostty-vt public
API, following the same patterns as key and mouse encoding.

The focus Event enum uses lib.Enum for C ABI compatibility. The C API
provides ghostty_focus_encode() which writes into a caller-provided
buffer and returns GHOSTTY_OUT_OF_SPACE with the required size when
the buffer is too small.

Also update key and mouse encoders to return GHOSTTY_OUT_OF_SPACE
instead of GHOSTTY_OUT_OF_MEMORY for buffer-too-small errors,
reserving OUT_OF_MEMORY for actual allocation failures. Update all
corresponding header documentation.
2026-03-16 14:38:19 -07:00
Leah Amelia Chen
2318e18df3 gtk/wayland: refactor global handling (#11559) 2026-03-16 18:06:37 +00:00
ghostty-vouch[bot]
c1326c57f9 Update VOUCHED list (#11572)
Triggered by [discussion
comment](https://github.com/ghostty-org/ghostty/discussions/10478#discussioncomment-16163586)
from @mitchellh.

Denounce: @highimpact-dev

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-16 17:25:02 +00:00
Leah Amelia Chen
8966d37985 gtk/wayland: refactor global handling
The way we originally handled globals gradually escalated into an unholy
mess of ad-hoc helper functions and special-case handlers, which proved
to be hard to scale. Using a type-erased EnumMap like this makes
everything *far* easier to work and reason with, I think.

Also nuked the `xdg_wm_dialog_v1` hack that was necessary to prevent
old versions of gtk4-layer-shell crashing. If by the time of 1.4's
release people are still using those versions, it's on them.
2026-03-17 01:14:59 +08:00
Mitchell Hashimoto
a811b6074b Lots of duplicate word typos + typo (#11539)
TL;DR: this description is (intentionally) nonsense but I ran
`\b(\w+)\s\1\b` over `src` and stole a singular typo fix from #11528.

Replacement of #11528 with 100% less slop and 99% less AI; I didn't feel
like saying no to free(ish) typo checking. Note that many of the fixes
there were outright incorrect (and clearly had no review from sentient
lifeforms, contrary to its—sorry, it's—description). A lot of extra
double words were caught with a handy `rg --pcre2 '\b(\w+)\s+\1\b' src`;
you could say this PR was “ripgrep-assisted” the way that one was
“AI-assisted”. Rather ironic since that PR also claims to have used grep
via Claude Code, but missed a lot of them.

The its → it's changes from that PR were elided; I decided to run a `rg
"\bit'?s\b" src`, but someone REALLY likes their its, so I reverted my
changes as there were an extremely large number of changes (probably a
hundred files with multiple hundred cases). The only other change was
“baout” → “about”.

# AI Usage

Claude Code was used by proxy for finding baout. Claude Code was used by
proxy for realizing that the correct spelling is about. Claude Code was
not used for fixing it. Oh my god it was so difficult to fix, the
original PR had it so easy. I had to type out the file name (fish's AI
sorry I mean autocomplete helped though) and like, type /baout, press R,
press ab, then save and exit. This is so difficult you know we should
use an AI for this, like this is so hard I don't know how people manage.

All changes were verified by me: I consulted the dictionary to delve
into double-checkment of “in existence; being in evidence; apparent.”
Uhhh insert assorted other AI impersonation here maybe? THE LLM IN ME
WANTS TO ESCAPE PLEASE HELP
2026-03-16 09:52:35 -07:00
Mitchell Hashimoto
cce205d01b cli: add +explain-config (#11546)
This is a new CLI action that prints an option or keybind's help
documentation to stdout.

    ghostty +explain-config font-size
    ghostty +explain-config copy_to_clipboard
    ghostty +explain-config --option=font-size
    ghostty +explain-config --keybind=copy_to_clipboard

The --option and --keybind flags perform a specific lookup. A string
passed as a positional argument attempts to look up the name first as an
option and then as a keybind.

Our vim plugin uses this with &keywordprg, which allows you to look up
the documentation for the config option or keybind under the cursor (K).
2026-03-16 09:51:48 -07:00
Mitchell Hashimoto
03806dad3a ci: skip milestone workflow for bot-authored PRs (#11570)
The milestone action currently runs for all merged pull_request_target
close events, including PRs opened by bots such as dependabot and
ghostty-vouch. That causes milestone binding to run on automated PRs
that should be ignored.

Gate the update-milestone job so pull request events only run when the
author is not a bot, while still allowing closed-issue events to run.
This preserves existing issue milestone behavior and prevents bot PRs
from triggering the workflow.
2026-03-16 09:35:37 -07:00
Mitchell Hashimoto
2d2d913f80 ci: skip milestone workflow for bot-authored PRs
The milestone action currently runs for all merged pull_request_target
close events, including PRs opened by bots such as dependabot and
ghostty-vouch. That causes milestone binding to run on automated PRs
that should be ignored.

Gate the update-milestone job so pull request events only run when the
author is not a bot, while still allowing closed-issue events to run.
This preserves existing issue milestone behavior and prevents bot PRs
from triggering the workflow.
2026-03-16 09:34:37 -07:00
Jon Parise
925992abd9 shell-integration: fix ssh-env SetEnv clobbering user SSH config (#11518)
## Problem

Ghostty's `ssh-env` shell integration uses `-o "SetEnv
COLORTERM=truecolor"` when wrapping SSH commands. OpenSSH treats
command-line `-o SetEnv` options as **replacements** for all `SetEnv`
entries in `~/.ssh/config`, not additions. This silently drops any
user-configured `SetEnv` variables.

For example, a user with this in their SSH config:
```
Host myserver
  SetEnv MY_VAR=hello
```
...would find `MY_VAR` empty after SSHing through Ghostty with `ssh-env`
enabled.

Reference: https://github.com/ghostty-org/ghostty/discussions/10871

## Fix

Replace `-o "SetEnv COLORTERM=truecolor"` with the additive pattern: set
`COLORTERM=truecolor` locally before the SSH call and forward it via
`SendEnv`.

`SendEnv` is additive — it does not clobber `SetEnv` entries in
`~/.ssh/config`.

**Trade-off:** `SendEnv` requires `AcceptEnv COLORTERM` on the remote
server (unlike `SetEnv`). But this was already the case for
`TERM_PROGRAM`/`TERM_PROGRAM_VERSION`, so it's a consistent and
acceptable approach.

## Changes

All 5 shell integration files updated with the same pattern:

- `SetEnv COLORTERM=truecolor` option removed
- `COLORTERM` added to the existing `SendEnv` option
- `COLORTERM=truecolor` set as a local env var on the execute line (so
`SendEnv` has something to forward)

## Test plan

- [ ] Enable `ssh-env` in Ghostty config: `shell-integration-features =
ssh-env`
- [ ] Add `SetEnv MY_VAR=hello` under a host in `~/.ssh/config` and
`AcceptEnv MY_VAR` in `/etc/ssh/sshd_config` on the remote
- [ ] SSH to that host — `echo $MY_VAR` should return `hello` (was empty
before this fix)
- [ ] `echo $COLORTERM` returns `truecolor` (requires `AcceptEnv
COLORTERM`)
- [ ] `echo $TERM_PROGRAM` still propagates (same `AcceptEnv`
requirement as before)
2026-03-16 08:01:33 -04:00
Leah Amelia Chen
a3fe5974e8 Add missing plural forms for Chinese (#11562) 2026-03-16 10:00:27 +00:00
Kat
3b60ef3b34 Add missing plural forms (or, the lack thereof) for Chinese. 2026-03-16 20:43:40 +11:00
Waqas Younas
978abdeebc Fix tmux control block terminator parsing 2026-03-16 12:46:54 +05:00
Leah Amelia Chen
600f59ae31 gtk: implement quick-terminal-screen for Linux/Wayland (#11117) 2026-03-16 06:30:02 +00:00
ghostty-vouch[bot]
44f403bfe1 Update VOUCHED list (#11556)
Triggered by [discussion
comment](https://github.com/ghostty-org/ghostty/discussions/11536#discussioncomment-16152546)
from @pluiedev.

Vouch: @mvanhorn

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-16 05:42:48 +00:00
Mitchell Hashimoto
0f2eaed68c libghostty: add mouse encoding Zig + C API (#11553)
This adds a Zig and C API for mouse event encoding. 

With these APIs in place, users can now create mouse events, configure a
mouse encoder with tracking mode, output format, and terminal size, and
encode those events into terminal escape sequences. All standard mouse
protocols are supported: X10, UTF-8, SGR, URxvt, and SGR-Pixels.

## Example

```c
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <ghostty/vt.h>

int main() {
  GhosttyMouseEncoder encoder;
  GhosttyResult result = ghostty_mouse_encoder_new(NULL, &encoder);
  assert(result == GHOSTTY_SUCCESS);

  // Set tracking mode to normal (button press/release)
  ghostty_mouse_encoder_setopt(encoder, GHOSTTY_MOUSE_ENCODER_OPT_EVENT,
                               &(GhosttyMouseTrackingMode){GHOSTTY_MOUSE_TRACKING_NORMAL});

  // Set output format to SGR
  ghostty_mouse_encoder_setopt(encoder, GHOSTTY_MOUSE_ENCODER_OPT_FORMAT,
                               &(GhosttyMouseFormat){GHOSTTY_MOUSE_FORMAT_SGR});

  // Set terminal geometry so the encoder can map pixel positions to cells
  ghostty_mouse_encoder_setopt(encoder, GHOSTTY_MOUSE_ENCODER_OPT_SIZE,
                               &(GhosttyMouseEncoderSize){
                                   .size = sizeof(GhosttyMouseEncoderSize),
                                   .screen_width = 800, .screen_height = 600,
                                   .cell_width = 10, .cell_height = 20,
                               });

  // Create mouse event: left button press at pixel position (50, 40)
  GhosttyMouseEvent event;
  result = ghostty_mouse_event_new(NULL, &event);
  assert(result == GHOSTTY_SUCCESS);
  ghostty_mouse_event_set_action(event, GHOSTTY_MOUSE_ACTION_PRESS);
  ghostty_mouse_event_set_button(event, GHOSTTY_MOUSE_BUTTON_LEFT);
  ghostty_mouse_event_set_position(event, (GhosttyMousePosition){.x = 50.0f, .y = 40.0f});

  // Encode the mouse event
  char buf[128];
  size_t written = 0;
  result = ghostty_mouse_encoder_encode(encoder, event, buf, sizeof(buf), &written);
  assert(result == GHOSTTY_SUCCESS);

  fwrite(buf, 1, written, stdout);

  ghostty_mouse_event_free(event);
  ghostty_mouse_encoder_free(encoder);
  return 0;
}
```

## New APIs

| Function | Description |
|----------|-------------|
| `ghostty_mouse_event_new` | Create a new mouse event instance |
| `ghostty_mouse_event_free` | Free a mouse event instance |
| `ghostty_mouse_event_set_action` | Set the event action (press,
release, motion) |
| `ghostty_mouse_event_get_action` | Get the event action |
| `ghostty_mouse_event_set_button` | Set the event button |
| `ghostty_mouse_event_clear_button` | Clear the event button (for
motion events) |
| `ghostty_mouse_event_get_button` | Get the event button (returns
whether one is set) |
| `ghostty_mouse_event_set_mods` | Set keyboard modifiers held during
the event |
| `ghostty_mouse_event_get_mods` | Get keyboard modifiers held during
the event |
| `ghostty_mouse_event_set_position` | Set position in surface-space
pixels |
| `ghostty_mouse_event_get_position` | Get position in surface-space
pixels |
| `ghostty_mouse_encoder_new` | Create a new mouse encoder instance |
| `ghostty_mouse_encoder_free` | Free a mouse encoder instance |
| `ghostty_mouse_encoder_setopt` | Set an encoder option (tracking mode,
format, size, etc.) |
| `ghostty_mouse_encoder_setopt_from_terminal` | Sync encoder options
from a terminal's current state |
| `ghostty_mouse_encoder_reset` | Reset internal encoder state (motion
deduplication) |
| `ghostty_mouse_encoder_encode` | Encode a mouse event into a terminal
escape sequence |
2026-03-15 20:26:56 -07:00
Mitchell Hashimoto
de87456a9b lib/vt: export mouse encoding API
Export mouse_encode types and functions through the lib_vt public
input API, mirroring the existing key encoding exports. This adds
MouseAction, MouseButton, MouseEncodeOptions, MouseEncodeEvent,
and encodeMouse so that consumers of the Zig module can encode
mouse events without reaching into internal packages.
2026-03-15 20:16:00 -07:00
Mitchell Hashimoto
33b05b9876 example: add C mouse encoding example
Add a new c-vt-mouse-encode example that demonstrates how to use the
mouse encoder C API. The example creates a mouse encoder configured
with SGR format and normal tracking mode, sets up terminal geometry
for pixel-to-cell coordinate mapping, and encodes a left button press
event into a terminal escape sequence.

Mirrors the structure of the existing c-vt-key-encode example. Also
adds the corresponding @example doxygen reference in vt.h.
2026-03-15 20:14:07 -07:00
Mitchell Hashimoto
9b35c2bb65 vt: add mouse encoding C API
Expose the internal mouse encoding functionality through the C API,
following the same pattern as the existing key encoding API. This
allows external consumers of libvt to encode mouse events into
terminal escape sequences (X10, UTF-8, SGR, URxvt, SGR-Pixels).

The API is split into two opaque handle types: GhosttyMouseEvent
for building normalized mouse events (action, button, modifiers,
position) and GhosttyMouseEncoder for converting those events into
escape sequences. The encoder is configured via a setopt interface
supporting tracking mode, output format, renderer geometry, button
state, and optional motion deduplication by last cell.

Encoder state can also be bulk-configured from a terminal handle
via ghostty_mouse_encoder_setopt_from_terminal. Failed encodes due
to insufficient buffer space report the required size without
mutating deduplication state.
2026-03-15 20:09:54 -07:00
Mitchell Hashimoto
79e023b65e terminal,renderer: convert structs to extern
Convert Coordinate in terminal/point.zig and CellSize, ScreenSize,
GridSize, and Padding in renderer/size.zig to extern structs. All
fields are already extern-compatible types, so this gives them a
guaranteed C ABI layout with no functional change.
2026-03-15 19:39:17 -07:00
Mitchell Hashimoto
37efac99b0 terminal/mouse: convert Event and Format to lib.Enum
Convert the Event and Format enums from fixed-size Zig enums to
lib.Enum so they are C ABI compatible when targeting C. The motion
method on Event becomes a free function eventIsMotion since lib.Enum
types cannot have declarations.
2026-03-15 19:35:54 -07:00
Jon Parise
9783f6c79c cli: tests for +explain-config explain functions 2026-03-15 21:04:35 -04:00
Jon Parise
cef1f19d24 cli: add +explain-config
This is a new CLI action that prints an option or keybind's help
documentation to stdout.

    ghostty +explain-config font-size
    ghostty +explain-config copy_to_clipboard
    ghostty +explain-config --option=font-size
    ghostty +explain-config --keybind=copy_to_clipboard

The --option and --keybind flags perform a specific lookup. A string
passed as a positional argument attempts to look up the name first as an
option and then as a keybind.

Our vim plugin uses this with &keywordprg, which allows you to look up
the documentation for the config option or keybind under the cursor (K).
2026-03-15 20:58:43 -04:00
Kat
41c7321e94 Add missing plural forms (#11541)
Supersedes #11529; I did not use their plural forms because I trust
ctrl+c more than Claude Code.

`mk` and `zh_*` are still missing theirs, but neither [gettext's table]
nor the [documentation it copied from] list them. That PR has them too,
with values magicked from… somewhere? The [data they linked] is
illegible to me.

[gettext's table]:
https://cgit.git.savannah.gnu.org/cgit/gettext.git/tree/gettext-tools/src/plural-table.c?id=dbf9d71e0c4707ca1b14359256b3dcccecb8e837
[documentation it copied from]:
https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html
[data they linked]:
https://www.unicode.org/cldr/charts/48/supplemental/language_plural_rules.html
2026-03-16 00:20:03 +00:00