Skip to content

Add configurable native TUI resource views - #9447

Merged
lawrencecchen merged 84 commits into
mainfrom
feat-tui-resource-columns
Aug 10, 2026
Merged

lawrencecchen merged 84 commits into
mainfrom
feat-tui-resource-columns

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Aug 3, 2026 •

Copy link
Copy Markdown
Contributor

Build configurable native resource views in cmux-tui.

  • Treat ordered native views as the extension primitive: stable IDs, independent widths, collapse priorities, arbitrary resource paths, and shared actions.
  • Add named sidebar profiles that compose those views. Switch profiles and hide or show individual rails from any right-click menu without reconnecting machines.
  • Include focused, three-column, and workspace tree profiles in the prototype. The focused default omits the tabs rail.
  • Support flat machine, workspace, pane, tab, and agent views plus workspace-to-agent and workspace-to-pane-to-tab trees. Existing sidebar.columns configurations still map through the compatibility path.
  • Keep the machine rail capability-driven instead of adding master and slave modes. Connected machines remain alive while users switch views.
  • Discover direct SSH aliases before recursively included inventories. Keep Add SSH host first in the searchable picker and retain native scrollbar behavior.
  • Bootstrap unpublished builds by uploading the exact running cmux-tui binary when the remote OS and architecture match. This repairs macOS arm64 hosts such as cmux-macmini.
  • Detect native Windows SSH shells and explain the WSL 2 distro requirement. A native Windows daemon still needs a future ConPTY and Windows socket transport.
  • Keep the connection dialog open through connecting and starting phases. Failures remain selectable and expose Retry, Close, and Copy message.
  • Add a visible Copy message control to bottom-right status errors. Hovering either the error or control pins it.
  • Preserve rename, sidebar focus, Alt/Option navigation, mouse-down activation, provider-neutral VM actions, resize stabilization, and the current origin/main fixes already on the branch.

Verification:

  • cargo +1.94.0 check -p cmux-tui -p cmux-remote
  • 15 SSH bootstrap tests passed.
  • 12 focused config, profile, context-menu, connection transaction, status-copy, and SSH discovery tests passed.
  • cmux-macmini accepted the uploaded unpublished binary and connected to both a fresh session and the previously failing sb9447d session.
  • cmux-windows now exits with the actionable WSL 2 requirement instead of a Windows shell parse error.
  • The exact arm64 binary and cmux-macmini both report PR head c7a8940.
  • The prototype rendered its focused two-column profile with the tabs rail omitted.
  • RemoteTmuxSizingUITests/testAttachSettlesStableAndCoherent passed with a recorded artifact: https://github.com/manaflow-ai/cmux-dev-artifacts/issues/9184

Note

Medium Risk
New subscribe event and regenerated protocol IR affect all protocol clients; machine SSH discovery and documented bootstrap behavior touch remote connection infrastructure.

Overview
Adds a new protocol v11 agent-changed subscribe event (surface, agent source/state, optional session, updated_at_ms) and regenerates all language SDK bindings and manifests to match the updated IR.

Introduces the glob dependency so SSH config Include patterns can be expanded when discovering direct SSH aliases for the machine rail.

README updates document that the machine rail and cmux ssh share the managed remote lifecycle (compatibility probe, pinned binary install for packaged builds, on-demand session start), and position machine-agent / raw relay as low-level diagnostics rather than the primary attach path.

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

@coderabbitai

coderabbitai Bot commented Aug 3, 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

The PR adds configurable sidebar rails and resource projections. It adds tabs and agent navigation, native machine creation and connection flows, SSH host discovery, client-machine and surface renaming, searchable menus, localization, and related tests.

Changes

Sidebar and source configuration

