Skip to content

Fix Claude failed resume clobbering surface restore#6014

Open
lawrencecchen wants to merge 3 commits into
mainfrom
debug-subrouter-session-resume
Open

Fix Claude failed resume clobbering surface restore#6014
lawrencecchen wants to merge 3 commits into
mainfrom
debug-subrouter-session-resume

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Root cause

Claude can emit SessionStart and UserPromptSubmit hooks for claude --resume <id> before it fails with No conversation found with session ID. cmux treated those no-transcript hook events as restorable and published surface.resume.set, so a failed resume attempt could overwrite the pane's durable resume binding with the missing id.

This was not the old subrouter state-path bug. Recent subrouter work correctly shares Claude state under _shared; the bad id had hook/session-env state but no transcript. The cmux hook layer was trusting the failed launch hooks too early.

Fix

Only publish Claude resume bindings from SessionStart, UserPromptSubmit, or Stop when the hook has a transcript-backed session, or when the launch argv is not claude --resume <same session id>. This preserves valid transcript-backed resumes and fresh sessions while leaving the prior durable binding intact for failed first-sighting resumes.

Verification

  • xcodebuild -project cmux.xcodeproj -scheme cmux-unit -configuration Debug -destination 'platform=macOS' -derivedDataPath /tmp/cmux-subres test -only-testing:cmuxTests/CLINotifyProcessIntegrationRegressionTests/testClaudeFailedResumePromptDoesNotPublishSurfaceResumeBinding -only-testing:cmuxTests/CLINotifyProcessIntegrationRegressionTests/testClaudePromptSubmitFromNewSessionCanReplaceStoppedSession
  • ./scripts/reload-cloud.sh --tag subres

Tagged build: http://127.0.0.1:17320/subres


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


Note

Medium Risk
Changes when Claude sessions become restorable and when pane resume bindings are published—session restore behavior for edge cases around failed resumes.

Overview
Prevents failed claude --resume attempts from overwriting a pane’s durable resume binding when hooks fire before Claude errors with a missing session.

Claude hook handling now uses shouldPublishClaudeResumeBinding on SessionStart, UserPromptSubmit, and Stop. surface.resume.set and isRestorable run only when the hook has a transcript path or the process was not launched with --resume / -r targeting the same session id (parsed from launch argv/env). Session promotion on SessionStart is gated the same way.

Adds an integration test for a failed first-sighting resume (no surface.resume.set, isRestorable: false) and adjusts an existing test to use runClaudeHookWithoutServer where appropriate; the mock server stub now accepts surface.resume.set.

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

Summary by CodeRabbit

  • New Features

    • Improved session resumption with conditional resume binding controls based on session eligibility checks.
  • Bug Fixes

    • Enhanced handling of failed session resume scenarios to prevent invalid session restoration attempts.
  • Tests

    • Added regression test coverage for failed session resume operations.

@vercel

vercel Bot commented Jun 12, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
cmux Canceled Canceled Jun 12, 2026 11:15pm
cmux-staging Building Building Preview, Comment Jun 12, 2026 11:15pm

