Skip to content

Fix remote tmux mirror pane titles#7836

Merged
austinywang merged 19 commits into
mainfrom
issue-7832-mirror-window-names
Jul 10, 2026
Merged

Fix remote tmux mirror pane titles#7836
austinywang merged 19 commits into
mainfrom
issue-7832-mirror-window-names

Conversation

@austinywang

@austinywang austinywang commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Closes #7832

Root cause

Multi-pane remote-tmux windows had split title ownership. The outer mirror tab used the authoritative tmux window name from RemoteTmuxWindow.name, but inner mirrored pane surfaces exposed titles from pane-level data, and the control/tree projection preferred tmux pane-border-format. On stock tmux that format expands to raw values like 0 "hostname", so the window name disappeared only in the multi-pane path.

Fix

RemoteTmuxWindowMirror now adopts the authoritative tmux window display title from each RemoteTmuxWindow update and derives every inner pane surface/tab title from that one value, with deterministic pane suffixes (logs, logs [1], logs [2]). Pane-border-format remains only pane-header label state and no longer becomes the surface title.

Tests

Added behavior coverage through the real control-mode title pipeline using captured list-windows and list-panes replies:

  • multi-pane mirror surface titles carry the tmux window name instead of raw pane header labels
  • single-pane mirror title behavior remains unchanged
  • a window transitioning from single-pane to multi-pane keeps the window name on recreated surfaces

Local allowed checks:

  • git diff --check HEAD~2..HEAD passed
  • ./scripts/lint-pbxproj-test-wiring.sh passed
  • python3 scripts/swift_file_length_budget.py reports the pre-existing origin/main AutomationSocketUITests budget mismatch (551 actual vs 528 budget), with no touched file over budget

Note: per task constraints, I did not run local xcodebuild, reload, or any cmux socket/app dogfood commands.


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


Note

Medium Risk
Changes user-visible remote-tmux titles and control-socket surface names; layout parsing now drops malformed duplicate-pane layouts. CI-only changes are low product risk.

Overview
Fixes #7832 by making remote tmux mirror inner pane and control-surface titles follow the tmux window name, not pane-border labels, foreground command, or CWD.

RemoteTmuxWindowMirror now keeps an authoritative windowTitle from each RemoteTmuxWindow update and builds tab titles via windowPaneTitle — base name for the first pane, then localized indexed suffixes (logs, logs [1], …). Control topology projection uses the same title(forPane:) path. RemoteTmuxRawLayoutParser rejects layouts with duplicate pane IDs. New localization keys cover the window fallback and indexed pane pattern; app-host tests cover multi-pane, single-pane, and single→multi transitions through the control surface list.

CI: swift-package-tests runs on vars.MACOS_RUNNER_DUAL_XCODE (SDK 15 helper build, then SDK 26 package tests). App-host focused regressions detect or install Node 20 when the runner image lacks node; Python wrapper tests use tests/node_runtime.py to repair PATH or skip. Runner docs and workflow guard tests were updated for the dual-Xcode variable.

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


Summary by cubic

Fixes #7832 by unifying all remote tmux mirror pane and control titles on the tmux window name with a localized fallback. CI routes swift-package-tests to the dual-Xcode runner and guarantees Node.js for wrapper regressions, pinning actions/setup-node@v6.4.0 to install Node 20 when absent.

  • Bug Fixes

    • Titles now come from the tmux window name via RemoteTmuxWindowMirror; pane-border labels, command, and CWD no longer affect titles.
    • Deterministic pane suffixes in multi-pane mirrors: "logs", "logs [1]", "logs [2]"; single-pane unchanged; single→multi keeps the window name.
    • Control topology uses title(forPane:).
    • RemoteTmuxRawLayoutParser rejects duplicate pane IDs.
  • Tests

    • Added end-to-end title tests for multi-pane, single-pane, and single→multi transitions; added localized strings for remoteTmux.tab.window and remoteTmux.tab.windowPaneIndexed.
    • CI: swift-package-tests runs on vars.MACOS_RUNNER_DUAL_XCODE; wrapper regressions ensure Node.js is on PATH and install Node 20 via actions/setup-node@v6.4.0 when missing. Tests use tests/node_runtime.py to repair PATH or skip when truly unavailable.