Layer / File(s) Summary
Sidebar and source configuration
cmux-tui/crates/cmux-tui/src/config.rs, cmux-tui/docs/*, cmux-tui/examples/*, cmux-tui/Cargo.toml, cmux-tui/crates/cmux-tui/Cargo.toml
Configuration resolves ordered resource views, sizing, collapse priorities, legacy columns, and validated machine creation sources. Documentation and prototype configurations describe the new settings.

Machine runtime and catalog flow

Layer / File(s) Summary
Machine runtime and catalog flow
cmux-tui/crates/cmux-tui/src/machine.rs, cmux-tui/crates/cmux-tui/src/machine_runtime.rs, cmux-tui/crates/cmux-tui/src/machine_provider_runtime.rs, cmux-tui/crates/cmux-tui/src/main.rs, cmux-tui/crates/cmux-tui/src/session/*
Machine runtimes expose creation and connection metadata, discover bounded SSH configuration targets, create local prototype entries, support client-local renaming, and merge expanded UI state.

Resource projection and rail interaction

Layer / File(s) Summary
Resource projection and rail interaction
cmux-tui/crates/cmux-tui/src/sidebar_projection.rs, cmux-tui/crates/cmux-tui/src/app.rs, cmux-tui/crates/cmux-tui/src/ui/*, cmux-tui/crates/cmux-tui/src/session/*, cmux-tui/crates/cmux-tui-core/src/mux.rs
Workspace, pane, tab, and agent rows are projected from local and cached remote data. Ordered rails support rendering, focus traversal, activation, scrolling, resizing, collapse, and width-based removal.

Searchable menus and action routing

Layer / File(s) Summary
Searchable menus and action routing
cmux-tui/crates/cmux-tui/src/app.rs, cmux-tui/crates/cmux-tui/src/ui/overlay.rs, cmux-tui/crates/cmux-tui/src/localization.rs, cmux-tui/spec/inventory.json, cmux-tui/scripts/check-spec-inventory.py
Menus support filtering, fallback actions, stable creation and connection targets, client-machine and surface renaming, and localized messages. Inventory metadata records the new actions.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant App
  participant SidebarProjection
  participant MachineRuntime
  participant WorkspaceState
  User->>App: focus rail or open searchable menu
  App->>SidebarProjection: build resource rows and targets
  App->>MachineRuntime: submit creation, connection, or rename request
  MachineRuntime-->>App: return updated machine UI state
  App->>WorkspaceState: activate selected surface or tab
  WorkspaceState-->>User: render updated sidebar state
Loading

Possibly related PRs


Important

Pre-merge checks failed

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

❌ Failed checks (3 errors, 1 warning)

Check name Status Explanation Resolution
Cmux Algorithmic Complexity ❌ Error sidebar_projection.rs:223 runs agents.iter().find() for every tab, making render projection O(T×A); draw_projection calls it during each draw, with no bound or benchmark. Build a SurfaceId-to-AgentInfo map once per projection and use O(1) lookups; cache the agent snapshot or rows if redraw frequency remains high.
Cmux User-Facing Error Privacy ❌ Error The new SSH-host picker routes through connect_machine, while SSH stderr is embedded in ssh transport closed: {diagnostic} and shown by the existing Machine action failed: {error} status path. Sanitize SSH and provider failures before assigning status text. Show a generic localized connection error and keep raw diagnostics in internal logs only.
Cmux Architecture Rethink ❌ Error FileDiffPageView adds a post-layout Task restore and ScrollRowTracker observer, splitting scroll state between UIKit, page flags, and pager persistence. Make one pager/coordinator own scroll restoration and persisted row state through value snapshots and actions; remove ScrollRowTracker, pending flags, and the post-layout Task.
Docstring Coverage ⚠️ Warning Docstring coverage is 35.20% 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
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 Swift diff adds no service protocols or unisolated mutable Sendable references; UI state is MainActor-bound, and new parsing/value work is explicitly nonisolated or @concurrent.
Cmux Swift Blocking Runtime ✅ Passed The Swift diff adds no prohibited production synchronization APIs; polling and wait helpers occur only in UI tests, while production changes use actor/async code without blocking waits, sleeps, del...
Cmux Browser Automation Off-Main ✅ Passed The feature diff changes only cmux-tui files; it does not modify TerminalController.swift, ControlCommandExecutionPolicy.swift, or add browser socket automation commands.
Cmux Expensive Synchronous Load ✅ Passed The PR feature diff has no Swift files or production Swift changes; it contains Rust, configuration, documentation, JSON, and Python changes only.
Cmux Cache Substitution Correctness ✅ Passed No TypeScript/JavaScript files changed; Swift changes use event-driven in-memory scroll hints and guard incomplete group snapshots, with call-site rationale and healthy-snapshot clearing.
Cmux No Hacky Sleeps ✅ Passed The feature diff contains Rust, Python metadata, JSON, TOML, and Markdown; it adds no TypeScript, JavaScript, shell, or timing-based runtime synchronization.
Cmux Swift Concurrency ✅ Passed Swift diff adds no new DispatchQueue/DispatchGroup, Combine, or completion-handler patterns; the only new production Task is a one-shot @MainActor SwiftUI scroll restoration.
Cmux Swift @Concurrent ✅ Passed Changed Swift diff adds @concurrent to the async, nonisolated diff parser/projection helpers; no new invalid synchronous or actor-isolated @concurrent use was found.
Cmux Swift Package Boundaries ✅ Passed The PR-side diff from the merge's main parent contains only Rust, JSON, TOML, Python, and Markdown files; it adds no production Swift or SwiftPM boundary changes.
Cmux Swiftpm Lockfiles ✅ Passed No Package.swift, Package.resolved, or .gitignore changes occurred; the Xcode diff only adds source files, not package references, and workflows add tests only.
Cmux Swift Logging ✅ Passed The PR diff contains only Rust, JSON, TOML, and documentation changes; it adds or materially changes no Swift logging or Swift runtime code.
Cmux Full Internationalization ✅ Passed Feature diff is confined to cmux-tui Rust/docs; new sidebar, picker, status, and error copy uses the existing English/Japanese catalog, with no Swift, web, or app-catalog changes.
Cmux Swiftui State Layout ✅ Passed The SwiftUI diff adds no ObservableObject, @Published, GeometryReader, or store-backed lazy rows; diff rows use value snapshots and action closures, with writes confined to lifecycle/event callbacks.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed The commit adds no standalone NSWindow/NSPanel/Window code; the changed Swift paths are app logic, UI components, and tests. scripts/lint_auxiliary_window_close_shortcuts.py passes.
Cmux Source Artifacts ✅ Passed The effective PR diff contains only source, config, docs, spec data, a required Cargo.lock, and prototype JSON fixtures; no forbidden artifact paths or binary files were added.
Cmux No Test Or Debug Seam In Production Source ✅ Passed The PR diff against its base changes only cmux-tui paths; it contains no Swift files under a production Sources/ path.
Cmux No Ambient Global State ✅ Passed The actual Swift diff adds no new file-scope functions, mutable globals, static-only namespaces, or singletons; new state is instance-owned by constructable types, with only static constants added.
Title check ✅ Passed The title clearly and concisely summarizes the main change: configurable native TUI resource views.
Description check ✅ Passed The description provides a detailed summary and verification results, but it omits the required demo video and checklist sections.
✨ 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-tui-resource-columns

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.

@blacksmith-sh

This comment has been minimized.

@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 `@cmux-tui/crates/cmux-tui/src/app.rs`:
- Around line 7335-7348: Update activate_sidebar_tab to avoid redundant
destination mutations: compare target.workspace with self.tree.active_workspace,
target.screen with that workspace’s active_screen, and target.pane with that
screen’s active_pane, then call select_workspace, select_screen, and focus_pane
only when their targets differ; keep select_tab behavior unchanged.
- Around line 16086-16096: Update the Hit::SidebarTab branch to avoid calling
sidebar_tab_targets, which materializes and scans every sidebar target on each
click. Use the identity fields already carried by Hit::SidebarTab (workspace,
screen, pane, index, and surface) to resolve the selected rail index through a
lightweight lookup, then preserve the existing focus, follow-selection,
selection, and activate_sidebar_tab behavior.
- Around line 14218-14236: Update the focus selection in focus_sidebar to derive
the preferred rail exclusively from visible_rail_order(), rather than
self.config.sidebar.columns. Select the first visible rail in the existing
preference order, and leave focus on the pane when visible_rail_order() is empty
so no invisible rail receives focus.

In `@cmux-tui/crates/cmux-tui/src/config.rs`:
- Around line 2445-2492: Update the resolved.is_empty() fallback in the sidebar
configuration flow to rebuild config.sidebar.columns using the resolved
config.machine_sidebar and config.sidebar width/max_width values, matching the
existing else branch. Preserve the warning, and ensure the fallback restores the
Machines and Workspaces columns instead of retaining Sidebar::default() values.

In `@cmux-tui/crates/cmux-tui/src/ui/sidebar.rs`:
- Around line 265-294: Update the sidebar render path around sidebar_tab_targets
so it no longer rebuilds and allocates every SidebarTabTarget each frame. Keep
TreeView authoritative, maintain a derived tab index/count when tree state
changes, and materialize only targets needed for visible viewport rows and hit
regions; preserve selection clamping, empty-state rendering, scrolling, and
existing row behavior.
🪄 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: d868cccc-3d1f-4d48-9d45-9e4cb3b76547

📥 Commits

Reviewing files that changed from the base of the PR and between 1927f13 and 7ad218b.

📒 Files selected for processing (16)
  • cmux-tui/crates/cmux-tui/src/app.rs
  • cmux-tui/crates/cmux-tui/src/config.rs
  • cmux-tui/crates/cmux-tui/src/localization.rs
  • cmux-tui/crates/cmux-tui/src/machine.rs
  • cmux-tui/crates/cmux-tui/src/machine_provider_runtime.rs
  • cmux-tui/crates/cmux-tui/src/machine_runtime.rs
  • cmux-tui/crates/cmux-tui/src/main.rs
  • cmux-tui/crates/cmux-tui/src/ui/mod.rs
  • cmux-tui/crates/cmux-tui/src/ui/sidebar.rs
  • cmux-tui/docs/configuration.md
  • cmux-tui/docs/keyboard.md
  • cmux-tui/docs/machines.md
  • cmux-tui/docs/mouse.md
  • cmux-tui/examples/resource-columns.prototype.json
  • cmux-tui/scripts/check-spec-inventory.py
  • cmux-tui/spec/inventory.json

Comment thread cmux-tui/crates/cmux-tui/src/app.rs
Comment thread cmux-tui/crates/cmux-tui/src/app.rs Outdated
Comment thread cmux-tui/crates/cmux-tui/src/app.rs
Comment thread cmux-tui/crates/cmux-tui/src/config.rs Outdated
Comment thread cmux-tui/crates/cmux-tui/src/ui/sidebar.rs

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

Caution

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

⚠️ Outside diff range comments (3)
cmux-tui/crates/cmux-tui/src/app.rs (1)

13216-13227: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Avoid rebuilding every tab target on each tabs-rail keypress.

handle_tabs_sidebar_key calls sidebar_tab_targets() for every key, including plain navigation keys. sidebar_tab_targets walks every screen, pane, and tab of the selected workspace and allocates two String values per tab. Navigation only needs the target count, and activation only needs one entry.

Resolve the count and the single selected target without materializing the full list.

♻️ Proposed refactor sketch
-        let targets = self.sidebar_tab_targets();
-        self.tabs_rail_selection = self.tabs_rail_selection.min(targets.len().saturating_sub(1));
+        let target_count = self.sidebar_tab_target_count();
+        self.tabs_rail_selection = self.tabs_rail_selection.min(target_count.saturating_sub(1));
         let page = rail_page_size(self.sidebar_layout.tabs);
         if let Some(next) =
-            rail_navigation_index(key, self.tabs_rail_selection, targets.len(), page)
+            rail_navigation_index(key, self.tabs_rail_selection, target_count, page)
         {
             self.tabs_rail_selection = next;
         } else if key.code == KeyCode::Enter
-            && let Some(target) = targets.get(self.tabs_rail_selection)
+            && let Some(target) = self.sidebar_tab_target_at(self.tabs_rail_selection)
         {
-            self.activate_sidebar_tab(target)?;
+            self.activate_sidebar_tab(&target)?;
         }

As per coding guidelines: "Avoid repeated full scans, sorting, filtering, or per-item nested scans over scalable collections in production code, especially in UI, event-driven, backend, and persistence paths."

🤖 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 `@cmux-tui/crates/cmux-tui/src/app.rs` around lines 13216 - 13227, The
handle_tabs_sidebar_key flow should avoid calling sidebar_tab_targets() and
materializing every target for ordinary navigation. Add or reuse lightweight
logic to compute only the sidebar tab count, use that count with
rail_navigation_index and selection clamping, and resolve/create only the
selected target when handling Enter before activate_sidebar_tab. Preserve
existing navigation and activation behavior.

Source: Coding guidelines

cmux-tui/crates/cmux-tui/src/machine_runtime.rs (1)

192-214: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Route create_from's error messages through the localization catalog.

Lines 198 and 202 use raw English strings: anyhow::anyhow!("unknown machine creation source {source_id:?}") and anyhow::anyhow!("machine creation is unavailable in this client"). rename_machine, added in this same diff just below, correctly uses crate::localization::catalog().sidebar... for its error text. Use the same pattern here for consistency with the localization convention this file (and machine_provider_runtime.rs, which has a dedicated test asserting notices are catalog-backed) otherwise follows.

🌐 Proposed fix
         let source = self
             .creation_sources
             .iter()
             .find(|source| source.id == source_id)
             .cloned()
-            .ok_or_else(|| anyhow::anyhow!("unknown machine creation source {source_id:?}"))?;
+            .ok_or_else(|| {
+                anyhow::anyhow!(
+                    "{}: {source_id:?}",
+                    crate::localization::catalog().sidebar.machine_creation_source_unavailable
+                )
+            })?;
         let target = self
             .prototype_target
             .clone()
-            .ok_or_else(|| anyhow::anyhow!("machine creation is unavailable in this client"))?;
+            .ok_or_else(|| {
+                anyhow::anyhow!(crate::localization::catalog().sidebar.client_machine_unavailable)
+            })?;
🤖 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 `@cmux-tui/crates/cmux-tui/src/machine_runtime.rs` around lines 192 - 214,
Update create_from to obtain both error messages from
crate::localization::catalog(), matching the localized sidebar error pattern
used by rename_machine: use the catalog entry for an unknown creation source and
the catalog entry for unavailable machine creation, preserving the existing
error flow and source_id context.
cmux-tui/crates/cmux-tui/src/main.rs (1)

1633-1643: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a test for StaticMachineController::perform's CreateFrom/RenameClientMachine dispatch.

Existing tests cover the UI layer (app.rs) that produces MachineRequest::CreateFrom, and the runtime layer (machine_runtime.rs::create_from), but no test exercises this controller dispatch directly. Add a test that calls StaticMachineController::perform(MachineRequest::CreateFrom { .. }) and asserts the resulting notice and ui.snapshot.machines reflect the new row, to catch regressions in this wiring.

🤖 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 `@cmux-tui/crates/cmux-tui/src/main.rs` around lines 1633 - 1643, Add a focused
test for StaticMachineController::perform covering CreateFrom and
RenameClientMachine dispatch, using the existing test setup and request types.
Assert that CreateFrom returns the expected notice and adds the new machine row
to ui.snapshot.machines, then exercise RenameClientMachine to verify the renamed
result and corresponding UI state.
🤖 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 `@cmux-tui/crates/cmux-tui/src/app.rs`:
- Around line 3682-3706: Update the searchable menu item construction to cache
each item's lowercase label once, then change refresh_search to compare terms
against that cached value instead of calling label.to_lowercase() for every
candidate on each keystroke. Preserve the existing filtering, separator,
fallback, and level replacement behavior in refresh_search.

In `@cmux-tui/crates/cmux-tui/src/localization.rs`:
- Line 1351: Update the English localization value for machine_name_required to
use an actionable instruction such as “Enter a machine name” instead of “Machine
name is required”, and update the corresponding assertion near line 2058 to
expect the new wording.

In `@cmux-tui/crates/cmux-tui/src/machine_runtime.rs`:
- Line 90: Trace all callers of MachineRuntime::with_creation_sources and
MachineRuntime::external to verify whether SSH discovery runs on the interactive
render/main thread. If either constructor can run there, move
discover_ssh_config_hosts to a bounded background operation with a timeout and
fall back to an empty connection-target list when it does not complete;
otherwise document or enforce the non-interactive execution context while
preserving both existing construction paths.

In `@cmux-tui/crates/cmux-tui/src/ui/overlay.rs`:
- Around line 254-257: Update the search overlay rendering around
visible_text_and_cursor to retain and use its returned cursor offset when
computing cursor_x, converting the offset to display columns if it is a
character index. Preserve correct cursor placement at the start, middle, and end
of input, including wide Unicode text, and add focused tests covering those
cases.

---

Outside diff comments:
In `@cmux-tui/crates/cmux-tui/src/app.rs`:
- Around line 13216-13227: The handle_tabs_sidebar_key flow should avoid calling
sidebar_tab_targets() and materializing every target for ordinary navigation.
Add or reuse lightweight logic to compute only the sidebar tab count, use that
count with rail_navigation_index and selection clamping, and resolve/create only
the selected target when handling Enter before activate_sidebar_tab. Preserve
existing navigation and activation behavior.

In `@cmux-tui/crates/cmux-tui/src/machine_runtime.rs`:
- Around line 192-214: Update create_from to obtain both error messages from
crate::localization::catalog(), matching the localized sidebar error pattern
used by rename_machine: use the catalog entry for an unknown creation source and
the catalog entry for unavailable machine creation, preserving the existing
error flow and source_id context.

In `@cmux-tui/crates/cmux-tui/src/main.rs`:
- Around line 1633-1643: Add a focused test for StaticMachineController::perform
covering CreateFrom and RenameClientMachine dispatch, using the existing test
setup and request types. Assert that CreateFrom returns the expected notice and
adds the new machine row to ui.snapshot.machines, then exercise
RenameClientMachine to verify the renamed result and corresponding UI state.
🪄 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: 59c79848-8808-42ad-8b58-2ba8ac620c6f

📥 Commits

Reviewing files that changed from the base of the PR and between 7ad218b and 4db16e0.

⛔ Files ignored due to path filters (1)
  • cmux-tui/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • cmux-tui/Cargo.toml
  • cmux-tui/crates/cmux-tui/Cargo.toml
  • cmux-tui/crates/cmux-tui/src/app.rs
  • cmux-tui/crates/cmux-tui/src/localization.rs
  • cmux-tui/crates/cmux-tui/src/machine.rs
  • cmux-tui/crates/cmux-tui/src/machine_provider_runtime.rs
  • cmux-tui/crates/cmux-tui/src/machine_runtime.rs
  • cmux-tui/crates/cmux-tui/src/main.rs
  • cmux-tui/crates/cmux-tui/src/ui/overlay.rs
  • cmux-tui/docs/machines.md
  • cmux-tui/scripts/check-spec-inventory.py
  • cmux-tui/spec/inventory.json

Comment thread cmux-tui/crates/cmux-tui/src/app.rs
Comment thread cmux-tui/crates/cmux-tui/src/localization.rs Outdated
Comment thread cmux-tui/crates/cmux-tui/src/machine_runtime.rs
Comment thread cmux-tui/crates/cmux-tui/src/ui/overlay.rs
@cursor

cursor Bot commented Aug 3, 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.

@lawrencecchen lawrencecchen changed the title Prototype configurable TUI resource columns Add configurable native TUI resource views Aug 3, 2026

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

Caution

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

⚠️ Outside diff range comments (2)
cmux-tui/crates/cmux-tui/src/localization.rs (1)

1371-1371: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

New English machine messages state a condition without a next action. The shared root cause is that these three new user-facing English strings describe what happened but do not tell the user what to do next. Give each one a concrete next action, and keep the Japanese values at Lines 1866-1868 equivalent in form.

  • cmux-tui/crates/cmux-tui/src/localization.rs#L1371-L1371: replace "Machine name is required" with an instruction such as "Enter a machine name", and update the matching localization assertion.
  • cmux-tui/crates/cmux-tui/src/localization.rs#L1370-L1370: extend "This machine creation source is unavailable" with a next action, such as choosing a different source from the picker.
  • cmux-tui/crates/cmux-tui/src/localization.rs#L1372-L1372: extend "This client-owned machine is unavailable" with a next action, such as selecting another machine in the rail.

As per coding guidelines, user-facing errors should state what happened in product terms and provide one or two concrete next actions.

🤖 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 `@cmux-tui/crates/cmux-tui/src/localization.rs` at line 1371, Update the three
English machine messages in cmux-tui/crates/cmux-tui/src/localization.rs at
lines 1370-1372: make machine_name_required instruct the user to enter a machine
name, extend the unavailable creation-source message with guidance to choose
another source, and extend the unavailable client-owned-machine message with
guidance to select another machine. Keep the Japanese values at lines 1866-1868
equivalent in form and update the matching localization assertion.

Source: Coding guidelines

cmux-tui/crates/cmux-tui/src/config.rs (1)

2592-2597: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

The empty-resolved sidebar.columns fallback keeps hardcoded struct defaults.

When raw.sidebar.columns is Some but every entry is invalid or duplicate, resolved is empty and config.sidebar.columns still holds the Sidebar::default() widths (22/0) instead of the resolved config.machine_sidebar.width/max_width and config.sidebar.width/max_width. Line 2612 then derives views from those stale values. Rebuild the columns the same way as the else branch at Line 2598.

🐛 Proposed fix
         if resolved.is_empty() {
             eprintln!("cmux-tui: sidebar.columns had no usable entries; keeping defaults");
+            config.sidebar.columns = vec![
+                SidebarColumn {
+                    kind: SidebarColumnKind::Machines,
+                    width: config.machine_sidebar.width,
+                    max_width: config.machine_sidebar.max_width,
+                },
+                SidebarColumn {
+                    kind: SidebarColumnKind::Workspaces,
+                    width: config.sidebar.width,
+                    max_width: config.sidebar.max_width,
+                },
+            ];
         } else {
🤖 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 `@cmux-tui/crates/cmux-tui/src/config.rs` around lines 2592 - 2597, Update the
empty-resolved branch in the sidebar column resolution logic to rebuild
`config.sidebar.columns` from the resolved machine-sidebar and sidebar
width/max_width settings, matching the construction used in the non-empty `else`
branch. Keep `columns_explicit` unchanged for this fallback so subsequent view
derivation uses the current configuration values rather than
`Sidebar::default()` widths.
🤖 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 `@cmux-tui/crates/cmux-tui/src/app.rs`:
- Around line 7610-7651: Update activate_projection_target to route workspace,
screen, and pane activation through select_workspace_for_client,
select_screen_for_client, and focus_pane_after_input instead of directly
mutating tree selection fields or calling lower-level session methods. Preserve
the existing prepare_pty_input_before_mutation guard and pane focus recording
behavior, and keep Surface activation delegated to activate_sidebar_tab.
- Around line 7505-7524: Update projection_rows and its callers to avoid
rebuilding projection data during navigation: borrow the collapsed state instead
of cloning it, and introduce frame-scoped caching so
handle_projection_sidebar_key reuses the rows already produced for rendering.
Ensure the cache is invalidated when relevant sidebar, workspace, pane, surface,
agent, or collapse state changes, while preserving the existing projection_rows
output.

In `@cmux-tui/crates/cmux-tui/src/cli/command.rs`:
- Around line 2621-2635: Extend the CLI parser tests near the existing
noncanonical state cases to cover `agent list` as well as `agent report`. For
each of "running", "waiting", and "error", build an `agent list` invocation with
the state and assert parsing fails, matching the rejection coverage provided by
the separate validator near `agent list`.

In `@cmux-tui/crates/cmux-tui/src/session/mod.rs`:
- Around line 539-555: The agent snapshot is rebuilt or cloned for every
agent-enabled projection in the render path. In
cmux-tui/crates/cmux-tui/src/session/mod.rs:539-555, update Session::agents and
the local agent-state update flow to cache or share one local snapshot per
update/paint instead of rescanning and allocating per projection; in
cmux-tui/crates/cmux-tui/src/session/remote.rs:3007-3010, change the remote path
to reuse the cached snapshot without cloning it for each projection.

In `@cmux-tui/crates/cmux-tui/src/session/remote.rs`:
- Around line 3035-3039: Update the agent refresh flow around the list-agents
request and cache assignment to track agent freshness independently from
workspace freshness. When the request or AgentInfo decoding fails, clear or
disable cached agent rows so cached_agents() cannot expose stale selectable
state; only publish agent rows after a successful snapshot, and preserve the
existing successful update path. Add a regression test covering a successful
workspace refresh followed by a failed agent refresh.

In `@cmux-tui/crates/cmux-tui/src/sidebar_projection.rs`:
- Around line 211-214: Build a single HashMap<SurfaceId, &AgentInfo> in rows
from the existing agents collection and pass it into append_level. Change
append_level’s agents parameter to the map type, then replace the per-tab
agents.iter().find lookup with an O(1) lookup by tab.surface while preserving
the existing agent_only filtering and TreeView/AgentInfo sources of truth.

---

Outside diff comments:
In `@cmux-tui/crates/cmux-tui/src/config.rs`:
- Around line 2592-2597: Update the empty-resolved branch in the sidebar column
resolution logic to rebuild `config.sidebar.columns` from the resolved
machine-sidebar and sidebar width/max_width settings, matching the construction
used in the non-empty `else` branch. Keep `columns_explicit` unchanged for this
fallback so subsequent view derivation uses the current configuration values
rather than `Sidebar::default()` widths.

In `@cmux-tui/crates/cmux-tui/src/localization.rs`:
- Line 1371: Update the three English machine messages in
cmux-tui/crates/cmux-tui/src/localization.rs at lines 1370-1372: make
machine_name_required instruct the user to enter a machine name, extend the
unavailable creation-source message with guidance to choose another source, and
extend the unavailable client-owned-machine message with guidance to select
another machine. Keep the Japanese values at lines 1866-1868 equivalent in form
and update the matching localization assertion.
🪄 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: b6a655a6-41e4-4a26-9c11-b6f7e58bf053

📥 Commits

Reviewing files that changed from the base of the PR and between 4db16e0 and e4cc513.

📒 Files selected for processing (19)
  • cmux-tui/crates/cmux-tui-core/src/mux.rs
  • cmux-tui/crates/cmux-tui/src/app.rs
  • cmux-tui/crates/cmux-tui/src/cli/command.rs
  • cmux-tui/crates/cmux-tui/src/config.rs
  • cmux-tui/crates/cmux-tui/src/localization.rs
  • cmux-tui/crates/cmux-tui/src/main.rs
  • cmux-tui/crates/cmux-tui/src/session/mod.rs
  • cmux-tui/crates/cmux-tui/src/session/remote.rs
  • cmux-tui/crates/cmux-tui/src/sidebar_projection.rs
  • cmux-tui/crates/cmux-tui/src/ui/mod.rs
  • cmux-tui/crates/cmux-tui/src/ui/rail.rs
  • cmux-tui/crates/cmux-tui/src/ui/sidebar.rs
  • cmux-tui/docs/configuration.md
  • cmux-tui/docs/keyboard.md
  • cmux-tui/docs/machines.md
  • cmux-tui/docs/mouse.md
  • cmux-tui/examples/resource-columns.prototype.json
  • cmux-tui/examples/resource-tree-no-agents.prototype.json
  • cmux-tui/examples/resource-tree.prototype.json

Comment thread cmux-tui/crates/cmux-tui/src/app.rs
Comment thread cmux-tui/crates/cmux-tui/src/app.rs
Comment thread cmux-tui/crates/cmux-tui/src/cli/command.rs
Comment thread cmux-tui/crates/cmux-tui/src/session/mod.rs
Comment thread cmux-tui/crates/cmux-tui/src/session/remote.rs Outdated
Comment thread cmux-tui/crates/cmux-tui/src/sidebar_projection.rs

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

🤖 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 `@cmux-tui/crates/cmux-tui/src/app.rs`:
- Around line 7723-7745: Extract the SidebarColumnKind-to-RailKind match into a
shared helper, then update rail_kind_for_view, reload_config, and focus_sidebar
to call it instead of maintaining local mappings. Preserve the existing
projection fallback and each caller’s current behavior while ensuring all
legacy-kind conversions use the single helper.
- Around line 13204-13218: Update the current-selection calculation in the
sidebar selection logic so an out-of-range Some(selected_action) returns None
rather than falling back to state.selected; preserve the existing action-row
offset for valid selected_action values and the state.selected fallback only
when selected_action is None.

In `@cmux-tui/crates/cmux-tui/src/ui/sidebar.rs`:
- Around line 370-372: Update the header construction near
projection_resource_label to obtain the projection path separator or complete
formatted header from localization::catalog() instead of hardcoding " › ". Add
the corresponding entry to every supported localization catalog and preserve the
existing label ordering and rail::header rendering.
🪄 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: 3352d746-f5fe-4ae7-bd18-9d3407689229

📥 Commits

Reviewing files that changed from the base of the PR and between e4cc513 and a122f1f.

📒 Files selected for processing (8)
  • cmux-tui/crates/cmux-tui/src/app.rs
  • cmux-tui/crates/cmux-tui/src/config.rs
  • cmux-tui/crates/cmux-tui/src/sidebar_projection.rs
  • cmux-tui/crates/cmux-tui/src/ui/sidebar.rs
  • cmux-tui/docs/configuration.md
  • cmux-tui/examples/resource-columns.prototype.json
  • cmux-tui/examples/resource-tree-no-agents.prototype.json
  • cmux-tui/examples/resource-tree.prototype.json

Comment thread cmux-tui/crates/cmux-tui/src/app.rs
Comment thread cmux-tui/crates/cmux-tui/src/app.rs
Comment thread cmux-tui/crates/cmux-tui/src/ui/sidebar.rs Outdated
@cursor

cursor Bot commented Aug 3, 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.

@cursor

cursor Bot commented Aug 3, 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.

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

Comment thread cmux-tui/crates/cmux-tui/src/machine_agent/runtime.rs
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