Skip to content

refactor: move the cloud tui transport into a CmuxCloudTui package - #14198

Merged
teamleaderleo merged 16 commits into
manaflow-ai:mainfrom
teamleaderleo:refactor/cloud-tui-package
Sep 24, 2026
Merged

teamleaderleo merged 16 commits into
manaflow-ai:mainfrom
teamleaderleo:refactor/cloud-tui-package

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

Next slice of the package-extraction RFC #13108 (after #13107 and #13135).

#13135 has landed; this branch now contains only this change.

Why this slice

PR compile admission recompiles every cmux app Swift task even on a DerivedData seed hit, so app-target size sets compile time. Picked by edit frequency: over 30 days, and leaving out bulk commits (>25 files), Sources/Cloud/ got 25% of app source touches.

I trial-compiled the hot Cloud clusters as standalone packages to find one that leaves cleanly:

Cluster Result
CloudTree*/MachinesPanel* (sidebar UI) pulls in VMClient, CloudMachineLinkManager, TabDragTransferRegistry, TerminalController. Too deep for one PR
CmuxTuiSurfaceProvider* 68+ files before reaching the app hubs
PortForward needs BrowserPanel and CloudMachineLink
CloudTui transport 20 files, closes over packages only once #13135 lands
Tunnel clean on its own, but only 0.5% of non-bulk touches

What moves

20 files from Sources/Cloud/ to Packages/macOS/CmuxCloudTui: the cmux-tui request and argv builders, the manual-IO socket (frame, decoder, command, connection, descriptor lease, grid, input router, resize scheduler), the manual-mirror deadlines, phase, request kind and watchdog, remote colors, resolved surface, and client paths. Dependencies: CmuxSurfaceCatalogModel, CmuxTerminal, CmuxCloudImagePaste, CmuxFoundation. No app imports.

Staying in the app:

  • CloudTuiManualMirrorSession: it binds a TerminalSurface.
  • CloudTuiCommandRunning, CloudTuiDaemonAnswer, CloudTuiPersistentResourceConnection: they use CloudMachineLink.LinkError, which is nested in the app's 900-line CloudMachineLink. The next step for them is moving LinkError out.

Changes besides the move

  • Declarations are now public. Four structs that relied on the synthesized initializer get an explicit public init with the same parameters. The resize scheduler's private(set) state is now publicly readable, because the app tests read it.
  • 62 app and test files gain a top-level import CmuxCloudTui. None go inside the #if canImport(cmux_DEV) blocks, and none go into cmuxUITests. No @_exported import.
  • Wiring: the pbxproj links the package to cmux only (see below for cmuxTests). None of the moved files belonged to cmux-cli. The workspace group comes from check-workspace-package-groups.py --write, and CmuxCloudTui is added to the CI package list.
  • Fixtures that copy sources by path now point at the package: tests/run_cloud_command_deadline_tests.sh, which also strips import CmuxCloudTui from copies, and tests/test_cli_cloud_hostname.py. The same applies to the path filter in cloud-command-deadlines.yml.
  • None of the moved files had entries in the warning budget or used String(localized:).

Changes after review

  • CloudTuiCommandLine and CloudTuiRequests carry the conventions lint's lint:allow namespace-type justification, like the catalog package's moved namespaces.
  • cmuxTests does not link CmuxCloudTui; it imports it and resolves symbols through the host app, like CmuxTerminal. Linking it made Xcode build CmuxTerminal and CmuxTerminalCore as shared package frameworks, and CmuxTerminalCore's copy of libghostty crashed the app host at launch.
  • CmuxTerminal vends its GhosttyRuntimeTestStubs target as a product so CmuxCloudTuiTests can link without libghostty, and the package-test job provisions GhosttyKit for CmuxCloudTui.

Verification

  • swift build and swift test --package-path Packages/macOS/CmuxCloudTui pass locally: 4 new public-surface tests, and no warnings from the package's own sources.
  • Upstream CI on this PR: macOS compile admission (app + test bundle, 304 app-host tests in 22 suites) and swift-package-tests pass. The full app-host unit suite fails only on tests that fail on main too (SSH/remote cluster, VMClientReadCoalescingTests).
  • A test merge with current main is clean, main has not touched the moved files, and none of main's newer commits add users of the moved types.

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

