Skip to content

Fix Claude process leaks when closing tabs - #9782

Closed
austinywang wants to merge 51 commits into
mainfrom
issue-9573-claude-process-leak
Closed

austinywang wants to merge 51 commits into
mainfrom
issue-9573-claude-process-leak

Conversation

@austinywang

@austinywang austinywang commented Aug 7, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • make each native terminal runtime generation own a one-shot access/teardown gate
  • synchronously close native-read admission before any teardown task hop, while allowing an already-admitted bounded read to finish safely
  • start Ghostty-owned process-group shutdown independently of bounded native-free worker availability
  • raise Claude's injected SessionEnd hook timeout from one second to ten seconds without overriding an explicit user exit-budget setting
  • preserve a stable POSIX process-group identity, give SessionEnd a 12-second SIGHUP grace window, then escalate surviving descendants once and bound the final reap
  • publish and checksum-pin the matching universal ReleaseFast GhosttyKit artifact

Closes #9573.

Root cause

The one-second SessionEnd hook timeout was real, but increasing it alone could not make pane process lifetime reliable.

A UI close removes the Swift-owned native surface and schedules Ghostty's final free away from the main actor. Process termination previously began only when a bounded worker reached ghostty_surface_free. If both native-free workers were occupied by stuck joins, a later closed pane could remain queued without its process group ever being told to stop.

Starting termination unconditionally before that queue exposed a second ownership race: bounded screen-tail reads capture the native pointer before their first actor suspension. A close could otherwise retire the native surface while one of those reads still held a valid Swift request but had not yet called Ghostty.

The structural defect was therefore missing ownership and ordering between three events: native-read admission, process termination, and final surface destruction.

Architectural invariant

Each installed TerminalSurface runtime pointer now gets a fresh TerminalSurfaceRuntimeNativeAccessGate. The gate is the sole owner of admission and the terminal teardown transition for that runtime generation.

  • Close first: the close bit is claimed synchronously, future native reads are rejected, Ghostty process termination starts before the coordinator's Task hop, and final native free enters the bounded worker pool.
  • Borrow first: the admitted read finishes against the still-live native pointer; the final borrower synchronously claims the retained one-shot teardown action, starts process termination, and only then queues final free.
  • Duplicate teardown requests are ignored for that generation, and installing a new runtime pointer installs a new gate.
  • ghostty_surface_free remains the final synchronization point for renderer and IO joins, callback userdata, and native allocation release.

This preserves the normal fast path—termination still begins synchronously before suspension when no read is active—without making a borrowed pointer invalid.

Why atomics, not an actor

Both sides need a decision before suspension: boundedScreenTailVT must acquire its borrow before awaiting the teardown actor, while close/deinit must close admission from a synchronous nonisolated path. An actor would require Task/await admission and reintroduce the ordering gap this change removes.

The gate uses the existing macOS 14-compatible C11 atomic layer: one UInt64 packs the permanent close bit and borrow count, and one atomic raw pointer publishes the retained one-shot action. There are no production locks or global registries.

AtomicRawPointerValue and AtomicUInt64Value use narrowly scoped @unchecked Sendable wrappers because Swift cannot infer the safety of C11 atomic storage. Each wrapper allocates one stable storage address, every pointee access goes through the C11 atomic API, and deallocation occurs only when the wrapper itself is no longer referenced. No broader runtime or domain object is declared @unchecked Sendable.

Ghostty process ownership

The final parent-repo pin is f76c132e526f124fe4aaebd39f516751656844bc, the current fork-main merge from manaflow-ai/ghostty#191. It contains this PR's complete process-teardown lineage through 90ba327fc6e0ea614e59a25f3ee5133b91d459da (#184, #187, #188, #192, and #193). The later pin only integrates already-merged fork work from current cmux main; it does not replace or bypass the process ownership fix.

Ghostty now:

  1. retires the embedded surface from app routing in the non-blocking, idempotent pre-free request;
  2. preserves both the session-leader group and a distinct foreground job-control group while each remains attributable to the live PTY generation;
  3. sends one SIGHUP and polls group liveness with signal 0 for a shared 12-second grace window;
  4. sends one SIGKILL to each surviving attributable group, bounds the final reap wait to three seconds, and stops targeting a group as soon as it disappears;
  5. refuses stale cached group IDs after the direct child is reaped, preventing PID-reuse signals, while still handling the pre-exec race through the waitable child.

