Skip to content

claude: run Claude Code on a VM of any provider, not only boxes - #1212

Merged
cdalar merged 2 commits into
mainfrom
claude-any-provider
Oct 21, 2026
Merged

cdalar merged 2 commits into
mainfrom
claude-any-provider

Conversation

@cdalar

@cdalar cdalar commented Oct 21, 2026

Copy link
Copy Markdown
Owner

Summary

onctl claude was pinned to the hosted boxes provider (the "for now" in root.go). This is the follow-up docs/plans/boxes-provider.md sketched: -p now picks any provider, and onctl -p hetzner claude (aws, fc, ac, ...) spins up the project's VM through it the way onctl create does, reaches it over plain ssh at its address with the configured key, installs tmux/git/curl and Claude Code, copies the project and starts Claude in tmux -- then everything (--task, ls, fetch/push, --handoff, detach/reattach) works as on a box. Boxes stay the default when no provider is named.

  • cmd/claudevm.go (new): find/resume/create the VM, wait for ssh, and -- where the provider's user isn't root (aws ubuntu, gcp, azure) -- let root in with the same key, replacing the restricted command="echo Please login as ..." line cloud-init leaves for it (sshd takes the first matching line).
  • boxSSH gains user/host/port and a remoteURL, so fetch/push address a VM by IP (ssh:// form off port 22).
  • --size/--image are the provider's VM type and image (unset, its onctl.yaml defaults); --idle-ttl stays boxes-only (warns); --github forward needs the box image's helpers, so off a box the default becomes off and an explicit forward is an error.
  • The setup step runs first now: a VM from a plain image has no git, and the project copy / identity steps need it. It also waits for cloud-init before apt.

Testing

  • go test ./..., go vet, golangci-lint run: clean. New tests run the root-login script with a stubbed sudo (restricted line replaced, other keys kept, idempotent, PermitRootLogin fixed in drop-in and sshd_config), check remoteURL, and check the setup script only installs what's missing.
  • End to end on ac (Apple container, Ubuntu 24.04): onctl -p ac claude --detach created the container, installed tmux/git/curl and Claude Code, copied the project, set the git identity and receive.denyCurrentBranch, and started Claude in tmux; claude ls showed it running; claude fetch pulled box/main over the IP. Not run against a non-root cloud image (aws/gcp/azure): that path is covered by the script test only.

🤖 Generated with Claude Code

https://claude.ai/code/session_019DqSGUERsT3cdmSJbNH7x7

`onctl claude` was pinned to the hosted boxes provider. Now `-p` picks
any provider -- `onctl -p hetzner claude`, aws, fc, ac, ... -- and the
command creates the project's VM through it the way `onctl create`
does, reaches it over plain ssh at its address with the configured key,
installs tmux, git, curl and Claude Code, copies the project and starts
Claude in tmux, as on a box. Boxes stay the default when no provider is
named. Where the provider's user isn't root (aws's ubuntu, gcp, azure),
the first connection lets root in with the same key, replacing the
restricted line cloud-init leaves for it.

--size/--image are the provider's VM type and image (unset, its
onctl.yaml defaults); --idle-ttl stays boxes-only; --github forward
needs the box image's helpers, so off a box the default is off.
`claude ls` lists the provider's VMs and fetch/push address the VM by
IP. The setup step now runs before anything that needs git, which a
plain image lacks.

Checked end to end on ac (Apple container, Ubuntu 24.04): create, setup,
copy, tmux, ls and fetch.

Claude-Session: https://claude.ai/code/session_019DqSGUERsT3cdmSJbNH7x7
@cdalar
cdalar enabled auto-merge October 21, 2026 19:26
…n attachHint

The session's hint stays pure: the test runs with whatever provider the
package's global holds (gcp in CI), and only a real run knows it.

Claude-Session: https://claude.ai/code/session_019DqSGUERsT3cdmSJbNH7x7
@codecov

codecov Bot commented Oct 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 11.17318% with 159 lines in your changes missing coverage. Please review.
✅ Project coverage is 45.22%. Comparing base (d36c123) to head (4d89ac7).
⚠️ Report is 15 commits behind head on main.

Files with missing lines Patch % Lines
cmd/claudevm.go 9.82% 101 Missing ⚠️
cmd/claude.go 13.11% 53 Missing ⚠️
cmd/claudels.go 0.00% 4 Missing ⚠️
cmd/claudegit.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1212      +/-   ##
==========================================
+ Coverage   41.25%   45.22%   +3.96%     
==========================================
  Files          69       75       +6     
  Lines        7560     8732    +1172     
==========================================
+ Hits         3119     3949     +830     
- Misses       4441     4782     +341     
- Partials        0        1       +1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@cdalar
cdalar merged commit 55ef6be into main Oct 21, 2026
14 checks passed
@cdalar
cdalar deleted the claude-any-provider branch October 21, 2026 19:35
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

⌂ 换网址