Repository navigation
fix: keep tabs and offer Resume when a Claude session is killed (INC-422) - #514
Merged
arzafran merged 2 commits intoOct 30, 2026
Conversation
arzafran
deleted the
franco/inc-422-force-quitting-a-leftover-background-app-kills-claude
branch
October 30, 2026 17:04
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.
What this does
Force-quitting a leftover background app from the Dock (an MCP server or a debug binary that Claude launched) no longer takes the Claude session down with it. If a Claude session is killed anyway, the tab stays open with a banner offering Resume or Close, instead of vanishing. When a Claude agent exits, Programa also cleans up the background processes it left behind so they stop piling up in the Dock.
Fixes INC-422
Summary
macOS charges everything Claude launches to the
claudepid, so force-quitting one of those apps killsclaude. Start withSources/LeftoverProcessReaper.swift(snapshots which processes each tracked agent is responsible for, reaps them when the agent exits), thenSources/AgentInterruptedBanner.swift(Resume/Close banner), thenSources/Workspace*.swift/TabManager.swift(keep the tab and surface the banner when the agent or pane process dies). The rest is wiring and localization strings (English and Japanese). New diagnostics.log lines (agent, surface, reaper) record these events.The reaper uses the private libsystem symbol
responsibility_get_pid_responsible_for_pid; if it is missing the reaper does nothing. Ownership is polled every 10 s, so anything launched in an agent's last ~10 s survives (marked with a SHORTCUT comment).Test Plan
kill -9ofclaudeshows the "Claude stopped unexpectedly" banner on a live shell.kill -9of the pane login keeps the tab with "This pane's processes were killed" (diagnostics: childExited kept=true).python3 scripts/check-structural-budgets.pyandpython3 scripts/check-settings-docs.pypass locally.Not verified: clicking Resume/Close (no Accessibility grant in the test session), and the reaper never reaped anything in testing because the MCP children exited on their own.
Unexplained: one force-quit at 12:30:20 killed 7 sessions at once. The new diagnostics lines should identify the cause next time it happens.
Screenshots: before/after needed for the banner.