Skip to content

Merge upstream (165 commits) + remove unused entitlements#44

Merged
Jesssullivan merged 167 commits intomainfrom
sid/entitlements-cleanup-upstream-sync
Mar 26, 2026
Merged

Merge upstream (165 commits) + remove unused entitlements#44
Jesssullivan merged 167 commits intomainfrom
sid/entitlements-cleanup-upstream-sync

Conversation

@Jesssullivan
Copy link
Copy Markdown
Owner

Summary

  • Entitlements cleanup: Removed unused device.camera and device.audio-input from cmux.entitlements
  • Upstream merge: All 165 upstream commits since 2026-03-22

Key upstream fixes ingested

Conflict resolution

Fork-specific files preserved

  • WebAuthn coordinator + JS bridge
  • FIDO2 module map + vendor/ctap2 submodule
  • Custom entitlements (camera/audio removed, USB/JIT/AppleEvents kept)
  • Fork CI/release workflows

Test plan

  • Fork CI builds clean
  • WebAuthn still works (webauthn.io test)
  • Cmd+N no longer crashes

grimmerk and others added 30 commits March 20, 2026 04:01
…bled

The underlying Ghostty fork does not include the `macos-applescript`
config key (added in upstream ghostty commit 25fa58143, 2026-03-06).
As a result, `appleScriptAutomationEnabled()` always returns false,
causing `scriptWindows` to return an empty array.

This makes `count windows`, `every window`, `front window`, and all
AppleScript window/tab/terminal access silently return empty results.

Fix: always return true from `isAppleScriptEnabled` until the fork
is updated with the upstream config key.

Test results (before fix):
  osascript -e 'tell application "cmux" to count windows'  →  0
  osascript -e 'tell application "cmux" to get version'    →  0.62.2

Test results (after fix):
  osascript -e 'tell application "cmux DEV ..." to count windows'  →  1
  osascript -e 'tell application "cmux DEV ..." to count terminals of tab 1 of window 1'  →  works
  osascript -e 'tell application "cmux DEV ..." to input text "..." to terminal 1 of ...'  →  works

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…Panel

TerminalPanel.directory is never updated (updateDirectory() is
never called anywhere). Workspace.panelDirectories is kept up to
date via updatePanelDirectory() from OSC 7 / shell integration.

Before: working directory always returns ""
After:  working directory returns correct cwd (e.g. "/Users/grimmer")

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Four call sites used `line.data(using: .utf8)!` to convert a String to
Data for FileHandle.write(). While .utf8 encoding never fails for Swift
strings (making the force unwrap safe in practice), `Data(line.utf8)` is
the idiomatic Swift equivalent that avoids the force unwrap entirely.

Changed files:
- GhosttyTerminalView.swift (3 occurrences: init log, surface log, size log)
- WorkspaceContentView.swift (1 occurrence: panel debug log)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Include the panel's custom title, terminal title, or directory name in
the close tab confirmation dialog's informative text so users know which
tab will be closed. Falls back to the generic message when no name is
available. The dialog title stays "Close tab?" for consistency with the
close-confirmation detection in AppDelegate.