Extracts the cloud TUI transport from the app target into a new CmuxCloudTui package so hot Cloud code stops recompiling with every app build. Built on #13135, which moved the shared surface-catalog value types into CmuxSurfaceCatalogModel (since squashed into this branch); the branch also carries merges of current main.

Refactors

  • 20 files move from Sources/Cloud/: the request and argv builders, the manual-IO socket (frame, decoder, command, connection, descriptor lease, grid, input router, resize scheduler), the manual-mirror deadlines, phase, request kind and watchdog, remote colors, resolved surface, and client paths.
  • The package depends only on CmuxSurfaceCatalogModel, CmuxTerminal, CmuxCloudImagePaste, and CmuxFoundation; no app imports.
  • Declarations are now public; four structs get explicit public init, in the resize scheduler the private(set) state is readable so app tests can keep reading it, and the two static namespaces carry the package lint's inline lint:allow justification.
  • CloudTuiManualMirrorSession (binds a TerminalSurface) and the files speaking CloudMachineLink.LinkError stay in the app.
  • 62 app and test files add a top-level import CmuxCloudTui; the CI package list, warning budget, and cloud-command-deadline paths follow the move.
  • One test file's CmuxSurfaceCatalogModel import sits outside its cmux_DEV block so the file compiles when the host module is cmux.
  • cmuxTests resolves CmuxCloudTui through the host app instead of linking it, since linking pulls CmuxTerminal in as shared frameworks whose duplicated libghostty crashed launch; CI prebuilds GhosttyKit, and CmuxCloudTuiTests stubs libghostty through CmuxTerminal's new GhosttyRuntimeTestStubs product.

Written for commit 280279d. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features
    • Added support for delivering files through a remote TUI connection.
    • Cloud TUI connection, input, sizing, color, request-building, and client-path capabilities are now available as a reusable component.
  • Tests
    • Added coverage for the component’s public interfaces, grid validation, resize scheduling, and malformed snapshot handling.
    • Updated automated tests and workflows to cover the component and its related functionality.

teamleaderleo and others added 3 commits September 23, 2026 23:35
Redone from current main instead of rebasing manaflow-ai#13135 (1.8k commits behind,
with main-side edits to the moved files and ~100 new consumers).

SurfaceMachineID, SurfaceResourceID, SurfaceResource, the CloudVM state
documents and the cmux-tui snapshot parser are pure values that the Cloud
sidebar, SurfaceCatalog, the socket commands and the CLI all share. They move
from the app target into Packages/macOS/CmuxSurfaceCatalogModel (depends on
CmuxCore, CMUXDebugLog and CMUXMobileCore only). SurfaceCatalog, the owner,
stays in the app.

Besides the move: declarations become public, structs that relied on the
synthesized memberwise initializer get an explicit public init with the same
parameters, cmuxDebugLog becomes CMUXDebugLog.logDebugEvent, and the parser's
port helpers and SurfaceResourceID.portKey move out of two larger app files
because the parser calls them. VMMachineKind.swift was also a member of the
cmux-cli target, so the CLI links the package.

Since manaflow-ai#13135 was cut, main split SurfaceMachineID, SurfaceDeviceInstanceID and
SurfaceDevicePresence out of SurfaceCatalogModel.swift; they move too (hence
the CMUXMobileCore dependency, for cmxCanonicalDeviceID). Main's new fields
(agent, device workspace detail/unread/pin, machine presence,
displayCreationMachines, displayPorts) are public and in the explicit inits.
CmuxTuiSnapshotParser.mergingDisplays stays in the app's +Displays extension,
where main moved it.

303 app, CLI and test files gain `import CmuxSurfaceCatalogModel`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The iOS/package conventions lint rejects public all-static types in
packages. CmuxTuiSnapshotParser, CloudWireNumber and
CloudVMEventFeedRecoveryDecision were internal static namespaces in the app
and moved unchanged; reshaping them is a separate change, so each carries the
lint's inline lint:allow justification.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Next slice of the package-extraction RFC (manaflow-ai#13108), picked by edit frequency:
Sources/Cloud gets about a quarter of 30-day app source touches, and every
PR compile recompiles the whole app target, so moving hot Cloud code out of
the target is what shortens edit-build loops.