@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (1)
  • .github/swift-file-length-budget.tsv is excluded by !**/*.tsv

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 72de3309-e902-47fe-8290-c7136352619a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR gates the publishing of Claude surface resume bindings (surface.resume.set) and the restorable flag based on a new eligibility check. Helper functions parse launch arguments and compare session/transcript identifiers to determine whether a resume context is valid, then multiple session-handling paths conditionally skip the resume-binding publication when ineligible. New regression tests verify that failed resume attempts do not emit the binding event.

Changes

Resume Binding Eligibility Gating

Layer / File(s) Summary
Resume binding eligibility helpers
CLI/cmux.swift
Two new private functions: shouldPublishClaudeResumeBinding(...) checks eligibility by comparing normalized identifiers and validating launch arguments; claudeResumeLaunchSessionId(...) parses --resume/-r from environment to extract the resume session ID.
Conditional resume binding in session lifecycle
CLI/cmux.swift
Session-start, surface/session updates, and prompt-submit code paths now compute canPublishResumeBinding and conditionally gate both isRestorable flag and publishAgentSurfaceResumeBinding(...) calls; ineligible contexts skip the publish and mark sessions as non-restorable.
Regression tests for failed resume scenarios
cmuxTests/CLINotifyProcessIntegrationRegressionTests.swift
New test verifies that failed resume attempts (missing session ID) do not publish surface.resume.set and do not mark sessions as restorable; test helper refactored to use runClaudeHookWithoutServer for legacy sessions and extended mock server to handle surface.resume.set requests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • manaflow-ai/cmux#5676: PR adds eligibility check in CLI/cmux.swift that conditionally skips publishing surface.resume.set, directly addressing the surface resume handling edge cases discussed in this issue.

Possibly related PRs

  • manaflow-ai/cmux#4237: This PR gates the conditional skipping of publishAgentSurfaceResumeBinding(...) that was originally introduced in that PR, with tests verifying surface.resume.set is not published on failed resume.
  • manaflow-ai/cmux#4583: Both PRs modify resume-binding publication logic in CLI/cmux.swift; this PR gates on eligibility checks while that PR handles turn ID and transcript parsing to prevent stale resumptions.
  • manaflow-ai/cmux#5242: That PR's resume transcript/sessionId resolution directly affects the eligibility outcome computed by the new shouldPublishClaudeResumeBinding(...) check.

Poem

🐰 Resume bindings hop with care,
Checking eligibility fair,
Parse the args with parsing's grace,
Failed resumes know their place—
No false bindings in this race!


Important

Pre-merge checks failed

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

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Cmux Algorithmic Complexity ❌ Error FAIL: CLI/cmux.swift adds mapped session lookups before upsert; each lookup/upsert runs withLockedState→pruneExpired filtering state.sessions/actives (full scans). Coalesce lookup+upsert into one withLockedState per hook event (load state once, compute canPublish, then upsert/publish), or cache sessionStore results to avoid repeated pruneExpired full scans.
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.
✅ Passed checks (19 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix Claude failed resume clobbering surface restore' accurately describes the main bug fix: preventing failed resume attempts from overwriting the pane's durable resume binding.
Description check ✅ Passed The description covers the root cause, fix, and verification steps, but the Testing and Demo sections are incomplete compared to the repository template.
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 logic adds only private pure Bool helpers and conditional resume-binding publication; no new @MainActor, Sendable, or UI-store access patterns found in production Swift around the changes.
Cmux Swift Blocking Runtime ✅ Passed Diff only adds resume-binding eligibility logic and test cases; no semaphores/locks/waits/sleeps/asyncAfter/DispatchQueue.main.sync/polling found in CLI/cmux.swift or the test file.
Cmux Expensive Synchronous Load ✅ Passed PR #6014 changes CLI resume-binding eligibility helpers and test stubs; the diff contains no occurrences of RestorableAgentSessionIndex.load() (or any SharedLiveAgentIndex.shared-to-load change) on...
Cmux Cache Substitution Correctness ✅ Passed In CLI/cmux.swift, surface resume binding publish is gated by shouldPublishClaudeResumeBinding (transcript-backed session or argv check); when false, publishAgentSurfaceResumeBinding is skipped, pr...
Cmux No Hacky Sleeps ✅ Passed PR diff vs main changes only Swift files (.github swift budget + CLI/cmux.swift + one test); no TS/JS/shell/build/runtime files changed and no sleep/timer/poll keywords appear in the diff.
Cmux Swift Concurrency ✅ Passed PR’s Swift changes only add synchronous resume-binding eligibility logic + a regression test; diff contains no new/expanded DispatchQueue/Task/Combine or legacy completion-handler APIs (search: no...
Cmux Swift @Concurrent ✅ Passed Swift diff for PR #6014 contains no async/nonisolated async work and no @concurrent annotations; therefore no violation of the swift-concurrent-annotation rules.
Cmux Swift File And Package Boundaries ✅ Passed Only CLI/cmux.swift (+86/-25) and cmuxTests regression test changed; no new production Swift files. Added lines to an already >800-line file are <250 and changes are focused private resume-eligibil...
Cmux Swift Logging ✅ Passed PR diff (CLI/cmux.swift + test) contains no new/changed Swift logging: no occurrences of print/debugPrint/dump/NSLog/Logger or ad-hoc stdout logging in the changed hunks.
Cmux User-Facing Error Privacy ✅ Passed In CLI/cmux.swift, new resume-binding helpers only compute booleans and call internal surface.resume.{set,clear}; no user-facing alerts/CLIError text added, and 'No conversation found' isn’t presen...
Cmux Full Internationalization ✅ Passed No new i18n/web/catalog changes; production Swift user-facing text uses String(localized:defaultValue:) with existing key cli.claude-hook.notification.title.
Cmux Swiftui State Layout ✅ Passed PR #6014 only modifies .github/swift-file-length-budget.tsv, CLI/cmux.swift, and cmuxTests/…; no SwiftUI files or Observable/@Published/GeometryReader changes appear in the diff.
Cmux Architecture Rethink ✅ Passed PR adds shouldPublishClaudeResumeBinding/claudeResumeLaunchSessionId to gate surface.resume.set and adjust restorable flags; no sleeps/polling/locks/observers or new state owners/duplicate wiring d...
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR #6014 changes only CLI/cmux.swift, a CLI integration test, and swift-file-length-budget TSV; no NSWindow/NSPanel/Window/WindowGroup or cmux.* close-shortcut identifier changes were introduced.
Cmux Source Artifacts ✅ Passed PR #6014 changes only .github/swift-file-length-budget.tsv, CLI/cmux.swift, and cmuxTests/CLINotifyProcessIntegrationRegressionTests.swift; none match forbidden local/generated artifact patterns pe...
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch debug-subrouter-session-resume

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.

@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 84d4644. Configure here.

Comment thread CLI/cmux.swift
@greptile-apps

greptile-apps Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Prevents a failed claude --resume <id> from clobbering a pane's durable restore binding when Claude fires SessionStart/UserPromptSubmit hooks before exiting with "No conversation found." The new shouldPublishClaudeResumeBinding helper and claudeResumeLaunchSessionId argument parser gate isRestorable and surface.resume.set publication on either a transcript path being present or the process not having been launched with --resume <same-id>.

  • CLI/cmux.swift: Three hook paths (SessionStart, Stop, UserPromptSubmit) now call shouldPublishClaudeResumeBinding; a false result skips the binding publish and sets isRestorable: false without changing the session upsert itself.
  • cmuxTests/CLINotifyProcessIntegrationRegressionTests.swift: Adds a regression test for the failed-resume case; migrates the stopped-session replacement test to a shared multi-connection mock server and adds surface.resume.set mock handling.

Confidence Score: 4/5

Safe to merge for the common production path; the guard correctly blocks the clobbering bug for any hook invocation that carries CMUX_AGENT_LAUNCH_ARGV_B64 or a readable PID.

The new helper correctly suppresses the resume binding on failed-resume hooks in the normal code path. The one gap — failing open when launch argv is entirely unresolvable — is an unusual fallback scenario and doesn't affect the well-tested primary path. No actor isolation, logging, or internationalization concerns were introduced.

CLI/cmux.swift — specifically the fail-open return path in shouldPublishClaudeResumeBinding when neither CMUX_AGENT_LAUNCH_ARGV_B64 nor a valid PID is available.

Important Files Changed

Filename Overview
CLI/cmux.swift Adds shouldPublishClaudeResumeBinding + claudeResumeLaunchSessionId helpers; gates isRestorable and surface.resume.set publication on transcript presence or non-resume launch at SessionStart, Stop, and UserPromptSubmit. Logic is correct for the common case; fail-open when launch argv cannot be resolved is a minor gap.
cmuxTests/CLINotifyProcessIntegrationRegressionTests.swift Adds testClaudeFailedResumePromptDoesNotPublishSurfaceResumeBinding regression test; migrates existing stopped-session replacement test to a shared multi-connection mock server and adds surface.resume.set handling. Both changes are correct and well-scoped.
.github/swift-file-length-budget.tsv Budget entries updated to reflect added lines in cmux.swift (+61) and CLINotifyProcessIntegrationRegressionTests.swift (+44); mechanical bookkeeping, no issues.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["Hook fires: SessionStart / UserPromptSubmit / Stop"] --> B{"parsedInput.sessionId present?"}
    B -- No --> Z["Skip binding logic"]
    B -- Yes --> C["shouldPublishClaudeResumeBinding()"]
    C --> D{"normalizedSessionId valid?"}
    D -- No --> E["return false"]
    D -- Yes --> F{"transcript path present?\n(parsedInput or mappedSession)"}
    F -- Yes --> G["return true"]
    F -- No --> H{"claudeResumeLaunchSessionId() == sessionId?"}
    H -- "Yes (failed resume)" --> I["return false\n→ skip isRestorable=true\n→ skip surface.resume.set"]
    H -- "No / nil (fresh session)" --> G
    G --> J["upsert isRestorable=true\npublishAgentSurfaceResumeBinding"]
    I --> K["upsert isRestorable=false\n(no binding publish)"]

    subgraph "claudeResumeLaunchSessionId"
        L["Read CMUX_AGENT_LAUNCH_ARGV_B64\nor processArguments(pid)"] --> M{"--resume / -r found?"}
        M -- Yes --> N["return normalizedHookValue(id)"]
        M -- No / unavailable --> O["return nil → guard fails open"]
    end
Loading

Reviews (1): Last reviewed commit: "Refresh Swift file length budget" | Re-trigger Greptile

Comment thread CLI/cmux.swift
Comment on lines +22985 to +22989
if let resumedSessionId = claudeResumeLaunchSessionId(env: env, fallbackPID: fallbackPID),
resumedSessionId == normalizedSessionId {
return false
}
return true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Guard is fail-open when launch argv is unavailable

claudeResumeLaunchSessionId returns nil if CMUX_AGENT_LAUNCH_ARGV_B64 is absent and processArguments(for:) cannot read the PID (e.g., claudePid is nil). When both fallbacks fail, the code skips the resume-id comparison and falls through to return true, publishing the binding for a failed resume — the exact outcome the PR is trying to prevent. The bug is only fully suppressed when at least one argv source is reliably available on the hook invocation path.

@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 `@CLI/cmux.swift`:
- Around line 22974-23006: The resume parsing should return on the first match
and avoid recreating the prefix list each iteration: in
claudeResumeLaunchSessionId use a static constant for the prefixes (e.g., let
resumePrefixes = ["--resume=", "-r="]) and iterate using that constant, ensuring
you return immediately for the first "--resume"/"-r" positional match or the
first prefix match; also update the other resume parsing block (the second parse
near the later code) to include "-r=" in its hasPrefix checks so short-form
equals-style flags are handled consistently; keep existing calls to
claudeRawLaunchArguments, normalizedHookValue and the early-return behavior in
shouldPublishClaudeResumeBinding unchanged.
🪄 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: 804c3bfa-611b-43c2-b223-939f27595caf

📥 Commits

Reviewing files that changed from the base of the PR and between ee98539 and 84d4644.

📒 Files selected for processing (2)
  • CLI/cmux.swift
  • cmuxTests/CLINotifyProcessIntegrationRegressionTests.swift

Comment thread CLI/cmux.swift
Comment on lines +22974 to +23006
private func shouldPublishClaudeResumeBinding(
sessionId: String,
parsedInput: ClaudeHookParsedInput,
mappedSession: ClaudeHookSessionRecord?,
env: [String: String],
fallbackPID: Int?
) -> Bool {
guard let normalizedSessionId = normalizedHookValue(sessionId) else { return false }
if normalizedHookValue(parsedInput.transcriptPath ?? mappedSession?.transcriptPath) != nil {
return true
}
if let resumedSessionId = claudeResumeLaunchSessionId(env: env, fallbackPID: fallbackPID),
resumedSessionId == normalizedSessionId {
return false
}
return true
}

private func claudeResumeLaunchSessionId(env: [String: String], fallbackPID: Int?) -> String? {
guard let arguments = claudeRawLaunchArguments(env: env, fallbackPID: fallbackPID) else {
return nil
}
for (index, argument) in arguments.enumerated() {
if argument == "--resume" || argument == "-r" {
guard index + 1 < arguments.count else { return nil }
return normalizedHookValue(arguments[index + 1])
}
for prefix in ["--resume=", "-r="] where argument.hasPrefix(prefix) {
return normalizedHookValue(String(argument.dropFirst(prefix.count)))
}
}
return nil
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

Does Claude CLI support multiple --resume flags, and if so which one takes precedence?

💡 Result:

The Claude CLI does not support passing multiple --resume flags in a single command. The --resume flag is designed to accept a single argument—either a specific session ID, a session name, or no argument at all to trigger an interactive session picker [1][2]. If you attempt to provide multiple --resume flags, it is not a supported use case, and the behavior is not explicitly defined in the official documentation [1][2]. To resume a session, you should use the flag once, followed by the desired session identifier [1][2]: claude --resume If you need to switch between sessions, you can use the interactive /resume picker within an active session or run the command without arguments to open the picker [2]. Additionally, you can use --continue to resume the most recent session in the current directory [2].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the target file
ls -la

# Search for CLI/cmux.swift existence
if [ -f "CLI/cmux.swift" ]; then
  echo "FOUND: CLI/cmux.swift"
else
  echo "NOT FOUND: CLI/cmux.swift; searching..."
  fd -a "cmux.swift" -t f
fi

# Print relevant regions for resume parsing logic
rg -n --no-heading "claudeResumeLaunchSessionId|--resume|\\-r\\b" CLI/cmux.swift || true

# Show surrounding code for the function
if [ -f "CLI/cmux.swift" ]; then
  line=$(rg -n "claudeResumeLaunchSessionId" CLI/cmux.swift | head -n1 | cut -d: -f1 || true)
  if [ -n "${line:-}" ]; then
    start=$((line-80))
    end=$((line+220))
    echo "---- Function region (approx) lines ${start}-${end} ----"
    nl -ba CLI/cmux.swift | sed -n "${start},${end}p"
  fi

  echo "---- All nearby resume parsing blocks (context) ----"
  rg -n --context 6 --no-heading "if argument == \"--resume\" \\|\\| argument == \"-r\"|hasPrefix\\(\"--resume=\"\\)|hasPrefix\\(\"-r=\"\\)|\\[\"--resume=\", \"-r=\"\\]" CLI/cmux.swift || true
fi

Repository: manaflow-ai/cmux

Length of output: 6963


🏁 Script executed:

#!/bin/bash
set -euo pipefail

if [ -f "CLI/cmux.swift" ]; then
  echo "FOUND: CLI/cmux.swift"
else
  echo "NOT FOUND: CLI/cmux.swift"
  fd -a -t f -e swift "cmux.swift"
fi

if [ -f "CLI/cmux.swift" ]; then
  rg -n --no-heading "claudeResumeLaunchSessionId|--resume|-r\\b" CLI/cmux.swift || true

  line=$(rg -n "claudeResumeLaunchSessionId" CLI/cmux.swift | head -n1 | cut -d: -f1 || true)
  if [ -n "${line:-}" ]; then
    start=$((line-80))
    end=$((line+260))
    echo "---- Function region (approx) lines ${start}-${end} ----"
    nl -ba CLI/cmux.swift | sed -n "${start},${end}p"
  fi

  echo "---- Candidate resume parsing blocks with context ----"
  rg -n --context 8 --no-heading "resume|--resume|\\-r\\b|normalizedHookValue" CLI/cmux.swift | head -n 200
fi

Repository: manaflow-ai/cmux

Length of output: 1651


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Verify file and inspect relevant resume parsing blocks in CLI/cmux.swift
if [ -f "CLI/cmux.swift" ]; then
  echo "FOUND: CLI/cmux.swift"
else
  echo "NOT FOUND: CLI/cmux.swift"
  fd -a -t f "cmux.swift"
  exit 0
fi

echo "---- resume-related matches ----"
rg -n --no-heading "--resume|\\-r\\b|claudeResumeLaunchSessionId|normalizedHookValue" CLI/cmux.swift

echo "---- showing function claudeResumeLaunchSessionId (approx) ----"
fn_line=$(rg -n --no-heading "claudeResumeLaunchSessionId" CLI/cmux.swift | head -n1 | cut -d: -f1)
start=$((fn_line-60))
end=$((fn_line+320))
nl -ba CLI/cmux.swift | sed -n "${start},${end}p" | sed -n '1,260p'

echo "---- showing any other occurrences of '--resume'/'-r' parsing (context) ----"
rg -n --context 12 --no-heading "if argument == \"--resume\" \\|\\| argument == \"-r\"|hasPrefix\\(\"--resume=\"\\)|hasPrefix\\(\"-r=\"\\)" CLI/cmux.swift

Repository: manaflow-ai/cmux

Length of output: 598


Use first --resume occurrence; make prefix list a constant; check -r= consistency

  • Keep the current precedence in claudeResumeLaunchSessionId: return immediately on the first --resume/-r match (and first --resume=/-r= prefix match).
  • In CLI/cmux.swift there’s a second resume parsing block around line ~25920: it checks hasPrefix("--resume=") but no corresponding hasPrefix("-r=") match is present—align support there if -r= should behave the same.
  • Refactor the ["--resume=", "-r="] prefix list in claudeResumeLaunchSessionId into a static constant so it isn’t recreated during the scan.
🤖 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 `@CLI/cmux.swift` around lines 22974 - 23006, The resume parsing should return
on the first match and avoid recreating the prefix list each iteration: in
claudeResumeLaunchSessionId use a static constant for the prefixes (e.g., let
resumePrefixes = ["--resume=", "-r="]) and iterate using that constant, ensuring
you return immediately for the first "--resume"/"-r" positional match or the
first prefix match; also update the other resume parsing block (the second parse
near the later code) to include "-r=" in its hasPrefix checks so short-form
equals-style flags are handled consistently; keep existing calls to
claudeRawLaunchArguments, normalizedHookValue and the early-return behavior in
shouldPublishClaudeResumeBinding unchanged.

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