Commit graph

317 commits

Author SHA1 Message Date
c1ca981f46 test: add an end-to-end drill against a real Incus
The repo has no tests and no CI, and everything in #9/#10/#13 was verified
against a stubbed incus. The interesting failures aren't in the bash — they're
in what Incus actually does, which is exactly what a stub gets wrong. So the
drill runs the real thing on a host you can format.

  A. Incus semantics — the assumptions claudebox is built on, probed directly:
     the user.claudebox=1 tag read (now on the path of every box command in
     #13), the list filter, the CSV shape, the state string, whether rename
     really refuses a running instance, the snapshot-list field order.
  B. The claudebox surface — mint, list, info, snapshot, clone-from-snapshot-of-
     a-renamed-box, rename, the escape hatch, the rm guard, the CLI contract —
     and the boundary: an instance claudebox did NOT mint has down/rm/hatch
     aimed at it, must refuse all three, and must still be standing after.
  C. Isolation — from inside a real box: public egress works, box → host is
     blocked, box → RFC1918 is dropped.

Destructive by design, and it says so before it starts: it asks for consent
(--yes to skip), and refuses outright with no TTY. Without /dev/kvm it reports
that the VM trust boundary was NOT validated rather than passing on a container.
2026-07-13 21:15:56 +00:00
Daniel Marin
0982a2d36f
Merge pull request #13 from claude-hdb/refactor/command-table
feat: make the command surface a table, add `rename` and an escape hatch
2026-07-13 21:56:45 +01:00
7d33ad8a00 feat: make the command surface a table, add rename and an escape hatch
Every incus verb is a candidate feature request, and wrapping them one at a
time grows a worse incus. This lands the rule instead: claudebox owns a command
when it must enforce an invariant incus cannot see — the user.claudebox=1
boundary, the isolation stack, or the creds-free snapshot workflow. Everything
else is incus's job, and now has a door.

- CMDS table: one row per command, carrying synopsis, preconditions, summary,
  action and success message. Dispatch AND help are rendered from it, so the
  help can no longer describe a command that doesn't exist — the drift that
  produced #8 is now impossible, not merely fixed.
- rename, via a table row: it needs the box stopped (incus won't rename a
  running instance), so it says so instead of leaking an incus error.
- `claudebox incus <box> -- <args...>`: the escape hatch. Box resolved and
  tag-checked, rest passed to incus verbatim, {} substituted, command echoed.
  Warns when it can move a box off the isolation stack.
- The boundary is now ENFORCED, not assumed: every box-taking command resolves
  through the user.claudebox=1 tag, so claudebox will not stop, rename or delete
  an instance it didn't mint.
- The rule, written into docs/claudebox-design.md.

Closes #11
2026-07-13 20:49:46 +00:00
Daniel Marin
f2dab00549
Merge pull request #10 from claude-hdb/fix/cli-help-and-contract
fix: standard help, honest flags, and an `rm` that asks first
2026-07-13 21:43:14 +01:00
Daniel Marin
754f1ca56b
Merge pull request #9 from claude-hdb/feat/list-command
feat: add `claudebox list`, with snapshot labels
2026-07-13 21:42:59 +01:00
8636d1abcb fix: standard help, honest flags, and an rm that asks first
The help was `sed -n '2,9p' "$0"` — the script scraping its own header comment
by line number — with no sections, no per-command help, no `-h`, and no
`--version`. Worse, parts of the interface it described weren't real: `--force`
was parsed and never read, so `claudebox rm work` force-deleted a running box
with no confirmation while advertising a flag that implied the bare form was
the careful one.

- usage()/help_cmd(): NAME/USAGE/COMMANDS/OPTIONS/EXAMPLES/EXIT STATUS, plus a
  page per command. `claudebox help <cmd>` and `claudebox <cmd> --help`.
- `-h`/`--help` anywhere; `--version`/`-V` (VERSION file).
- Unknown command → stderr, exit 2, and a did-you-mean by edit distance.
- Unknown options are rejected, not swallowed as positionals: `snapshot work
  --labl x` no longer names the snapshot "--labl". `--` still passes everything
  through for exec.
- `--force` is real: `rm` confirms on a TTY, refuses without one unless forced.
  BEHAVIOR CHANGE — a scripted `claudebox rm` now needs `--force`.
- Exit 2 for usage errors, 1 for runtime failures; accurate per-command usage
  strings (`exec` no longer omits `-- <cmd...>`).
- shellcheck is clean: SC2034 (dead `force`) and SC2015 both gone.

Closes #8
2026-07-13 20:41:21 +00:00
5ce2a0ae8d feat: add claudebox list and claudebox info
`status` was the only lister: misnamed, silently ignoring the `<box>` its own
help advertised, and unable to show a snapshot label — the one thing the
README's snapshot→clone flow requires you to know. Typing the obvious
`claudebox list` printed the help and exited 0.

- `list` — a table of your boxes (name, state, type, snapshot count).
- `info <box>` — detail, the snapshot labels, and the `--from` line to clone one.
- `list <box>` is a wrong guess we can answer: it points at `info`.
- `--json` passthrough; `--remote` honored; a real error on an unknown box.
- `status` stays as a deprecated alias for `list` so muscle memory keeps working.

Reads are filtered by the `user.claudebox=1` tag, so an Incus instance
claudebox didn't mint is never reported on or touched.

Closes #7
2026-07-13 20:40:17 +00:00
Daniel Marin
188c8b0f95
Add MIT License to the project 2026-07-11 21:33:51 +01:00
Daniel Marin
00e5ef524e
Merge pull request #5 from claude-hdb/fix/preinstall-gh-cli
fix: preinstall the GitHub CLI in boxes
2026-07-11 12:25:40 +01:00
1abd776850 fix: preinstall the GitHub CLI in boxes
The README's auth flow tells operators to run `gh auth login`, but the
cloud-init package set never installed gh — a fresh box couldn't follow
its own instructions. Debian 13 ships gh natively, so a plain packages
entry suffices.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 11:21:30 +00:00
Daniel Marin
34158aeafa
Merge pull request #4 from claude-hdb/feat/drop-name-prefix
feat: drop the claude- instance-name prefix
2026-07-10 18:11:30 +01:00
d956614269 feat: drop the claude- instance-name prefix; tag boxes instead
Instance names now equal the box name (claudebox new --name work -> 'work',
not 'claude-work'). To still tell claudebox's instances apart from any other
incus instances, tag each on creation with user.claudebox=1 and filter status
+ teardown by that tag instead of a name prefix. Clones (new --from) inherit
the tag.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 17:09:45 +00:00
Daniel Marin
0628ac81b6
Merge pull request #2 from claude-hdb/fix/install-public-canonical
fix: install from the public canonical repo
2026-07-10 17:00:21 +01:00
e175c416c3 fix: install from the public canonical heavy-duty/claudebox
The fork claude-hdb/claudebox is private, so an anonymous 'curl | bash' against
it 401s. Point the installer default and the README one-liner at the public
canonical repo so the install flow works without auth.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 15:08:18 +00:00
Daniel Marin
95ba6abbe2
Merge pull request #1 from claude-hdb/import-claudebox
Import claudebox: creds-free, trust-less Claude Code VMs
2026-07-10 16:01:39 +01:00
0c9971ecf8 Import claudebox: creds-free, trust-less Claude Code VMs
A CLI that mints trust-less, network-isolated Incus VMs with Claude Code
installed. Boxes are strictly creds-free — the operator logs into Claude
interactively inside; authenticated state is reused via snapshots. The tool
knows nothing about projects; a repo ships an optional agent-facing .claudebox/
runbook that Claude reads.

- bin/claudebox: new/shell/exec/snapshot/restore/down/start/rm/status; creds-free
  'new' (fresh launch or clone via --from <src>[/<snap>]).
- cloud-init: global ~/.claude/CLAUDE.md self-describing the box + .claudebox/ runbook.
- install.sh: curl-pipe-bash installer.
- host/: Incus isolation stack (claudenet + claude-isolate ACL + claude-dev
  profile + firewall).
- docs/: design + .claudebox/ convention.

Initial canonical import (prototyped separately; re-homed onto the heavy-duty fork).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 15:00:36 +00:00
Daniel Marin
ec41ade3fc
Create README.md 2026-07-10 15:53:40 +01:00