Twenty files move from Sources/Cloud to Packages/macOS/CmuxCloudTui: the
cmux-tui request and argv builders, the manual-IO socket (frame, decoder,
command, connection, descriptor lease, grid, input router, resize
scheduler), the manual-mirror deadlines, phase, request kind and watchdog,
the remote colors document, the resolved-surface result and the client
paths. The package depends on CmuxSurfaceCatalogModel (from manaflow-ai#13135, which
this branch is stacked on), CmuxTerminal, CmuxCloudImagePaste and
CmuxFoundation; no app imports.

Staying in the app: CloudTuiManualMirrorSession (binds a TerminalSurface)
and the three files that speak CloudMachineLink.LinkError (CommandRunning,
DaemonAnswer, PersistentResourceConnection).

Besides the move: declarations become public, four structs that relied on
the synthesized initializer get an explicit public init, and the resize
scheduler's private(set) state is publicly readable. 62 app and test files
gain a top-level `import CmuxCloudTui`. The cloud command deadline fixture,
the CLI hostname test and the deadline workflow's path filter follow the
files; CI's package list gains CmuxCloudTui.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@coderabbitai

coderabbitai Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: d6352377-a58a-4710-b66d-4d271a76e453

📥 Commits

Reviewing files that changed from the base of the PR and between fcd0019 and 280279d.

📒 Files selected for processing (1)
  • cmux.xcodeproj/project.pbxproj
💤 Files with no reviewable changes (1)
  • cmux.xcodeproj/project.pbxproj

Included review availability: Your plan provides up to 10 included reviews per hour; 1 remains after this review.


📝 Walkthrough

Walkthrough

Adds the CmuxCloudTui macOS Swift package and makes its existing transport APIs public. Updates app and test targets, test fixtures, and CI configuration to use and test the package.

Changes

CmuxCloudTui package

