diff --git a/README.md b/README.md index 1b2bb25..6fee60e 100644 --- a/README.md +++ b/README.md @@ -69,20 +69,30 @@ claudebox new --name feature --from work/authed # clone the authed state into preserving isolation. You can also `claudebox new --name x --from work` to clone a box's live state, or roll a box back with `claudebox restore work authed`. +Forgotten what you called a checkpoint? `claudebox info work` prints the box's +snapshot labels and the `--from` line to clone one. + ## Commands ``` claudebox new --name [--from [/]] [--vm|--container] [--remote r] +claudebox list # list your boxes +claudebox info # one box: state, IP, snapshot labels claudebox shell # enter as the claude user claudebox exec -- # run a command in the box claudebox snapshot [label] # checkpoint (label defaults to manual-) claudebox restore # roll back to a snapshot claudebox down # stop (state kept; `start` resumes) claudebox start # start a stopped box -claudebox rm # delete the box (irreversible; snapshot first) -claudebox status # list boxes +claudebox rm [--force] # delete the box + its snapshots (asks first) +claudebox status # deprecated alias for `list` +claudebox help [] # full help, or one command's page ``` +Every command takes `--help`, and options come after the command +(`claudebox list --json`). Exit status: `0` ok, `1` it went wrong, `2` you asked +wrong. + `new` fresh-launches from cloud-init, or with `--from` clones an existing box or snapshot. VM mode (`--vm`, the default where `/dev/kvm` exists) is the trust-less target; container mode (auto-fallback, `security.nesting=true`) is for hosts diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..0ea3a94 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.2.0 diff --git a/bin/claudebox b/bin/claudebox index 47c2d3b..1e1017d 100755 --- a/bin/claudebox +++ b/bin/claudebox @@ -1,35 +1,298 @@ #!/usr/bin/env bash # claudebox — trust-less, isolated Incus VMs with Claude Code, creds-free. -# claudebox new --name [--from [/]] [--remote r] [--vm|--container] -# claudebox shell|down|start|status|rm -# claudebox exec -- -# claudebox snapshot [label] -# claudebox restore -# Boxes carry NO secrets: log into Claude interactively inside ('claude' then -# /login). Reuse an authenticated box via 'snapshot' + 'new --from'. +# The help text lives in usage()/help_cmd(), not in this comment. set -euo pipefail root="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")/.." && pwd)" -remote=""; mode="auto"; name=""; from=""; force=0 +remote=""; mode="auto"; name=""; from=""; force=0; json=0; want_help=0 + +die() { echo "claudebox: $*" >&2; exit 1; } # 1 = it went wrong +usage_error() { echo "claudebox: $*" >&2; echo "try 'claudebox help'." >&2; exit 2; } # 2 = you asked wrong +version() { echo "claudebox $(cat "$root/VERSION" 2>/dev/null || echo unknown) ($root)"; } + +COMMANDS="new list info shell exec snapshot restore down start rm status help" +is_command() { case " $COMMANDS " in *" $1 "*) return 0 ;; *) return 1 ;; esac; } + +synopsis_of() { + case "$1" in + new) echo "claudebox new --name [--from [/]] [--vm|--container]" ;; + list) echo "claudebox list [--json]" ;; + info) echo "claudebox info [--json]" ;; + shell) echo "claudebox shell " ;; + exec) echo "claudebox exec -- " ;; + snapshot) echo "claudebox snapshot [