2026-07-10 15:00:36 +00:00
|
|
|
#cloud-config
|
|
|
|
|
users:
|
|
|
|
|
- name: claude
|
|
|
|
|
shell: /bin/bash
|
|
|
|
|
sudo: "ALL=(ALL) NOPASSWD:ALL"
|
|
|
|
|
lock_passwd: true
|
|
|
|
|
write_files:
|
|
|
|
|
- path: /home/claude/.claude/CLAUDE.md
|
|
|
|
|
owner: "claude:claude"
|
|
|
|
|
permissions: '0644'
|
|
|
|
|
defer: true
|
|
|
|
|
content: |
|
chore: finish the debrand — env vars, install dir, docs are 'box', not 'claudebox'
The 0.4.0 rename left surface leftovers the user hit through the
CLAUDEBOX_* env vars. Sweep them, drawing a clean line:
box = everything the user touches — env vars (BOX_REPO/REF/HOME/
BIN), installer messages (box-install:), the install tree
(~/.local/share/box, with the installer sweeping the old
~/.local/share/claudebox on upgrade), tool prose, and the
docs (docs/box-{design,recipe}.md).
claudebox = the GitHub repo name (URLs, the claudebox-<ref> tarball
dir, issue refs), the legacy user.claudebox=1 tag, the
old-stack cleanup code (claudenet/claude-dev/claude-isolate/
claudebox-firewall), and the .claudebox/ runbook convention
— a deliberate v1 hold, since renaming it breaks consuming
repos.
Renamed the two doc files and their links; updated drill.sh/doctor.sh
paths and BOX_REPO/BOX_REF; fixed the claude template's in-box briefing
to say 'box'. RUNS.md left as-is (append-only history). No behavior
change beyond the install-dir move, which the installer migrates.
2026-07-14 17:44:24 +00:00
|
|
|
# You are running inside a box (template: claude)
|
2026-07-10 15:00:36 +00:00
|
|
|
|
chore: finish the debrand — env vars, install dir, docs are 'box', not 'claudebox'
The 0.4.0 rename left surface leftovers the user hit through the
CLAUDEBOX_* env vars. Sweep them, drawing a clean line:
box = everything the user touches — env vars (BOX_REPO/REF/HOME/
BIN), installer messages (box-install:), the install tree
(~/.local/share/box, with the installer sweeping the old
~/.local/share/claudebox on upgrade), tool prose, and the
docs (docs/box-{design,recipe}.md).
claudebox = the GitHub repo name (URLs, the claudebox-<ref> tarball
dir, issue refs), the legacy user.claudebox=1 tag, the
old-stack cleanup code (claudenet/claude-dev/claude-isolate/
claudebox-firewall), and the .claudebox/ runbook convention
— a deliberate v1 hold, since renaming it breaks consuming
repos.
Renamed the two doc files and their links; updated drill.sh/doctor.sh
paths and BOX_REPO/BOX_REF; fixed the claude template's in-box briefing
to say 'box'. RUNS.md left as-is (append-only history). No behavior
change beyond the install-dir move, which the installer migrates.
2026-07-14 17:44:24 +00:00
|
|
|
A box is a trust-less, network-isolated, ephemeral VM created by the
|
|
|
|
|
`box` CLI. Keep this context in mind:
|
2026-07-10 15:00:36 +00:00
|
|
|
|
|
|
|
|
- **Creds-free by default.** The box starts with no Claude and no git
|
|
|
|
|
credentials. If you need to authenticate Claude, the operator runs `/login`
|
|
|
|
|
interactively. For git, the operator adds their own credentials (a PAT or
|
|
|
|
|
`gh auth login`). Never assume credentials are present; never ask for or
|
|
|
|
|
store secrets on disk beyond what the operator sets up.
|
|
|
|
|
- **Isolated.** The box reaches the public internet but nothing on the host or
|
|
|
|
|
local network. There is no inbound path.
|
|
|
|
|
- **Disposable.** Nothing here is backed up. State is discarded when the box is
|
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
|
|
|
removed; the operator persists work via git push and via `box snapshot`.
|
2026-07-10 15:00:36 +00:00
|
|
|
- **Bootstrap runbook.** If the repository you are working in contains a
|
2026-07-14 18:01:34 +00:00
|
|
|
`.box/` folder (older repos may use `.claudebox/`), read it as your setup runbook — how to install
|
2026-07-10 15:00:36 +00:00
|
|
|
dependencies, start services, template environment files, seed data, and
|
|
|
|
|
smoke-test — and follow it. It is documentation for you, not a script the
|
|
|
|
|
host runs.
|
|
|
|
|
package_update: true
|
|
|
|
|
packages:
|
|
|
|
|
- git
|
2026-07-11 11:21:30 +00:00
|
|
|
- gh
|
2026-07-10 15:00:36 +00:00
|
|
|
- curl
|
|
|
|
|
- ca-certificates
|
|
|
|
|
- gnupg
|
|
|
|
|
- ripgrep
|
|
|
|
|
- jq
|
|
|
|
|
- tmux
|
|
|
|
|
- age
|
|
|
|
|
- unzip
|
|
|
|
|
- build-essential
|
|
|
|
|
- zsh
|
|
|
|
|
runcmd:
|
|
|
|
|
- curl -fsSL https://get.docker.com | sh
|
|
|
|
|
- usermod -aG docker claude
|
|
|
|
|
- curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
|
|
|
|
|
- apt-get install -y nodejs
|
|
|
|
|
- sudo -u claude bash -lc 'curl -fsSL https://claude.ai/install.sh | bash'
|
chore: finish the debrand — env vars, install dir, docs are 'box', not 'claudebox'
The 0.4.0 rename left surface leftovers the user hit through the
CLAUDEBOX_* env vars. Sweep them, drawing a clean line:
box = everything the user touches — env vars (BOX_REPO/REF/HOME/
BIN), installer messages (box-install:), the install tree
(~/.local/share/box, with the installer sweeping the old
~/.local/share/claudebox on upgrade), tool prose, and the
docs (docs/box-{design,recipe}.md).
claudebox = the GitHub repo name (URLs, the claudebox-<ref> tarball
dir, issue refs), the legacy user.claudebox=1 tag, the
old-stack cleanup code (claudenet/claude-dev/claude-isolate/
claudebox-firewall), and the .claudebox/ runbook convention
— a deliberate v1 hold, since renaming it breaks consuming
repos.
Renamed the two doc files and their links; updated drill.sh/doctor.sh
paths and BOX_REPO/BOX_REF; fixed the claude template's in-box briefing
to say 'box'. RUNS.md left as-is (append-only history). No behavior
change beyond the install-dir move, which the installer migrates.
2026-07-14 17:44:24 +00:00
|
|
|
# 'box exec <box> -- claude …' runs through a NON-interactive shell, which
|
2026-07-13 22:22:50 +00:00
|
|
|
# reads no .bashrc/.zshrc — a PATH export there is invisible to it. The
|
|
|
|
|
# symlink makes claude reachable from every shell, interactive or not.
|
|
|
|
|
- ln -sf /home/claude/.local/bin/claude /usr/local/bin/claude
|
2026-07-10 15:00:36 +00:00
|
|
|
- echo 'export PATH="$HOME/.local/bin:$PATH"' >> /home/claude/.bashrc
|
|
|
|
|
- chsh -s /usr/bin/zsh claude
|
|
|
|
|
- sudo -u claude bash -lc 'RUNZSH=no CHSH=no sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"'
|
|
|
|
|
- echo 'export PATH="$HOME/.local/bin:$PATH"' >> /home/claude/.zshrc
|
|
|
|
|
- echo 'set -g mouse on' > /home/claude/.tmux.conf
|
|
|
|
|
- chown claude:claude /home/claude/.tmux.conf
|