Repository navigation
Suppress codex's blocking startup update prompt on cmux-driven resumes - #7222
Conversation
codex's TUI shows a blocking "Update available!" picker at startup whenever no initial prompt is passed, which is exactly the shape of every cmux-generated `codex resume <id>`. After a cmux update restarts the app, auto-restored codex panes land on that picker instead of the restored conversation. Expect all cmux-generated codex resume commands (auto-restore argv, codex-teams launcher, sessions-panel command) to carry the per-invocation `-c check_for_update_on_startup=false` override. Failing-test commit; the fix follows. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…esumes codex shows a blocking "Update available!" picker at TUI startup whenever no initial prompt is passed, which is the shape of every cmux-generated `codex resume <id>`. After a cmux update restarted the app, auto-restored codex panes sat on that picker instead of the restored conversation. Inject codex's per-invocation config override `-c check_for_update_on_startup=false` into every cmux-generated codex resume command: the shared resume argv builder (auto-restore and cmux-cli surface restore), the codex-teams launcher resolution, and the sessions-panel resume command. The override affects only that process; ~/.codex/config.toml and manual codex launches keep their update checks. Injection is skipped when the captured launch args already set check_for_update_on_startup, so an explicit user choice wins and restore-of-a-restore stays idempotent. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds Codex resume suppression for the startup update-check prompt, wires it into resume-command construction and replay normalization, and updates expectations so Codex resume paths include ChangesCodex Update-Check Suppression
Estimated code review effort: 4 (Complex) | ~45 minutes Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (2 errors)
✅ Passed checks (23 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
|
@codex review |
Greptile SummaryThis PR fixes a UX regression where cmux-driven codex resume commands could land on codex's blocking "Update available!" startup picker instead of the restored conversation, because
Confidence Score: 5/5Safe to merge — targeted argv-manipulation changes with no mutations to persistent state or user config, covered by broad unit and integration tests. All four resume code paths (AgentResumeArgv, SessionIndexModels, CLI codex-teams, stale-binding canonicalizer) receive well-scoped, tested changes. The idempotency guard is exercised for both two-token and equals-form variants. The ordering constraint (suppression before portable-executable repair) is correctly implemented and explained. No actor isolation, blocking runtime, or expensive sync-load concerns are introduced. No files require special attention. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[cmux relaunch / auto-restore] --> B{Resume path}
B --> C[AgentResumeArgv]
B --> D[SessionIndexModels]
B --> E[CLI codexTeams remote resume]
B --> F[Stale binding replay]
C --> G{override already in preserved args?}
G -- No --> H[inject -c check_for_update_on_startup=false]
G -- Yes --> I[skip injection]
D --> J[unconditionally append override]
E --> K[append override after threadId]
F --> L[SurfaceResumeCommandCanonicalizer]
L --> M{kind == codex or nil?}
M -- No --> N[return unchanged]
M -- Yes --> O{override already present?}
O -- Yes --> N
O -- No --> Q{command shape?}
Q -- direct --> R[insert after session id]
Q -- remote resume --> S[insert after thread id]
Q -- sh wrapper --> T[recurse into body]
Q -- wrapper token --> U[strip token then offset insert]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[cmux relaunch / auto-restore] --> B{Resume path}
B --> C[AgentResumeArgv]
B --> D[SessionIndexModels]
B --> E[CLI codexTeams remote resume]
B --> F[Stale binding replay]
C --> G{override already in preserved args?}
G -- No --> H[inject -c check_for_update_on_startup=false]
G -- Yes --> I[skip injection]
D --> J[unconditionally append override]
E --> K[append override after threadId]
F --> L[SurfaceResumeCommandCanonicalizer]
L --> M{kind == codex or nil?}
M -- No --> N[return unchanged]
M -- Yes --> O{override already present?}
O -- Yes --> N
O -- No --> Q{command shape?}
Q -- direct --> R[insert after session id]
Q -- remote resume --> S[insert after thread id]
Q -- sh wrapper --> T[recurse into body]
Q -- wrapper token --> U[strip token then offset insert]
Reviews (10): Last reviewed commit: "Handle short codex config override form" | Re-trigger Greptile |
| // wrapped in `/bin/sh -c '…'`; the `cd` guard stays outside in | ||
| // `resumeCommandWithCwd`. https://github.com/manaflow-ai/cmux/issues/5639 | ||
| var parts = ["\(AgentResumeArgv.codexWrapperShellExecutableToken) resume \(sessionId)"] | ||
| parts.append(AgentResumeArgv.codexUpdateCheckSuppressionOverride.joined(separator: " ")) |
There was a problem hiding this comment.
Unconditional injection bypasses the documented idempotency guard
The PR description says "injection is skipped when the captured launch arguments already set check_for_update_on_startup, so an explicit user choice stays authoritative." That guarantee is enforced in the AgentResumeArgv code paths via codexResumeConfigOverrides(preserved:), which inspects the raw sanitizer-preserved argv before injecting. This sessions-panel path, however, always appends the override unconditionally — no guard against a user who had -c check_for_update_on_startup=true in their original invocation. Because check_for_update_on_startup is not stored as a structured field in SessionEntry.agent.codex, the sessions-panel resume command cannot check for it, so the user's explicit preference is silently overridden for every sessions-panel resume. The workaround (~/.codex/config.toml) is also ineffective: the per-invocation -c override takes precedence over the config file, so a user with check_for_update_on_startup = true in toml would still have it suppressed for all cmux-driven resumes.
There was a problem hiding this comment.
Intentional: the sessions-panel command is built from per-session captured settings (model/approval/sandbox/effort), which don't include the launch argv, so there is nothing to dedup against there. The command is displayed and copy-pastable, so the flag is visible and editable before running. The automated paths (auto-restore argv, persisted-binding replay) do respect an explicit captured check_for_update_on_startup setting.
| executablePath: "/opt/bin/codex", | ||
| arguments: ["/opt/bin/codex"] | ||
| ) == ["/opt/bin/codex", "resume", "SID"] | ||
| ) == ["/opt/bin/codex", "resume", "SID", "-c", "check_for_update_on_startup=false"] | ||
| ) | ||
| } | ||
|
|
||
| @Test("Codex resume suppresses codex's blocking startup update prompt per-invocation") | ||
| func codexResumeSuppressesStartupUpdatePrompt() { | ||
| // `codex resume <id>` passes no initial prompt, so codex's TUI shows a blocking | ||
| // "Update available!" picker before restoring the session — a cmux relaunch that | ||
| // auto-restores codex panes lands them on that prompt instead of the conversation. | ||
| // The per-invocation `-c` override keeps cmux-driven restores non-interactive | ||
| // without mutating the user's ~/.codex/config.toml, and it precedes the preserved | ||
| // launch arguments so a user-captured explicit override still wins. | ||
| let overrides = ["-c", "check_for_update_on_startup=false"] | ||
| #expect( | ||
| AgentResumeArgv().builtInKind( | ||
| kind: "codex", | ||
| sessionId: "SID", | ||
| executablePath: nil, | ||
| arguments: ["codex", "--model", "gpt-5.4"] | ||
| ) == ["codex", "resume", "SID"] + overrides + ["--model", "gpt-5.4"] | ||
| ) | ||
| #expect( | ||
| AgentResumeArgv().launcherResolution( | ||
| launcher: "codexTeams", | ||
| sessionId: "SID", | ||
| executablePath: nil, | ||
| arguments: ["cmux", "codex-teams", "--model", "gpt-5.4"] | ||
| ) == .resolved(["cmux", "codex-teams", "resume", "SID"] + overrides + ["--model", "gpt-5.4"]) | ||
| ) |
There was a problem hiding this comment.
Deduplication guard is untested
codexResumeConfigOverrides(preserved:) has three distinct early-return branches: the two-token -c/--config form, the single-token --config=check_for_update_on_startup= form, and the out-of-bounds guard when -c is the last element. None of these branches are exercised by the new test. If the idempotency logic has a bug — for instance, a captured session that was already a cmux-driven restore and thus has -c check_for_update_on_startup=false in its preserved args — the duplicate injection would go undetected. A few #expect cases with preserved containing each variant would close this gap.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
Dedup-branch coverage added in 9fb1b1e049 (explicit true/false pair forms for both builtInKind and the codexTeams launcher). The --config= single-token form is defensive; the sanitizer normalizes captured pairs, so it isn't reachable from real captures.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cabbc4ee92
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| /// `check_for_update_on_startup` (see ``codexResumeConfigOverrides(preserved:)``): | ||
| /// that keeps an explicit user choice authoritative and keeps restore-of-a-restore | ||
| /// idempotent, since the codex sanitizer policy preserves `-c key=value` pairs. | ||
| public static let codexUpdateCheckSuppressionOverride = ["-c", "check_for_update_on_startup=false"] |
There was a problem hiding this comment.
Apply update suppression to Codex Teams subagent resumes
When the Codex Teams watcher opens a spawned subagent pane, codexTeamsResumeCommandText in CLI/cmux.swift:20309-20320 still builds env ... codex resume --remote <url> <threadId> without this override. That resume has no initial prompt, so the same cached-update picker can still block Codex Teams subagent panes even though the root codex/codex-teams resume paths are suppressed; please reuse this shared override on that path as well.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 50c89522f0: codexTeamsResumeCommandText now appends the shared override tokens, so spawned subagent panes resume with the update check suppressed too.
There was a problem hiding this comment.
2 issues found across 7 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="Sources/SessionIndexModels.swift">
<violation number="1" location="Sources/SessionIndexModels.swift:352">
P2: This resume-command path always appends `-c check_for_update_on_startup=false`, which can override a session that was originally launched with an explicit `check_for_update_on_startup=true`. Consider adding the same idempotency check used in `codexResumeConfigOverrides(preserved:)` (or persisting this setting in session metadata) so explicit user config is preserved.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| // wrapped in `/bin/sh -c '…'`; the `cd` guard stays outside in | ||
| // `resumeCommandWithCwd`. https://github.com/manaflow-ai/cmux/issues/5639 | ||
| var parts = ["\(AgentResumeArgv.codexWrapperShellExecutableToken) resume \(sessionId)"] | ||
| parts.append(AgentResumeArgv.codexUpdateCheckSuppressionOverride.joined(separator: " ")) |
There was a problem hiding this comment.
P2: This resume-command path always appends -c check_for_update_on_startup=false, which can override a session that was originally launched with an explicit check_for_update_on_startup=true. Consider adding the same idempotency check used in codexResumeConfigOverrides(preserved:) (or persisting this setting in session metadata) so explicit user config is preserved.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Sources/SessionIndexModels.swift, line 352:
<comment>This resume-command path always appends `-c check_for_update_on_startup=false`, which can override a session that was originally launched with an explicit `check_for_update_on_startup=true`. Consider adding the same idempotency check used in `codexResumeConfigOverrides(preserved:)` (or persisting this setting in session metadata) so explicit user config is preserved.</comment>
<file context>
@@ -349,6 +349,7 @@ struct SessionEntry: Identifiable, Hashable {
// wrapped in `/bin/sh -c '…'`; the `cd` guard stays outside in
// `resumeCommandWithCwd`. https://github.com/manaflow-ai/cmux/issues/5639
var parts = ["\(AgentResumeArgv.codexWrapperShellExecutableToken) resume \(sessionId)"]
+ parts.append(AgentResumeArgv.codexUpdateCheckSuppressionOverride.joined(separator: " "))
if let model, !model.isEmpty {
parts.append("-m \(Self.shellQuote(model))")
</file context>
Fold the update-check override into the initial parts literal so the file stays at its budgeted line count. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Greptile flagged the early-return branches of codexResumeConfigOverrides as untested: an explicit captured check_for_update_on_startup setting must stay authoritative, and restore-of-a-restore must not stack duplicate overrides. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9fb1b1e049
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| return [parts.executable, "resume", sessionId] | ||
| + Self.codexResumeConfigOverrides(preserved: preserved) + preserved |
There was a problem hiding this comment.
Normalize persisted Codex resume bindings before restore
On the first launch after updating from a build that saved an agent-hook resume binding, workspace restore does not call this new AgentResumeArgv path: Workspace.createPanel builds restoredBindingLaunch from the persisted SurfaceResumeBindingSnapshot.command and then suppresses the restorable-agent launch, so an existing saved command like 'codex' 'resume' '<id>' still runs without -c check_for_update_on_startup=false. That is the relaunch-after-update path this change is meant to fix; please canonicalize/migrate Codex resume bindings as they are decoded/restored, or let the regenerated restorable-agent command override matching stale bindings.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 50c89522f0: binding replay now normalizes stale codex resume bindings via SurfaceResumeCommandCanonicalizer.insertingCodexUpdateCheckSuppression (inserted after the parsed resume words, before the stale-executable repair so sh-wrapped repairs don't hide the argv). Commands that already set check_for_update_on_startup, non-codex kinds, and shapes that don't parse as a codex resume argv replay unchanged and self-heal on the next hook persist. Covered by SurfaceResumeBindingCodexUpdateCheckTests.
Codex review flagged two gaps in the update-prompt suppression: Codex Teams subagent panes: the watcher-built subagent resume command (codexTeamsResumeCommandText) ran `codex resume --remote <url> <thread>` without the override, so spawned teammate panes could still hit the blocking update picker. The shared override tokens are now appended there too. Stale persisted bindings: agent-hook resume bindings are persisted rendered shell strings, so bindings saved by a cmux build before this change replay verbatim on the FIRST relaunch after updating cmux, which is exactly the reported scenario. Replay now normalizes stale codex bindings by inserting the override directly after the parsed `resume <session-id>` words (insertingCodexUpdateCheckSuppression), before the existing stale-executable repair so /bin/sh-wrapped repairs don't hide the argv. Commands that already set check_for_update_on_startup, non-codex kinds, and shapes that don't parse as a codex resume argv (remote thread resumes, sh-wrapped bodies) replay unchanged; the unparsed shapes self-heal on the next hook persist. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 50c8952. Configure here.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 50c89522f0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| guard sessionIndex < words.count, | ||
| words[resumeIndex].value == "resume", | ||
| !words[sessionIndex].value.hasPrefix("-") else { | ||
| return command |
There was a problem hiding this comment.
Normalize wrapped Codex resume bindings too
Fresh evidence in this revision: the new replay normalizer still only accepts commands whose parsed word after the executable (or codex-teams) is resume. Existing agent-hook bindings saved by builds since the wrapper-shim change are rendered as cd ... && /bin/sh -c '<codex wrapper> resume <id> ...' from RestorableAgentSession.resumeCommand; for those, commandExecutableWordIndex returns /bin/sh, so this guard sees -c instead of resume and returns the stale command unchanged. Those users still hit the Codex update picker on the first relaunch after updating, which is the migration path this normalizer is meant to cover.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
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 `@cmuxTests/SurfaceResumeBindingCodexUpdateCheckTests.swift`:
- Around line 16-99: Add a test covering the stale codex replay path that goes
through remoteStartupInputWithLauncherScript, since this branch currently skips
update-check suppression when repairPortableAgentExecutable is gated off. Extend
SurfaceResumeBindingCodexUpdateCheckTests with a stale codex case that exercises
SurfaceResumeBindingSnapshot.startupInput for the remote launcher-script shape
and assert the replayed input includes check_for_update_on_startup=false for
codex/codex-teams-style resumes.
🪄 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: 3e593f9e-4938-4309-8f70-288b395497f6
📒 Files selected for processing (5)
CLI/cmux.swiftSources/SurfaceResumeCommandCanonicalizer+CodexUpdateCheck.swiftSources/SurfaceResumeCommandCanonicalizer+PortableAgentExecutable.swiftcmux.xcodeproj/project.pbxprojcmuxTests/SurfaceResumeBindingCodexUpdateCheckTests.swift
There was a problem hiding this comment.
3 issues found across 5 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="Sources/SessionIndexModels.swift">
<violation number="1" location="Sources/SessionIndexModels.swift:352">
P2: This resume-command path always appends `-c check_for_update_on_startup=false`, which can override a session that was originally launched with an explicit `check_for_update_on_startup=true`. Consider adding the same idempotency check used in `codexResumeConfigOverrides(preserved:)` (or persisting this setting in session metadata) so explicit user config is preserved.</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dbda5a2e5a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| guard sessionIndex < words.count, | ||
| words[resumeIndex].value == "resume", | ||
| !words[sessionIndex].value.hasPrefix("-") else { |
There was a problem hiding this comment.
Normalize remote Codex resume bindings
When replaying a persisted agent-hook binding whose command is the Codex Teams remote attach form (codex resume --remote <url> <thread>), this guard returns because the word after resume is --remote, so the stale command is left without -c check_for_update_on_startup=false. Fresh evidence in this revision is the new remote-binding replay path that intentionally leaves this exact shape unchanged, even though codexTeamsResumeCommandText now adds the override for newly opened subagent panes; users with subagent panes saved before updating can still land on Codex's blocking startup update picker on the first relaunch. Handle the remote shape by inserting after the thread id rather than skipping it.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
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 `@Sources/SurfaceResumeCommandCanonicalizer`+CodexUpdateCheck.swift:
- Around line 155-167: The override-detection logic is duplicated between
codexResumeConfigOverrideAlreadyPresent(in:) and
AgentResumeArgv.codexResumeConfigOverrides(preserved:), so factor the shared
-c/--config check_for_update_on_startup= scan into a single helper on
AgentResumeArgv and call it from both places. Keep the existing behavior, but
make the canonicalizer reuse the shared helper instead of reimplementing the
loop so the resume-argv builder and replay path stay in sync.
🪄 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: a56773d9-fcc7-449d-9455-3c95d8a0be1c
📒 Files selected for processing (3)
Sources/SurfaceResumeCommandCanonicalizer+CodexUpdateCheck.swiftSources/SurfaceResumeCommandCanonicalizer+PortableAgentExecutable.swiftcmuxTests/SurfaceResumeBindingCodexUpdateCheckTests.swift
There was a problem hiding this comment.
1 issue found across 3 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="Sources/SessionIndexModels.swift">
<violation number="1" location="Sources/SessionIndexModels.swift:352">
P2: This resume-command path always appends `-c check_for_update_on_startup=false`, which can override a session that was originally launched with an explicit `check_for_update_on_startup=true`. Consider adding the same idempotency check used in `codexResumeConfigOverrides(preserved:)` (or persisting this setting in session metadata) so explicit user config is preserved.</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
…ng, themes) Delta: #7318/#7319 mouse cursor-shape + right/middle drag forwarding, #7320 ghostty upstream, #6664 iOS themes, #7196 iOS scroll, #7257/#7307 web, #7329 CLI suggestions, #7222 codex resume update-suppression. Conflicts resolved keeping HEAD structure: - GhosttyTerminalView.swift: took main's viewDidEndLiveResize + resetCursorRects (cursor-shape #7318; ghosttyMouseShape/ghosttyMouseCursor already in HEAD). - Mobile/MobileHostService.swift: union (kept HEAD sharedRequestActivity + main publicStatusPayload theme payload #6664). - project.pbxproj: union-dedup, normalized; test-wiring green. - swift-file-length-budget.tsv regenerated. #7222 (codex update-check suppression) partially landed: the CMUXAgentLaunch package part (AgentResumeArgv.codexUpdateCheckSuppressionOverride) auto-merged and is present; the app-target files (+CodexUpdateCheck.swift + test) extend SurfaceResumeCommandCanonicalizer, a type HEAD dissolved into the CmuxWorkspaces package, so they can't compile and the suppression was never wired (call site was in the HEAD-deleted +PortableAgentExecutable). Removed those two files; re-wire recorded in merge-deferred-gaps. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
After a cmux update restarts the app, auto-restored codex sessions can land on codex's blocking "Update available!" startup picker instead of the restored conversation, so the pane looks like the session never restarted. codex shows that picker whenever a new release is cached and no initial prompt is passed (openai/codex
codex-rs/tui/src/lib.rs,run_update_prompt_if_needed), which is exactly the shape of every cmux-generatedcodex resume <id>.Fix: inject codex's per-invocation config override
-c check_for_update_on_startup=falseinto every cmux-generated codex resume command: the shared resume argv builder inAgentResumeArgv(covers close-and-reopen auto-restore and the cmux-cli surface-restore publisher), thecodexTeamslauncher resolution, and the sessions-panel resume command inSessionIndexModels.-c key=valueis a clap-global flag in codex, so it is valid after theresumesubcommand and overrides config for that process only;~/.codex/config.tomland the user's own manual codex launches keep their update checks. Injection is skipped when the captured launch arguments already setcheck_for_update_on_startup, so an explicit user choice stays authoritative and restore-of-a-restore does not stack duplicate overrides (the codex sanitizer policy preserves-c key=valuepairs).Two-commit structure: the first commit updates/adds the resume-command expectations only (red), the second adds the fix (green).
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
🤖 Generated with Claude Code
Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.Note
Low Risk
Targeted argv/shell-string changes for codex resume only, with broad tests and no changes to user
~/.codex/config.tomlor non-codex agents.Overview
Fixes auto-restored codex panes landing on codex’s blocking “Update available!” picker instead of the conversation after cmux relaunch (typical when
codex resume <id>has no initial prompt).Every new cmux-generated codex resume path now appends a per-process
-c check_for_update_on_startup=falsevia sharedAgentResumeArgv(codex,codex-teams, CLI codex-teams shell quoting, and sessions-panel resume commands). Injection is skipped when captured args already setcheck_for_update_on_startupvia-c/--config, so user choice stays authoritative and restore-of-restore stays idempotent.Stale persisted agent-hook bindings are upgraded at replay (no migration):
SurfaceResumeCommandCanonicalizer+CodexUpdateCheckparses shell strings and inserts the override afterresume <id>(or after the thread id forresume --remote), including/bin/sh -cand codex wrapper-token bodies; this runs before portable-executable repair on hook bindings.Reviewed by Cursor Bugbot for commit 0697cf1. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by cubic
Stops
codex’s blocking update prompt oncmux-driven resumes so panes return to the conversation after updates. Adds a per-process-c check_for_update_on_startup=falseto allcodexresume paths without changing user config.codexresumes:codex resume <id>,codex-teams resume <id>, andcodex resume --remote <url> <thread>(sharedAgentResumeArgv, sessions panel, CLIcodex-teamslauncher). Skips when args already setcheck_for_update_on_startupvia-c,--config, or short equals forms (-c=…,--config=…) to honor user choice and avoid duplicates.codexbindings at replay by inserting the override afterresume <id>(or after the thread id for--remote); handles/bin/sh -cand wrapper-token forms, and runs before portable-executable repair.Written for commit 589af22. Summary will update on new commits.
Summary by CodeRabbit
New Features / Improvements
check_for_update_on_startupis explicitly set.Tests