Skip to content

Fix embedded surface updates during pane strip motion#15

Open
lawrencecchen wants to merge 608 commits intomainfrom
issue-1221-paper-window-manager-layout
Open

Fix embedded surface updates during pane strip motion#15
lawrencecchen wants to merge 608 commits intomainfrom
issue-1221-paper-window-manager-layout

Conversation

@lawrencecchen
Copy link

@lawrencecchen lawrencecchen commented Mar 18, 2026

Summary

  • keep embedded surface geometry in sync while pane strips animate horizontally
  • reduce stale hosted surface placement during reveal and pan transitions
  • support the cmux paper-canvas motion harness without overlapping terminal surfaces

Testing

  • verified through the cmux pane-strip motion scenarios on the Sequoia VM

Summary by cubic

Keeps embedded terminal surfaces aligned with moving pane strips during horizontal animations and pans, removing lag and overlap. Addresses Linear 1221 (paper window manager layout) and improves cmux paper-canvas motion harness compatibility.

  • Bug Fixes
    • Sync embedded surface geometry while pane strips animate horizontally.
    • Reduce stale hosted-surface placement during reveal and pan transitions.
    • Prevent overlapping terminal surfaces under the cmux motion harness.

Written for commit 937af72. Summary will update on new commits.

mitchellh and others added 30 commits February 27, 2026 11:32
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.

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.
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.
mitchellh and others added 26 commits March 8, 2026 13:01
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>
@chatgpt-codex-connector
Copy link

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@coderabbitai
Copy link

coderabbitai bot commented Mar 18, 2026

Important

Review skipped

Too many files!

This PR contains 299 files, which is 149 over the limit of 150.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a30358d8-02fb-44f4-aef9-adc9e60740ff

📥 Commits

Reviewing files that changed from the base of the PR and between b9989c1 and 937af72.

