Skip to content

feat: add Multipass provider#197

Merged
steipete merged 3 commits into
openclaw:mainfrom
jwmoss:feat/multipass-provider
Jun 2, 2026
Merged

feat: add Multipass provider#197
steipete merged 3 commits into
openclaw:mainfrom
jwmoss:feat/multipass-provider

Conversation

@jwmoss
Copy link
Copy Markdown
Contributor

@jwmoss jwmoss commented Jun 2, 2026

From https://x.com/_lopopolo/status/2061613371883954430 adding multipass as a provider for crabbox.


Summary

Adds provider=multipass as a local Ubuntu VM SSH-lease provider backed by Canonical Multipass.

  • launches local Ubuntu VMs with multipass launch and Crabbox cloud-init
  • creates per-lease SSH keys/users and runs through the normal Crabbox SSH sync/run path
  • supports warmup, run, ssh, status, stop, cleanup, portable --os image defaults, and cache volumes
  • keeps lifecycle local-only with no coordinator/cloud credentials
  • rejects unsupported surfaces like Tailscale and --actions-runner

Verification

  • go test ./internal/providers/...
  • go test ./internal/cli -run 'TestValidateActionsRunnerCapability|TestMultipass|TestConfigShow|TestPortableOS|TestExplicitProviderImagesSurvivePortableOSDefaults|TestAppleContainerImageFollowsOSImageDefault|TestAppleContainerExplicitImageSurvivesOSDefault|TestProviderFlag'
  • go test ./internal/cli -run '^$'
  • go build -trimpath -o bin/crabbox ./cmd/crabbox
  • bin/crabbox providers --json | jq -r '.[] | select(.provider=="multipass")'
  • bin/crabbox doctor --provider multipass
  • bin/crabbox warmup --provider multipass --slug multipass-smoke
  • bin/crabbox run --provider multipass --id multipass-smoke -- sh -lc 'pwd && uname -a && test -d /work/crabbox && test -f go.mod && git --version && rsync --version >/dev/null && jq --version'
  • bin/crabbox run --provider multipass --slug multipass-cache-smoke --multipass-cpus 2 --multipass-memory 2G --multipass-disk 10G --cache-volume mp-e2e-cache:/var/cache/crabbox/e2e -- sh -lc 'printf cache-ok > /var/cache/crabbox/e2e/probe && test "$(cat /var/cache/crabbox/e2e/probe)" = cache-ok'
  • bin/crabbox warmup --provider multipass --actions-runner --ttl 1s --slug should-not-start exits before provisioning with the expected unsupported-provider error
  • bin/crabbox status --provider multipass --id multipass-smoke
  • bin/crabbox ssh --provider multipass --id multipass-smoke
  • bin/crabbox stop --provider multipass multipass-smoke
  • bin/crabbox cleanup --provider multipass --dry-run
  • multipass list --format json
  • git diff --check

Live E2E Evidence

Multipass version:

multipass   1.16.3+mac
multipassd  1.16.3+mac

Warmup provisioned:

provisioned lease=cbx_2fe2671a391d instance=crabbox-multipass-smoke-36ebb60e state=ready
leased cbx_2fe2671a391d slug=multipass-smoke provider=multipass server=crabbox-multipass-smoke-36ebb60e type=26.04 ip=192.168.252.3 idle_timeout=30m0s expires=2026-06-02T04:26:21Z
ready ssh=crabbox@192.168.252.3:22 network=public workroot=/work/crabbox
warmup complete total=38.224s

Run/sync executed on the VM:

syncing workspace to crabbox@192.168.252.3:/work/crabbox/cbx_2fe2671a391d/crabbox
sent 602 files / 9.4 MiB
/work/crabbox/cbx_2fe2671a391d/crabbox
Linux crabbox-multipass-smoke-36ebb60e 7.0.0-15-generic #15-Ubuntu SMP PREEMPT_DYNAMIC Wed Apr 22 15:54:12 UTC 2026 aarch64 GNU/Linux
git version 2.53.0
jq-1.8.1
command complete in 74ms total=4.365s