Written for commit 3f472d3. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Remote tmux mirror pane/control titles are now based on the mirrored tmux window name, with non-zero pane indices showing an indexed suffix.
  • Bug Fixes

    • Titles remain consistent across layout changes using stable window-title tracking and pane ordering.
    • Layouts containing duplicate pane identifiers are now rejected.
  • Tests

    • Added/updated coverage for multi-pane, single-pane, and layout transition title behavior.
    • Added tests verifying duplicate pane identifiers are rejected.
  • Chores

    • Expanded localization coverage for the remote tmux window title (including indexed suffixes).
    • Updated CI runner selection checks for the dual-Xcode macOS 15 lane.

@vercel

vercel Bot commented Jul 10, 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 Jul 10, 2026 4:58pm
cmux-staging Building Building Preview, Comment Jul 10, 2026 4:58pm

@coderabbitai

coderabbitai Bot commented Jul 10, 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

Remote tmux mirrors now derive pane titles from the remote window name and pane order. Multi-pane titles receive indexed suffixes, duplicate pane IDs are rejected, CI uses a dual-Xcode runner, and tests cover title transitions and validation.

Changes

Remote tmux mirror titles

Layer / File(s) Summary
Window title state and indexed formatting
Sources/RemoteTmuxWindowMirror.swift, Sources/RemoteTmuxWindowMirror+BonsplitLayout.swift
The mirror tracks the remote window title, maps panes to layout indices, and formats indexed titles.
Pane title integration
Sources/RemoteTmuxWindowMirror+Bonsplit.swift, Sources/RemoteTmuxWindowMirror+ControlTopology.swift
Pane and control-pane titles now derive from the window title and pane order.
Surface-title validation and localization
cmuxTests/RemoteTmuxMirrorTargetingTests.swift, cmuxTests/RemoteTmuxMirrorLayoutMathTests.swift, Resources/Localizable.xcstrings
Tests cover single-pane titles, multi-pane titles, layout transitions, and localized title strings.

Layout validation

Layer / File(s) Summary
Duplicate pane validation
Sources/RemoteTmuxRawLayoutParser.swift, cmuxTests/RemoteTmuxControlParserTests.swift
Raw layouts with duplicate pane IDs are rejected and covered by a parser test.

CI runner selection

Layer / File(s) Summary
Dual-Xcode runner wiring and checks
.github/workflows/ci.yml, tests/test_ci_change_areas.py, tests/test_ci_release_sdk_lane.sh, tests/test_ci_self_hosted_guard.sh
The package-test job uses the dual-Xcode macOS runner, and CI checks enforce that selection.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant RemoteTmux
  participant RemoteTmuxSessionMirror
  participant RemoteTmuxWindowMirror
  participant TerminalController

  RemoteTmux->>RemoteTmuxSessionMirror: provide window and pane state
  RemoteTmuxSessionMirror->>RemoteTmuxWindowMirror: provide window title
  RemoteTmuxWindowMirror->>RemoteTmuxWindowMirror: map pane IDs to ordered indices
  RemoteTmuxWindowMirror->>TerminalController: publish titled control surfaces
Loading

Possibly related issues

  • manaflow-ai/cmux-dev-artifacts#3110 — Covers window-name propagation and indexed multi-pane titles.
  • manaflow-ai/cmux-dev-artifacts#3115 — Concerns tmux session rename and title authority.
  • manaflow-ai/cmux-dev-artifacts#3103 — Covers authoritative tmux window names for mirrored pane titles.
  • manaflow-ai/cmux#7833 — Shares the mirror reconciliation and single-to-multi-pane transition code path.

Possibly related PRs

Suggested reviewers: lawrencecchen

