Skip to content

Fix nightly startup crash - #4318

Merged
lawrencecchen merged 6 commits into
mainfrom
issue-nightly-instant-crash
May 19, 2026
Merged

lawrencecchen merged 6 commits into
mainfrom
issue-nightly-instant-crash

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented May 18, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • fix GhosttyApp runtime callback re-entry during singleton initialization
  • normalize and verify the bundled Nucleo FFI dylib install name
  • add signed app launch smoke coverage to nightly and release workflows
  • add sparse startup breadcrumbs for nightly/dev startup failures

Verification

  • Release arm64 build succeeded with isolated DerivedData
  • local nightly-shaped app with bundle ID com.cmuxterm.app.nightly stayed alive for 5s via scripts/smoke-launch-macos-app.sh
  • scripts/verify-command-palette-nucleo-ffi-artifact.sh passes on the rebuilt app and fails on the currently installed broken nightly
  • ./scripts/reload.sh --tag ncrash succeeded

Note

Medium Risk
Touches macOS startup/termination paths and Ghostty runtime callback routing, plus adds new CI smoke-launch and signing/linkage verification; failures could impact app launch or release pipelines if assumptions differ across environments.

Overview
Fixes a macOS nightly instant-launch crash by routing Ghostty C runtime callbacks (wakeup_cb/action_cb) to the correct GhosttyApp instance via userdata plus a locked ghostty_app_t→GhosttyApp registry, avoiding GhosttyApp.shared re-entry during initialization.

Adds lightweight startup breadcrumbs (StartupBreadcrumbLog) and instruments key launch/single-instance/termination milestones in cmuxApp and AppDelegate (enabled by default for nightly/debug or via env flags) to aid post-mortem startup debugging.

Hardens packaging/release automation: nightly + release workflows now smoke-launch the signed/notarized app; the Nucleo command-palette dylib build normalizes its install name to @rpath, and signing verifies the dylib’s install name and rejects CI/source-tree absolute load paths.

Reviewed by Cursor Bugbot for commit 7ee42f6. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Fixes the nightly instant startup crash by hardening Ghostty runtime callback routing to prevent GhosttyApp singleton re-entry during init. Adds env-toggleable startup breadcrumbs and a CI smoke launch step, and enforces an @rpath install name for the bundled Nucleo FFI dylib with signing-time verification.

  • Bug Fixes

    • wakeup_cb now targets the app from userdata; action_cb resolves via a locked registry keyed by ghostty_app_t and falls back to the in-flight app during runtime init, eliminating singleton re-entry crashes.
    • Sets libcmux_command_palette_nucleo_ffi.dylib install name to @rpath/... during build and verifies it during signing (including checks for absolute load paths).
  • New Features

    • Startup breadcrumbs (nightly/debug by default; env-toggleable) write sanitized, bounded JSONL with PID/bundle/version metadata using a locked, synchronous append. Instrumented across cmuxApp/AppDelegate, including single-instance and termination paths.
    • Nightly and release workflows run scripts/smoke-launch-macos-app.sh to launch the signed app, wait for PID registration, filter pre-existing processes, ensure brief liveness, and print breadcrumbs (system logs are optional via CMUX_SMOKE_DEBUG_LOGS).

Written for commit 7ee42f6. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

  • New Features

    • App startup now records local breadcrumb events for richer diagnostic logs.
  • Improvements

    • Better runtime handling for multiple concurrent app instances and more reliable callback routing.
    • More thorough post-signing verification of packaged runtime artifacts.
  • Chores

    • macOS release/build flow adds an automated smoke-launch verification step during packaging.
    • Packaging adjusts dynamic library metadata to ensure correct runtime linking.

Review Change Stack

@chatgpt-codex-connector

Copy link
Copy Markdown

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.

@vercel

vercel Bot commented May 18, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment May 19, 2026 0:39am
cmux-staging Building Building Preview, Comment May 19, 2026 0:39am

@coderabbitai

coderabbitai Bot commented May 18, 2026 •

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds StartupBreadcrumbLog and instruments app startup/teardown and single-instance logic with breadcrumbs; adapts Ghostty runtime callbacks to per-instance routing; adds smoke-launch and dylib-verification scripts and integrates them into build/sign/notarize CI steps.

