Skip to content

Sync fork with upstream Ghostty main#11

Closed
lawrencecchen wants to merge 750 commits intomainfrom
issue-824-sync-upstream
Closed

Sync fork with upstream Ghostty main#11
lawrencecchen wants to merge 750 commits intomainfrom
issue-824-sync-upstream

Conversation

@lawrencecchen
Copy link

@lawrencecchen lawrencecchen commented Mar 12, 2026

Summary

  • rebase the cmux Ghostty fork onto current ghostty-org/ghostty main at a2b2b883e
  • reapply the cmux patch stack for OSC 99 notifications, resize stale-frame handling, keyboard copy-mode selection, Pure prompt redraws, and the theme picker helper hooks
  • publish the matching xcframework release for the rebased fork commit at https://github.com/manaflow-ai/ghostty/releases/tag/xcframework-3cc60d5e399d9f2985f64155f451808afd876a4c

Testing

  • zig build -Demit-xcframework=true -Demit-macos-app=false -Dxcframework-target=universal -Doptimize=ReleaseFast

Issues

jcollie and others added 30 commits March 4, 2026 14:04
…11169)

This reverts commit ee4c6f8.

This breaks standard `zig build run` from a dev shell in Nix/NixOS. I
think we need to rethink some of the protections here, possibly only to
apply to packaging/release modes or something.

cc @jcollie
Fixes ghostty-org#8208

Split-tree updates currently clear `tree_bin` and then wait for every surface
to become parentless before rebuilding. That leaves the split area blank for
one or more frames, which is the visible flicker during split create/close/
resize/equalize actions.

Keep the previous widget tree attached until the idle rebuild runs, then
swap in the rebuilt tree in one step. During rebuild, reuse existing
leaf widgets by detaching and reparenting them into the new `GtkPaned` 
hierarchy instead of recreating wrappers for every leaf.

This removes the parent-settling rebuild path and avoids transient blank
frames while preserving debounced rebuild behavior.
…-org#11170)

Fixes ghostty-org#8208

Split-tree updates currently clear `tree_bin` and then wait for every
surface to become parentless before rebuilding. That leaves the split
area blank for one or more frames, which is the visible flicker during
split create/close/ resize/equalize actions.

Keep the previous widget tree attached until the idle rebuild runs, then
swap in the rebuilt tree in one step. During rebuild, reuse existing
leaf widgets by detaching and reparenting them into the new `GtkPaned`
hierarchy instead of recreating wrappers for every leaf.

This removes the parent-settling rebuild path and avoids transient blank
frames while preserving debounced rebuild behavior.
…ty-org#10809)

Fixes: ghostty-org#8862
Fixes: ghostty-org#10716

This adds the machinery to pass configuration settings received over
DBus down to the GObject Surface so that that configuration information
can be used to override some settings from the current "live" config
when creating a new window. Currently it's only possible to override
`--working-directory`, `--command`, and `--title`. `-e` on the `ghostty
+new-window` CLI works as well.