⛔ Files ignored due to path filters (1)
  • dist/linux/com.mitchellh.ghostty.metainfo.xml.in is excluded by !**/dist/**
📒 Files selected for processing (299)
  • .github/VOUCHED.td
  • .github/workflows/flatpak.yml
  • .github/workflows/milestone.yml
  • .github/workflows/nix.yml
  • .github/workflows/release-tag.yml
  • .github/workflows/release-tip.yml
  • .github/workflows/snap.yml
  • .github/workflows/test.yml
  • .github/workflows/update-colorschemes.yml
  • .github/workflows/vouch-check-issue.yml
  • .github/workflows/vouch-check-pr.yml
  • .github/workflows/vouch-manage-by-discussion.yml
  • .github/workflows/vouch-manage-by-issue.yml
  • .github/workflows/vouch-sync-codeowners.yml
  • .gitignore
  • .prettierignore
  • .swiftlint.yml
  • AGENTS.md
  • CODEOWNERS
  • CONTRIBUTING.md
  • HACKING.md
  • build.zig
  • build.zig.zon
  • build.zig.zon.bak
  • build.zig.zon.json
  • build.zig.zon.nix
  • build.zig.zon.txt
  • flake.nix
  • flatpak/zig-packages.json
  • include/ghostty.h
  • include/ghostty/vt/sgr.h
  • macos/.swiftlint.yml
  • macos/AGENTS.md
  • macos/Ghostty-Info.plist
  • macos/Ghostty.sdef
  • macos/Ghostty.xcodeproj/project.pbxproj
  • macos/Ghostty.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
  • macos/Sources/App/macOS/AppDelegate+Ghostty.swift
  • macos/Sources/App/macOS/AppDelegate.swift
  • macos/Sources/App/macOS/MainMenu.xib
  • macos/Sources/App/macOS/ghostty-bridging-header.h
  • macos/Sources/App/macOS/main.swift
  • macos/Sources/Features/About/AboutController.swift
  • macos/Sources/Features/About/AboutView.swift
  • macos/Sources/Features/About/AboutViewModel.swift
  • macos/Sources/Features/About/CyclingIconView.swift
  • macos/Sources/Features/App Intents/CloseTerminalIntent.swift
  • macos/Sources/Features/App Intents/CommandPaletteIntent.swift
  • macos/Sources/Features/App Intents/Entities/CommandEntity.swift
  • macos/Sources/Features/App Intents/Entities/TerminalEntity.swift
  • macos/Sources/Features/App Intents/GetTerminalDetailsIntent.swift
  • macos/Sources/Features/App Intents/InputIntent.swift
  • macos/Sources/Features/App Intents/IntentPermission.swift
  • macos/Sources/Features/App Intents/KeybindIntent.swift
  • macos/Sources/Features/App Intents/NewTerminalIntent.swift
  • macos/Sources/Features/App Intents/QuickTerminalIntent.swift
  • macos/Sources/Features/AppleScript/AppDelegate+AppleScript.swift
  • macos/Sources/Features/AppleScript/Ghostty.Input.Mods+AppleScript.swift
  • macos/Sources/Features/AppleScript/ScriptInputTextCommand.swift
  • macos/Sources/Features/AppleScript/ScriptKeyEventCommand.swift
  • macos/Sources/Features/AppleScript/ScriptMouseButtonCommand.swift
  • macos/Sources/Features/AppleScript/ScriptMousePosCommand.swift
  • macos/Sources/Features/AppleScript/ScriptMouseScrollCommand.swift
  • macos/Sources/Features/AppleScript/ScriptRecord.swift
  • macos/Sources/Features/AppleScript/ScriptSurfaceConfiguration.swift
  • macos/Sources/Features/AppleScript/ScriptTab.swift
  • macos/Sources/Features/AppleScript/ScriptTerminal.swift
  • macos/Sources/Features/AppleScript/ScriptWindow.swift
  • macos/Sources/Features/ClipboardConfirmation/ClipboardConfirmationController.swift
  • macos/Sources/Features/ClipboardConfirmation/ClipboardConfirmationView.swift
  • macos/Sources/Features/Colorized Ghostty Icon/ColorizedGhosttyIcon.swift
  • macos/Sources/Features/Command Palette/CommandPalette.swift
  • macos/Sources/Features/Command Palette/TerminalCommandPalette.swift
  • macos/Sources/Features/Custom App Icon/AppIcon.swift
  • macos/Sources/Features/Custom App Icon/ColorizedGhosttyIcon.swift
  • macos/Sources/Features/Custom App Icon/ColorizedGhosttyIconImage.swift
  • macos/Sources/Features/Custom App Icon/ColorizedGhosttyIconView.swift
  • macos/Sources/Features/Custom App Icon/DockTilePlugin.swift
  • macos/Sources/Features/Custom App Icon/Extensions/Notification+AppIcon.swift
  • macos/Sources/Features/Custom App Icon/Extensions/UserDefaults+AppIcon.swift
  • macos/Sources/Features/Global Keybinds/GlobalEventTap.swift
  • macos/Sources/Features/QuickTerminal/QuickTerminalController.swift
  • macos/Sources/Features/QuickTerminal/QuickTerminalPosition.swift
  • macos/Sources/Features/QuickTerminal/QuickTerminalScreen.swift
  • macos/Sources/Features/QuickTerminal/QuickTerminalScreenStateCache.swift
  • macos/Sources/Features/QuickTerminal/QuickTerminalSize.swift
  • macos/Sources/Features/QuickTerminal/QuickTerminalSpaceBehavior.swift
  • macos/Sources/Features/QuickTerminal/QuickTerminalWindow.swift
  • macos/Sources/Features/Secure Input/SecureInput.swift
  • macos/Sources/Features/Secure Input/SecureInputOverlay.swift
  • macos/Sources/Features/Services/ServiceProvider.swift
  • macos/Sources/Features/Settings/ConfigurationErrorsController.swift
  • macos/Sources/Features/Splits/SplitTree.swift
  • macos/Sources/Features/Splits/SplitView.Divider.swift
  • macos/Sources/Features/Splits/SplitView.swift
  • macos/Sources/Features/Splits/TerminalSplitTreeView.swift
  • macos/Sources/Features/Terminal/BaseTerminalController.swift
  • macos/Sources/Features/Terminal/TerminalController.swift
  • macos/Sources/Features/Terminal/TerminalRestorable.swift
  • macos/Sources/Features/Terminal/TerminalTabColor.swift
  • macos/Sources/Features/Terminal/TerminalView.swift
  • macos/Sources/Features/Terminal/TerminalViewContainer.swift
  • macos/Sources/Features/Terminal/Window Styles/HiddenTitlebarTerminalWindow.swift
  • macos/Sources/Features/Terminal/Window Styles/TerminalWindow.swift
  • macos/Sources/Features/Terminal/Window Styles/TitlebarTabsTahoeTerminalWindow.swift
  • macos/Sources/Features/Terminal/Window Styles/TitlebarTabsVenturaTerminalWindow.swift
  • macos/Sources/Features/Terminal/Window Styles/TransparentTitlebarTerminalWindow.swift
  • macos/Sources/Features/Update/UpdateBadge.swift
  • macos/Sources/Features/Update/UpdateController.swift
  • macos/Sources/Features/Update/UpdateDelegate.swift
  • macos/Sources/Features/Update/UpdateDriver.swift
  • macos/Sources/Features/Update/UpdatePill.swift
  • macos/Sources/Features/Update/UpdatePopoverView.swift
  • macos/Sources/Features/Update/UpdateSimulator.swift
  • macos/Sources/Features/Update/UpdateViewModel.swift
  • macos/Sources/Ghostty/FullscreenMode+Extension.swift
  • macos/Sources/Ghostty/Ghostty.Action.swift
  • macos/Sources/Ghostty/Ghostty.App.swift
  • macos/Sources/Ghostty/Ghostty.Config.swift
  • macos/Sources/Ghostty/Ghostty.ConfigTypes.swift
  • macos/Sources/Ghostty/Ghostty.Input.swift
  • macos/Sources/Ghostty/Ghostty.Surface.swift
  • macos/Sources/Ghostty/GhosttyPackage.swift
  • macos/Sources/Ghostty/GhosttyPackageMeta.swift
  • macos/Sources/Ghostty/NSEvent+Extension.swift
  • macos/Sources/Ghostty/Package.swift
  • macos/Sources/Ghostty/Surface View/InspectorView.swift
  • macos/Sources/Ghostty/Surface View/SurfaceDragSource.swift
  • macos/Sources/Ghostty/Surface View/SurfaceGrabHandle.swift
  • macos/Sources/Ghostty/Surface View/SurfaceProgressBar.swift
  • macos/Sources/Ghostty/Surface View/SurfaceScrollView.swift
  • macos/Sources/Ghostty/Surface View/SurfaceView+Transferable.swift
  • macos/Sources/Ghostty/Surface View/SurfaceView.swift
  • macos/Sources/Ghostty/Surface View/SurfaceView_AppKit.swift
  • macos/Sources/Ghostty/Surface View/SurfaceView_UIKit.swift
  • macos/Sources/Helpers/AnySortKey.swift
  • macos/Sources/Helpers/AppInfo.swift
  • macos/Sources/Helpers/Backport.swift
  • macos/Sources/Helpers/ExpiringUndoManager.swift
  • macos/Sources/Helpers/Extensions/Array+Extension.swift
  • macos/Sources/Helpers/Extensions/EventModifiers+Extension.swift
  • macos/Sources/Helpers/Extensions/NSAppearance+Extension.swift
  • macos/Sources/Helpers/Extensions/NSApplication+Extension.swift
  • macos/Sources/Helpers/Extensions/NSColor+Extension.swift
  • macos/Sources/Helpers/Extensions/NSPasteboard+Extension.swift
  • macos/Sources/Helpers/Extensions/NSScreen+Extension.swift
  • macos/Sources/Helpers/Extensions/NSView+Extension.swift
  • macos/Sources/Helpers/Extensions/NSWindow+Extension.swift
  • macos/Sources/Helpers/Extensions/NSWorkspace+Extension.swift
  • macos/Sources/Helpers/Extensions/OSColor+Extension.swift
  • macos/Sources/Helpers/Extensions/ObjectIdentifier+Extension.swift
  • macos/Sources/Helpers/Extensions/String+Extension.swift
  • macos/Sources/Helpers/Extensions/Transferable+Extension.swift
  • macos/Sources/Helpers/Fullscreen.swift
  • macos/Sources/Helpers/LastWindowPosition.swift
  • macos/Sources/Helpers/MetalView.swift
  • macos/Sources/Helpers/ObjCExceptionCatcher.h
  • macos/Sources/Helpers/ObjCExceptionCatcher.m
  • macos/Sources/Helpers/PermissionRequest.swift
  • macos/Sources/Helpers/TabTitleEditor.swift
  • macos/Tests/ColorizedGhosttyIconTests.swift
  • macos/Tests/Ghostty/ShellTests.swift
  • macos/Tests/NSPasteboardTests.swift
  • macos/Tests/NSScreenTests.swift
  • macos/Tests/Terminal/TerminalViewContainerTests.swift
  • macos/Tests/Update/ReleaseNotesTests.swift
  • macos/Tests/Update/UpdateStateTests.swift
  • macos/Tests/Update/UpdateViewModelTests.swift
  • macos/build.nu
  • nix/devShell.nix
  • nix/package.nix
  • nix/pkgs/blessed.nix
  • nix/pkgs/ucs-detect.nix
  • nix/pkgs/wcwidth.nix
  • pkg/afl++/LICENSE
  • pkg/afl++/afl.c
  • pkg/afl++/build.zig
  • pkg/afl++/build.zig.zon
  • pkg/android-ndk/build.zig
  • pkg/android-ndk/build.zig.zon
  • pkg/dcimgui/build.zig
  • pkg/dcimgui/ext.cpp
  • pkg/dcimgui/main.zig
  • pkg/highway/build.zig
  • pkg/highway/build.zig.zon
  • pkg/macos/animation.zig
  • pkg/macos/video/display_link.zig
  • pkg/oniguruma/main.zig
  • pkg/oniguruma/match_param.zig
  • pkg/oniguruma/regex.zig
  • pkg/simdutf/build.zig
  • pkg/simdutf/build.zig.zon
  • pkg/utfcpp/build.zig
  • pkg/utfcpp/build.zig.zon
  • po/README_TRANSLATORS.md
  • po/bg.po
  • po/bg_BG.UTF-8.po
  • po/ca.po
  • po/ca_ES.UTF-8.po
  • po/de.po
  • po/de_DE.UTF-8.po
  • po/es_AR.UTF-8.po
  • po/es_AR.po
  • po/es_BO.UTF-8.po
  • po/es_BO.po
  • po/es_ES.po
  • po/fr.po
  • po/fr_FR.UTF-8.po
  • po/ga.po
  • po/ga_IE.UTF-8.po
  • po/he.po
  • po/he_IL.UTF-8.po
  • po/hr.po
  • po/hr_HR.UTF-8.po
  • po/hu.po
  • po/hu_HU.UTF-8.po
  • po/id.po
  • po/id_ID.UTF-8.po
  • po/it.po
  • po/it_IT.UTF-8.po
  • po/ja.po
  • po/ja_JP.UTF-8.po
  • po/kk.po
  • po/ko_KR.UTF-8.po
  • po/ko_KR.po
  • po/lt.po
  • po/lt_LT.UTF-8.po
  • po/lv.po
  • po/lv_LV.UTF-8.po
  • po/mk.po
  • po/mk_MK.UTF-8.po
  • po/nb.po
  • po/nb_NO.UTF-8.po
  • po/nl.po
  • po/nl_NL.UTF-8.po
  • po/pl.po
  • po/pl_PL.UTF-8.po
  • po/pt_BR.UTF-8.po
  • po/pt_BR.po
  • po/ru.po
  • po/ru_RU.UTF-8.po
  • po/tr.po
  • po/tr_TR.UTF-8.po
  • po/uk.po
  • po/uk_UA.UTF-8.po
  • po/vi.po
  • po/zh_CN.UTF-8.po
  • po/zh_CN.po
  • po/zh_TW.UTF-8.po
  • po/zh_TW.po
  • snap/local/launcher
  • src/Command.zig
  • src/Surface.zig
  • src/apprt/action.zig
  • src/apprt/embedded.zig
  • src/apprt/gtk/Surface.zig
  • src/apprt/gtk/class/application.zig
  • src/apprt/gtk/class/command_palette.zig
  • src/apprt/gtk/class/imgui_widget.zig
  • src/apprt/gtk/class/split_tree.zig
  • src/apprt/gtk/class/surface.zig
  • src/apprt/gtk/class/tab.zig
  • src/apprt/gtk/class/window.zig
  • src/apprt/gtk/ipc/new_window.zig
  • src/apprt/gtk/ui/1.2/surface.blp
  • src/apprt/gtk/ui/1.5/window.blp
  • src/apprt/ipc.zig
  • src/benchmark/CodepointWidth.zig
  • src/build/GhosttyLibVt.zig
  • src/build/GhosttyXcodebuild.zig
  • src/build/GitVersion.zig
  • src/build/SharedDeps.zig
  • src/build/uucode_config.zig
  • src/cli/list_actions.zig
  • src/cli/new_window.zig
  • src/cli/ssh-cache/DiskCache.zig
  • src/cli/ssh-cache/Entry.zig
  • src/config.zig
  • src/config/CApi.zig
  • src/config/Config.zig
  • src/config/command.zig
  • src/config/path.zig
  • src/config/string.zig
  • src/config/url.zig
  • src/datastruct/split_tree.zig
  • src/font/shaper/coretext.zig
  • src/font/shaper/harfbuzz.zig
  • src/input/Binding.zig
  • src/input/command.zig
  • src/input/key_encode.zig
  • src/lib/enum.zig
  • src/lib/main.zig
  • src/lib/string.zig
  • src/lib_vt.zig
  • src/os/homedir.zig
  • src/os/hostname.zig
  • src/os/i18n_locales.zig
  • src/os/string_encoding.zig
  • src/os/windows.zig

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-1221-paper-window-manager-layout
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

9 issues found across 3000 files

Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed.

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="macos/AGENTS.md">

<violation number="1" location="macos/AGENTS.md:28">
P2: The AppleScript example path is inconsistent with the documented macOS app output directory; use `macos/build/Debug/Ghostty.app` to avoid targeting a non-existent bundle path.</violation>
</file>

<file name="macos/Sources/Features/About/AboutViewModel.swift">

<violation number="1" location="macos/Sources/Features/About/AboutViewModel.swift:36">
P2: When `currentIcon` is nil, the first advance skips the first icon (`.official`) due to the `?? 0` fallback before calling `indexWrapping(after:)`.</violation>
</file>

<file name="macos/Sources/Features/AppleScript/ScriptSurfaceConfiguration.swift">

<violation number="1" location="macos/Sources/Features/AppleScript/ScriptSurfaceConfiguration.swift:79">
P2: Invalid `environmentVariables` input types are silently ignored instead of producing a parse error.</violation>
</file>

<file name="macos/Sources/Features/Custom App Icon/DockTilePlugin.swift">

<violation number="1" location="macos/Sources/Features/Custom App Icon/DockTilePlugin.swift:143">
P2: Avoid declaring `NSDockTile` as `@unchecked Sendable`. This masks thread-safety issues for a main-thread-only AppKit type; instead keep dock tile updates on the main thread and remove the unchecked conformance.</violation>
</file>

<file name="macos/Sources/Features/QuickTerminal/QuickTerminalPosition.swift">

<violation number="1" location="macos/Sources/Features/QuickTerminal/QuickTerminalPosition.swift:89">
P2: Center initial Y origin uses `window.frame.width` and omits `visibleFrame.origin.y`, causing incorrect vertical placement during center transitions.</violation>
</file>

<file name="macos/Sources/Features/AppleScript/AppDelegate+AppleScript.swift">

<violation number="1" location="macos/Sources/Features/AppleScript/AppDelegate+AppleScript.swift:291">
P2: The `new tab` fallback can return a tab object anchored to a transient window ID. If tab-group state hasn’t settled yet, later AppleScript resolution of that returned tab may fail.</violation>
</file>

<file name="macos/Sources/App/macOS/AppDelegate.swift">

<violation number="1" location="macos/Sources/App/macOS/AppDelegate.swift:782">
P2: The local `NSSound` instance will be deallocated by ARC before the asynchronous playback completes, causing the custom bell audio to cut off or fail.</violation>
</file>

<file name="macos/Ghostty.xcodeproj/project.pbxproj">

<violation number="1" location="macos/Ghostty.xcodeproj/project.pbxproj:413">
P1: DockTilePlugin target has no synchronized source group membership, leaving its Sources phase empty and producing a plugin bundle without the plugin implementation.</violation>

<violation number="2" location="macos/Ghostty.xcodeproj/project.pbxproj:869">
P1: `NSPrincipalClass` is empty for DockTilePlugin, so the dock tile plugin class is not declared as the bundle entry point.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

);
dependencies = (
);
name = DockTilePlugin;
Copy link

@cubic-dev-ai cubic-dev-ai bot Mar 18, 2026

Choose a reason for hiding this comment

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

P1: DockTilePlugin target has no synchronized source group membership, leaving its Sources phase empty and producing a plugin bundle without the plugin implementation.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At macos/Ghostty.xcodeproj/project.pbxproj, line 413:

<comment>DockTilePlugin target has no synchronized source group membership, leaving its Sources phase empty and producing a plugin bundle without the plugin implementation.</comment>

<file context>
@@ -328,6 +398,25 @@
+			);
+			dependencies = (
+			);
+			name = DockTilePlugin;
+			packageProductDependencies = (
+			);
</file context>
Fix with Cubic

GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = "Ghostty Dock Tile Plugin";
INFOPLIST_KEY_NSHumanReadableCopyright = "";
INFOPLIST_KEY_NSPrincipalClass = "";
Copy link

@cubic-dev-ai cubic-dev-ai bot Mar 18, 2026

Choose a reason for hiding this comment

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

P1: NSPrincipalClass is empty for DockTilePlugin, so the dock tile plugin class is not declared as the bundle entry point.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At macos/Ghostty.xcodeproj/project.pbxproj, line 869:

<comment>`NSPrincipalClass` is empty for DockTilePlugin, so the dock tile plugin class is not declared as the bundle entry point.</comment>

<file context>
@@ -712,6 +854,93 @@
+				GENERATE_INFOPLIST_FILE = YES;
+				INFOPLIST_KEY_CFBundleDisplayName = "Ghostty Dock Tile Plugin";
+				INFOPLIST_KEY_NSHumanReadableCopyright = "";
+				INFOPLIST_KEY_NSPrincipalClass = "";
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
+				LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
</file context>
Fix with Cubic

(1) Build with `macos/build.nu`
(2) Launch and activate the app via osascript using the absolute path
to the built app bundle:
`osascript -e 'tell application "<absolute path to build/Debug/Ghostty.app>" to activate'`
Copy link

@cubic-dev-ai cubic-dev-ai bot Mar 18, 2026

Choose a reason for hiding this comment

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

P2: The AppleScript example path is inconsistent with the documented macOS app output directory; use macos/build/Debug/Ghostty.app to avoid targeting a non-existent bundle path.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At macos/AGENTS.md, line 28:

<comment>The AppleScript example path is inconsistent with the documented macOS app output directory; use `macos/build/Debug/Ghostty.app` to avoid targeting a non-existent bundle path.</comment>

<file context>
@@ -0,0 +1,34 @@
+  (1) Build with `macos/build.nu`
+  (2) Launch and activate the app via osascript using the absolute path
+      to the built app bundle:
+      `osascript -e 'tell application "<absolute path to build/Debug/Ghostty.app>" to activate'`
+  (3) Wait a few seconds for the app to fully launch and open a terminal.
+  (4) Run test scripts with `osascript`, always targeting the app by
</file context>
Fix with Cubic

}

func advanceToNextIcon() {
let currentIndex = currentIcon.flatMap(icons.firstIndex(of:)) ?? 0
Copy link

@cubic-dev-ai cubic-dev-ai bot Mar 18, 2026

Choose a reason for hiding this comment

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

P2: When currentIcon is nil, the first advance skips the first icon (.official) due to the ?? 0 fallback before calling indexWrapping(after:).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At macos/Sources/Features/About/AboutViewModel.swift, line 36:

<comment>When `currentIcon` is nil, the first advance skips the first icon (`.official`) due to the `?? 0` fallback before calling `indexWrapping(after:)`.</comment>

<file context>
@@ -0,0 +1,40 @@
+    }
+
+    func advanceToNextIcon() {
+        let currentIndex = currentIcon.flatMap(icons.firstIndex(of:)) ?? 0
+        let nextIndex = icons.indexWrapping(after: currentIndex)
+        currentIcon = icons[nextIndex]
</file context>
Fix with Cubic

}
}

if let assignments = raw["environmentVariables"] as? [String], !assignments.isEmpty {
Copy link

@cubic-dev-ai cubic-dev-ai bot Mar 18, 2026

Choose a reason for hiding this comment

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

P2: Invalid environmentVariables input types are silently ignored instead of producing a parse error.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At macos/Sources/Features/AppleScript/ScriptSurfaceConfiguration.swift, line 79:

<comment>Invalid `environmentVariables` input types are silently ignored instead of producing a parse error.</comment>

<file context>
@@ -0,0 +1,140 @@
+            }
+        }
+
+        if let assignments = raw["environmentVariables"] as? [String], !assignments.isEmpty {
+            environmentVariables = try Self.parseScriptEnvironmentAssignments(assignments)
+        }
</file context>
Fix with Cubic


// This is required because of the DispatchQueue call above. This doesn't
// feel right but I don't know a better way to solve this.
extension NSDockTile: @unchecked @retroactive Sendable {}
Copy link

@cubic-dev-ai cubic-dev-ai bot Mar 18, 2026

Choose a reason for hiding this comment

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

P2: Avoid declaring NSDockTile as @unchecked Sendable. This masks thread-safety issues for a main-thread-only AppKit type; instead keep dock tile updates on the main thread and remove the unchecked conformance.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At macos/Sources/Features/Custom App Icon/DockTilePlugin.swift, line 143:

<comment>Avoid declaring `NSDockTile` as `@unchecked Sendable`. This masks thread-safety issues for a main-thread-only AppKit type; instead keep dock tile updates on the main thread and remove the unchecked conformance.</comment>

<file context>
@@ -0,0 +1,143 @@
+
+// This is required because of the DispatchQueue call above. This doesn't
+// feel right but I don't know a better way to solve this.
+extension NSDockTile: @unchecked @retroactive Sendable {}
</file context>
Fix with Cubic


case .center:
return .init(x: round(screen.visibleFrame.origin.x + (screen.visibleFrame.width - window.frame.width) / 2), y: screen.visibleFrame.height - window.frame.width)
return .init(x: round(screen.visibleFrame.origin.x + (screen.visibleFrame.width - window.frame.width) / 2), y: screen.visibleFrame.height - window.frame.width)
Copy link

@cubic-dev-ai cubic-dev-ai bot Mar 18, 2026

Choose a reason for hiding this comment

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

P2: Center initial Y origin uses window.frame.width and omits visibleFrame.origin.y, causing incorrect vertical placement during center transitions.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At macos/Sources/Features/QuickTerminal/QuickTerminalPosition.swift, line 89:

<comment>Center initial Y origin uses `window.frame.width` and omits `visibleFrame.origin.y`, causing incorrect vertical placement during center transitions.</comment>

<file context>
@@ -86,13 +86,13 @@ enum QuickTerminalPosition : String {
 
         case .center:
-            return .init(x: round(screen.visibleFrame.origin.x + (screen.visibleFrame.width - window.frame.width) / 2), y:  screen.visibleFrame.height - window.frame.width)
+            return .init(x: round(screen.visibleFrame.origin.x + (screen.visibleFrame.width - window.frame.width) / 2), y: screen.visibleFrame.height - window.frame.width)
         }
     }
</file context>
Suggested change
return .init(x: round(screen.visibleFrame.origin.x + (screen.visibleFrame.width - window.frame.width) / 2), y: screen.visibleFrame.height - window.frame.width)
return .init(x: round(screen.visibleFrame.origin.x + (screen.visibleFrame.width - window.frame.width) / 2), y: round(screen.visibleFrame.origin.y + (screen.visibleFrame.height - window.frame.height) / 2))
Fix with Cubic


// Fall back to wrapping the created controller if AppKit tab-group
// bookkeeping has not fully refreshed in the current run loop.
let fallbackWindow = ScriptWindow(primaryController: createdController)
Copy link

@cubic-dev-ai cubic-dev-ai bot Mar 18, 2026

Choose a reason for hiding this comment

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

P2: The new tab fallback can return a tab object anchored to a transient window ID. If tab-group state hasn’t settled yet, later AppleScript resolution of that returned tab may fail.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At macos/Sources/Features/AppleScript/AppDelegate+AppleScript.swift, line 291:

<comment>The `new tab` fallback can return a tab object anchored to a transient window ID. If tab-group state hasn’t settled yet, later AppleScript resolution of that returned tab may fail.</comment>

<file context>
@@ -0,0 +1,351 @@
+
+        // Fall back to wrapping the created controller if AppKit tab-group
+        // bookkeeping has not fully refreshed in the current run loop.
+        let fallbackWindow = ScriptWindow(primaryController: createdController)
+        return ScriptTab(window: fallbackWindow, controller: createdController)
+    }
</file context>
Fix with Cubic

if (ghostty.config.bellFeatures.contains(.attention)) {
if ghostty.config.bellFeatures.contains(.audio) {
if let configPath = ghostty.config.bellAudioPath,
let sound = NSSound(contentsOfFile: configPath.path, byReference: false) {
Copy link

@cubic-dev-ai cubic-dev-ai bot Mar 18, 2026

Choose a reason for hiding this comment

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

P2: The local NSSound instance will be deallocated by ARC before the asynchronous playback completes, causing the custom bell audio to cut off or fail.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At macos/Sources/App/macOS/AppDelegate.swift, line 782:

<comment>The local `NSSound` instance will be deallocated by ARC before the asynchronous playback completes, causing the custom bell audio to cut off or fail.</comment>

<file context>
@@ -775,25 +773,35 @@ class AppDelegate: NSObject,
-        if (ghostty.config.bellFeatures.contains(.attention)) {
+        if ghostty.config.bellFeatures.contains(.audio) {
+            if let configPath = ghostty.config.bellAudioPath,
+               let sound = NSSound(contentsOfFile: configPath.path, byReference: false) {
+                sound.volume = ghostty.config.bellAudioVolume
+                sound.play()
</file context>
Fix with Cubic

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.