🚥 Pre-merge checks | ✅ 23 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The CI runner swap and duplicate-pane-ID parser validation are unrelated to the tmux title bug fix and go beyond #7832. Remove or split the CI runner and parser-validation changes into a separate PR unless they are required for the linked issue.
Docstring Coverage ⚠️ Warning Docstring coverage is 10.53% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (23 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The pane title changes and regression tests address the reported multi-pane title loss and preserve single-pane behavior as requested in #7832.
Cmux Swift Actor Isolation ✅ Passed The diff keeps new state on @MainActor and adds only pure nonisolated helpers; no new MainActor/Sendable isolation debt appears.
Cmux Swift Blocking Runtime ✅ Passed The non-test Swift changes only adjust title derivation and layout parsing; no new blocking waits, sleeps, syncs, or locks appear. Test-only harness uses a brief RunLoop pump.
Cmux Browser Automation Off-Main ✅ Passed Only cmuxTests/RemoteTmuxMirrorTargetingTests.swift changed; it adds remote-tmux tests and no browser.* commands, worker routing, or WebKit/AppKit waits.
Cmux Expensive Synchronous Load ✅ Passed No touched Swift path adds or moves an agent-history/JSONL loader onto a main-actor or interactive path; changes only retitle tmux mirrors and parse tmux layouts.
Cmux Cache Substitution Correctness ✅ Passed PASS: pane titles use an event-updated windowTitle cache with a localized cold fallback, and the call sites are transient UI/control-surface state, not persistence.
Cmux No Hacky Sleeps ✅ Passed PASS: The PR adds no new sleep/timer/polling logic in touched non-workflow runtime scripts; the only sleep usage is preexisting CI workflow YAML, which the rule excludes.
Cmux Algorithmic Complexity ✅ Passed No new hot-path quadratic scan remains: titles use paneIndexByPaneId O(1), and the duplicate-ID parser check is a single linear pass.
Cmux Swift Concurrency ✅ Passed PASS: The PR diff only changes synchronous title/layout logic and tests; it adds no new DispatchQueue, Task lifecycle, Combine state, or new completion-handler APIs.
Cmux Swift @Concurrent ✅ Passed Touched Swift changes are synchronous title/layout helpers; no @concurrent or nonisolated async boundaries were added or misused.
Cmux Swift File And Package Boundaries ✅ Passed PASS: Touched production Swift files stay small (<500 lines) and the diff only adds title formatting, an index map, and duplicate-ID validation—focused bug-fix glue, not a mixed/oversized file.
Cmux Swiftpm Lockfiles ✅ Passed No cmux-owned .gitignore, Package.resolved, or xcodeproj/package-reference changes appear in the PR diff; policy script reports OK.
Cmux Swift Logging ✅ Passed No added or materially changed production Swift logging in the PR diff; the only nearby cmuxDebugLog is unchanged and debug-only.
Cmux User-Facing Error Privacy ✅ Passed The diff only changes tmux window/pane titles, tests, and CI; it does not add or alter user-facing error, alert, or recovery copy.
Cmux Full Internationalization ✅ Passed All new user-facing Swift text is localized with matching catalog keys, and both touched keys include translations for every locale in the catalog.
Cmux Swiftui State Layout ✅ Passed Diff is model/test/localization-only; no new ObservableObject/@published, GeometryReader layout, lazy-row store refs, or render-time state mutation found.
Cmux Architecture Rethink ✅ Passed The diff is a local title/validation fix with one mirror-owned title source, a derived pane-index map, no timing hacks, and only test-only RunLoop sync.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed The PR only changes remote-tmux mirror title logic/tests; no NSWindow/NSPanel/WindowGroup/NSWindowController additions or identifier/close-shortcut ownership changes.
Cmux Source Artifacts ✅ Passed All changed paths are intentional source/config/test/localization files; no logs, caches, DerivedData, temp, or other artifact directories were added.
Cmux No Test Or Debug Seam In Production Source ✅ Passed No modified Sources/ file adds a DEBUG/test-only seam or test-only name; changes are production title/state plumbing and layout validation.
Cmux No Ambient Global State ✅ Passed The diff keeps new state inside RemoteTmuxWindowMirror; no new file-scope funcs/vars or singleton/static-namespace API were added in production Swift.
Title check ✅ Passed The title clearly and concisely summarizes the main change: fixing remote tmux mirror pane titles.
Description check ✅ Passed It covers the summary and testing well, but omits the Demo Video, Review Trigger, and Checklist sections from the template.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-7832-mirror-window-names

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.

@greptile-apps

greptile-apps Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes remote tmux mirror pane titles and updates the related test and CI support. The main changes are:

  • Remote tmux pane and control titles now come from the tmux window name.
  • Multi-pane mirrors add deterministic indexed suffixes.
  • Duplicate pane IDs in raw tmux layouts are rejected.
  • Localization entries were added for the new title strings.
  • CI now uses the dual-Xcode runner lane and ensures Node is available for wrapper tests.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
Sources/RemoteTmuxWindowMirror.swift Tracks the authoritative tmux window title and pane ordering during mirror reconciliation.
Sources/RemoteTmuxWindowMirror+BonsplitLayout.swift Builds pane titles from the window title with localized indexed suffixes.
Sources/RemoteTmuxWindowMirror+Bonsplit.swift Uses the shared window-title path for Bonsplit pane titles.
Sources/RemoteTmuxWindowMirror+ControlTopology.swift Uses the same window-title path for control topology pane titles.
Sources/RemoteTmuxRawLayoutParser.swift Rejects parsed tmux layouts that contain duplicate pane IDs.
Resources/Localizable.xcstrings Adds localized strings for remote tmux window and indexed pane titles.
.github/workflows/ci.yml Moves package tests to the dual-Xcode runner and adds Node setup for wrapper regressions.
tests/node_runtime.py Adds a test helper that locates Node and repairs PATH for wrapper tests.
cmuxTests/RemoteTmuxMirrorTargetingTests.swift Adds behavior coverage for remote tmux mirror surface title updates.

Reviews (14): Last reviewed commit: "ci: match the repo's pinned setup-node v..." | Re-trigger Greptile

@austinywang austinywang enabled auto-merge (squash) July 10, 2026 09:49

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Resources/Localizable.xcstrings (1)

133936-133940: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use the standard Korean macOS term for “window”.

Change tmux 창 to tmux 윈도우; this key is shown as the fallback title for unnamed remote tmux windows, so the current value uses the wrong macOS UI terminology.

Proposed fix
-            "value": "tmux 창"
+            "value": "tmux 윈도우"
🤖 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 `@Resources/Localizable.xcstrings` around lines 133936 - 133940, Update the
Korean localization value for the relevant tmux window fallback title in the
"en" stringUnit from "tmux 창" to "tmux 윈도우", preserving the existing key and
localization structure.

Source: Learnings

🤖 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.

Outside diff comments:
In `@Resources/Localizable.xcstrings`:
- Around line 133936-133940: Update the Korean localization value for the
relevant tmux window fallback title in the "en" stringUnit from "tmux 창" to
"tmux 윈도우", preserving the existing key and localization structure.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 25ba900b-cbb2-4bd8-86b8-1a9c42c8b489

📥 Commits

Reviewing files that changed from the base of the PR and between 0d0e847 and 5291d70.

📒 Files selected for processing (3)
  • Resources/Localizable.xcstrings
  • Sources/RemoteTmuxWindowMirror+Bonsplit.swift
  • Sources/RemoteTmuxWindowMirror.swift

@blacksmith-sh

This comment has been minimized.

Comment thread .github/workflows/ci.yml Outdated
Comment thread Sources/RemoteTmuxWindowMirror.swift
austinywang and others added 4 commits July 10, 2026 04:14
The warp-macos-15 runner image dropped node from the job PATH on
2026-07-10, failing every branch (including main) in app-host unit
tests shard 4 with 'exec: node: not found'. The claude wrapper tests
build fake claude binaries that exec node, so they now resolve a node
runtime themselves (shutil.which plus Homebrew/nvm/volta locations),
prepend it to PATH, and skip with a message only when node is truly
absent — same pattern as the existing bun skip in
test_pi_extension_install.py.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@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 0cab431. Configure here.

Comment thread Sources/RemoteTmuxWindowMirror+BonsplitLayout.swift
austinywang and others added 2 commits July 10, 2026 06:06
MACOS_RUNNER_15 was flipped to the tart-macos-15 fleet at 09:17 UTC
today and its VM image has no node on the runner PATH, so the claude
wrapper regressions (fake claude binaries that exec node) failed on
every branch including main. Probe for an image-provided node first
(PATH, Homebrew prefixes) and export it to GITHUB_PATH; only when the
image truly has none, install a pinned node via actions/setup-node.
This keeps the wrapper coverage running instead of silently relying on
the test-side skip.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
release.yml and nightly.yml already pin actions/setup-node v6.4.0 for
the same runners-without-node failure mode; use the identical pin here.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@austinywang austinywang merged commit 62ac682 into main Jul 10, 2026
28 of 30 checks passed
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.

ssh-tmux mirror: multi-pane windows lose their tmux window name; surfaces titled with raw pane index + hostname

1 participant