- Add hasLiveSurface guard in TabManager.inheritedTerminalConfigForNewWorkspace
to protect the cmuxInheritedSurfaceConfig call site missed in the initial fix
- Expand malloc_size comment to clarify it is a best-effort heuristic, not a
lifetime guarantee (per Copilot review)
ghostty_surface_quicklook_font returns an unretained CTFont pointer that
can become stale on Intel Macs, leading to EXC_BAD_ACCESS (SIGSEGV) when
creating a split. This is a follow-up to the same crash pattern fixed in
#1496.
Add malloc_size validation in cmuxCurrentSurfaceFontSizePoints to detect
freed heap allocations before interpreting the pointer as a CTFont. Also
add hasLiveSurface guards in inheritedTerminalConfig and
rememberTerminalConfigInheritanceSource to skip surfaces whose native
state is closing or closed. All callers already handle nil gracefully by
falling back to inherited config values.
When a non-Latin input source like Korean 두벌식 is active,
event.charactersIgnoringModifiers returns Hangul characters (e.g. ㅅ
for T key) instead of Latin letters. This caused all character-based
shortcut matching to fail — Cmd+T, Cmd+D, Cmd+1-9, Ctrl+N/P, etc.
Root cause: KeyboardLayout.character(forKeyCode:modifierFlags:) assumed
CJK input sources lack kTISPropertyUnicodeKeyLayoutData, but Korean
두벌식 has it. UCKeyTranslate returned Korean characters and the ASCII
fallback was never reached.
Fix:
- KeyboardLayout.character(): check result is ASCII before accepting;
fall through to TISCopyCurrentASCIICapableKeyboardInputSource() when
the current source returns non-ASCII characters
- Add KeyboardLayout.normalizedCharacters(for:) helper that normalizes
event.charactersIgnoringModifiers for shortcut comparison
- Apply normalization in handleCustomShortcut (AppDelegate),
BrowserPanelView omnibar key handler, and BrowserPopupWindowController
Cmd+W handler
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add regressions for SSH image transfer followups
* Fix SSH image transfer followup regressions
---------
Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
* Add regression test for browser back history
* Fix browser back history handoff
* Fix browser tab favicon not updating on navigation
Two issues caused stale or missing favicons in browser tabs:
1. KVO race: The isLoading observer read webView.isLoading inside a deferred
Task instead of capturing the KVO change value at observation time. For fast
navigations (back-forward cache), isLoading flips true→false before the Task
runs, so handleWebViewLoadingChanged(true) was never called and the old
favicon was never cleared.
2. SPA favicon discovery: Sites that inject <link rel="icon"> via JavaScript
(e.g. React apps) had no favicon link in the DOM when didFinish fired. The
fallback to /favicon.ico often 404'd, leaving the globe icon permanently.
Now retries the JS query after 600ms to give client-side scripts time to
add the tag.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.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>
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>
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#1429
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>
Two root causes for issue #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#879
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fixes#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>
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.
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>