Skip to content

mux: Rust modernization — edition 2024, MSRV 1.88, latest deps, workspace lints - #7657

Merged
lawrencecchen merged 4 commits into
mainfrom
feat-mux-rust-modernize
Jul 9, 2026
Merged

lawrencecchen merged 4 commits into
mainfrom
feat-mux-rust-modernize

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Jul 8, 2026 •

Copy link
Copy Markdown
Contributor

Modernization pass over the mux Rust workspace and cmux-client, no behavior change (spec untouched, conformance must stay green).

  • Edition 2021 -> 2024 everywhere (explicit unsafe blocks in ghostty FFI per unsafe_op_in_unsafe_fn).
  • MSRV rust-version = 1.88 (floor set by ratatui 0.30).
  • Deps: crossterm 0.28->0.29, ratatui 0.29->0.30.2, tungstenite 0.24->0.29 (Utf8Bytes/Bytes churn handled), bindgen 0.71->0.72.1, cargo update. libc stays 0.2 (1.0.0-alpha is pre-release).
  • Workspace lints table inherited by all crates; all new warnings fixed; cargo fmt.

Local verification was limited to mux-cdp + cmux-client (this Mac's ghostty zig build is broken — known host libSystem regression), so CI is the compile gate for the FFI crates and the TUI dep churn.


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


Note

Medium Risk
Large dependency upgrades (especially ratatui 0.30 and tungstenite 0.29) and edition 2024 touch the TUI, CDP WebSocket path, and FFI build; risk is compile/runtime regressions in rendering and browser attach, not auth or data handling.

Overview
Modernizes the mux Rust workspace (cmux-client, ghostty-vt, mux-cdp/core/tui) without intended protocol or product behavior changes.

The workspace moves to Rust edition 2024 with rust-version = 1.88, adds a shared [workspace.lints] table inherited by every crate, and bumps key deps: crossterm 0.29, ratatui 0.30 (split into core/crossterm/widgets crates), tungstenite 0.29, bindgen 0.72, plus a large Cargo.lock refresh.

Code changes are mostly edition/lint-driven: let-chain style conditionals, import reordering, std::mem::size_of → size_of, explicit unsafe in FFI where unsafe_op_in_unsafe_fn is denied, and tungstenite API updates (Message::Text now takes owned UTF-8; binary payloads use .to_vec()). CDP builds JSON-RPC params via indexed assignment instead of a single json! with params. Chrome::launch_with takes &ChromeLaunchOptions instead of owned options. Tests and config tests wrap set_var/remove_var in unsafe blocks per Rust 2024 rules.

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

Summary by CodeRabbit

  • Chores
    • Updated the workspace to Rust 2024 (min Rust 1.88), refreshed selected dependency versions, and aligned lint/package metadata across crates.
  • Refactor
    • Reduced unnecessary data copying in CDP stream/client handling, updated Chrome launch to use borrowed options, and simplified internal control flow while preserving behavior.
  • Tests
    • Updated WebSocket/JSON test helpers and fake CDP responses to match revised request/response handling.

… workspace lints

Edition 2021->2024 across all crates incl. cmux-client (explicit unsafe blocks
in FFI per unsafe_op_in_unsafe_fn). Deps: crossterm 0.29, ratatui 0.30.2,
tungstenite 0.29 (Utf8Bytes/Bytes API), bindgen 0.72.1; libc stays 0.2 (1.0 is
pre-release alpha). Workspace lints table (unsafe_op_in_unsafe_fn deny,
uninlined_format_args, semicolon_if_nothing_returned, redundant_clone,
needless_pass_by_value). cargo fmt. Wire/protocol/CLI unchanged; spec untouched.
@vercel

vercel Bot commented Jul 8, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment Jul 9, 2026 6:55am
cmux-staging Building Building Preview, Comment Jul 9, 2026 6:55am

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Jul 8, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The workspace is upgraded to Rust 2024 with shared lint and dependency settings. Several CDP and bindings paths now pass borrowed values instead of owned ones, and many mux-core, mux-tui, and ghostty-vt files were reformatted or had equivalent conditional guards rewritten.

Changes

Workspace and Manifest Upgrade

Layer / File(s) Summary
Workspace edition and dependency bumps
mux/Cargo.toml
Edition set to 2024, rust-version set to 1.88, workspace lint tables added, and crossterm/ratatui/tungstenite/bindgen versions updated.
Per-crate manifest inheritance
mux/bindings/rust/Cargo.toml, mux/crates/ghostty-vt-sys/Cargo.toml, mux/crates/ghostty-vt/Cargo.toml, mux/crates/mux-cdp/Cargo.toml, mux/crates/mux-core/Cargo.toml, mux/crates/mux-tui/Cargo.toml
Crate manifests add workspace rust-version and lint inheritance, with ghostty-vt-sys also switching bindgen to the workspace version.
Build script target flag condition
mux/crates/ghostty-vt-sys/build.rs
The Zig target check is rewritten into a single short-circuiting condition.

Borrowed-Reference API Refactor

Layer / File(s) Summary
CmuxStream request borrowing
mux/bindings/rust/src/lib.rs, mux/bindings/rust/examples/e2e.rs
CmuxClient::open_stream and CmuxStream::open use borrowed request values, and recv_timeout keeps the same event parsing through an explicit loop.
Chrome launch options by reference
mux/crates/mux-cdp/src/chrome.rs, mux/crates/mux-core/src/browser.rs
Chrome::launch_with takes &ChromeLaunchOptions, callers pass references, and the DevTools detection branch is collapsed into one condition.
CDP client reader and message handling
mux/crates/mux-cdp/src/client.rs, mux/crates/mux-cdp/src/lib.rs
The reader path takes shared state by reference, request JSON is assigned in two steps, binary frames convert through Vec<u8>, and text frame construction uses .into().
Fake CDP helpers and session tests
mux/crates/mux-cdp/tests/fake_cdp.rs
The fake server helper accepts borrowed JSON, tests pass &json!(...), concurrent call setup is renamed, and the guard is explicitly dropped.

Import Reordering and Conditional Formatting Sweep

Layer / File(s) Summary
ghostty-vt imports and size_of calls
mux/crates/ghostty-vt/src/{key,lib,render,terminal}.rs
Imports and re-exports are reordered, and several size_of calls switch to the unqualified form.
mux-core import and guard refactors
mux/crates/mux-core/src/{browser,lib,mux,platform,server,surface}.rs, mux/crates/mux-core/tests/*
Imports are reordered and several guards/branches are rewritten into equivalent compact forms across browser, mux, server, surface, platform, and tests.
mux-tui imports and formatting
mux/crates/mux-tui/src/{app,browser_input,cli,config,main}.rs, mux/crates/mux-tui/src/session/*, mux/crates/mux-tui/src/ui/*
Imports are reordered across app, CLI, config, main, session, and UI modules, with a few single-line conditionals and named-format writes updated; config tests switch env mutations to unsafe blocks.

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

Possibly related PRs

  • manaflow-ai/cmux#7180: Updates the shared Rust workspace manifests and crate-level inheritance patterns that this PR continues.
  • manaflow-ai/cmux#7378: Shares the CDP browser launch and reader plumbing updated in this change set.
  • manaflow-ai/cmux#7480: Touches the mux-tui CLI socket-resolution path that is also adjusted here.
🚥 Pre-merge checks | ✅ 24 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 43.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (24 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 Diff touches only Rust files; no Swift sources changed, so no actor-isolation issues were introduced.
Cmux Swift Blocking Runtime ✅ Passed No Swift files were changed in either PR commit; the diff is Rust-only, so the Swift blocking-runtime rule doesn’t apply.
Cmux Browser Automation Off-Main ✅ Passed PR only changes Rust crates; HEAD^..HEAD shows no edits to the Swift browser-routing files covered by the rule.
Cmux Expensive Synchronous Load ✅ Passed PASS: HEAD only changes Rust files in mux-tui; no Swift files or main-actor sync-load paths are touched, so the Swift rule is not applicable.
Cmux Cache Substitution Correctness ✅ Passed HEAD changes only touch Rust files; no Swift/TypeScript/JavaScript cache-substitution paths are present.
Cmux No Hacky Sleeps ✅ Passed Diff only refactors Rust TUI code; no added fixed sleeps, timers, polling, or retry waits in changed files, and no JS/TS/shell/build scripts were touched.
Cmux Algorithmic Complexity ✅ Passed PASS: The diff only refactors conditionals/imports/formatting; no new nested scans, rescans, or repeated sorts/filters were introduced in hot runtime paths.
Cmux Swift Concurrency ✅ Passed No cmux-owned Swift files were changed; the PR only touches Rust files, so the Swift concurrency modernization rule is not applicable.
Cmux Swift @Concurrent ✅ Passed No Swift files were changed in the PR diff, so the Swift concurrent-annotation rule is not applicable.
Cmux Swift File And Package Boundaries ✅ Passed No .swift files are touched in the diff, so the Swift file/package boundary rule is not applicable.
Cmux Swiftpm Lockfiles ✅ Passed No .gitignore, Package.swift, Package.resolved, workflow, or Xcode project files changed in the PR diff.
Cmux Swift Logging ✅ Passed No Swift files changed in the PR diff, so the Swift logging rule is not applicable.
Cmux User-Facing Error Privacy ✅ Passed The diff only refactors control flow/imports in TUI code; no added or changed user-facing error text or prohibited sensitive terms appear.
Cmux Full Internationalization ✅ Passed Only internal Rust refactors changed; no .xcstrings, .lproj, web/i18n, or user-facing localized text was touched.
Cmux Swiftui State Layout ✅ Passed No SwiftUI files or state/layout changes were touched; the PR diff is limited to Rust workspace crates.
Cmux Architecture Rethink ✅ Passed PASS: The diff touches only Rust files under mux; no Swift files or Swift architecture changes are present, so the Swift rethink rule is not applicable.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed No Swift files or cmux window-ownership changes are present in the PR diff, so the auxiliary-window close-shortcuts rule is not applicable.
Cmux Source Artifacts ✅ Passed Changed paths are source/config/Cargo.lock only; no logs, temp dirs, caches, screenshots, or build outputs appear in the diff.
Cmux No Test Or Debug Seam In Production Source ✅ Passed Diff only changes Rust files under mux/crates/...; no Swift production Sources/ files were touched, so the seam rule is not applicable.
Cmux No Ambient Global State ✅ Passed Diff only refactors existing Rust functions; no new file-scope funcs, global vars, or singletons were added.
Title check ✅ Passed The title is concise and accurately summarizes the main modernization work: edition 2024, MSRV 1.88, dependency bumps, and workspace lints.
Description check ✅ Passed Mostly complete: it has a clear summary and testing notes, but the demo video, review trigger, and checklist sections from the template are missing.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-mux-rust-modernize

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.

@socket-security

socket-security Bot commented Jul 8, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedcargo/​bindgen@​0.71.1 ⏵ 0.72.17910093100100
Updatedcargo/​crossterm@​0.28.1 ⏵ 0.29.09910093100100
Updatedcargo/​ratatui@​0.29.0 ⏵ 0.30.2100 +110093 -1100100
Updatedcargo/​tungstenite@​0.24.0 ⏵ 0.29.010010093100100
Updatedcargo/​unicode-width@​0.2.0 ⏵ 0.2.299 +1100100100100

View full report

@greptile-apps

greptile-apps Bot commented Jul 8, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR modernizes the mux Rust workspace: edition 2021 → 2024, MSRV 1.88, and a dependency refresh (crossterm 0.29, ratatui 0.30, tungstenite 0.29, bindgen 0.72). Call-site churn from the tungstenite API change (Message::Text now holds Utf8Bytes; Message::Binary holds bytes::Bytes) is handled throughout via .into() and .to_vec() adapters. No protocol-level behavior changes are introduced.

  • Edition 2024 + workspace lints: unsafe_op_in_unsafe_fn = deny enforced across all crates; set_var/remove_var in tests wrapped in unsafe {} with a real CONFIG_ENV_LOCK mutex already in place; size_of used from the new prelude.
  • let-chain refactors: All nested if let / if patterns flattened to let-chains — semantically equivalent, confirmed by unchanged tests.
  • API adaptations: ChromeLaunchOptions and several other hot-path values promoted from owned to borrowed parameters; String → Utf8Bytes coercions applied at every Message::Text send site.

Confidence Score: 5/5

Mechanical modernization with no protocol or behavioral changes; all API adaptations follow the tungstenite 0.29 migration path correctly and the unsafe env-mutation in tests is properly gated behind CONFIG_ENV_LOCK.

Every tungstenite Message::Text send site converts String to Utf8Bytes via .into(); the Binary receive path is correct (only minor extra allocation). The let-chain refactors are semantically equivalent by construction. The unsafe_op_in_unsafe_fn lint is satisfied by existing unsafe {} blocks in the FFI wrappers, and the env::set_var wrapping in tests is backed by a real mutex. CI is the compile gate for the ghostty FFI crates as the author notes, but the Rust-side changes are sound.

mux/crates/mux-cdp/src/client.rs — Binary message handler has a small unnecessary allocation (bytes.to_vec()); otherwise no files require special attention.

Important Files Changed

Filename Overview
mux/Cargo.toml Workspace root: edition 2024, rust-version 1.88, workspace.lints table with unsafe_op_in_unsafe_fn=deny, crossterm/ratatui/tungstenite/bindgen bumps.
mux/crates/mux-cdp/src/client.rs tungstenite 0.29 adaptation: Message::Text sends use .into(), Binary handler uses bytes.to_vec() (extra copy vs. borrowing in place); reader_loop/drain_outbound now take references instead of owned values — safe because they execute synchronously within the owning closure.
mux/crates/mux-core/src/browser.rs let-chains flatten nested if-let/if patterns in surface thread, runtime endpoint, and notification logic; ChromeLaunchOptions now passed by reference; no behavioral changes.
mux/crates/mux-core/src/surface.rs Removes redundant mux.clone() before PTY reader thread spawn — safe because mux (a Weak) is not used after the spawn point; let-chains for ScrollChanged and SurfaceOutput emission.
mux/crates/mux-tui/src/config.rs env::set_var/remove_var in tests wrapped in unsafe {} with CONFIG_ENV_LOCK already defined and locked; correct unsafe handling.
mux/crates/mux-tui/src/app.rs Input thread now moves tx directly (clone removed — safe since tx is not used in outer scope after this spawn); let-chain refactors throughout; ratatui import reordering.
mux/crates/mux-cdp/tests/fake_cdp.rs write_json now takes &Value (avoids needless_pass_by_value); client_guard + explicit drop after server.join() makes teardown order explicit; test restructuring is equivalent.
mux/bindings/rust/src/lib.rs CmuxStream::open now takes &Value; with_read_timeout loop reformatted to block-style; no behavioral changes.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant App as mux-tui App
    participant CDP as CdpClient (mux-cdp)
    participant WS as WebSocket (tungstenite 0.29)
    participant Chrome as Chrome DevTools

    App->>CDP: call(method, params)
    CDP->>CDP: "json!({id, method, params:null})"
    CDP->>WS: send(Message::Text(text.into()))
    Note over WS: String to Utf8Bytes via .into()
    WS->>Chrome: WebSocket frame

    Chrome->>WS: WebSocket frame
    alt Text frame
        WS->>CDP: Message::Text(Utf8Bytes)
        CDP->>CDP: handle_text via Deref to str
    else Binary frame
        WS->>CDP: Message::Binary(Bytes)
        CDP->>CDP: from_utf8(bytes.to_vec()) then handle_text
    end
    CDP->>App: Result / CdpEvent
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant App as mux-tui App
    participant CDP as CdpClient (mux-cdp)
    participant WS as WebSocket (tungstenite 0.29)
    participant Chrome as Chrome DevTools

    App->>CDP: call(method, params)
    CDP->>CDP: "json!({id, method, params:null})"
    CDP->>WS: send(Message::Text(text.into()))
    Note over WS: String to Utf8Bytes via .into()
    WS->>Chrome: WebSocket frame

    Chrome->>WS: WebSocket frame
    alt Text frame
        WS->>CDP: Message::Text(Utf8Bytes)
        CDP->>CDP: handle_text via Deref to str
    else Binary frame
        WS->>CDP: Message::Binary(Bytes)
        CDP->>CDP: from_utf8(bytes.to_vec()) then handle_text
    end
    CDP->>App: Result / CdpEvent
Loading

Reviews (4): Last reviewed commit: "mux-tui: collapse nested ifs into let-ch..." | Re-trigger Greptile

Comment on lines 4 to +5
edition.workspace = true
rust-version.workspace = true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Published crate now carries a hard MSRV floor

cmux-client is the only crate in the workspace with publish = true, and it now inherits rust-version = "1.88" from the workspace. Any downstream consumer pinned to an older stable toolchain will see a hard rust-version rejection from Cargo 1.73+. This is intentional per the PR description, but the published CHANGELOG / crate docs should call it out explicitly so users aren't surprised on cargo update.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines 147 to +152
let mut msg = json!({
"id": id,
"method": method,
"params": params,
"params": null,
});
msg["params"] = params;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Two-step params assignment obscures intent

The pattern of initialising "params": null and then overwriting with msg["params"] = params works correctly but is surprising to readers — null is a valid JSON params value and the extra step looks intentional. The actual motivation (suppressing clippy::needless_pass_by_value on the params: Value argument) is invisible at the call site. A brief comment explaining why the macro and direct assignment are split, or an #[allow(clippy::needless_pass_by_value)] on the function with a note, would make the intent clear without the two-step workaround.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

mux-core: collapse 13 nested ifs into let-chains (edition 2024 idiom), drop
one redundant clone, remove needless_pass_by_value from workspace lints
(signature churn). mux-tui: wrap test env set_var/remove_var in unsafe
(unsafe fn in edition 2024; serialized by CONFIG_ENV_LOCK), inline format
args in cli.rs print_tree, add missing statement semicolons in main.rs.
@lawrencecchen
lawrencecchen merged commit 760e343 into main Jul 9, 2026
29 of 32 checks passed

This branch was successfully deployed

1 active deployment
Preview – cmux — 8cd6b03d Deployed Jul 9, 2026 by vercel[bot]
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