Skip to content

Merge upstream-main into main#34

Merged
nicosuave merged 309 commits intomainfrom
merge-upstream-2026-03-10
Mar 10, 2026
Merged

Merge upstream-main into main#34
nicosuave merged 309 commits intomainfrom
merge-upstream-2026-03-10

Conversation

@nicosuave
Copy link
Member

Summary

  • merge the latest upstream Ghostty changes from upstream-main into Ghostree main
  • keep Ghostree-specific dock badge, titlebar, and workspace container behavior while resolving macOS merge conflicts
  • fix follow-up macOS build issues around glass container updates and Swift Sendable annotations so zig build run works again

Verification

  • zig build run
  • zig build test

mitchellh and others added 30 commits February 27, 2026 11:41
Following the discussion at ghostty-org#10852, I believe this is the right default.
I'm willing to continue to revisit this decisions, but Ghostty 1.3 is
around the corner and I don't think such a change like this should be
pushed into it.

This was proposed before but I wanted to wait to iron out any bugs here
and I think we have. Namely we identified one bug where we were
accidentally overriding our _default_ palette which shouldn't happen.
But now that it has sat awhile and we've gathered enough feedback, I'm
willing to commit to it.

In general, we got **very little negative feedback.** The linked
discussion shows very little activity relative to other more
controversial changes we've made. It has basically 1 upvote with around
5 participants whereas our most popular or breaking features/bugs have
had at least dozens if not over a hundred. I think this shows that this
change isn't that disruptive, either because the colors work fine or
because not that many things use the 256-color palette (probably the
latter moreso but a mix for sure). For that reason, I do think
revisiting this at some point is warranted.

I think palette generation is best left as a _theme author_ tool. A
Ghostty color theme could include `palette-generate=true` if it wants to
customize the 256-color palette more easily. Of course, end users can as
well anytime.

