Skip to content

Focus Mac pairing QR flow on Tailscale - #9493

Merged
azooz2003-bit merged 7 commits into
mainfrom
feat-tailscale-qr-focus
Aug 4, 2026
Merged

azooz2003-bit merged 7 commits into
mainfrom
feat-tailscale-qr-focus

Conversation

@azooz2003-bit

@azooz2003-bit azooz2003-bit commented Aug 4, 2026 •

Copy link
Copy Markdown
Collaborator

Summary\n\n- Remove the visible Iroh QR from Mac pairing because it has no separate manual workflow. Same-account automatic Iroh connection and legacy decoding stay intact.\n- Rename every visible entrypoint and destination to Tailscale Pairing, including the command palette, sidebar, configurable tab action, Settings, workspace title, and iOS guidance.\n- Localize the new English and Japanese copy while preserving existing CLI and configuration identifiers.\n\n## Validation\n\n- Tagged macOS build: ./scripts/reload.sh --tag tsqr\n- Computer Use preflight verified the command palette, sidebar, Settings row, workspace title, page heading, and single Tailscale QR.\n- Swift parse checks, localization completeness, JSON validation, and git diff checks passed.\n- Focused remote tests could not start because the fleet Mac remained below its disk floor after cleanup.\n- Hosted UI run stopped before tests when the GhosttyKit artifact download failed: https://github.com/manaflow-ai/cmux/actions/runs/30864222895\n- iOS installation is pending because Aziz was unreachable and the approved local fallback ran out of disk while unpacking Sentry.

Summary by CodeRabbit

  • New Features

    • Introduced a Tailscale-focused pairing flow using a single QR code and reachable Tailscale route.
    • Updated pairing controls, command palette entries, settings, and window titles to “Tailscale Pairing.”
    • Added clearer scanner guidance and onboarding instructions, including an in-scanner guidance panel.
  • Bug Fixes

    • Clarified unavailable and invalid-pairing messages with actionable Tailscale instructions.
    • Preserved compatibility with existing Iroh links and explicit device-attachment flows.
  • Documentation

    • Updated pairing and compatibility documentation to reflect current Tailscale behavior.

@coderabbitai

coderabbitai Bot commented Aug 4, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR makes Tailscale the sole Mac pairing transport, retains compatibility decoding for existing Iroh codes, updates iOS and macOS pairing guidance, and revises English and Japanese labels, errors, documentation, and regression tests.

Changes

Tailscale pairing flow

Layer / File(s) Summary
Pairing contract and route model
Packages/Shared/CMUXMobileCore/..., Sources/Mobile/Pairing/..., Sources/Mobile/MobileAttachTicketStore.swift, cmuxTests/MobilePairingConnectionTransitionTests.swift, docs/iroh-app-transport-architecture.md
The model now selects reachable Tailscale routes and creates one attach URL. Iroh-only plans are unavailable. Existing Iroh decoding and explicit attach flows remain supported.
Mac pairing surfaces and discovery
Sources/..., Packages/macOS/CmuxSettingsUI/..., cmuxTests/..., docs/pro-badge-options.html
Pairing windows, settings, command-palette entries, feature-flag text, availability errors, and related tests now use Tailscale Pairing terminology.
iOS pairing flow and scanner guidance
Packages/iOS/..., ios/cmux/Resources/Localizable.xcstrings, ios/cmuxUITests/cmuxUITests.swift
Physical-device instructions now direct users to Tailscale QR scanning. Manual entry remains limited to simulator loopback. Scanner guidance is localized and exposed through accessibility identifiers.
Pairing localization and documentation
Resources/Localizable.xcstrings, ios/cmux/Resources/Localizable.xcstrings
English and Japanese strings now describe Tailscale Pairing, Tailscale QR codes, same-network requirements, and unavailable states.

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

Sequence Diagram(s)

sequenceDiagram
  participant MacPairing
  participant TailscaleRoute
  participant MobileApp
  MacPairing->>TailscaleRoute: select phone-reachable route
  TailscaleRoute-->>MacPairing: return disclosure mode
  MacPairing->>MobileApp: display Tailscale pairing QR
  MobileApp->>MobileApp: scan QR and connect
Loading

Possibly related issues

  • manaflow-ai/cmux-dev-artifacts#8010 — The PR updates mobile pairing transition tests for Tailscale-only route behavior.