Cache-volume smoke passed: the provider launched crabbox-multipass-cache-smoke-e0fd1aef, mounted the host cache directory, synced the checkout, wrote/read the mounted probe file, and released the ephemeral VM automatically.

Unsupported actions-runner path fails before provisioning:

--actions-runner is not supported for provider=multipass; use normal crabbox run or a remote SSH provider

Final cleanup state:

{"list":[]}

Notes

This is a headless provider, so there is no useful screenshot. The relevant proof is the terminal transcript above showing create, SSH readiness, sync, remote command execution, cache mount, unsupported runner rejection, stop, and empty final inventory.

@clawsweeper
Copy link
Copy Markdown

clawsweeper Bot commented Jun 2, 2026

Codex review: needs changes before merge. Reviewed June 2, 2026, 8:28 AM ET / 12:28 UTC.

Summary
The branch adds a Canonical Multipass local Ubuntu VM SSH-lease provider with CLI/config flags, provider registration, docs, tests, cache-volume support, and unsupported-surface rejection.

Reproducibility: yes. From source, a stopped unclaimed Multipass instance reaches shouldCleanup, which returns delete before the missing-claim path; I did not run tests because this review is read-only.

Review metrics: 2 noteworthy metrics.

  • Diff size: 25 files, +2145/-13. The provider spans CLI, docs, registration, and tests, so the destructive cleanup path deserves targeted review before merge.
  • Local destructive path: 1 new cleanup implementation. The PR adds a path that can call multipass delete --purge on workstation VMs, making ownership filtering merge-critical.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🦞 diamond lobster
Patch quality: 🧂 unranked krab
Result: blocked by patch quality or review findings.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Add the cleanup ownership guard and regression coverage for an unrelated stopped Multipass VM.
  • Re-run the focused Multipass provider and CLI tests listed in the PR body after the guard lands.

Risk before merge

  • [P1] Merging as-is could delete a user's unrelated stopped local Multipass VM when crabbox cleanup --provider multipass runs, because the ownership check is reached after the stopped-state delete decision.

Maintainer options:

  1. Guard Multipass cleanup before merge (recommended)
    Add an ownership filter before shouldCleanup/removeInstance so unclaimed non-Crabbox Multipass instances are skipped, with a regression test for an unrelated stopped VM.
Copy recommended automerge instruction
@clawsweeper automerge

Special instructions:
Add an ownership guard in the Multipass cleanup path so unclaimed, non-Crabbox-named instances are skipped before shouldCleanup/removeInstance, and add a regression test covering an unrelated stopped Multipass VM.

Next step before merge

  • [P2] A narrow automated repair can add the cleanup ownership guard and regression tests on the PR branch.

Security
Cleared: No credential, dependency, or supply-chain issue was found; the destructive cleanup behavior is tracked as a functional compatibility blocker.

Review findings

  • [P1] Guard cleanup to owned Multipass instances — internal/providers/multipass/backend.go:293
Review details

Best possible solution:

Land the Multipass provider only after cleanup deletes only claimed or explicitly Crabbox-owned instances and regression tests cover unrelated local VMs.

Do we have a high-confidence way to reproduce the issue?

Yes. From source, a stopped unclaimed Multipass instance reaches shouldCleanup, which returns delete before the missing-claim path; I did not run tests because this review is read-only.

Is this the best way to solve the issue?

No. The provider direction is viable, but cleanup needs a narrow ownership guard and regression coverage before the implementation is safe to merge.

Full review comments:

  • [P1] Guard cleanup to owned Multipass instances — internal/providers/multipass/backend.go:293
    Cleanup passes every multipass list result into shouldCleanup, and shouldCleanup deletes stopped instances before checking whether there is a Crabbox lease claim. With the sample inventory shape in the tests, an unrelated stopped VM such as primary would be sent to multipass delete --purge; skip unclaimed/non-Crabbox-owned instances before this call and add the stopped-unrelated regression test.
    Confidence: 0.95