Adding more overridable settings is possible, but being able to fully
override any possible setting would better be served with a major revamp
of how Ghostty handles configs, which is way out of scope at the moment.
Triggered by
[comment](ghostty-org#11175 (comment))
from @jcollie.

Vouch: @douglas

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Triggered by [discussion
comment](ghostty-org#11164 (comment))
from @mitchellh.

Vouch: @Michielvk

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This was introduced in ghostty-org#10611. This doesn't fix all of the current
Windows build problems, but at least fixes one that I introduced.
This was introduced in ghostty-org#10611. This doesn't fix all of the current
Windows build problems, but at least fixes one that I introduced.
Fixes ghostty-org#11177

Use per-search Oniguruma match params (retry_limit_in_search) in
StringMap-backed link detection to avoid pathological backtracking hangs
on very long lines.

The units are ticks in the internal loop so its kind of opaque but
this seems to still match some very long URLs. The test case in question
was a 169K character line (which is now rejected).
…hostty-org#11181)

Fixes ghostty-org#11177

Use per-search Oniguruma match params (retry_limit_in_search) in
StringMap-backed link detection to avoid pathological backtracking hangs
on very long lines.

The units are ticks in the internal loop so its kind of opaque but this
seems to still match some very long URLs. The test case in question was
a 169K character line (which is now rejected).
Adds support for the Vietnamese language
…hostty-org#11185)

I encountered an issue related to
ghostty-org#8641 and
ghostty-org#8647, but in `zsh` instead
of `bash`.

One of my aliases is:

```bash
alias sudo='sudo '
```

Which causes following error when sourcing the zsh shell integrations:

```shell
source /usr/share/ghostty/shell-integration/zsh/ghostty-integration
/usr/share/ghostty/shell-integration/zsh/ghostty-integration:149: defining function based on alias `sudo'
/usr/share/ghostty/shell-integration/zsh/ghostty-integration:233: parse error near `()'
```
Triggered by
[comment](ghostty-org#11190 (comment))
from @00-kat.

Vouch: @AnthonyZhOon

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Triggered by [discussion
comment](ghostty-org#11184 (comment))
from @mitchellh.

Vouch: @mac0ne

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Some more fixes to get Windows building again. `zig build` on
x64_64-windows now succeeds but `zig build test` fails in
`src/terminal/page.zig` because Zig/Windows lacks a POSIX `mmap`
implementation.
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.19.2 to 7.0.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](docker/build-push-action@10e90e3...d08e5c3)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
…tty-org#11199)

Bumps
[docker/build-push-action](https://github.com/docker/build-push-action)
from 6.19.2 to 7.0.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/docker/build-push-action/releases">docker/build-push-action's
releases</a>.</em></p>
<blockquote>
<h2>v7.0.0</h2>
<ul>
<li>Node 24 as default runtime (requires <a
href="https://github.com/actions/runner/releases/tag/v2.327.1">Actions
Runner v2.327.1</a> or later) by <a
href="https://github.com/crazy-max"><code>@​crazy-max</code></a> in <a
href="https://redirect.github.com/docker/build-push-action/pull/1470">docker/build-push-action#1470</a></li>
<li>Remove deprecated <code>DOCKER_BUILD_NO_SUMMARY</code> and
<code>DOCKER_BUILD_EXPORT_RETENTION_DAYS</code> envs by <a
href="https://github.com/crazy-max"><code>@​crazy-max</code></a> in <a
href="https://redirect.github.com/docker/build-push-action/pull/1473">docker/build-push-action#1473</a></li>
<li>Remove legacy export-build tool support for build summary by <a
href="https://github.com/crazy-max"><code>@​crazy-max</code></a> in <a
href="https://redirect.github.com/docker/build-push-action/pull/1474">docker/build-push-action#1474</a></li>
<li>Switch to ESM and update config/test wiring by <a
href="https://github.com/crazy-max"><code>@​crazy-max</code></a> in <a
href="https://redirect.github.com/docker/build-push-action/pull/1466">docker/build-push-action#1466</a></li>
<li>Bump <code>@​actions/core</code> from 1.11.1 to 3.0.0 in <a
href="https://redirect.github.com/docker/build-push-action/pull/1454">docker/build-push-action#1454</a></li>
<li>Bump <code>@​docker/actions-toolkit</code> from 0.62.1 to 0.79.0 in
<a
href="https://redirect.github.com/docker/build-push-action/pull/1453">docker/build-push-action#1453</a>
<a
href="https://redirect.github.com/docker/build-push-action/pull/1472">docker/build-push-action#1472</a>
<a
href="https://redirect.github.com/docker/build-push-action/pull/1479">docker/build-push-action#1479</a></li>
<li>Bump minimatch from 3.1.2 to 3.1.5 in <a
href="https://redirect.github.com/docker/build-push-action/pull/1463">docker/build-push-action#1463</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/docker/build-push-action/compare/v6.19.2...v7.0.0">https://github.com/docker/build-push-action/compare/v6.19.2...v7.0.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/docker/build-push-action/commit/d08e5c354a6adb9ed34480a06d141179aa583294"><code>d08e5c3</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/build-push-action/issues/1479">#1479</a>
from docker/dependabot/npm_and_yarn/docker/actions-t...</li>
<li><a
href="https://github.com/docker/build-push-action/commit/cbd2dff9a0f0ef650dcce9c635bb2f877ab37be5"><code>cbd2dff</code></a>
chore: update generated content</li>
<li><a
href="https://github.com/docker/build-push-action/commit/f76f51f12900bb84aa9d1a498f35870ef1f76675"><code>f76f51f</code></a>
chore(deps): Bump <code>@​docker/actions-toolkit</code> from 0.78.0 to
0.79.0</li>
<li><a
href="https://github.com/docker/build-push-action/commit/7d03e66b5f24d6b390ab64b132795fd3ef4152c8"><code>7d03e66</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/build-push-action/issues/1473">#1473</a>
from crazy-max/rm-deprecated-envs</li>
<li><a
href="https://github.com/docker/build-push-action/commit/98f853d923dd281a3bcbbb98a0712a91aa913322"><code>98f853d</code></a>
chore: update generated content</li>
<li><a
href="https://github.com/docker/build-push-action/commit/cadccf6e8c7385c86d9cb0800cf07672645cc238"><code>cadccf6</code></a>
remove deprecated envs</li>
<li><a
href="https://github.com/docker/build-push-action/commit/03fe8775e325e34fffbda44c73316f8287aea372"><code>03fe877</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/build-push-action/issues/1478">#1478</a>
from docker/dependabot/github_actions/docker/setup-b...</li>
<li><a
href="https://github.com/docker/build-push-action/commit/827e36650e1fa7386d09422b5ba3c068fdbe0a1d"><code>827e366</code></a>
chore(deps): Bump docker/setup-buildx-action from 3 to 4</li>
<li><a
href="https://github.com/docker/build-push-action/commit/e25db879d025485a4eebd64fea9bb88a43632da6"><code>e25db87</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/build-push-action/issues/1474">#1474</a>
from crazy-max/rm-export-build-tool</li>
<li><a
href="https://github.com/docker/build-push-action/commit/1ac2573b5c8b4e4621d5453ab2a99e83725242bd"><code>1ac2573</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/build-push-action/issues/1470">#1470</a>
from crazy-max/node24</li>
<li>Additional commits viewable in <a
href="https://github.com/docker/build-push-action/compare/10e90e3645eae34f1e60eeb005ba3a3d33f178e8...d08e5c354a6adb9ed34480a06d141179aa583294">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=docker/build-push-action&package-manager=github_actions&previous-version=6.19.2&new-version=7.0.0)](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>
This is an update to address common agentic issues I run into,
but the `build.nu` script may be generally helpful to people using
the Nix env since `xcodebuild` is broken by default in Nix due to the
compiler/linker overrides Nix shell does.
mitchellh and others added 25 commits March 14, 2026 15:42
)

This adds an initial C API for terminals and formatting. There is a new
example that shows how to use this.

With these APIs in place, users of the C API can now create a terminal,
pass raw VT streams to it, and dump the terminal viewport to various
formats. As noted in the docs, **the formatter API is not a rendering
API**, it isn't high performance enough for that. But it's a simpler API
to implement than the render state API so I started with that.

Both APIs are purposely fairly minimal, we're just setting the stage for
future functionality.

## Example

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

int main() {
  GhosttyTerminal term;
  GhosttyTerminalOptions opts = { .cols = 80, .rows = 24, .max_scrollback = 0 };
  ghostty_terminal_new(NULL, &term, opts);

  const char *input = "Hello, \033[1mBold\033[0m World!\r\nLine 2\r\n";
  ghostty_terminal_vt_write(term, (const uint8_t *)input, strlen(input));

  GhosttyFormatterTerminalOptions fmt = GHOSTTY_INIT_SIZED(GhosttyFormatterTerminalOptions);
  fmt.emit = GHOSTTY_FORMATTER_FORMAT_PLAIN;
  fmt.trim = true;

  GhosttyFormatter fmtr;
  ghostty_formatter_terminal_new(NULL, &fmtr, term, fmt);

  uint8_t *buf;
  size_t len;
  ghostty_formatter_format_alloc(fmtr, NULL, &buf, &len);
  fwrite(buf, 1, len, stdout);

  free(buf);
  ghostty_formatter_free(fmtr);
  ghostty_terminal_free(term);
}
```

## New APIs

| Function | Description |
|----------|-------------|
| `ghostty_terminal_new` | Create a new terminal instance |
| `ghostty_terminal_free` | Free a terminal instance |
| `ghostty_terminal_reset` | Full reset of the terminal (RIS) |
| `ghostty_terminal_resize` | Resize the terminal to given dimensions |
| `ghostty_terminal_vt_write` | Write VT-encoded data to the terminal |
| `ghostty_terminal_scroll_viewport` | Scroll the terminal viewport |
| `ghostty_formatter_terminal_new` | Create a formatter for a terminal's
active screen |
| `ghostty_formatter_format_buf` | Format into a caller-provided buffer
|
| `ghostty_formatter_format_alloc` | Format into an allocated buffer |
| `ghostty_formatter_free` | Free a formatter instance |

## Future

- Obviously need to expose a lot more from the terminal:
  * Read current set modes
  * Read cursor information
  * Read screen information
  * etc...
- Need an optional callback system so that `vt_write` can invoke
callbacks for side effect sequences like clipboards, title setting,
responses, etc.
- `terminal.RenderState` C API so that people can build high performance
renderers on top of libghostty-vt

And so on...
Change `window-padding-balance` from `bool` to an enum with three
values:

- `false` - no balancing (default, unchanged)
- `true` - balance with vshift that caps top padding and shifts excess
  to bottom (existing behavior, unchanged)
- `equal` - balance whitespace equally on all four sides

This gives users who prefer truly equal padding a way to opt in without
changing the default behavior.
…1491)

Change `window-padding-balance` from `bool` to an enum with three
values:

- `false` - no balancing (default, unchanged)
- `true` - balance with vshift that caps top padding and shifts excess
to bottom (existing behavior, unchanged)
- `equal` - balance whitespace equally on all four sides

This gives users who prefer truly equal padding a way to opt in without
changing the default behavior.
Expose the key encoder Options.fromTerminal function to the C API as
ghostty_key_encoder_setopt_from_terminal. This lets C callers sync all
terminal-derived encoding options (cursor key application mode, keypad
mode, alt escape prefix, modifyOtherKeys, and Kitty flags) in a single
call instead of setting each option individually.
Expose the key encoder Options.fromTerminal function to the C API as
ghostty_key_encoder_setopt_from_terminal. This lets C callers sync all
terminal-derived encoding options (cursor key application mode, keypad
mode, alt escape prefix, modifyOtherKeys, and Kitty flags) in a single
call instead of setting each option individually.
Triggered by [discussion
comment](ghostty-org#11041 (comment))
from @mitchellh.

Vouch: @davidsanchez222

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Triggered by [discussion
comment](ghostty-org#11250 (comment))
from @mitchellh.

Vouch: @PowerUser64

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Triggered by [discussion
comment](ghostty-org#11237 (comment))
from @mitchellh.

Vouch: @cadebrown

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Move mouse event encoding logic from Surface.zig into a new
input/mouse_encode.zig file.

The new file encapsulates event filtering (shouldReport),
button code computation, viewport bounds checking, motion
deduplication, and all five wire formats (X10, UTF-8, SGR,
urxvt, SGR-pixels). This makes the encoding independently
testable and adds unit tests covering each format and edge
case.

Additionally, Surface `mouseReport` can no longer fail, since the only
failure mode is no buffer space which should be impossible. Updated
the signature to remove the error set.
…1538)

Move mouse event encoding logic from Surface.zig into a new
input/mouse_encode.zig file.

The new file encapsulates event filtering (shouldReport), button code
computation, viewport bounds checking, motion deduplication, and all
five wire formats (X10, UTF-8, SGR, urxvt, SGR-pixels). This makes the
encoding independently testable and adds unit tests covering each format
and edge case.

Additionally, Surface `mouseReport` can no longer fail, since the only
failure mode is no buffer space which should be impossible. Updated the
signature to remove the error set.
Triggered by
[comment](ghostty-org#11518 (comment))
from @jparise.

Vouch: @j0hnm4r5

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3cc60d5e39

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1207 to +1211
if (self.last_bottom_node == @intFromPtr(br.node) and
self.last_bottom_y == br.y) break :scroll;

// Update tracked pin state for next frame
self.last_bottom_node = @intFromPtr(br.node);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Limit output auto-scroll trigger to real terminal output

This heuristic treats any bottom-right pin change as "new output," but that pin also changes during resize/reflow, so users with scroll-to-bottom.output enabled can be forced back to the bottom just by resizing while reading scrollback. The config docs define output as new data arriving, so this check should be tied to actual terminal output/dirty state rather than geometry-driven pin movement.

Useful? React with 👍 / 👎.

@lawrencecchen
Copy link
Author

Superseded by #14, which rebases the fork from a fresh non-issue branch and publishes the matching xcframework release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.