That keeps Claude's ten-second SessionEnd callback inside a larger native grace budget and still prevents a pathological child or foreground job from holding a teardown worker indefinitely.

Shared close-path audit

The UI close button, Cmd-W/configured shortcuts, context menus, and command palette all converge through TabManager/Workspace panel removal. CLI/socket close commands converge on the same TabManager/Workspace operations. TerminalPanel teardown and TerminalSurface deinit both end at the injected TerminalSurfaceRuntimeTeardownCoordinator.

No entrypoint gained its own PID lookup, TTY heuristic, signal path, or optimistic process state. The shared native ownership boundary handles every surface close.

Scope reconciliation after latest main merge

The paths previously flagged as out of scope—Sources/NotificationsPage.swift, Sources/Panels/FilePreviewPDFSharingPresenter.swift, and scripts/ci/run-app-host-xcodebuild.sh—are now part of origin/main and are absent from the current PR diff. The remaining origin/main...HEAD diff is limited to the terminal lifecycle/atomic ownership fix, its behavioral tests and stubs, the Claude hook budget, and the matching Ghostty pin/docs/checksum records.

Regression proof

The branch preserves test-first evidence.

  • cmux test-only SHA 3e05822 failed the swift-package-tests job in CI run 31168665963 with the exact assertion: “process termination began while a native surface read held a borrow.” The run was intentionally cancelled after the red proof was captured.
  • c9b543f introduced the first gate; f4e112f replaced the interim shared registry/locking design with per-runtime lock-free ownership; 8fc0ece added one-shot and runtime-generation coverage.
  • The earlier test/fix pairs remain split in history for the hook timeout, blocked native-free slots, and process teardown beyond saturated slots.
  • Ghostty test-only SHA b8a643561 reproduced both late repeated-SIGHUP behavior and descendants surviving after the group leader was reaped: 75/77 passed. Fix SHA 81b4de4f5 made the subprocess stop filter pass 77/77; the later babe4266c/47e9bd4c9 and 53239618f/bc7e9f746 pairs cover foreground job-control groups and stale process-group reuse, integrated through 90ba327fc and retained by the final f76c132e5 pin.

GhosttyKit artifact

The downloaded archive passed scripts/validate-xcframework-archive.py, matched the checksum pinned in scripts/ghosttykit-checksums.txt, and matched GitHub's release-asset digest. The submodule is on main, the exact pin is reachable from origin/main, and 90ba327fc… is an ancestor of it.

Verification completed before final CI

  • Exact app-host regression TabManagerCloseCurrentTabSpamTests/testCloseWorkspaceEnqueuesTerminalRuntimeTeardownOffMainThread: 1/1 passed with a real Ghostty runtime surface
  • CmuxTerminal lifecycle coverage: 25 tests across 3 suites passed
  • CmuxFoundation atomic coverage: 6 tests across 2 suites passed
  • python3 tests/test_claude_wrapper_hooks.py: passed
  • ./scripts/lint-pbxproj-test-wiring.sh: passed (662 files checked)
  • Package-resolved policy, workspace package grouping, and git diff --check: passed
  • ./scripts/reload.sh --tag issue-9573-claude-leak: succeeded without launching
  • cmux-unit scheme build against the same tagged DerivedData: succeeded
  • Canonical structured autoreview: no accepted/actionable code findings; patch judged correct at 0.92 confidence
  • Merge-conflict gate against current origin/main: clean

The mechanical cmux policy lane flags cmuxTests/TabManagerUnitTests.swift because the touched legacy file imports XCTest. This is the documented existing-suite exception: the regression already exists on main in Aziz's XCTest behavior suite (commit 2275df619a), and this PR only replaces its unsafe fake native pointer with a real runtime. Moving one assertion would split the suite while the necessary edit to the XCTest file would still trigger the same path-level grep.

Warning and localization audits

  • .github/swift-warning-budget.tsv and .github/swift-file-length-budget.tsv are unchanged.
  • No warning suppression was added; the source-level actor annotations and modern onChange closures remove warnings instead of spending budget.
  • The only unchecked concurrency escape hatch is the documented, stable-address C11 atomic wrapper described above.
  • No user-facing strings, Settings rows, menus, schemas, help text, or web catalog messages changed, so no localization catalog update is required.