Overall correctness: patch is incorrect
Overall confidence: 0.95

AGENTS.md: found and applied where relevant.

Codex review notes: model gpt-5.5, reasoning high; reviewed against 1c7342d1c002.

Label changes

Label justifications:

  • P1: The PR introduces a merge-blocking cleanup bug that can delete unrelated local VM state on a user's workstation.
  • merge-risk: 🚨 compatibility: Existing users with non-Crabbox Multipass VMs could lose or break local VM setups after adopting this provider and running cleanup.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🦞 diamond lobster and patch quality is 🧂 unranked krab.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (terminal): The PR body includes terminal live output for Multipass version, warmup, SSH sync/run, cache-volume smoke, unsupported actions-runner rejection, stop/cleanup, and empty final inventory.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes terminal live output for Multipass version, warmup, SSH sync/run, cache-volume smoke, unsupported actions-runner rejection, stop/cleanup, and empty final inventory.
Evidence reviewed

Acceptance criteria:

  • [P1] go test ./internal/providers/multipass.
  • [P1] go test ./internal/providers/...
  • [P1] go test ./internal/cli -run 'TestValidateActionsRunnerCapability|TestMultipass|TestConfigShow|TestPortableOS|TestExplicitProviderImagesSurvivePortableOSDefaults|TestAppleContainerImageFollowsOSImageDefault|TestAppleContainerExplicitImageSurvivesOSDefault|TestProviderFlag'.

What I checked:

  • Current main does not implement Multipass: Searching current main for multipass outside the changelog returned no matches, so the central feature is not already implemented. (1c7342d1c002)
  • PR adds a broad provider surface: The PR head changes 25 files with 2145 additions and adds the new provider, docs, registration, CLI/config, and tests. (d0defce8cbc7)
  • Cleanup evaluates every listed Multipass instance: Cleanup iterates all multipass list instances and calls shouldCleanup even when no local Crabbox claim exists for the instance. (internal/providers/multipass/backend.go:293, d0defce8cbc7)
  • Stopped instances are deleted before missing-claim handling: shouldCleanup returns delete for any non-running/non-ready status before it considers whether the instance has a Crabbox claim. (internal/providers/multipass/backend.go:724, d0defce8cbc7)
  • Docs define ownership as claim/name based: The new docs say Multipass ownership comes from the instance name and local lease claim, and that cleanup is for stopped Crabbox VMs, not arbitrary user-created VMs. (docs/providers/multipass.md:153, d0defce8cbc7)
  • Comparable local-provider history: Current-main history shows local provider cleanup and cache-volume work concentrated in the existing local-container/apple-container paths. (internal/providers/localcontainer/backend.go:938, 1c7342d1c002)

Likely related people:

  • Peter Steinberger: Current-main history shows Peter introduced and recently maintained comparable local provider code and release integration around the affected provider/config paths. (role: recent local-provider area contributor; confidence: high; commits: 6caae5246f02, 25ba60b020af, 4a7aff330e6f; files: internal/providers/localcontainer/backend.go, internal/providers/applecontainer/backend.go, internal/cli/config.go)
  • Vincent Koc: Git history shows a focused local-container hardening commit in the closest existing local provider area. (role: adjacent hardening contributor; confidence: medium; commits: 30ab47686986; files: internal/providers/localcontainer/backend.go)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P2 Normal priority bug or improvement with limited blast radius. labels Jun 2, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P1 Urgent regression or broken agent/channel workflow affecting real users now. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. and removed rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P2 Normal priority bug or improvement with limited blast radius. labels Jun 2, 2026
@steipete steipete merged commit 41daa62 into openclaw:main Jun 2, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P1 Urgent regression or broken agent/channel workflow affecting real users now. proof: sufficient Contributor real behavior proof is sufficient. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants