feat: vm-side CLI (claw) with tool abstraction and signal cleanup#19
Merged
feat: vm-side CLI (claw) with tool abstraction and signal cleanup#19
Conversation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New VM-side CLI that replaces bash provisioning scripts: - `claw provision system|tools|openclaw` — idempotent provisioning - `claw doctor` — structured health checks with --json support - `claw checkpoint` — atomic signal file for host-side auto-commit Adds CHECKPOINT_REQUEST_FILE and CLAW_BIN_PATH constants to @clawctl/types. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Rewrite provision.ts to deploy claw binary and call `claw provision` subcommands instead of bash scripts - Simplify verify.ts to delegate to `claw doctor --json` - Add `clawctl watch` command for checkpoint-driven auto-commits - Add `build:claw` script to root package.json - Remove dead provisioning template files and their tests - Update templates/index.ts exports Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The VM mounts the instance project directory at /mnt/project, not the clawctl repo. Use driver.copy() (limactl copy) to transfer the binary from the host, then sudo mv to /usr/local/bin. Resolves the binary path from the monorepo root via import.meta.dir, with a clear error message if the binary hasn't been built yet. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
clawctl-dev now builds the VM-side claw binary (cross-compiled for linux-arm64) before launching the CLI. The build takes ~0.5s and ensures the binary is always up to date during development. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
exec() now forwards stdout/stderr in real-time by default so the user can follow installation progress (apt-get, homebrew, tailscale, etc.). Short check commands (version queries, dpkg -l, systemctl is-active) pass `quiet: true` to suppress their output. In JSON mode, forwarded output goes to stderr to keep the JSON envelope on stdout clean. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…arn-only claw is a compiled standalone binary — bun is not needed in the VM. service-gateway and openclaw-doctor checks are now warn-only since they only pass after bootstrap/onboarding, not after provisioning. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract all raw exec() calls from provision commands and doctor into
typed tool wrappers in tools/. Each module (apt, systemd, node,
tailscale, homebrew, op-cli, openclaw) encapsulates interactions with
one system tool. Provision commands become thin orchestrators.
- Unify SystemStep/ToolStep/OpenclawStep into ProvisionResult
- Replace exec("rm",...) with fs/promises where possible
- Replace awk passwd parsing with pure TypeScript
- Delete helpers.ts (distributed across tool modules)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract cleanup logic into shared cleanup.ts module with: - cleanupVM(): idempotent VM + project dir removal - onSignalCleanup(): register SIGINT/SIGTERM handlers Headless path: signal handlers active during provisioning window, removed in finally block. Wizard path: track creation state via mutable ref passed to App. Ink captures Ctrl+C as raw input (not SIGINT), so we detect interrupted exits via the waitUntilExit() result. SIGTERM handled via process signal listener. Handlers removed once the wizard exits normally to avoid cleaning up during retryable onboarding. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
verifyProvisioning() was dropping the `warn` field from doctor checks, so headless.ts treated service-gateway (warn-only, expected inactive before bootstrap) as a hard failure — aborting provisioning and cleaning up the VM. Preserve the warn flag in VerifyResult and skip warnings in the headless verify loop. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Create docs/vm-cli.md: dedicated doc explaining why we use a compiled binary inside the VM instead of shell scripts, the tool abstraction layer, ProvisionResult protocol, cross-tool composition, and how to add new tools - Update docs/architecture.md: new directory structure reflecting the monorepo layout, add internal CLI as a key design decision, update provisioning flow diagrams, update templates section - Rewrite docs/vm-provisioning.md: replace shell-script-based content with the current claw-based approach, document each provisioning stage, idempotency guarantees, verification, and cleanup on failure - Update CLAUDE.md: add vm-cli to workspace structure, add key directories, add internal CLI conventions section, add build:claw command Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nings Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ings Replace ad-hoc orchestrator functions with declarative ProvisionStage constants and a shared runStage() runner. Replace hardcoded warn: true flags in doctor checks with availableAfter lifecycle phases, computed via the new --after flag. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…isioning Update references from "orchestrators" to "stages", document the --after flag in architecture flows, and add stage/lifecycle conventions to CLAUDE.md. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…atterns Move detailed stage and lifecycle documentation out of CLAUDE.md (which should stay concise) into module-level comments in stages.ts, doctor.ts, and constants.ts where the patterns are declared. Fix last "orchestrator" reference in vm-cli.md. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
@clawctl/vm-clipackage — a CLI (claw) that runs inside the Lima VM and handles provisioning, health checks, and checkpoint signalingtools/abstraction layer: typed wrappers for each system tool (apt, systemd, node, tailscale, homebrew, op-cli, openclaw) so provision commands are thin orchestratorsTest plan
bun test— 244 passbun run lint— cleanbun run build:claw— binary compilesclawctl-dev create --config ...— full end-to-end provisioning🤖 Generated with Claude Code