cmux link machine update: a DEV build pins its Cloud machine build from its published commit or cmux-tui tree
Leo, 2026-10-31: "whenever i start a chat it should be able to send me to cloud autommatically keep launching/downloading new dev builds and such".
This re-lands the Rust half of #30258 together with #30421, which it supersedes. Lawrence's merge tool reverted #30258 in #30438: "CmuxNextApp +21 lines turned the feat tip arch ratchet red; re-land with the code moved to a package". The ratchet counts CmuxNextApp lines only. This PR touches only cmux-tui/crates. The Swift retry re-lands separately, at net zero CmuxNextApp lines.
Why
In a fleet capture, a DEV build signed in to the Cloud test account sent its first chat to a fresh cloud-chats machine. The machine's image carries an older cmux-tui, which refused the folder copy ("cloud-chats runs an older cmux that can't take this chat yet"). The app could not update the machine: a DEV build ships no cmux-tui-ssh/manifest.json, so cmux link machine update answered machine_update_unavailable.
Change (cmux-remote pinned_linux_payload, cmux link machine update)
When no manifest is bundled, the pin comes from what CI already publishes:
- The build's own commit manifest,
files.cmux.com/cmux-tui/<commit>/manifest.json. The manifest must name that commit and carry a 64-hex digest. - Otherwise, for a tree-mode DEV bundle (
mode=tree,key=incmux-tui.version),tree/<key>/source.json. It must have the same key, and its publishing commit's manifest pins the build. The tree must also list the same digest, asRemoteInstaller.planalready requires for SSH hosts.
The download is still checked against the pinned digest before anything is staged, and every fetch is HTTPS only. Release, nightly, pin-mode and npm builds are unchanged. An offline, dirty or unpublished build still gets machine_update_unavailable, now with an accurate message.
machine update treats a machine already on the publishing commit as current (same_tree). Without this, a tree bundle whose own commit differs from the publishing commit would update the machine on every send.
Reviews: Review (subagent claude-opus-5-5 medium): SHIP at 6522d021 (#30258, receipt) and at 40b7c363 (#30421, receipt). The three files here are byte-identical to 40b7c363's. Follow-ups are tracked in #30373 and #30423.
Tests
cmux-ci test on the Linux pool at the same content:
cargo fmt --check: clean.cargo test -p cmux-remote --lib published_pin_tests: 4 passed.cargo clippy -p cmux-remote -p cmux-tui --all-targets -D warnings: clean.
Agent session: agent session
š¤ Generated with Claude Code
Summary by cubic
Enables DEV builds to update Cloud machines via cmux link machine update. Previously a DEV build ships no manifest, so updating a machine running an older cmux-tui failed with machine_update_unavailable ā and a fresh machine would refuse the first chat send.
- When no manifest is bundled, the pin now comes from the build's own commit manifest published by CI, or, for tree-mode DEV bundles, from the tree's publishing commit via
tree/<key>/source.json; the tree must list the matching digest. - Downloads are still checked against the pinned digest before staging and fetched over HTTPS only.
- A machine already on the tree's publishing commit is treated as current (
same_tree), so a tree bundle whose own commit differs from the publishing commit no longer triggers an update on every send. - Release, nightly, pin-mode, and npm builds are unchanged; offline, dirty, or unpublished builds still get
machine_update_unavailablewith a more accurate message.