Changes

Startup Instrumentation and Verification

Layer / File(s) Summary
Startup breadcrumb logging foundation
Sources/App/StartupBreadcrumbLog.swift, cmux.xcodeproj/project.pbxproj
StartupBreadcrumbLog provides thread-safe newline-delimited JSON startup event logging; file is added to the app target.
App lifecycle breadcrumb instrumentation
Sources/AppDelegate.swift, Sources/cmuxApp.swift
Breadcrumb calls added across AppDelegate launch/termination flows and in cmuxApp.init() around test wiring, migrations, settings, and UI bootstrap.
Multi-instance Ghostty runtime support
Sources/GhosttyTerminalView.swift
Replaces singleton callback routing with an NSLock-protected registry mapping ghostty_app_t pointers to GhosttyApp instances; callbacks and handlers now resolve and dispatch to the correct instance.
Smoke-launch and dylib verification scripts
scripts/smoke-launch-macos-app.sh, scripts/verify-command-palette-nucleo-ffi-artifact.sh
smoke-launch-macos-app.sh launches the app, polls for the new PID, validates stability, and dumps logs on failure. verify-command-palette-nucleo-ffi-artifact.sh validates dylib install-name and rejects absolute CI/workspace load paths.
Build/sign/notarize integration
scripts/build-command-palette-nucleo-ffi.sh, scripts/sign-cmux-bundle.sh, .github/workflows/nightly.yml, .github/workflows/release.yml
build-command-palette-nucleo-ffi.sh sets the dylib ID to @rpath/...; sign-cmux-bundle.sh invokes the dylib verifier; CI notarization steps run the smoke-launch script after spctl/stapler validation.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Poem

🐰 I hopped through startup logs and trails,