Note

High Risk
Changes concurrency ordering and child-process teardown on every terminal close path; regressions could cause use-after-free, hung teardown workers, or lingering processes.

Overview
Fixes Claude and other child processes leaking when closing tabs by ordering native API use, process termination, and final ghostty_surface_free per runtime generation instead of tying shutdown to bounded free-worker slots.

Each installed Ghostty surface gets a TerminalSurfaceRuntimeNativeAccessGate (C11 atomics via new AtomicRawPointerValue and extended AtomicUInt64Value). Screen-tail reads acquire a borrow before touching the pointer; close/deinit closes admission and runs a one-shot teardown action when borrows drain. requestTeardown on the coordinator now calls ghostty_surface_request_process_termination before the async enqueue to the free queue, so stuck native joins cannot defer telling the process group to stop. Teardown uses paired TerminalSurfaceRuntimeNativeTeardown (begin + free) instead of a lone freeSurface closure; screen-tail work goes through a TerminalSurfaceRuntimeScreenTailReader actor with global serialization.

Claude injected SessionEnd hook timeout rises from 1s to 10s; Ghostty fork docs/checksums add the bounded embedded-surface teardown lineage through 90ba327fc. Tests and Ghostty runtime stubs cover gate races, overlapping reads, and close paths with real runtime surfaces.

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

Summary by CodeRabbit

  • Bug Fixes

    • Improved terminal runtime teardown reliability, preventing cleanup from racing with active screen reads.
    • Added safer handling when replacing runtime surfaces, including protection against stale access.
    • Improved concurrent terminal cleanup so later closures continue progressing when earlier cleanup is delayed.
    • Extended process termination and resource cleanup safeguards.
    • Improved screen-tail reading reliability and native text cleanup.
  • Documentation

    • Updated Ghostty integration documentation with teardown behavior, verification steps, and merge guidance.
  • Chores

    • Increased the Claude session-end hook timeout to 10 seconds for more reliable completion.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026 •

Copy link
Copy Markdown

Review Change Stack

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

Terminal surface teardown now uses per-runtime native-access gates, paired process termination and free operations, serialized screen-tail reads, and bounded close scheduling. Tests cover atomic operations, lifecycle coordination, concurrency, and Ghostty stubs. Claude SessionEnd hooks now use a 10-second timeout.

Changes

Runtime teardown