Possibly related PRs

Suggested reviewers: lawrencecchen, austinywang


Important

Pre-merge checks failed

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

❌ Failed checks (2 errors, 2 warnings)

Check name Status Explanation Resolution
Cmux Full Internationalization ❌ Error Resources/Localizable.xcstrings supports 20 locales, but the PR adds or changes pairing entries such as cli.workspaceAction.tailscalePairingUnavailable with only en and ja translations. Add translated stringUnit entries for every supported locale in Resources/Localizable.xcstrings for each changed or new key; retain complete en/ja coverage in the iOS catalog.
Cmux No Ambient Global State ❌ Error The PR adds enum MobilePairingScannerGuidanceCopy with only a static computed property at MobilePairingScannerSheet.swift:184-185, a new ambient namespace. Move scanner guidance onto an owning constructable/injectable scanner type, or use a private/fileprivate helper/property; do not add a caseless static-only enum.
Description check ⚠️ Warning The description explains the changes and validation but omits the required Demo Video, Review Trigger, and Checklist sections. Add the required Demo Video, Review Trigger, and Checklist sections, and rename Validation to Testing or include the required Testing headings.
Docstring Coverage ⚠️ Warning Docstring coverage is 24.24% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (21 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: focusing the Mac pairing QR flow on Tailscale.
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 The production diff keeps MobilePairingModel explicitly @MainActor, adds a nonisolated pure route helper, and introduces no protocols or shared mutable Sendable references; UI changes remain SwiftU...
Cmux Swift Blocking Runtime ✅ Passed The PR adds no production semaphores, blocking waits, sleeps, delayed dispatch, polling, main-queue sync, or locks; its only wait-like addition is test-only UI existence checking.
Cmux Browser Automation Off-Main ✅ Passed The PR diff contains no browser socket automation changes; its only TerminalController change updates the mobile_connect unavailable message, with no worker policy, router, WebKit wait, or browser...
Cmux Expensive Synchronous Load ✅ Passed The PR diff adds no RestorableAgentSessionIndex load, agent-store/transcript parsing, directory scan, or large-file read; changed Swift paths only update pairing behavior, UI, and strings.
Cmux Cache Substitution Correctness ✅ Passed The PR changes pairing UI and route planning only; no fresh persistence/history/undo/snapshot read is replaced. Host status cache use is event-driven and feeds transient UI state.
Cmux No Hacky Sleeps ✅ Passed The exact PR diff contains only Swift, localization, Markdown, and HTML files; it introduces no covered TypeScript, JavaScript, shell, or build/runtime script changes.
Cmux Algorithmic Complexity ✅ Passed The full pairing PR diff adds no nested scans, batch rescans, sorting, joins, or unbounded collection work; it mainly changes copy/UI, and route planning uses one linear contains check.
Cmux Swift Concurrency ✅ Passed The pairing diff adds no Dispatch, Combine, completion-handler, or fire-and-forget Task pattern; it removes one nested Task, while existing SwiftUI tasks remain unchanged.
Cmux Swift @Concurrent ✅ Passed The PR adds no @concurrent or nonisolated async declarations; its only concurrency changes remove an extra await and refresh task, while remaining work stays in the existing @MainActor model.
Cmux Swift Package Boundaries ✅ Passed The PR adds no new reusable domain type in app Sources. PairingModel logic shrinks and remains AppDelegate/MobileHostService-bound; other additions are UI glue or shared-package documentation.
Cmux Swiftpm Lockfiles ✅ Passed The PR-side diff has no Package.swift, Package.resolved, .gitignore, workflow, or Xcode project changes, so the SwiftPM lockfile rule is not triggered.
Cmux Swift Logging ✅ Passed The PR diff adds or changes no prohibited logging calls, Logger declarations, or stdout/stderr logging; existing AppDelegate NSLog sites are unchanged.
Cmux User-Facing Error Privacy ✅ Passed Changed pairing errors use cmux terms and selected Tailscale guidance; they add no raw upstream messages, secrets, tokens, headers, IDs, or payload dumps.
Cmux Swiftui State Layout ✅ Passed The diff adds no prohibited state or layout patterns; @Observable and GeometryReader predate it, and added Swift lines contain no state wrappers, lazy/list rows, or render-time writes.
Cmux Architecture Rethink ✅ Passed The PR removes the Iroh-upgrade flag and duplicate QR path, keeps one @MainActor model owner, and uses existing event-driven status streams without adding sleeps, polling, locks, or delayed dispatch.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed The PR only renames the existing pairing window; cmux.mobilePairingWindow remains assigned and registered in cmuxAuxiliaryWindowIdentifiers, and scripts/lint_auxiliary_window_close_shortcuts.py...
Cmux Source Artifacts ✅ Passed The PR-specific diff contains only tracked Swift source/tests, localization catalogs, and durable docs; no artifact directories, generated outputs, binary blobs, or untracked files were added.
Cmux No Test Or Debug Seam In Production Source ✅ Passed The PR adds no DEBUG/test guards or debug/test seam members in production Sources; the new scanner copy is called by production views, and existing debug code is touched only incidentally.
✨ 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 feat-tailscale-qr-focus

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.

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

🤖 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/PostHogAnalyticsPropertiesTests.swift`:
- Around line 189-190: Rename the test method mobileConnectButtonDefaultsHidden
to tailscalePairingButtonDefaultsHidden so it matches the updated test title,
while leaving the isMobileConnectButtonEnabled compatibility identifier
unchanged.

In `@ios/cmux/Resources/Localizable.xcstrings`:
- Around line 435-441: Update the mobile.tailscale.pairingHelp localization and
its translations to remove the stale trusted-local-network host/port pairing
guidance, matching the simulator-loopback-only manual flow used by
mobile.addDevice.help.

In `@Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/PairingView.swift`:
- Line 102: Update PairingView.pair() and connectManualHost() so manual pairing
is accepted only for simulator loopback hosts, rejecting non-loopback hosts
before connection. Keep the QR/Tailscale pairing path unchanged, and ensure the
UI warning matches this enforced simulator-only contract.

In `@Resources/Localizable.xcstrings`:
- Around line 53692-53708: Add or update the translated values for every
supported locale in Resources/Localizable.xcstrings for all affected
pairing-related keys, including cli.workspaceAction.tailscalePairingUnavailable
and the additional referenced entries. Preserve the existing English and
Japanese translations while ensuring each of the catalog’s 20 supported locale
blocks has a translated value, updating stale Mobile/Iroh wording where
necessary.

In `@Sources/AppDelegate.swift`:
- Line 7555: Update the default title used when creating the pairing workspace
in the surrounding pairing-workspace creation flow to the new “Tailscale
Pairing” value, while leaving the reuse path and any user-defined custom titles
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 Plus

Run ID: 3a33ab8c-5c23-46b4-a5cf-42969c9f0047

📥 Commits

Reviewing files that changed from the base of the PR and between d35187e and 8ded7e5.

📒 Files selected for processing (34)
  • Packages/Shared/CMUXMobileCore/Sources/CMUXMobileCore/CmxPairingQRCode.swift
  • Packages/Shared/CMUXMobileCore/Sources/CMUXMobileCore/CmxPairingRouteDisclosureMode.swift
  • Packages/Shared/CMUXMobileCore/Sources/CMUXMobileCore/CompactAttachTicket.swift
  • Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobilePairingFailure.swift
  • Packages/iOS/CmuxMobileShell/Tests/CmuxMobileShellTests/MobilePairingFailureTests.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobileConnectionMethodSection.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/OnboardingConnectionView.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/PairingView.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/SetupHelpGateContent.swift
  • Packages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Navigation/CuratedSettingEntry+Default.swift
  • Packages/macOS/CmuxSettingsUI/Sources/CmuxSettingsUI/Sections/MobileSection.swift
  • Resources/Localizable.xcstrings
  • Sources/AppDelegate.swift
  • Sources/Auth/AccountSignInView.swift
  • Sources/ClosedItemHistory+PanelTitle.swift
  • Sources/CmuxSurfaceTabBarBuiltInAction.swift
  • Sources/ContentView+CommandPaletteSurfaceMetadata.swift
  • Sources/ContentView.swift
  • Sources/FeatureFlags.swift
  • Sources/Mobile/MobileAttachTicketStore.swift
  • Sources/Mobile/Pairing/MobilePairingModel.swift
  • Sources/Mobile/Pairing/MobilePairingView+Connected.swift
  • Sources/Mobile/Pairing/MobilePairingView.swift
  • Sources/Mobile/Pairing/MobilePairingWindowController.swift
  • Sources/TerminalController.swift
  • Sources/VerticalTabsSidebar+EmptyAreasAndFooter.swift
  • cmuxTests/AppDelegateShortcutRoutingTests.swift
  • cmuxTests/CmuxConfigContextMenuTests.swift
  • cmuxTests/CommandPaletteSearchEngineTests.swift
  • cmuxTests/MobilePairingConnectionTransitionTests.swift
  • cmuxTests/PostHogAnalyticsPropertiesTests.swift
  • docs/iroh-app-transport-architecture.md
  • docs/pro-badge-options.html
  • ios/cmux/Resources/Localizable.xcstrings

Comment thread cmuxTests/PostHogAnalyticsPropertiesTests.swift Outdated
Comment thread ios/cmux/Resources/Localizable.xcstrings Outdated
Comment thread Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/PairingView.swift Outdated
Comment thread Resources/Localizable.xcstrings
Comment thread Sources/AppDelegate.swift
@cursor

cursor Bot commented Aug 4, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@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/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/PairingView.swift`:
- Around line 102-106: The manual-entry flow still permits non-loopback hosts
despite the simulator-only copy. Update the Pair button validation near the
manual host input and the connectManualHost() path to reject non-loopback
addresses before connecting, preserving loopback support; alternatively, revise
the displayed copy to accurately describe intentional arbitrary-host support.

In `@Resources/Localizable.xcstrings`:
- Line 134739: Update the English localization values associated with the
Tailscale pairing instructions at all referenced entries so they explicitly
state that Tailscale must be installed and connected on both the Mac and iPhone,
and that both devices must use the same Tailscale network. Preserve the existing
pairing-code context while replacing the ambiguous network wording consistently.
🪄 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 Plus

Run ID: 10cb182c-8132-46d2-bb87-718934dfcfde

📥 Commits

Reviewing files that changed from the base of the PR and between 8ded7e5 and 4c00963.

📒 Files selected for processing (10)
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobileConnectionMethodSection.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobilePairingScannerPreview.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobilePairingScannerSheet.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/OnboardingConnectionView.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/PairingView.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/SetupHelpGateContent.swift
  • Resources/Localizable.xcstrings
  • Sources/Mobile/Pairing/MobilePairingView.swift
  • ios/cmux/Resources/Localizable.xcstrings
  • ios/cmuxUITests/cmuxUITests.swift

Comment thread Resources/Localizable.xcstrings 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.

Caution

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

⚠️ Outside diff range comments (4)
Sources/AppDelegate.swift (1)

10939-11038: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Do not expand the production target with a new UI-test seam.

Lines 10939-11038 add environment-controlled test setup and test-specific panel creation to Sources/AppDelegate.swift.

Move this four-panel setup to an isolated test or debug facility. Do not add more UI-test branches to AppDelegate.

As per path instructions, production Swift source under **/Sources/** must not add test-only or debug-only seams. The coding guidelines require genuinely debug-only facilities to use a dedicated debug file or folder.

🤖 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 `@Sources/AppDelegate.swift` around lines 10939 - 11038, Remove the
environment-controlled Bonsplit UI-test setup, including runSetupWhenWindowReady
and its four-panel creation logic, from AppDelegate. Move this behavior into an
isolated UI-test or dedicated debug facility outside the production Sources
target, preserving the existing setup behavior without adding further test-only
branches to AppDelegate.

Sources: Coding guidelines, Path instructions

ios/cmux/Resources/Localizable.xcstrings (1)

8572-8589: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Update mobile.tailscale.pairingHelp to match the simulator-only manual-entry policy.

mobile.tailscale.pairingHelp still tells the user they can "pair by host and port on a trusted local network". mobile.addDevice.manualRouteWarning in this same catalog now states that manual credentials work only in the simulator, and physical devices must use Tailscale and scan the Mac QR. These two strings contradict each other. Update mobile.tailscale.pairingHelp (English and Japanese) to remove the trusted-local-network host/port guidance, matching the simulator-only manual flow.

💬 Proposed copy fix
-            "value": "QR pairing usually needs both devices on the same Tailscale network. Turn Tailscale on first, or pair by host and port on a trusted local network."
+            "value": "QR pairing usually needs both devices on the same Tailscale network. Turn Tailscale on first. Host and port entry is an advanced fallback for reconnecting an already paired Mac, and works only in the simulator on a device."

Update the matching ja value to remove the trusted-local-network guidance as well.

🤖 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 `@ios/cmux/Resources/Localizable.xcstrings` around lines 8572 - 8589, Update
the English and Japanese values for mobile.tailscale.pairingHelp to remove
guidance about pairing by host and port on a trusted local network, keeping the
message consistent with the simulator-only manual-entry policy and Tailscale QR
pairing flow.
Resources/Localizable.xcstrings (1)

35814-35830: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Complete locale coverage for all changed catalog entries.

The changed entries provide English and Japanese text, but the catalog supports additional locales. Add or update translations for every supported locale.

  • Resources/Localizable.xcstrings#L35814-L35830: add all supported locale entries for cli.surfaceResume.set.error.unknownFlag.
  • Resources/Localizable.xcstrings#L110629-L110635: localize the sidebar Tailscale Pairing description in every supported locale.
  • Resources/Localizable.xcstrings#L134756-L134762: localize the Tailscale pairing-code detail in every supported locale.
  • Resources/Localizable.xcstrings#L135283-L135289: localize the setup requirement in every supported locale.
  • Resources/Localizable.xcstrings#L135317-L135323: localize the Mac-connected guidance in every supported locale.

As per coding guidelines, changed catalog keys must include translated values for every supported locale. As per path instructions, .github/review-bot-rules/full-internationalization.md is authoritative for this requirement. Based on learnings, this catalog currently supports 20 locales.

🤖 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 35814 - 35830, Complete
translations for all 20 supported locales in Resources/Localizable.xcstrings:
update cli.surfaceResume.set.error.unknownFlag at lines 35814-35830 and localize
the sidebar Tailscale Pairing description at 110629-110635, pairing-code detail
at 134756-134762, setup requirement at 135283-135289, and Mac-connected guidance
at 135317-135323. Follow .github/review-bot-rules/full-internationalization.md
and provide translated values for every supported locale at each listed entry.

Sources: Coding guidelines, Path instructions, Learnings

Sources/ContentView.swift (1)

8409-8409: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Gate the command palette entry before invoking Tailscale Pairing.

palette.mobileConnect is registered unconditionally, but performMobileConnectWorkspaceAction(..., enforceFeatureFlag: false) ignores CmuxFeatureFlags.shared.isMobileConnectButtonEnabled. Use the shared flag here so the command is not visible/executable while the feature flag is disabled.

🤖 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 `@Sources/ContentView.swift` at line 8409, Update the palette.mobileConnect
registration and its performMobileConnectWorkspaceAction call to honor
CmuxFeatureFlags.shared.isMobileConnectButtonEnabled, so the command is hidden
or blocked when the flag is disabled while preserving the existing Tailscale
Pairing behavior when enabled.
♻️ Duplicate comments (1)
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/PairingView.swift (1)

100-108: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Manual host/port pairing restriction is inconsistent across code and copy. The intended policy is that manual host/port entry works only on the simulator, but the button logic does not enforce it and one catalog string still advertises host/port pairing "on a trusted local network".

  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/PairingView.swift#L100-L108,233-239: confirm whether connectManualHost()/pair() reject non-loopback hosts on a physical device, or gate the Pair button on loopback when running on device.
  • ios/cmux/Resources/Localizable.xcstrings#L8572-L8589: update mobile.tailscale.pairingHelp (English and Japanese) to drop the "pair by host and port on a trusted local network" guidance once the code-side policy is confirmed.
🤖 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 `@Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/PairingView.swift`
around lines 100 - 108, Enforce the simulator-only manual host/port pairing
policy in PairingView.swift by updating connectManualHost()/pair() or gating the
Pair button so physical devices reject non-loopback hosts; preserve valid
loopback behavior. Then update ios/cmux/Resources/Localizable.xcstrings at lines
8572-8589 for mobile.tailscale.pairingHelp in both English and Japanese to
remove guidance about pairing by host and port on a trusted local network.
🤖 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 `@ios/cmux/Resources/Localizable.xcstrings`:
- Around line 8572-8589: Update the English and Japanese values for
mobile.tailscale.pairingHelp to remove guidance about pairing by host and port
on a trusted local network, keeping the message consistent with the
simulator-only manual-entry policy and Tailscale QR pairing flow.

In `@Resources/Localizable.xcstrings`:
- Around line 35814-35830: Complete translations for all 20 supported locales in
Resources/Localizable.xcstrings: update cli.surfaceResume.set.error.unknownFlag
at lines 35814-35830 and localize the sidebar Tailscale Pairing description at
110629-110635, pairing-code detail at 134756-134762, setup requirement at
135283-135289, and Mac-connected guidance at 135317-135323. Follow
.github/review-bot-rules/full-internationalization.md and provide translated
values for every supported locale at each listed entry.

In `@Sources/AppDelegate.swift`:
- Around line 10939-11038: Remove the environment-controlled Bonsplit UI-test
setup, including runSetupWhenWindowReady and its four-panel creation logic, from
AppDelegate. Move this behavior into an isolated UI-test or dedicated debug
facility outside the production Sources target, preserving the existing setup
behavior without adding further test-only branches to AppDelegate.

In `@Sources/ContentView.swift`:
- Line 8409: Update the palette.mobileConnect registration and its
performMobileConnectWorkspaceAction call to honor
CmuxFeatureFlags.shared.isMobileConnectButtonEnabled, so the command is hidden
or blocked when the flag is disabled while preserving the existing Tailscale
Pairing behavior when enabled.

---

Duplicate comments:
In `@Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/PairingView.swift`:
- Around line 100-108: Enforce the simulator-only manual host/port pairing
policy in PairingView.swift by updating connectManualHost()/pair() or gating the
Pair button so physical devices reject non-loopback hosts; preserve valid
loopback behavior. Then update ios/cmux/Resources/Localizable.xcstrings at lines
8572-8589 for mobile.tailscale.pairingHelp in both English and Japanese to
remove guidance about pairing by host and port on a trusted local network.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2ddab00b-c3e6-4557-b517-972d79d98432

📥 Commits

Reviewing files that changed from the base of the PR and between 4c00963 and b2d99bc.

📒 Files selected for processing (8)
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/PairingView.swift
  • Resources/Localizable.xcstrings
  • Sources/AppDelegate.swift
  • Sources/ContentView.swift
  • Sources/FeatureFlags.swift
  • Sources/Mobile/Pairing/MobilePairingView.swift
  • cmuxTests/PostHogAnalyticsPropertiesTests.swift
  • ios/cmux/Resources/Localizable.xcstrings

@azooz2003-bit
azooz2003-bit merged commit 6f99395 into main Aug 4, 2026
31 checks passed
@azooz2003-bit
azooz2003-bit deleted the feat-tailscale-qr-focus branch August 4, 2026 04:08
azooz2003-bit added a commit that referenced this pull request Aug 8, 2026
The caseless MobilePairingScannerGuidanceCopy enum (from #9493) trips the
namespace-enum rule in scripts/lint-ios-package-conventions.sh, turning the
package-conventions-lint job red for every branch that touches Packages/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
azooz2003-bit added a commit that referenced this pull request Aug 9, 2026
* Add standalone iOS keyboard pinning lab

* Test rapid iOS keyboard dock reversals

* Unify iOS keyboard dock presentation

* Fix CLI compile break from classify() tuple access

#9804 landed
`FeedEventClassifier.classify(...).0` while classify() already returned
the named FeedEventClassification struct, so CLI/cmux.swift no longer
compiles on main (every app-host and tests-build-and-lag CI job fails
with "value of type 'FeedEventClassification' has no member '0'").
Use .hookEventName, matching the other call site.

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

* Strengthen rapid keyboard dock coverage

* test(panes): drop stale MobileInjectedAttachStartupTests referencing removed API

The main merge replaced MobileStartupConnectionCoordinator's
connectInjectedAttach with the claim/finish lifecycle, and
DogfoodAttachPreparationTests already covers that lifecycle end to end.
The stale file kept the whole CmuxMobileShellUITests target from
compiling, so no package UI suite could run in CI.

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

* Scope pairing scanner guidance copy onto MobilePairingScannerSheet

The caseless MobilePairingScannerGuidanceCopy enum (from #9493) trips the
namespace-enum rule in scripts/lint-ios-package-conventions.sh, turning the
package-conventions-lint job red for every branch that touches Packages/.

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

* Scope keyboard dock seam measurement to transitions

* Scope dock seam metric to keyboard transitions

* Test whole dock during keyboard reversal

* Isolate keyboard dock from terminal layout

* Animate hosted keyboard dock reflows

* Localize keyboard pinning lab name

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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