tiny crumbs that mark the rails.
Ghostty learned to share its hat,
smoke-tests chased the startup spat.
Build and sign — a tidy cheer, all clear.


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (1 error, 1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Cmux Swift Logging ❌ Error Pull request violates swift-logging.md: Multiple unguarded print() and NSLog() statements in app/runtime code (Sources/GhosttyTerminalView.swift, AppDelegate.swift, cmuxApp.swift) Remove or guard with #if DEBUG: 6 print() calls in GhosttyTerminalView (lines 1993, 1999, 2131, 2170, 5444, 5681); 2 NSLog() in AppDelegate (lines 982, 13811); 1 NSLog() in cmuxApp (line 5723). Use os.Logger instead for production logging.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive PR description is comprehensive but deviates from the template structure; it lacks explicit Testing and Demo Video sections required by the repository template. Add a dedicated 'Testing' section detailing test methodology, and include 'Demo Video' section or clarify if not applicable. Ensure 'Verification' section aligns with template's 'Testing' guidance.
✅ Passed checks (13 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix nightly startup crash' is concise and directly references the main objective of the PR, which is to fix a nightly-only instant-startup crash by addressing Ghostty runtime callback routing.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Actor Isolation ✅ Passed PR introduces no actor isolation violations. StartupBreadcrumbLog is properly designed; registry uses NSLock; all MainActor code correctly annotated.
Cmux Swift Blocking Runtime ✅ Passed New NSLocks are documented and justified for C callback routing/coalescing. No prohibited patterns found in new Swift code.
Cmux No Hacky Sleeps ✅ Passed Sleeps only in CI smoke test script for post-notarization app verification. Bounded polling with timeouts is test-only scaffolding, an allowed exception.
Cmux Swift Concurrency ✅ Passed No legacy async patterns found. StartupBreadcrumbLog is synchronous. AppDelegate/cmuxApp only add logging. GhosttyTerminalView uses NSLock for required C API callback routing.
Cmux Swift @Concurrent ✅ Passed No async functions added. All callbacks use explicit actor hops. StartupBreadcrumbLog is synchronous with proper locking. Complies with concurrent annotation rules.
Cmux Swift File And Package Boundaries ✅ Passed StartupBreadcrumbLog.swift (96 lines) under 400-line threshold, single responsibility. File additions (14-65 lines) under 250-line limit. Complies with package-boundary rules.
Cmux User-Facing Error Privacy ✅ Passed No user-facing errors, alerts, or output were added that would violate privacy rules. All new text is internal diagnostics (breadcrumb logging) or CI scripts not shipped to users.
Cmux Swiftui State Layout ✅ Passed No new SwiftUI state violations. Changes add logging utilities and callback routing, not new @Published/@StateObject/@observable patterns or layout/render-time mutations.
Cmux Architecture Rethink ✅ Passed Uses NSLock registry for C callback bridging, test-only polling in CI, and diagnostic logging—all allowed patterns with clear ownership and documented reasons.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed Adds breadcrumb logging (14 lines). Window declarations are pre-existing code, not modified. No new windows introduced. Per rule, existing unregistered windows not worsened pass check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-nightly-instant-crash

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.

@greptile-apps

greptile-apps Bot commented May 18, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

Fixes the nightly instant-startup crash caused by GhosttyApp.shared re-entry during singleton initialization by routing C runtime callbacks through a locked ghostty_app_t→GhosttyApp registry with an in-flight fallback, and hardens macOS packaging with @rpath dylib normalization, post-sign verification, and a CI smoke-launch guard.

  • Crash fix (GhosttyTerminalView.swift): wakeup_cb now resolves the app from the userdata pointer directly; action_cb uses runtimeAppForActionCallback which checks the locked registry first and falls back to initializingRuntimeApp during ghostty_app_new, eliminating the GhosttyApp.shared re-entry window. The SAFETY: comment and deliberate single-lifetime rationale are documented.
  • Startup breadcrumbs (StartupBreadcrumbLog.swift, cmuxApp.swift, AppDelegate.swift): New opt-in JSONL diagnostic log gated to nightly/debug bundle identifiers; uses flock-protected synchronous writes to survive launch aborts; instrumented across ~15 startup and termination sites. Previous review feedback (NSLock → flock, NSLog → os.Logger) has been addressed.
  • Packaging hardening (scripts): build-command-palette-nucleo-ffi.sh normalizes the dylib install name to @rpath/… post-lipo; sign-cmux-bundle.sh runs the new verify-command-palette-nucleo-ffi-artifact.sh after codesign; nightly and release workflows run smoke-launch-macos-app.sh after notarization to ensure the signed app survives 5 s of live running.

Confidence Score: 5/5

Safe to merge — crash fix is correctly scoped to the re-entry window and the packaging changes are additive CI guards.

The registry+in-flight-fallback design for callback routing is sound for a single process-lifetime GhosttyApp: wakeup_cb resolves the app directly from its userdata pointer, and action_cb uses the locked registry with a deliberate fallback to initializingRuntimeApp only during ghostty_app_new, cleared by defer when init exits. StartupBreadcrumbLog is nightly/debug-gated, uses flock for cross-process serialization, and all previous review concerns have been addressed. Packaging changes are isolated to build and CI scripts with no effect on app logic.

No files require special attention. GhosttyTerminalView.swift carries the most risk as the crash fix, but the logic is well-contained and the CI smoke-launch guard will catch regressions.

Important Files Changed

Filename Overview
Sources/GhosttyTerminalView.swift Core crash fix: adds appRegistry, appRegistryLock (NSLock with SAFETY comment), and initializingRuntimeApp to route wakeup_cb/action_cb without re-entering GhosttyApp.shared during init. The registry+init-fallback design is sound for a process-lifetime singleton.
Sources/App/StartupBreadcrumbLog.swift New 101-line enum namespace for nightly/debug-gated startup JSONL breadcrumbs. Uses flock-protected synchronous appends, sanitized payloads, bounded field lengths, nonisolated Logger, and bundle-identifier allow-list gating. Previous review concerns addressed.
Sources/AppDelegate.swift Adds ~20 breadcrumb call sites across didFinishLaunching, applicationShouldTerminate, applicationWillTerminate, enforceSingleInstance, and observeDuplicateLaunches. All gated by StartupBreadcrumbLog.isEnabled. No logic changes to existing paths.
Sources/cmuxApp.swift Adds 10 breadcrumb call sites through the App init chain. No logic changes to existing init path.
scripts/smoke-launch-macos-app.sh New CI-only smoke script: launches app via open -n -g, polls for PID using pgrep+sleep, verifies 5s liveness, prints breadcrumb log and system log on failure. Bounded timeouts configurable via env vars.
scripts/verify-command-palette-nucleo-ffi-artifact.sh New verification script: reads install name via otool -D, asserts @rpath/libcmux_command_palette_nucleo_ffi.dylib, checks for CI/source-tree absolute load paths in otool -L output.
scripts/build-command-palette-nucleo-ffi.sh Adds install_name_tool -id @rpath/${LIB_NAME} after lipo to normalize the dylib install name before bundle copy.
scripts/sign-cmux-bundle.sh Computes SCRIPT_DIR and invokes verify-command-palette-nucleo-ffi-artifact.sh after codesign --verify. Minimal change, correct placement.
.github/workflows/nightly.yml Adds smoke-launch-macos-app.sh invocation after stapler validate and spctl check, before DMG creation.
.github/workflows/release.yml Same smoke-launch step added in the release workflow at the same post-notarization point. Consistent with nightly.yml.
cmux.xcodeproj/project.pbxproj Adds PBXBuildFile and PBXFileReference entries for StartupBreadcrumbLog.swift in the main app target. Routine project file update.

Reviews (5): Last reviewed commit: "Address final launch review feedback" | Re-trigger Greptile

Comment thread Sources/App/StartupBreadcrumbLog.swift Outdated
Comment thread Sources/App/StartupBreadcrumbLog.swift
Comment thread Sources/GhosttyTerminalView.swift
coderabbitai[bot]
coderabbitai Bot previously requested changes May 18, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/smoke-launch-macos-app.sh`:
- Around line 24-27: The cleanup() function and PID handling currently may pick
an unrelated running app because APP_PID is obtained globally; change the launch
logic to capture and use the child PID returned by the local background launch
(use the shell $! equivalent) and store that in APP_PID immediately after
starting the app so cleanup() always targets the instance you just launched;
update every place that assigns or checks APP_PID (the other launch/wait blocks
and any pgrep/pidof-based checks) to rely on the stored launch PID rather than
querying processes globally, and keep the existing kill -0 / kill calls but only
referencing that scoped APP_PID in cleanup().
- Around line 40-50: The current loop polls with sleep to detect the launched
app (using APP_PID, find_app_pid, OPEN_PID, SECONDS/STARTUP_TIMEOUT_SECONDS),
violating the no-sleep policy; replace it with blocking/wait-based
synchronization by removing the while/sleep loop and using wait "$OPEN_PID" to
block until the open/launcher process finishes, then call find_app_pid once (or
a small bounded non-sleep retry using a timeout wrapper) to obtain APP_PID;
enforce the overall startup timeout by running the open command under a timeout
utility (e.g., timeout/gtimeout) or by using a trap/alarm-based timeout instead
of polling with SECONDS and sleep.

In `@Sources/App/StartupBreadcrumbLog.swift`:
- Around line 10-11: The NSLock usage (lock.lock()/defer { lock.unlock() }) only
protects within one process; replace per-process NSLock protection in
StartupBreadcrumbLog write/append methods with an inter-process file lock: open
the breadcrumb file (or create it) and acquire an exclusive POSIX lock (flock or
fcntl F_SETLKW) on its file descriptor before seeking/appending JSONL, then
release the lock (LOCK_UN) in a defer; update all places that use the local
`lock` (including the other write/append blocks referenced) to use this fd-based
lock around the file writes so concurrent processes cannot corrupt the shared
file. Ensure the lock is taken on the same file descriptor used for the write
and that errors opening/locking are handled/logged.
- Around line 22-24: The loop that merges caller-provided `fields` into
`payload` (the code using `for (key, value) in fields { payload[key] =
sanitized(value) }`) must ignore or namespace reserved breadcrumb keys so
callers cannot overwrite built-in metadata; update the merge to skip keys in a
reserved set (e.g., "timestamp", "event", "pid", and any version keys) or rename
them (e.g., prefix with "custom_") before calling `sanitized(value)`, ensuring
the `payload` and any related types in StartupBreadcrumbLog keep the original
built-in keys intact.

In `@Sources/GhosttyTerminalView.swift`:
- Around line 3619-3621: The code currently calls applyBackgroundToKeyWindow()
on the global key window (mutating cmux.main*), which lets runtime A repaint
runtime B; change the call so the background is applied only to windows/surfaces
owned by this GhosttyTerminalView instance (e.g., add/use a method on
GhosttyTerminalView like applyBackgroundToOwnedWindows() or a variant that
accepts the specific window(s)/surface(s) for self) and invoke that instead of
applyBackgroundToKeyWindow(); update both occurrences (the one inside
DispatchQueue.main.async near applyBackgroundToKeyWindow and the other
occurrence around lines 3851–3853) to scope changes to self’s windows.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 99002098-8736-40ac-84f6-0144d36e979e

📥 Commits

Reviewing files that changed from the base of the PR and between 267954b and 64239f9.

📒 Files selected for processing (11)
  • .github/workflows/nightly.yml
  • .github/workflows/release.yml
  • Sources/App/StartupBreadcrumbLog.swift
  • Sources/AppDelegate.swift
  • Sources/GhosttyTerminalView.swift
  • Sources/cmuxApp.swift
  • cmux.xcodeproj/project.pbxproj
  • scripts/build-command-palette-nucleo-ffi.sh
  • scripts/sign-cmux-bundle.sh
  • scripts/smoke-launch-macos-app.sh
  • scripts/verify-command-palette-nucleo-ffi-artifact.sh

Comment thread scripts/smoke-launch-macos-app.sh
Comment thread scripts/smoke-launch-macos-app.sh
Comment thread Sources/App/StartupBreadcrumbLog.swift Outdated
Comment thread Sources/App/StartupBreadcrumbLog.swift
Comment thread Sources/GhosttyTerminalView.swift

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

2 issues found across 11 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread Sources/App/StartupBreadcrumbLog.swift Outdated
Comment thread scripts/smoke-launch-macos-app.sh Outdated
coderabbitai[bot]
coderabbitai Bot previously requested changes May 18, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/smoke-launch-macos-app.sh`:
- Around line 65-67: The script currently prints raw launcher and system logs
unconditionally (e.g., the cat "$OPEN_LOG" block and the app stability check and
the /usr/bin/log show invocation); change these to only dump raw logs when an
explicit debug env flag is set (use CMUX_SMOKE_DEBUG_LOGS=1) by wrapping the cat
"$OPEN_LOG", the app-stability log dump, and the /usr/bin/log show call in a
conditional that checks CMUX_SMOKE_DEBUG_LOGS, and when the flag is not set
replace the raw output with a short sanitized message (e.g., "Detailed logs
available with CMUX_SMOKE_DEBUG_LOGS=1") so default error output does not leak
internal system/framework details.

In `@Sources/GhosttyTerminalView.swift`:
- Around line 2010-2012: The runtimeConfig.action_cb assignment can be nil
during app construction because appRegistry isn't populated until
ghostty_app_new returns; to fix, register an init-time fallback on
runtimeConfig.action_cb that safely handles the startup window by first
attempting GhosttyApp.runtimeApp(for:) and calling
runtimeApp.handleAction(target:action:) if present, but if runtimeApp is nil
either queue the action for replay or return a defined fallback response (e.g.,
false) until ghostty_app_new completes; update the closure at the sites
referencing runtimeConfig.action_cb (the current block using
GhosttyApp.runtimeApp(for:) and handleAction, and the other similar blocks
around the indicated ranges) so they use this fallback/queue mechanism and
ensure the queued actions are flushed once ghostty_app_new has populated the
registry.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 468db082-fb67-4fc2-a235-476e893048a1

📥 Commits

Reviewing files that changed from the base of the PR and between 64239f9 and e305c73.

📒 Files selected for processing (3)
  • Sources/App/StartupBreadcrumbLog.swift
  • Sources/GhosttyTerminalView.swift
  • scripts/smoke-launch-macos-app.sh

Comment thread scripts/smoke-launch-macos-app.sh Outdated
Comment thread Sources/GhosttyTerminalView.swift

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
Sources/GhosttyTerminalView.swift (1)

1672-1676: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

action_cb still has an init-time hole.

The new registry is only populated after ghostty_app_new(...) returns, but the added safety comment explicitly says Ghostty callbacks can run during singleton initialization. If action_cb fires in that window, runtimeApp(for:) is nil and the callback is dropped by returning false. This still leaves startup behavior dependent on callback timing. Please add an init-time fallback for the constructing instance (or queue actions until registerRuntimeApp runs) instead of relying solely on the post-construction registry.

Also applies to: 2011-2013, 2100-2103, 2149-2161

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Sources/GhosttyTerminalView.swift` around lines 1672 - 1676, The action_cb
can fire before registerRuntimeApp populates appRegistry, so update the startup
path to provide an init-time fallback: add a temporary construct-time holder
(e.g. a static optional like constructingApp keyed by the same UInt id) and set
it during GhosttyApp initialization, then have runtimeApp(for:) check that
constructingApp when appRegistry lookup returns nil; alternatively make
action_cb enqueue the incoming actions into a short-lived per-id queue
(protected by appRegistryLock) that registerRuntimeApp drains once it sets
appRegistry. Concretely, set the constructing instance before calling
ghostty_app_new, clear it inside registerRuntimeApp when moving into
appRegistry, and modify runtimeApp(for:) (and action_cb) to consult the
constructingApp or the per-id queue as a fallback so callbacks are not dropped
during initialization.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@Sources/GhosttyTerminalView.swift`:
- Around line 1672-1676: The action_cb can fire before registerRuntimeApp
populates appRegistry, so update the startup path to provide an init-time
fallback: add a temporary construct-time holder (e.g. a static optional like
constructingApp keyed by the same UInt id) and set it during GhosttyApp
initialization, then have runtimeApp(for:) check that constructingApp when
appRegistry lookup returns nil; alternatively make action_cb enqueue the
incoming actions into a short-lived per-id queue (protected by appRegistryLock)
that registerRuntimeApp drains once it sets appRegistry. Concretely, set the
constructing instance before calling ghostty_app_new, clear it inside
registerRuntimeApp when moving into appRegistry, and modify runtimeApp(for:)
(and action_cb) to consult the constructingApp or the per-id queue as a fallback
so callbacks are not dropped during initialization.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 58f43dce-68fc-475f-be88-774a582206b8

📥 Commits

Reviewing files that changed from the base of the PR and between e305c73 and 391914b.

📒 Files selected for processing (2)
  • Sources/App/StartupBreadcrumbLog.swift
  • Sources/GhosttyTerminalView.swift

Comment thread Sources/App/StartupBreadcrumbLog.swift Outdated
Comment thread Sources/GhosttyTerminalView.swift

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 7ee42f6. Configure here.

appRegistryLock.lock()
defer { appRegistryLock.unlock() }
return appRegistry[key]
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unused private method runtimeApp(for:) is dead code

Low Severity

The newly added runtimeApp(for app: ghostty_app_t?) -> GhosttyApp? static method is never called anywhere in the codebase. The wakeup_cb uses runtimeApp(from: UnsafeMutableRawPointer?) (a different overload), and the action_cb uses runtimeAppForActionCallback(_:). This method is dead code that adds confusion alongside the two actually-used lookup methods.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7ee42f6. Configure here.

@lawrencecchen
lawrencecchen dismissed stale reviews from coderabbitai[bot] and coderabbitai[bot] May 19, 2026 00:40

Stale bot change request. Inline findings were addressed in later commits and resolved on the PR.

@lawrencecchen
lawrencecchen merged commit 76ba2bf into main May 19, 2026
28 of 30 checks passed
@lawrencecchen
lawrencecchen deleted the issue-nightly-instant-crash branch May 19, 2026 00:40

This branch was successfully deployed

1 active deployment
Preview – cmux — 7ee42f6f Deployed May 19, 2026 by vercel[bot]
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.

1 participant