Commit graph

12 commits

Author SHA1 Message Date
github-actions[bot]
a17903f07c chore: bump main to 0.9.1-dev — a dev install must not impersonate 0.9.0 2026-07-21 18:06:51 +00:00
dan-claude-bot
991acd2ba6 release: 0.9.0 2026-07-21 17:42:38 +00:00
github-actions[bot]
15b67d938e chore: bump main to 0.8.1-dev — a dev install must not impersonate 0.8.0 2026-07-19 23:04:15 +00:00
Claude
8661067468 release: 0.8.0
Stamp the ceremony: VERSION 0.7.1-dev -> 0.8.0 (bare), and rewrite
'## Unreleased' into '## 0.8.0 — 2026-07-19' with an empty '## Unreleased'
put back above it — the re-arm half of the two-edit stamp (#108), so main is
never disarmed between this merge and the automatic -dev bump.

0.8.0 rather than 0.7.1: the section carries an '### Added' (#96, the merge
door), and #105 changes 'box restore' to ask before it destroys — which
breaks non-interactive callers that did not pass --force.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 21:33:05 +00:00
dan-claude-bot
0fbd60e6ff chore: bump main to 0.7.1-dev — a dev install must not impersonate 0.7.0
The post-release step of the ceremony (#83, the 0.6.1-dev precedent):
versions/ names install trees after VERSION, so a main install without
the bump would land in versions/0.7.0 and impersonate the released tree.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 15:48:12 +00:00
dan-claude-bot
07c0edd60a release: 0.7.0
The first release cut by the flow itself (#83): VERSION leaves 0.6.1-dev
for 0.7.0 and the Unreleased section is stamped with today's date. The
whole surface was drilled twice on 2026-07-19 — before and after the #92/
#93/#94 round — 85/0 on real incus both times, all three install channels
live, and the ceremony itself rehearsed end to end on a scratch fork
(mismatch and missing-section guards firing, the real path publishing).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 13:44:32 +00:00
dan-claude-bot
7044f8e0c1 chore: bump main to 0.6.1-dev — a dev install must not impersonate 0.6.0 (#83)
0.6.0 is released; the versioned layout names install trees after
the tree's own VERSION file — so a main install at VERSION 0.6.0
would land in versions/0.6.0, impersonating the released tree: the
converging no-op then refuses to update it, and BOX_REINSTALL=1
silently swaps a release tree for a dev one under the same name. A
-dev version keeps dev installs side by side with releases. The
post-release bump is now part of the release ritual (CONTRIBUTING).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 22:17:51 +00:00
Dan
77599ab3ee chore: bump version for cleanness 2026-07-18 14:39:45 +01:00
claude-hdb
5deef69621 chore: VERSION → 0.5.0 (templates, migrate-host, expose) 2026-07-14 16:13:08 +00:00
claude-hdb
c11f3d7552 feat!: claudebox becomes box — the Claude box is one template among several
The tool underneath was already generic: a thin, honest wrapper over
Incus. What was Claude-specific was welded on — one image, one profile,
one cloud-init file, one hardcoded 'sudo -u claude'. The weld is now a
template.

The mechanic: 'box new' stamps the template's identity onto the
instance (user.box=1, user.box.template, user.box.user); shell/exec/
tmux read the user back off the instance, and 'incus copy' carries
user.* keys (audit B2), so a clone knows what it is without consulting
the template. Templates are box.env (parsed against a strict allowlist,
never sourced — no key for a network exists, on purpose) plus a
verbatim cloud-init. Every template launches with the shared box-net
profile: the isolated NIC and root disk, nothing template-controlled —
resources land per-instance from box.env, overridable via BOX_CPU/
BOX_MEMORY/BOX_DISK (which is also how the drill shrinks boxes on a
small host now that profile edits can't).

The three open calls, taken as recommended: clean cut at 0.4.0 (no
claudebox shim; the installer retires the old symlink); default
template = claude (muscle memory survives); repo stays heavy-duty/
claudebox, binary is box.

Compat is the tag, not the name: resolve_box and list honor the legacy
user.claudebox=1 forever, and the legacy tag maps to the claude user —
a pre-rename box lists, shells, clones, unchanged.

Deliberate divergence from #17's table: the host-stack resource names
(claudenet, claude-isolate, nft tables, claudebox-firewall.*) are NOT
renamed — they are host-internal, invisible to users, and renaming
them breaks every provisioned host for zero user-visible gain.
claude-dev is no longer created; setup-host creates box-net, teardown
removes both.

Closes #17
2026-07-14 14:22:50 +00: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
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