Another part of my reasoning is that TUI programs who want this behavior
can already achieve it themselves by mixing dark/light theme detection
via CSI 996
(https://contour-terminal.org/vt-extensions/color-palette-update-notifications/)
with OSC 4/10/11 color query and change sequences, both of which are
decently supported in the terminal ecosystem and fully supported in
Ghostty.

I'm also open to considering some kind of new sequence to make this
easier for TUIs (probably a mode) where they can opt-in to palette
generation plus "harmonius" palettes (see `palette-harmonius`) and
Ghostty does it on demand then. I think that'd solve the legacy vs new
TUI argument where legacy programs can continue to make assumptions
about the palette and new programs can opt-in to a more dynamic palette
without having to do a lot of work themselves.

cc @jake-stewart
“always include a language and a country code” reads as “always include
a language, and also always include a country code”, while the intended
meaning was that it includes both a language *code* and a country code.
That line was intended to guide those who do not normally edit po files
with a plain text editor, but ended up sounding like it states the
obvious (“to do X, do X”) before this change.
This fixes two overlapping issues regarding window positioning and Cmd+W window closures on macOS:

1. `window-position-x` and `window-position-y` coordinates were being ignored on initial launch because `TerminalWindow.setInitialWindowPosition` depended on the `TerminalController`, which isn't fully attached during `awakeFromNib`. This logic was moved so explicit coordinates are correctly enforced.
2. When closing a window via Cmd+W (leaving the app active), reopening the window would continuously cascade down and to the right rather than restoring to the previous position. It now checks if there are other windows open before cascading.
3. `LastWindowPosition` was updated to save both the frame origin and size (width/height), ensuring that restoring a closed window correctly mimics native AppKit State Restoration size behaviors while honoring explicit configurations.
Triggered by
[comment](ghostty-org#11070 (comment))
from @mitchellh.

Vouch: @abdurrahmanski

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Portugal exists! Wikipedia notes [1] it to be the main other dialect.
There's already a PR for pt_PT support too:
ghostty-org#9078.

It was renamed from pt_BR.UTF-8.po to pt.po in ghostty-org#10976.

[1]: https://en.wikipedia.org/wiki/Portuguese_dialects
Follow-up to ghostty-org#10976.

Portugal exists! [Wikipedia notes it] to be the main other dialect.
There's already a PR for `pt_PT` support too: ghostty-org#9078.

[Wikipedia notes it]: https://en.wikipedia.org/wiki/Portuguese_dialects
While it was renamed from ko_KR.UTF-8.po to ko.po in ghostty-org#10976, @uhojin,
a Korean locale maintainer, notes [1] that “ko_KR [*South* Korean] makes
more sense in locale context just to avoid any potential confusion
between 한국어 vs 조선어”.

Despite ko_KP (North Korean) not being present in glibc (as of version
2.43), and the ISO639 maintainers expressing disapproval of ko_KP [2],
it is possible opinions may change in the future, and individual
opinions may be contested—disambiguating doesn't hurt.

[1]: ghostty-org#10976 (comment)
[2]: ghostty-org#10976 (comment)
While it was renamed from `ko_KR.UTF-8.po` to `ko.po` in ghostty-org#10976,
@uhojin, a Korean locale maintainer, [notes] that “ko_KR [*South*
Korean] makes more sense in locale context just to avoid any potential
confusion between 한국어 vs 조선어”.

Despite `ko_KP` (North Korean) not being present in glibc (as of version
2.43), and the ISO639 maintainers [expressing disapproval of `ko_KP`],
it is possible opinions may change in the future, and individual
opinions may be contested—disambiguating doesn't hurt.

Requesting a review from all involved parties; I wish you ***all* opine
before merging**.

[notes]:
ghostty-org#10976 (comment)
[expressing disapproval of `ko_KP`]:
ghostty-org#10976 (comment)
Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
Triggered by [discussion
comment](ghostty-org#11076 (comment))
from @jcollie.

Vouch: @DiaaEddin

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
apply reviewer suggestion for cascading

Co-authored-by: Lukas <134181853+bo2themax@users.noreply.github.com>
)

I'd like to contribute a fix for an issue I found regarding how macOS
window restoration works when a window is closed via Cmd+W (leaving the
app active).

Currently, the position cascades down and to the right on every reopen,
and size explicitly resets. Also, explicit `window-position-x/y` configs
get ignored on first launch.

I've diagnosed the issues:
1. In `TerminalWindow.swift`, `setInitialWindowPosition` relies on the
`TerminalController` which isn't present during `awakeFromNib`. I moved
the `screen.origin` calculation directly into the window class to ensure
fixed coordinates are respected immediately.
2. In `TerminalController.swift`, I consolidated the window spawning
cascade logic into a new `applyCascade(to:hasFixedPos:)` helper. It now
only calls `cascadeTopLeft` if `TerminalController.all.count > 1`
(meaning another window is active) and fixed coords aren't set. If it's
the only window, it anchors exactly where `LastWindowPosition` placed
it.
3. In `LastWindowPosition.swift`, I updated the `save` and `restore`
logic to persist the full `window.frame` (origin + size) instead of just
the origin.

*Disclosure: I used Cursor (Tab) to assist in navigating the codebase
and formatting the Swift code, but I fully understand the AppKit
lifecycle changes and edge cases I'm proposing.*

I have the commit locally formatted with `swiftlint` and ready to push!
We haven't used or run these in forever (literally like 3+ years).
They're just wasting cognitive space and confuse some users as to what
they're for. Remove them.
We haven't used or run these in forever (literally like 3+ years).
They're just wasting cognitive space and confuse some users as to what
they're for. Remove them.
When a DCS sequence has more than MAX_PARAMS parameters, entering
dcs_passthrough would write to params[params_idx] without a bounds
check, causing an out-of-bounds access. Drop the entire DCS hook
when params overflow, consistent with how csi_dispatch handles it.

Found by AFL fuzzing.
…1088)

When a DCS sequence has more than MAX_PARAMS parameters, entering
dcs_passthrough would write to params[params_idx] without a bounds
check, causing an out-of-bounds access. Add the same guard that
csi_dispatch already has.

Found by AFL fuzzing, test and fix produced by Codex.
ghostty-vouch bot and others added 26 commits March 8, 2026 19:58
Triggered by [discussion
comment](ghostty-org#11207 (comment))
from @mitchellh.

Vouch: @MOlechowski

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Remove the stale GHOSTTY_SGR_ATTR_RESET_UNDERLINE entry from the C
header and renumber subsequent GhosttySgrAttributeTag values to match
src/terminal/sgr.zig Attribute.Tag ordering.

This fixes misclassified attributes from ghostty_sgr_next for C
consumers that switch on the enum tags from include/ghostty/vt/sgr.h.
If you have multiple splits and start searching naturally the focus
transfers over to the search widget which would apply the unfocused
options. This could make it difficult to view your matches from
searching without re-focusing the surface.

This was discovered when I tested
ghostty-org#11218 (which is a
different issue)
Triggered by [discussion
comment](ghostty-org#11246 (comment))
from @jcollie.

Vouch: @jmcgover

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This adds two new propeties to make it easy to get the frontmost (main)
window and the focused terminal within a tab. We already had a property
to get the selected tab of a tab group.
…hostty-org#11251)

This adds two new propeties to make it easy to get the frontmost (main)
window and the focused terminal within a tab. We already had a property
to get the selected tab of a tab group.

## Examples

### Send Input to Focused Terminal

```AppleScript
tell application "Ghostty"
  set term to focused terminal of selected tab of front window
  input text "pwd\n" to term
end tell
```

### Split the Focused Terminal

```applescript
tell application "Ghostty"
  set currentTerm to focused terminal of selected tab of front window
  set newTerm to split currentTerm direction right
  input text "echo split-ready\n" to newTerm
end tell
```
…for rendering." (ghostty-org#11227)

- "Unable to acquire an OpenGL context for rendering."
This could be translated to "No se puede" or "No se pudo", depends on
the context of the message.
If the message is showing a current intent the translation should be "No
se puede", if the message is communicating that Ghostty failed to
acquire the OpenGL then the translation should be "No se pudo", here I
need more context.
Either case the wording "No se puedo" is incorrect.
This fixes an error if the script was sourced a second time:

    bash: __ghostty_ps0: readonly variable

Because this is a non-exported variable, this would only happen if the
script was sourced multiple times in the same bash session.
If an existing PROMPT_COMMAND was a string ending in ; (and maybe some
spaces), we'd add a redundant ;, resulting in a syntax error. Now we
strip any trailing `;[[:space:]]*` characters from the original string
before add ours.
If an existing PROMPT_COMMAND was a string ending in ; (and maybe some
spaces), we'd add a redundant ;, resulting in a syntax error. Now we
strip any trailing `;[[:space:]]*` characters from the original string
before add ours.

Fixes ghostty-org#11259
This fixes an error if the script was sourced a second time:

    bash: __ghostty_ps0: readonly variable

Because this is a non-exported variable, this would only happen if the
script was sourced multiple times in the same bash session.
When a grapheme expands to width 2 at the screen edge, this path can write
spacer_head before printWrap() sets row.wrap. With an active hyperlink,
printCell triggers hyperlink bookkeeping and page integrity checks in that
intermediate state, causing UnwrappedSpacerHead.

Mark row.wrap before writing spacer_head in this grapheme-wrap path to keep
the intermediate state valid.
…rg#11264)

When a grapheme expands to width 2 at the screen edge, this path can
write spacer_head before printWrap() sets row.wrap. With an active
hyperlink, printCell triggers hyperlink bookkeeping and page integrity
checks in that intermediate state, causing UnwrappedSpacerHead.

Mark row.wrap before writing spacer_head in this grapheme-wrap path to
keep the intermediate state valid.
…ostty-org#11257)

Fixes ghostty-org#11256, which is rather hard to reproduce on macOS 26, but after
adding breaking points on size update, we can see that it happens when
the `intrinsicContentSize` is not properly updated.

<img width="998" height="556" alt="Xnip2026-03-09_11-38-40"
src="https://github.com/user-attachments/assets/8ac1de91-5895-45fc-a443-002eb016a1ce"
/>
Band-aid for ghostty-org#10304

We don't have a robust fix yet but this should help mitigate more
scenarios.
…ostty-org#11265)

Band-aid for ghostty-org#10304

We don't have a robust fix yet but this should help mitigate more
scenarios.
Triggered by [discussion
comment](ghostty-org#11274 (comment))
from @jcollie.

Vouch: @seruman

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
PR ghostty-org#11154 didn't fully update the docs regarding `bell-features=audio`
on macOS.
Triggered by [discussion
comment](ghostty-org#11287 (comment))
from @mitchellh.

Vouch: @ocean6954

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

Vouch: @dzhlobo

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
PR ghostty-org#11154 didn't fully update the docs regarding `bell-features=audio`
on macOS.
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: ed9b473f88

ℹ️ 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 +61 to +62
if (std.mem.eql(u8, stripped, "home")) return try alloc.dupeZ(u8, arg);
if (std.mem.eql(u8, stripped, "inherit")) return try alloc.dupeZ(u8, arg);

Choose a reason for hiding this comment

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

P1 Badge Mark special working-directory values as explicitly set

When --working-directory=home or --working-directory=inherit is parsed, these early returns skip setting _working_directory_seen, so runArgs later treats working-directory as missing and appends a fallback --working-directory=<cwd>. In the GTK new-window handler (src/apprt/gtk/class/application.zig), each --working-directory= assignment overwrites the previous one, so the appended cwd value wins and the caller’s explicit home/inherit choice is ignored. This breaks expected behavior for those two documented modes.

Useful? React with 👍 / 👎.

@nicosuave nicosuave merged commit 1dd0c81 into main Mar 10, 2026
179 of 181 checks passed
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.