Layer / File(s) Summary
Atomic lifecycle primitives
Packages/macOS/CmuxFoundation/Sources/CmuxFoundation/Concurrency/*, Packages/macOS/CmuxFoundation/Sources/CmuxFoundationAtomicsC/*, Packages/macOS/CmuxFoundation/Tests/CmuxFoundationTests/Concurrency/*
Adds acquire loads and compare-exchange operations for uint64 and raw-pointer atomic values, with tests.
Native access and teardown model
Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRuntimeNativeAccess*, TerminalSurfaceRuntimeTeardownAction.swift, TerminalSurfaceRuntimeNativeTeardown.swift
Adds borrow tracking, one-shot teardown admission, deferred teardown actions, and paired process-termination and surface-free operations.
Bounded teardown and screen-tail scheduling
Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRuntimeTeardown*, TerminalSurfaceRuntimeScreenTail*
Queues teardown requests, serializes screen-tail reads, gates native access, and dispatches bounded native frees.
Terminal surface integration
Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface*
Stores a per-runtime gate and passes it through screen-tail, normal, debug, and agent-hibernation teardown paths.
Lifecycle and native stub validation
Packages/macOS/CmuxTerminal/Tests/CmuxTerminalTests/*RuntimeNativeAccessTests.swift, TerminalSurfaceRuntimeTeardownCoordinatorTests.swift, TerminalSurfaceTeardownCallbackLifetimeTests.swift, Packages/macOS/CmuxTerminal/Tests/GhosttyRuntimeTestStubs/*, cmuxTests/TabManagerUnitTests.swift
Tests deferred and one-shot teardown, serialized reads, cancellation, blocked frees, surface replacement, callback cleanup, and live-surface termination. Ghostty stubs provide blocking and concurrency controls.

Claude SessionEnd timeout

Layer / File(s) Summary
Set and validate SessionEnd timeout
Resources/bin/cmux-claude-wrapper, tests/test_claude_wrapper_hooks.py
Changes the generated SessionEnd hook timeout from 1 second to 10 seconds and requires the exact value in the regression test.

Ghostty fork records

Layer / File(s) Summary
Update Ghostty fork records
docs/ghostty-fork.md, scripts/ghosttykit-checksums.txt
Documents bounded embedded-surface process teardown, reorganizes VT commit history, and adds six GhosttyKit checksum mappings.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TerminalSurface
  participant ScreenTailReader
  participant NativeAccessGate
  participant TeardownCoordinator
  participant GhosttyRuntime

  TerminalSurface->>ScreenTailReader: submit screen-tail request
  ScreenTailReader->>NativeAccessGate: acquire native borrow
  TeardownCoordinator->>NativeAccessGate: begin surface teardown
  NativeAccessGate-->>TeardownCoordinator: defer while borrow is active
  ScreenTailReader->>GhosttyRuntime: read screen tail
  ScreenTailReader->>NativeAccessGate: release native borrow
  NativeAccessGate->>TeardownCoordinator: admit teardown
  TeardownCoordinator->>GhosttyRuntime: request process termination
  TeardownCoordinator->>GhosttyRuntime: free surface
Loading

Possibly related issues

  • manaflow-ai/cmux#7596 — Concerns runtime-surface teardown and hibernation behavior, which this PR extends with native-access coordination and bounded freeing.

Possibly related PRs

Suggested reviewers: azooz2003-bit, lawrencecchen

🚥 Pre-merge checks | ✅ 24 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.69% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (24 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes address issue [#9573] by extending SessionEnd, starting process-group termination, coordinating native teardown, and bounding process reaping.
Out of Scope Changes check ✅ Passed The changes remain within the stated scope: terminal lifecycle fixes, process teardown, tests, hook configuration, and supporting Ghostty documentation and artifacts.
Cmux Swift Actor Isolation ✅ Passed Production changes use actors or explicit Sendable atomic wrappers with documented safety; UI access remains @MainActor, and no implicit service protocol or background UI-store access was introduced.
Cmux Swift Blocking Runtime ✅ Passed Production Swift adds actor serialization and C11 atomic CAS only; no new blocking wait, sleep, delayed dispatch, lock, or main-queue sync. Semaphore waits are test-only.
Cmux Browser Automation Off-Main ✅ Passed The PR diff changes no browser automation files or routing symbols; it does not add or move any browser.* socket command, WebKit wait, worker router, or policy test.
Cmux Expensive Synchronous Load ✅ Passed Changed production Swift adds atomic, teardown, and bounded screen-tail logic; audits found no agent-history loaders, file reads, JSON parsing, directory scans, or moved expensive calls.
Cmux Cache Substitution Correctness ✅ Passed The snapshot diff only adds the runtime gate; it still obtains a live surface and calls Ghostty's screen-tail read. No changed production code substitutes a cache in persistence, history, or undo p...
Cmux No Hacky Sleeps ✅ Passed The only covered production change raises the Claude SessionEnd hook budget from 1s to 10s; the diff adds no sleep, timer, polling loop, delayed dispatch, or backoff. Other wait code is test/docs/S...
Cmux Algorithmic Complexity ✅ Passed Changed production code uses amortized FIFO queueing, atomic CAS loops, and explicitly bounded two-slot sets; no nested scalable scans, per-target rescans, or new sorting/filtering paths were intro...
Cmux Swift Concurrency ✅ Passed New screen-tail work uses an actor; the coordinator Task is an existing actor hop moved inside the synchronous gate. No new Combine state or background queue pattern was added; test synchronization...
Cmux Swift @Concurrent ✅ Passed The changed UI path awaits the separate TerminalSurfaceRuntimeScreenTailReader actor before native formatting; no changed @concurrent misuse or un-hopped heavy async helper was found.
Cmux Swift Package Boundaries ✅ Passed All production Swift changes are inside the existing CmuxFoundation or CmuxTerminal SwiftPM targets; the only outside-package Swift change is test code, and lifecycle code is Ghostty integration glue.
Cmux Swiftpm Lockfiles ✅ Passed The PR changes no Package.swift, Package.resolved, .gitignore, or Xcode project/package-reference files; no SwiftPM pin or package-reference change lacks a lockfile diff.
Cmux Swift Logging ✅ Passed The PR adds or changes no production Swift logging: no print, debugPrint, dump, NSLog, ad hoc output, or Logger declarations appear in the Swift diff.
Cmux User-Facing Error Privacy ✅ Passed The production diff adds no user-facing errors, alerts, or output; the only text change is an internal hook comment/config timeout, and existing wrapper diagnostics are unchanged.
Cmux Full Internationalization ✅ Passed The PR adds no user-facing UI or web copy. Changed Swift additions are lifecycle code/comments; other text is tests, operational docs, protocol/config data, or diagnostics, with no catalog or local...
Cmux Swiftui State Layout ✅ Passed Changed Swift adds no SwiftUI views, state wrappers, GeometryReader, lazy/list rows, or render-time writes; existing TerminalSurface ObservableObject/@published state is untouched except for runtim...
Cmux Architecture Rethink ✅ Passed Production Swift uses a per-runtime atomic gate, one screen-tail reader, and one teardown coordinator; added-line audit found no repair sleeps, polling, locks, observers, or duplicate native paths....
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed The PR adds no user-visible window, panel, controller, WindowGroup, identifier, or close shortcut; the existing headless window is unchanged. scripts/lint_auxiliary_window_close_shortcuts.py passes.
Cmux Source Artifacts ✅ Passed All 28 changed paths are intentional source, test, script, documentation, or checksum files; no artifact directories, binary blobs, or local-output files appear in the diff.
Cmux No Test Or Debug Seam In Production Source ✅ Passed Changed production Swift adds lifecycle and atomic APIs, with no new DEBUG/test guards or test/debug-named members; existing test seams remain unchanged.
Cmux No Ambient Global State ✅ Passed Changed production Swift adds no file-scope API functions, mutable globals, static-only namespaces, or shared/default singletons; runtime state is instance-owned by TerminalSurface and injected lif...
Description check ✅ Passed The description is comprehensive and covers the change, root cause, testing, risks, verification, and linked issue objectives.
Title check ✅ Passed The title clearly summarizes the primary change: preventing Claude process leaks when users close terminal tabs.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-9573-claude-process-leak

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.

Comment thread docs/ghostty-fork.md Outdated

@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: 1

🤖 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 `@ghostty`:
- Line 1: Update the ghostty submodule pointer from unreachable commit
5b20c62297aca8289b400cb7f5583f65a5c759bc to a reachable commit in
manaflow-ai/ghostty, and update the associated fork and changelog records to
reference the same commit; alternatively, ensure the missing commit is available
from the configured submodule remote before merging.
🪄 Autofix

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 Plus

Run ID: 0e5163d4-f1bf-4175-8d1c-c8f7e1ee0d90

📥 Commits

Reviewing files that changed from the base of the PR and between f998d9d and db465d9.

📒 Files selected for processing (8)
  • Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRuntimeTeardownCoordinator.swift
  • Packages/macOS/CmuxTerminal/Tests/CmuxTerminalTests/TerminalSurfaceRuntimeTeardownCoordinatorTests.swift
  • Packages/macOS/CmuxTerminal/Tests/GhosttyRuntimeTestStubs/GhosttyRuntimeTestStubs.c
  • Packages/macOS/CmuxTerminal/Tests/GhosttyRuntimeTestStubs/include/GhosttyRuntimeTestStubs.h
  • docs/ghostty-fork.md
  • ghostty
  • scripts/check-test-determinism.py
  • scripts/ghosttykit-checksums.txt

Comment thread ghostty Outdated

@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 using default effort 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 c3d4e12. Configure here.

@austinywang

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 10, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@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
`@Packages/macOS/CmuxTerminal/Tests/GhosttyRuntimeTestStubs/GhosttyRuntimeTestStubs.c`:
- Around line 474-513: Add a configurable success mode to
ghostty_surface_read_screen_tail_vt that populates text with valid sample
content and returns true, while preserving the existing false path. Update the
relevant runtime tests to enable this mode, assert
TerminalSurfaceRuntimeScreenTailRequest.read() returns the expected string, and
verify ghostty_surface_free_text is called exactly once for each successful
read.

In `@tests/test_claude_wrapper_hooks.py`:
- Around line 617-622: Update the SessionEnd assertion using the hooks data in
this test: flatten all SessionEnd groups, select the hook whose command is
"hooks claude session-end", and assert that this command’s timeout is exactly
10. Do not allow an unrelated hook or only the first group to satisfy the check.
🪄 Autofix

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 Plus

Run ID: 4eb9614c-7458-4685-af27-59e856caa4bb

📥 Commits

Reviewing files that changed from the base of the PR and between 621164d and 75d6a0c.

📒 Files selected for processing (28)
  • Packages/macOS/CmuxFoundation/Sources/CmuxFoundation/Concurrency/AtomicRawPointerValue.swift
  • Packages/macOS/CmuxFoundation/Sources/CmuxFoundation/Concurrency/AtomicUInt64Value.swift
  • Packages/macOS/CmuxFoundation/Sources/CmuxFoundationAtomicsC/CmuxFoundationAtomicsC.c
  • Packages/macOS/CmuxFoundation/Sources/CmuxFoundationAtomicsC/include/CmuxFoundationAtomicsC.h
  • Packages/macOS/CmuxFoundation/Tests/CmuxFoundationTests/Concurrency/AtomicRawPointerValueTests.swift
  • Packages/macOS/CmuxFoundation/Tests/CmuxFoundationTests/Concurrency/AtomicUInt64ValueTests.swift
  • Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRuntimeNativeAccessBorrow.swift
  • Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRuntimeNativeAccessGate.swift
  • Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRuntimeNativeTeardown.swift
  • Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRuntimeScreenTailReader.swift
  • Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRuntimeScreenTailRequest.swift
  • Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRuntimeTeardownAction.swift
  • Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRuntimeTeardownCoordinator.swift
  • Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRuntimeTeardownRequest.swift
  • Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Lifecycle/TerminalSurfaceRuntimeTeardownRequestQueue.swift
  • Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface+RuntimeLifecycle.swift
  • Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface+ScreenSnapshot.swift
  • Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Surface/TerminalSurface.swift
  • Packages/macOS/CmuxTerminal/Tests/CmuxTerminalTests/TerminalSurfaceRuntimeNativeAccessTests.swift
  • Packages/macOS/CmuxTerminal/Tests/CmuxTerminalTests/TerminalSurfaceRuntimeTeardownCoordinatorTests.swift
  • Packages/macOS/CmuxTerminal/Tests/CmuxTerminalTests/TerminalSurfaceTeardownCallbackLifetimeTests.swift
  • Packages/macOS/CmuxTerminal/Tests/GhosttyRuntimeTestStubs/GhosttyRuntimeTestStubs.c
  • Packages/macOS/CmuxTerminal/Tests/GhosttyRuntimeTestStubs/include/GhosttyRuntimeTestStubs.h
  • Resources/bin/cmux-claude-wrapper
  • cmuxTests/TabManagerUnitTests.swift
  • docs/ghostty-fork.md
  • scripts/ghosttykit-checksums.txt
  • tests/test_claude_wrapper_hooks.py

Comment thread tests/test_claude_wrapper_hooks.py
@austinywang

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 10, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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: 1

🤖 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
`@Packages/macOS/CmuxTerminal/Tests/GhosttyRuntimeTestStubs/GhosttyRuntimeTestStubs.c`:
- Around line 459-467: Update ghostty_surface_free_text to increment
cmux_test_surface_free_text_call_count immediately at function entry, before
checking surface or text validity, while preserving the existing cleanup
behavior for non-null text->text values.
🪄 Autofix

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 Plus

Run ID: fea90a57-c190-46ef-944d-e3079e8e973c

📥 Commits

Reviewing files that changed from the base of the PR and between 75d6a0c and 9ac0ef5.

📒 Files selected for processing (4)
  • Packages/macOS/CmuxTerminal/Tests/CmuxTerminalTests/TerminalSurfaceRuntimeNativeAccessTests.swift
  • Packages/macOS/CmuxTerminal/Tests/GhosttyRuntimeTestStubs/GhosttyRuntimeTestStubs.c
  • Packages/macOS/CmuxTerminal/Tests/GhosttyRuntimeTestStubs/include/GhosttyRuntimeTestStubs.h
  • tests/test_claude_wrapper_hooks.py

@austinywang

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 11, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Closed tabs leak claude-code processes: injected SessionEnd hook has timeout:1 and never reaps the session

3 participants