Layer / File(s) Summary
Package definition and transport APIs
Packages/macOS/CmuxCloudTui/Package.swift, Packages/macOS/CmuxCloudTui/README.md, Packages/macOS/CmuxCloudTui/Sources/CmuxCloudTui/*
Defines the package and makes existing command-line, request-building, client-path, snapshot-parser, remote-color, manual I/O, grid, resize, and mirror APIs public. The reported implementations remain unchanged.
App target integration
cmux.xcodeproj/project.pbxproj, Sources/AppDelegate.swift, Sources/Cloud/*, Sources/RemoteTui/*, Sources/Surfaces/*
Adds the package dependency to the app target, removes package-owned source entries, and imports CmuxCloudTui where app files use its APIs.
Package tests and CI integration
Packages/macOS/CmuxCloudTui/Tests/*, Packages/macOS/CmuxTerminal/Package.swift, cmuxTests/*, tests/*, .github/workflows/*
Adds package-surface tests and the Ghostty runtime test-stub product. Updates test imports and fixtures, the hostname test source path, and CI package selection and path filters.

Priority: ⬇️ Low

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

Change: Refactor

Merge Risk: ⚪ Minimal · up to 28027

No actionable merge-blocking issue is established; proceed with the normal build and test checks.


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 Swiftpm Lockfiles ❌ Error The PR adds the CmuxCloudTui SwiftPM package reference in cmux.xcodeproj/project.pbxproj, including an XCLocalSwiftPackageReference and product dependency. The required root Xcode lockfile, `cmu… Regenerate or update cmux.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved for the new CmuxCloudTui Xcode package reference, then commit that lockfile in the PR alongside the project change.
Docstring Coverage ⚠️ Warning Docstring coverage is 65.57% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 122 functions across 49 files. (1 skipped… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (23 passed)
Check name Status Explanation
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 Cloud Persistent Session And Early Input ✅ Passed The pull request does not introduce a failure condition from the rule. The 20 transport files are renames with access-control changes; normalized comparison found only explicit initializers for synthe…
Cmux Swift Actor Isolation ✅ Passed No actor-isolation mistake is introduced. The new target explicitly keeps Swift language mode 5, with no default MainActor setting. Normalized comparisons show the moved production sources changed onl…
Cmux Swift Blocking Runtime ✅ Passed PASS — the PR adds no blocking or timing primitive. The renamed production files retain their existing withCheckedContinuation and clock.sleep code; the diff changes access levels and package loca…
Cmux Browser Automation Off-Main ✅ Passed The check is not applicable. The authoritative PR diff does not modify Sources/TerminalController.swift, ControlCommandExecutionPolicy.swift, or its policy tests, and the changed-file diff contain…
Cmux Expensive Synchronous Load ✅ Passed The PR is a Cloud TUI transport package extraction. Its changed production lines add module imports, public access modifiers, package manifests, and package wiring. It does not introduce an expensive …
Cmux Cache Substitution Correctness ✅ Passed PASS. The PR moves the Cloud TUI transport and widens access, but does not replace an authoritative read with a cache. CloudTuiClientPaths.loadDevices() still reads and decodes vm-tui-devices.json…
Cmux No Hacky Sleeps ✅ Passed PASS. The pull request does not introduce a covered hacky sleep or fixed runtime delay. The only changed shell and Python files are test fixtures, and their changes only update source paths and import…
Cmux Algorithmic Complexity ✅ Passed No algorithmic-complexity violation is introduced. The diff moves the existing Cloud TUI production code and changes visibility, imports, initializers, and package wiring; it does not add a new scalab…
Cmux Swift Concurrency ✅ Passed The PR does not introduce or materially expand a covered legacy concurrency pattern. The three moved files that contain asynchronous machinery retain the same DispatchQueue operations, checked conti…
Cmux Swift @Concurrent ✅ Passed PASS. The diff adds no @concurrent annotations, removes none, and changes no async call sites. The moved async transport function CloudTuiManualIOConnection.start() differs only by public visibi…
Cmux Swift Package Boundaries ✅ Passed The diff moves the independently testable Cloud TUI transport and protocol logic from Sources/Cloud into the new CmuxCloudTui SwiftPM target. The package has explicit package dependencies, isolate…
Cmux Swift Logging ✅ Passed The diff adds no print, debugPrint, dump, NSLog, Logger, or ad hoc diagnostic logging statements. The moved transport files retain their existing content apart from access changes, and app/r…
Cmux User-Facing Error Privacy ✅ Passed No privacy violation is introduced. The package is linked to the production app, but the moved Cloud TUI sources are identical to their base versions after access-modifier and import normalization, ex…
Cmux Full Internationalization ✅ Passed The PR moves existing Cloud TUI transport sources and changes access control. After removing import and access-control edits, the 20 renamed Swift sources have no behavioral or user-facing text change…
Cmux Swiftui State Layout ✅ Passed The check is not triggered. The PR moves Cloud TUI transport code and adds module imports, but it does not add or modify SwiftUI state, view layout, GeometryReader, lazy/list row subtrees, or render-t…
Cmux Architecture Rethink ✅ Passed PASS. The diff relocates 20 Cloud TUI files into CmuxCloudTui and changes visibility and imports. The moved implementations show no behavioral changes beyond access modifiers, explicit initializers,…
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed The PR does not add or materially change a standalone cmux-owned window. The authoritative Swift diff adds no NSWindow, NSPanel, NSWindowController, WindowGroup, window-identifier, or close-shortcut c…
Cmux Source Artifacts ✅ Passed No source-control artifact violation is present. The authoritative diff contains hand-written Swift source and tests, package manifests, README documentation, CI/Xcode/workspace configuration, and tes…
Cmux No Test Or Debug Seam In Production Source ✅ Passed PASS. The diff adds no test/debug seam in production Swift. The 20 transport files are rename-aware moves from Sources/Cloud into Packages/macOS/CmuxCloudTui/Sources; their changes are access wide…
Title check ✅ Passed The title clearly and concisely describes the primary change: moving the cloud TUI transport into a new package.
Description check ✅ Passed The description clearly covers the motivation, scope, package dependencies, retained app files, wiring changes, and verification results. It uses a Verification section instead of the template's Testi…
Full details: Docstring Coverage

Explanation

Docstring coverage is 65.57% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 122 functions across 49 files. (1 skipped: 1 unsupported.)

Full details: Cmux Swiftpm Lockfiles

Explanation

The PR adds the CmuxCloudTui SwiftPM package reference in cmux.xcodeproj/project.pbxproj, including an XCLocalSwiftPackageReference and product dependency. The required root Xcode lockfile, cmux.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved, is unchanged and absent from the PR diff. The new package uses only local path dependencies, so no external package-pin change is shown.

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

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.

teamleaderleo and others added 5 commits September 24, 2026 05:49
The package conventions lint rejects public all-static types in packages.
CloudTuiCommandLine and CloudTuiRequests were internal static namespaces in
the app and moved unchanged, so each carries the lint's inline lint:allow
justification, matching the catalog package.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CmuxCloudTui depends on CmuxTerminal, which links the GhosttyKit binary
target, so its swift test needs the prebuilt framework and the same
tolerated binaryTarget diagnostic as the terminal packages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cursor

cursor Bot commented Sep 24, 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.

teamleaderleo and others added 7 commits September 24, 2026 06:15
The import sat inside #if canImport(cmux_DEV), so the file would not
compile when the host module is cmux.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	cmuxTests/CloudNotificationSyncTests.swift
…loudTuiTests

cmuxTests now links CmuxCloudTui, which depends on CmuxTerminal, so Xcode
builds CmuxTerminal and CmuxTerminalCore as shared package frameworks
instead of static code inside the app. The test bundle then no longer
finds their symbols through the host app; link both directly, as it
already does for every other package it shares with the app.

CmuxCloudTuiTests links CmuxTerminal, whose libghostty calls SwiftPM
cannot satisfy from the GhosttyKit archive. Vend CmuxTerminal's existing
GhosttyRuntimeTestStubs target as a product and depend on it, the same way
CmuxTerminalTests does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	Sources/Cloud/VMTunnelManager.swift
@teamleaderleo teamleaderleo changed the title refactor: move the cloud tui transport into a CmuxCloudTui package (stacked on #13135) refactor: move the cloud tui transport into a CmuxCloudTui package Sep 24, 2026
…t into cmuxTests

Linking CmuxCloudTui into cmuxTests made Xcode build CmuxTerminal and
CmuxTerminalCore as shared package frameworks. CmuxTerminalCore then
carried its own copy of libghostty, so the app called ghostty_config_serialize
in a copy it never initialized and crashed at launch (CI run 35993531179).
cmuxTests already reaches CmuxTerminal through the host app without
linking it; do the same for CmuxCloudTui and drop the direct terminal links.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cursor

cursor Bot commented Sep 24, 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.

@teamleaderleo
teamleaderleo merged commit 066eaf1 into manaflow-ai:main Sep 24, 2026
60 checks passed
rustybret pushed a commit to rustybret/bmux that referenced this pull request Sep 24, 2026
d37a348 ci: route unpinned E2E runs by the pull request pool rule, 12vcpu first (manaflow-ai#14225)
f016250 fix(ssh): keep legacy relay configurations off the cmux-tui path (manaflow-ai#14216)
066eaf1 refactor: move the cloud tui transport into a CmuxCloudTui package (manaflow-ai#14198)
acd8850 Pin one workspace.list for a workspace ref in workspace loading (manaflow-ai#14219)
ae81635 ci: pick one macOS pool per pull request run by preference and live queue depth (manaflow-ai#14205)

# Conflicts:
#	.github/workflows/ci-guards.yml
#	.github/workflows/ci-macos.yml
#	.github/workflows/ci-queue-janitor.yml
#	.github/workflows/ci.yml
#	.github/workflows/cli-pipe-regressions.yml
#	.github/workflows/cloud-command-deadlines.yml
#	.github/workflows/remote-daemon.yml
#	.github/workflows/test-e2e.yml
#	.github/workflows/test-macos-suite.yml
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