Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 0 additions & 55 deletions .github/workflows/publish.yml

This file was deleted.

28 changes: 21 additions & 7 deletions .github/workflows/release.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,12 +8,18 @@ on:
permissions:
contents: read

# Prerequisite: each npm package must have this workflow configured as a
# trusted publisher on npmjs.com (package → Settings → Trusted Publishers).
# Packages are submitted to npm staging here; run `npm stage approve <id>`
# with 2FA to make them live.

jobs:
release:
name: Build & Pre-release
name: Build, Stage & Release
runs-on: macos-latest
permissions:
contents: write
id-token: write # for OIDC trusted publishing + provenance
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
Expand All@@ -22,8 +28,12 @@ jobs:

- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 22
node-version: 22.14.0
package-manager-cache: false
registry-url: https://registry.npmjs.org

- name: Upgrade npm (staged publishing requires npm ≥ 11.15.0)
run: npm install -g npm@11.15.0

- run: npm ci

Expand DownExpand Up@@ -57,16 +67,20 @@ jobs:
- name: Pack npm tarballs
run: npm pack --workspaces

- name: Create pre-release
- name: Stage to npm
run: |
shopt -s nullglob
for tarball in ./*.tgz; do
npm stage publish "$tarball" --access public --provenance
done

- name: Create GitHub release
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release create "$GITHUB_REF_NAME" \
--prerelease \
--title "$GITHUB_REF_NAME" \
--generate-notes \
packages/vmm/dist/vmm \
./*.tgz
--generate-notes

- name: Cleanup keychain
if: always()
Expand Down
45 changes: 32 additions & 13 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

161 changes: 161 additions & 0 deletions packages/cli/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
# sandboxctl

A CLI tool that spins up a Linux sandbox VM on your machine for local development. Powered by QEMU and Ubuntu cloud images — no Docker, no VirtualBox, no cloud account required.

## Requirements

- **macOS or Linux** (Windows support is experimental)
- **macOS or Linux**: QEMU — `brew install qemu` / `sudo apt install qemu-system qemu-utils`
- **Node.js** 18+

## Agent Skill

sandboxctl ships an agent skill for Claude Code, Cursor, Codex, and other AI coding assistants. It analyzes your project and writes a `sandbox.json` for you — detecting runtimes, port requirements, and appropriate VM sizing automatically.

Install it with:

```sh
npx skills add inputforge/sandboxctl
```

Once installed, ask your assistant: _"create a sandbox for this project"_ and it will run the full setup wizard inline.

## Quickstart

Run in any project directory:

```sh
npx sandboxctl
```

This launches a setup wizard that checks prerequisites, walks you through configuration, and optionally boots the VM — all in one session.

Or install globally for day-to-day use:

```sh
npm install -g sandboxctl
sandboxctl # setup wizard
sandboxctl ssh # shell inside the VM
```

## Commands

```
sandboxctl <command>

Commands:
init Configure sandbox.json interactively
start Build (if needed) and boot the sandbox VM
stop Gracefully shut down the VM
destroy Delete the VM and all associated files
status Show sandbox name, status, SSH port, and uptime
ssh Open an interactive SSH session into the VM
send Sync project files from host → VM (uses rsync or tar)
receive Sync files from VM → host
forward [port] Forward a port: <guest-port> or <host-port>:<guest-port>
doctor Check that required dependencies are installed
```

### No-argument wizard

Running `sandboxctl` with no arguments starts the setup wizard:

1. **Prerequisite check** — verifies the required backend (Lima on macOS, QEMU on Linux) is installed and prints the install command if not
2. **Configuration** — runs the `init` prompts; if `sandbox.json` already exists all fields are pre-populated with current values so you can press Enter to keep them
3. **Boot offer** — asks whether to start the VM immediately after saving config

### `doctor`

Checks that the required binaries are present for your platform and reports the install command for anything missing:

```sh
sandboxctl doctor
```

### First `start`

On first boot, the tool will:

1. Download the Ubuntu cloud image (cached in `~/.local/share/sandboxctl/images/`)
2. Create a QCOW2 overlay disk
3. Build a cloud-init seed image with your SSH public key and install script
4. Boot the VM in the background
5. Stream the package install log until `==> Done.`
6. Rsync your project files into the VM

Subsequent `start` calls skip provisioning and boot in seconds.

## Configuration — `sandbox.json`

Generated by `sandboxctl init` (or the wizard). You can also write it by hand:

```json
{
"ubuntu": "24.04",
"vm": {
"cpus": 4,
"memory": "4G",
"disk": "20G"
},
"packages": {
"nodejs": { "enabled": true, "version": "22" },
"bun": { "enabled": false },
"python": { "enabled": true },
"go": { "enabled": false }
},
"send": {
"remotePath": "/home/ubuntu/my-project"
},
"ports": [{ "host": 3000, "guest": 3000, "protocol": "tcp" }]
}
```

### Supported packages

| Package | Versioned | Default |
| -------------- | --------- | ------- |
| Node.js | yes | 22 |
| Bun | yes | 1.3.12 |
| Python 3 | no | — |
| Java (OpenJDK) | yes | 21 |
| Go | yes | 1.24.3 |
| Ruby | no | — |
| PHP | no | — |
| Swift | yes | 6.0.3 |

### Port forwarding

`ports` is an optional array of host↔guest port mappings. Useful for accessing a dev server running inside the VM.

### Config change rules

| Change | Action required |
| --------------------------- | ------------------- |
| `ubuntu` version | `destroy` + `start` |
| `packages` | `destroy` + `start` |
| `vm.disk` (grow only) | `stop` + `start` |
| `vm.cpus` / `vm.memory` | `stop` + `start` |
| `ports` / `send.remotePath` | `stop` + `start` |

## File sync

`send` pushes your current directory to the VM (respects `.gitignore`). It uses `rsync` when available and falls back to `tar` over SSH.

```sh
sandboxctl send # host → VM
sandboxctl receive # VM → host
```

## Providers

sandboxctl supports multiple VM backends via the `provider` field in `sandbox.json`:

| Provider | Description | Platform |
| ----------------- | ------------------------------ | ------------ |
| `local` (default) | QEMU — works everywhere | macOS, Linux |
| `vmm` | Apple Virtualization framework | macOS only |
| `ec2` | AWS EC2 | any |

## License

MIT
Loading
Loading