Merge upstream (165 commits) + remove unused entitlements#44
Merged
Jesssullivan merged 167 commits intomainfrom Mar 26, 2026
Merged
Merge upstream (165 commits) + remove unused entitlements#44Jesssullivan merged 167 commits intomainfrom
Jesssullivan merged 167 commits intomainfrom
Conversation
…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>
…#1859) Co-authored-by: Brian Le <brian@brianle.xyz>
…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>
…-ai#1860) Co-authored-by: jjonyo <jonyo.park@gmail.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>
* 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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
device.cameraanddevice.audio-inputfromcmux.entitlementsKey upstream fixes ingested
Conflict resolution
BrowserPanel.swift: Upstream refactored config into helper method; already includes our forMainFrameOnly:true fix (merged PR fix: Cloudflare/CAPTCHA verification failures in browser panel manaflow-ai/cmux#1877)Fork-specific files preserved
Test plan