Fixes manaflow-ai#1603

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add English and Japanese translations for the named tab close
confirmation message. Uses %@ format specifier for the tab name
to support proper localization word order.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… prompts (manaflow-ai#1677)

Co-authored-by: BillionClaw <billionclaw@users.noreply.github.com>
…-ai#1700)

* fix: skip Korean from CJK font-codepoint-map auto-injection

The automatic CJK font-codepoint-map injection (PR manaflow-ai#1017) maps Korean
ranges to Apple SD Gothic Neo, which has a different style/weight from
the primary terminal font. This overrides Ghostty's native
CTFontCreateForString fallback, which dynamically selects a
better-matching font for Hangul.

Ghostty itself (ghostty-org/ghostty) has no hardcoded CJK font names
and relies entirely on CTFontCreateForString for fallback. For Korean,
this native fallback produces visually consistent results with the
primary font.

Remove the Korean branch from cjkFontMappings() so Ghostty's native
fallback handles Hangul rendering. Japanese and Chinese mappings are
unaffected.

* test: update CJK font mapping tests for Korean removal

- testCJKFontMappingsReturnsAppleSDGothicNeoWithHangulForKorean
  → renamed to testCJKFontMappingsReturnsNilForKoreanOnly
  → asserts nil since Korean is no longer auto-mapped

- testCJKFontMappingsMultiLanguageMapsScriptSpecificRanges
  → renamed to testCJKFontMappingsMultiLanguageSkipsKorean
  → asserts no Apple SD Gothic Neo mapping exists
  → Japanese mappings remain unchanged

---------

Co-authored-by: dante-ad-shield <danate@ad-shield.io>
Change cancel-in-progress from true to false so concurrent nightly
runs queue instead of being killed.

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
Supports left/right/up/down, defaulting to right (existing behavior).
Matches the --direction flag convention used by new-pane and new-split.
The titlebar control icons (sidebar, notifications, new tab) were
vertically misaligned — centered within the full titlebar+tab-bar
area instead of the titlebar alone.

Use the close button's superview height as the true titlebar height
so the icons sit at the same vertical center as the traffic lights,
matching the behavior of apps like Slack.
…anaflow-ai#1735)

Fixes manaflow-ai#1715

The resolveTabForReport() function had an early guard that returned nil
when self.tabManager was nil, even when a valid --tab argument was
provided. This prevented Claude hook commands from resolving tabs via
AppDelegate.shared when the local tabManager wasn't available.

Changes:
- Modified resolveTabForReport() to allow tab resolution via --tab param
  even when self.tabManager is nil
- Removed early guard in upsertSidebarMetadata() that blocked resolution

Co-authored-by: BillionClaw <267901332+BillionClaw@users.noreply.github.com>
…ng area

Two root causes for issue manaflow-ai#879:

1. GhosttyNSView was missing makeBackingLayer(), so AppKit provided a
   generic CALayer as the view's backing layer. libghostty expects
   (view.layer as? CAMetalLayer) != nil to set up Metal rendering on
   the existing layer. Without a CAMetalLayer backing layer, the Metal
   surface defaulted to isOpaque=true, making the terminal area fully
   opaque regardless of background-opacity config.

   Fix: override makeBackingLayer() to return a CAMetalLayer with
   isOpaque=false and bgra8Unorm pixel format (matching standalone
   Ghostty's SurfaceView behavior).

2. ghostty_set_window_background_blur(app, window) is exposed in
   ghostty.h but was never called in cmux. Without this call the
   macOS window never gets the NSVisualEffectView blur backdrop that
   background-blur requires.

   Fix: add applyWindowBlurIfNeeded() on GhosttyApp that reads
   background-blur from config via ghostty_config_get and calls
   ghostty_set_window_background_blur when the value is non-zero.
   Called from applyBackgroundToKeyWindow() and
   applyWindowBackgroundIfActive() whenever the window is made
   transparent.

Fixes manaflow-ai#879

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…se, Japanese) (manaflow-ai#1649)

When a non-Latin input source is active, event.charactersIgnoringModifiers
returns CJK characters that cannot match Latin shortcut keys. This adds
ASCII-capable input source fallback in KeyboardLayout and updates the
matchShortcut guard to skip early-return when event chars are non-ASCII.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add popup browser context regression tests

* Share browser context with OAuth popups

---------

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
CAPTCHA providers (reCAPTCHA, hCaptcha, Cloudflare Turnstile) detect
environment tampering in their cross-origin iframes. With
forMainFrameOnly: false, the telemetry hooks (overridden console.*)
and address bar focus tracker (__cmux* globals) run inside CAPTCHA
iframes, causing challenges to fail or score the session as a bot.

Change forMainFrameOnly from false to true on:
- telemetryHookBootstrapScriptSource
- addressBarFocusTrackingBootstrapScript

Both only need to run in the top-level page context.

Fixes manaflow-ai#1429
…naflow-ai#1889)

Rapid pushes to main spawn 7+ WarpBuild jobs simultaneously, causing
intermittent runner failures (shutdown during submodule clone, lost
communication). Add workflow-level concurrency groups to ci.yml and
build-ghosttykit.yml.

On PRs, stale runs are canceled when a new push arrives. On main, runs
queue serially (cancel-in-progress is false to avoid GitHub treating
cancelled runs as failures).

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
* Add remote image drag-and-drop uploads

* test: cover ssh image paste planning

* fix: upload images pasted into ssh terminals

* fix: share zsh history in cmux ssh relay shells

* fix: add cancellable ssh image transfer indicator

* fix: harden async ssh image transfer callbacks

* fix: address ssh image upload review feedback

---------

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
* Add dynamic OG image and use large Twitter cards

Generate a 1200x630 OG image with the cmux logo, tagline, and
description using next/og ImageResponse. Switch Twitter card type
from "summary" to "summary_large_image" across all pages so shared
links show a full-width preview instead of the tiny favicon thumbnail.

* Use Geist font and app screenshot in OG image, update landing/README images

Replace the centered text-only OG image with a split layout: branding
on the left (logo, name, tagline) and a full app screenshot on the
right. Load Geist Regular/SemiBold from Google Fonts for consistent
typography. Replace the homepage landing image and README screenshot
with a new screenshot showing cmux with multiple workspaces, tabs,
browser panel, and code diffs.

* Fine-tune OG image layout and update homepage/README screenshots

Apply tuned values from OG editor: 112px logo, 48px title with -8
translateY, 34px subtitle at #cfcfcf, 320px fade height. Use Geist
font loaded from Google Fonts. Render at 2x (2400x1260) for sharper
previews on social platforms. Remove GitHub URL from footer.

Add pre-resized og-screenshot.png (2208px wide) for the OG image to
avoid Satori downscale blur. Update homepage landing image and README
screenshot with new app screenshot.

---------

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
jorgitin02 and others added 28 commits March 25, 2026 00:26
* test: add resize_split regression coverage

* fix: implement Ghostty resize_split behavior

* test: cover more resize_split cases

* test: deduplicate split snapshot helper

* Resolve merge conflict: keep both splitNodes and waitForCondition helpers

---------

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
…manaflow-ai#2034)

* Handle Cmd+O in handleCustomShortcut to prevent Documents folder open

Cmd+O for "Open Folder" was only handled in SwiftUI menu, which can
fail due to focus bugs when terminal is focused. This caused AppKit's
default NSDocumentController to open the Documents folder instead.
Now Cmd+O is intercepted in handleCustomShortcut like other shortcuts.

Fixes manaflow-ai#2010

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix fallback directory loss and deduplicate Open Folder logic

Address review feedback:
1. Pass selected directory URL to fallback window creation so the
   user's folder choice is not silently discarded
2. Replace inline NSOpenPanel code in cmuxApp.swift menu action
   with a call to AppDelegate.showOpenFolderPanel() to avoid
   future divergence between the two code paths

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Set NSOpenPanel directoryURL to current terminal working directory

Address review feedback: set panel.directoryURL to the focused
terminal's working directory so Open Folder starts in a contextually
relevant location instead of AppKit's default.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Use shared main-window resolver and openWorkspaceForExternalDirectory in showOpenFolderPanel

Address review feedback: use preferredMainWindowContextForWorkspaceCreation
for directory seeding (works when auxiliary windows are key) and
openWorkspaceForExternalDirectory for workspace creation (ensures
shouldBringToFront and consistent fallback behavior).

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
The confirm dialog showed a sanitized command (BiDi/zero-width stripped)
but executed the raw string, creating a display/consent mismatch.
Now the command is sanitized once and the same string is used for both
display and execution.

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
* New window inherits size from current window

When creating a new window via Cmd+Shift+N, use the key window's
frame dimensions instead of the hardcoded 460x360 default. The new
window cascades from the existing window's position so it doesn't
stack directly on top.

* Use Ghostty's cascade algorithm for new window positioning

Match upstream Ghostty's window cascade logic: maintain a
lastCascadePoint that tracks where the next window should appear.
First window seeds the point from its own top-left corner, subsequent
windows advance the cascade point via NSWindow.cascadeTopLeft(from:).
On window close, reset the cascade point to the closing window's
position so the next window appears nearby.

New windows still inherit the key window's size so Cmd+Shift+N
creates a window matching the previous one's dimensions.

* Fix frame-to-contentRect conversion and use preferred window resolver

Convert existingFrame to a content rect via
NSWindow.contentRect(forFrameRect:styleMask:) so the new window
matches the source window's actual size instead of growing by
titlebar insets on each Cmd+Shift+N.

Use preferredMainWindowContextForWorkspaceCreation to resolve the
source window, consistent with showOpenFolderPanel and other
callers.

---------

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
…ai#2127)

* Add Cmd+N workspace snapshot regression coverage (manaflow-ai#2017)

* Add dev flag to stress Cmd+N workspace creation
* test: cover accessible window frame restore

* fix: preserve accessible window frame on relaunch
…-crash-regression

Fix Cmd+N crash from stale workspace creation snapshots
* test: cover cached update pill first-click flow

* fix: use cached sidebar update popover
…-ai#2101)

* test: add stale inherited surface regression

* fix: guard inherited terminal config against stale surfaces

* fix: address stale surface review feedback
* Add regression tests for Cmd+N workspace snapshot mutations

* Fix Cmd+N workspace creation snapshot races
…w-ai#2168)

* Fix update attempt refreshing pill without actually updating

The attemptUpdate() subscriber watched for .updateAvailable state to
auto-confirm, but showUpdateFound used setStateAfterMinimumCheckDelay
which delays the transition by up to 2 seconds. During that window,
dismissUpdateInstallation (from a background probe race) could cancel
the pending transition, reverting state to idle without ever confirming.
The subscriber then tore down on the transient idle, silently abandoning
the update.

Fix: move auto-confirm to the Sparkle driver level via an
autoInstallOnNextUpdate flag. When set, showUpdateFound immediately
calls reply(.install) bypassing the delay entirely. The subscriber
is kept as a fallback but no longer tears down on transient idle
while the flag is active.

Closes manaflow-ai#2166

* Revert "Fix update attempt refreshing pill without actually updating"

This reverts commit 1cd842d.

* Fix update attempt refreshing pill without actually updating

The attemptUpdate() subscriber tore down monitoring whenever it saw
.idle after observing progress. During check startup (retry loop,
background probe race), state can transiently return to .idle before
Sparkle's interactive check begins. The subscriber interpreted this
as "check completed" and stopped monitoring, so the auto-confirm
for .updateAvailable never fired.

Fix: add !state.isIdle to the teardown guard so monitoring only
stops on terminal failures (.notFound, .error), not transient idle.

Closes manaflow-ai#2166

---------

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
* test: cover command palette focus guard

* fix: block terminal find from stealing palette focus

* test: cover text view focus-stealer fallback

* Add regression for hidden DevTools sync republish loop

* Avoid redundant DevTools visibility publishes

* test: cover browser find focus after workspace round-trip

* fix: restore browser find focus after workspace round-trip

* fix: keep browser find caret on workspace return

* Add workspace round-trip split find regressions

* Keep inactive find overlays from stealing focus

---------

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
…i#2165)

Dev builds should use the most permissionless socket mode so coding
agents and external tools can connect without any restrictions.
Changes automation → allowAll in the LSEnvironment plist entries and
the launch-time env vars.

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
* Add regression test for detached remote cleanup

* Skip SSH cleanup after remote surface transfer

* Add SSH lifecycle regression coverage

* Add SSH detach cleanup transfer regressions

* Transfer SSH cleanup ownership with detached remote terminals

* Document intentional SSH workspace focus

---------

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
…#2178)

* Add workspace config sanitization regression test

* Sanitize workspace creation config snapshots

---------

Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
…lowup-comments

Fix command palette follow-up review comments
* test: reproduce Cmd+N snapshot workspace lifetime race

* fix: retain snapshot workspaces through Cmd+N creation

* fix: repair workspace lifetime regression test
…w-ai#2183)

* test: reproduce Cmd+N snapshot workspace lifetime race

* fix: retain snapshot workspaces through Cmd+N creation

* fix: repair workspace lifetime regression test
Neither device.camera nor device.audio-input are used in cmux code.
Camera: no AVCapture/NSCamera usage. Audio: only NSSound output (bell),
which doesn't require audio-input. Removing reduces entitlement surface
for fork builds.

Remaining entitlements: cs.disable-library-validation, cs.allow-unsigned-
executable-memory, cs.allow-jit, automation.apple-events, device.usb,
application-identifier.
Ingests all upstream fixes since 2026-03-22 including:
- Fix Cmd+N crash: retain snapshot workspaces (manaflow-ai#2183, manaflow-ai#2181, manaflow-ai#2178, manaflow-ai#2173)
- Fix browser pane restore after reopen (manaflow-ai#2141)
- Fix Ghostty resize_split keybind (manaflow-ai#1899)
- Reduce shell integration prompt latency (manaflow-ai#2109)
- Fix command palette focus after terminal find (manaflow-ai#2089)
- Add Codex CLI hooks (manaflow-ai#2103)
- Add cmux.json custom commands (manaflow-ai#2011)
- Fix window position restore on relaunch (manaflow-ai#2129)

Conflict resolution:
- BrowserPanel.swift: accepted upstream configureWebViewConfiguration()
  refactor (already includes our forMainFrameOnly:true CAPTCHA fix from PR manaflow-ai#1877)

Fork-specific files preserved:
- Sources/Panels/WebAuthn{Coordinator,BridgeJavaScript}.swift
- Sources/FIDO2/module.modulemap
- vendor/ctap2 submodule
- cmux.entitlements (with camera/audio-input removed)
- cmux.embedded.entitlements
- .github/workflows/fork-{ci,release}.yml
@Jesssullivan Jesssullivan merged commit c82f6a2 into main Mar 26, 2026
2 of 4 checks passed
@Jesssullivan Jesssullivan deleted the sid/entitlements-cleanup-upstream-sync branch March 27, 2026 14:12
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.