refactor!: rename project to bot-bottle

Assisted-by: Codex
This commit is contained in:
2026-05-28 17:56:14 -04:00
parent 8875d8cc17
commit c08b09dc9f
200 changed files with 1271 additions and 1271 deletions
+22 -22
View File
@@ -8,7 +8,7 @@
Ship a second concrete `BottleBackend`
`SmolmachinesBottleBackend`, selected via
`CLAUDE_BOTTLE_BACKEND=smolmachines` — that runs each bottle inside
`BOT_BOTTLE_BACKEND=smolmachines` — that runs each bottle inside
a per-agent libkrun microVM via `smolvm`. Egress is enforced by
libkrun's TSI ("Transport Socket Interface") allowlist set to a
**single /32** — the docker IP of the per-bottle sidecar bundle
@@ -28,7 +28,7 @@ port-granular.
The Docker backend ships unchanged; this is opt-in via the existing
env-var selector. The acceptance gate is PRD 0022's
`tests/integration/test_sandbox_escape.py` running green against
`CLAUDE_BOTTLE_BACKEND=smolmachines`.
`BOT_BOTTLE_BACKEND=smolmachines`.
### Design pivot from the first draft
@@ -63,7 +63,7 @@ with significantly less code.
container-based bottles on macOS; `smolmachines-as-vm-backend.md`
evaluates smolmachines as the lifecycle wrapper. Today, the only
backend in the registry is Docker
(`claude_bottle/backend/__init__.py:_BACKENDS = {"docker": ...}`),
(`bot_bottle/backend/__init__.py:_BACKENDS = {"docker": ...}`),
and four things motivate a second one now:
- **Network reach beyond pipelock.** The threat model is a malicious
@@ -85,7 +85,7 @@ and four things motivate a second one now:
enforced by the CPU's MMU instead of namespace bookkeeping.
- **PRD 0022 is backend-agnostic by design** but currently only
exercises the Docker backend. The suite was written with
`CLAUDE_BOTTLE_BACKEND` selection in mind precisely so the
`BOT_BOTTLE_BACKEND` selection in mind precisely so the
smolmachines path could be validated against the same five
attacks. Until a second backend exists, the abstraction is
unproven.
@@ -143,7 +143,7 @@ virtio-net carve-out smolvm doesn't expose anyway).
The feature works when all of the following are observable on a
macOS host with smolmachines installed:
- `CLAUDE_BOTTLE_BACKEND=smolmachines python3 cli.py start <agent>`
- `BOT_BOTTLE_BACKEND=smolmachines python3 cli.py start <agent>`
brings up a microVM, runs claude-code inside it, and tears it
down on exit. Same y/N preflight UX as Docker — only the
resolved-runtime line differs.
@@ -160,14 +160,14 @@ macOS host with smolmachines installed:
The feature is **done** when all of the following ship:
- A new `claude_bottle/backend/smolmachines/` subpackage exists,
mirroring the layout of `claude_bottle/backend/docker/`
- A new `bot_bottle/backend/smolmachines/` subpackage exists,
mirroring the layout of `bot_bottle/backend/docker/`
(`backend.py`, `bottle.py`, `bottle_plan.py`,
`bottle_cleanup_plan.py`, `prepare.py`, `launch.py`,
`cleanup.py`, `util.py`, and a `provision/` subpackage for the
five `provision_*` methods).
- `SmolmachinesBottleBackend` registered under the
`"smolmachines"` key in `claude_bottle/backend/__init__.py:_BACKENDS`.
`"smolmachines"` key in `bot_bottle/backend/__init__.py:_BACKENDS`.
- Per-bottle Smolfile generation: a runtime-rendered TOML written
to the bottle's stage dir using smolvm 0.8.0's actual schema
(`image`, `entrypoint`, `cmd`, `env = ["K=V", …]`, `[network]
@@ -197,7 +197,7 @@ The feature is **done** when all of the following ship:
step is part of `prepare`, analogous to
`docker_mod.build_image`.
- The PRD 0022 sandbox-escape suite, run with
`CLAUDE_BOTTLE_BACKEND=smolmachines`, passes locally on a
`BOT_BOTTLE_BACKEND=smolmachines`, passes locally on a
smolmachines-capable host. The suite is updated to skip cleanly
on hosts that can't reach smolmachines (same shape as the
existing `GITEA_ACTIONS == "true"` skip), not to fail.
@@ -215,7 +215,7 @@ The feature is **done** when all of the following ship:
side. Selection stays env-driven; the manifest does not gain a
`backend` field.
- **No default-backend change.** `docker` remains the default
value of `CLAUDE_BOTTLE_BACKEND`; smolmachines is strictly
value of `BOT_BOTTLE_BACKEND`; smolmachines is strictly
opt-in until it has been load-bearing on at least one operator's
workflow for a release cycle.
- **No `--outbound-localhost-only`.** That TSI flag opens the
@@ -251,7 +251,7 @@ The feature is **done** when all of the following ship:
### In scope
- New `claude_bottle/backend/smolmachines/` subpackage with the
- New `bot_bottle/backend/smolmachines/` subpackage with the
full set of `BottleBackend` overrides.
- Smolfile generator (TOML) emitting the smolvm 0.8.0 schema:
top-level `image`, `entrypoint`, `cmd`, `env = [...]`,
@@ -267,7 +267,7 @@ The feature is **done** when all of the following ship:
- Per-bottle CA install path: the bundle's CA cert lands inside
the microVM via `smolvm machine exec` after start
(analogous to the existing `provision_ca` for Docker).
- Per-bottle docker bridge: a `claude-bottle-bundle-<slug>`
- Per-bottle docker bridge: a `bot-bottle-bundle-<slug>`
network with a /24 subnet derived from the slug hash; the
bundle gets a pinned IP at `.2` (gateway is `.1`). Pinning the
IP at start time avoids a race between the bundle's IP being
@@ -314,7 +314,7 @@ The feature is **done** when all of the following ship:
### Backend layout
```
claude_bottle/backend/smolmachines/
bot_bottle/backend/smolmachines/
__init__.py re-exports SmolmachinesBottleBackend
backend.py SmolmachinesBottleBackend façade
bottle.py SmolmachinesBottle (exec_claude / exec / cp_in / close)
@@ -339,7 +339,7 @@ design needs neither.
```
┌── macOS host ─────────────────────────────────────────────────────┐
│ │
│ ┌── per-bottle docker bridge claude-bottle-bundle-<slug> ──┐ │
│ ┌── per-bottle docker bridge bot-bottle-bundle-<slug> ──┐ │
│ │ subnet: 192.168.X.0/24 (X = hash(slug) mod 254) │ │
│ │ │ │
│ │ ┌── bundle container (pinned --ip 192.168.X.2) ────────┐ │ │
@@ -401,9 +401,9 @@ Three changes vs. the Docker backend:
transport tested. The conversion path is a registry hop: bring
up an ephemeral `registry:2.8.3` container bound to
`127.0.0.1:<random>`, `docker tag` + `docker push` into it,
`smolvm pack create --image localhost:<port>/claude-bottle:<id>`,
`smolvm pack create --image localhost:<port>/bot-bottle:<id>`,
tear down the registry. The `.smolmachine` is cached under
`~/.cache/claude-bottle/smolmachines/` keyed by the docker
`~/.cache/bot-bottle/smolmachines/` keyed by the docker
image ID, so Dockerfile changes invalidate the cache and
unchanged rebuilds skip the whole pipeline.
4. Render the per-bottle Smolfile to `stage_dir/smolfile.toml`
@@ -424,7 +424,7 @@ Three changes vs. the Docker backend:
`SmolmachinesBottleBackend.launch(plan)`:
1. Create the per-bottle docker bridge network
(`claude-bottle-bundle-<slug>` with the resolved subnet) and
(`bot-bottle-bundle-<slug>` with the resolved subnet) and
start the sidecar bundle container with `docker run --network
... --ip <bundle-ip> ...`. Wait for its daemons to bind:
pipelock on 8888, git-gate on 9418 (conditional), supervise
@@ -457,7 +457,7 @@ The `BottleSpec` dataclass and the `Bottle` ABC do not change.
### Selection wiring
In `claude_bottle/backend/__init__.py`:
In `bot_bottle/backend/__init__.py`:
```python
from .docker import DockerBottleBackend
@@ -508,7 +508,7 @@ The existing "unknown backend" `die()` path stays as-is.
(egress's port) is refused — confirming the bundle-internal
bind of egress to `127.0.0.1` works as the port-granularity
layer TSI doesn't provide.
- **PRD 0022 re-run:** with `CLAUDE_BOTTLE_BACKEND=smolmachines`,
- **PRD 0022 re-run:** with `BOT_BOTTLE_BACKEND=smolmachines`,
all five attack categories return sandbox-block markers and the
suite passes. The test code does not change beyond the env-var
flip — that's the contract the PRD 0022 abstraction was
@@ -517,7 +517,7 @@ The existing "unknown backend" `die()` path stays as-is.
## Sizing — into chunks
PRD 0024's bundle image is a prerequisite — this PRD assumes
`claude-bottle-sidecars:<pinned>` is available when chunk 3 lands.
`bot-bottle-sidecars:<pinned>` is available when chunk 3 lands.
1. **Backend skeleton + selection + Smolfile/gvproxy renderers.**
*Shipped (PR #62), but under the now-rejected gvproxy design.*
@@ -598,7 +598,7 @@ PRD 0024's bundle image is a prerequisite — this PRD assumes
enumerate active bottles (`list_active` queries the daemon).
The microVM enumeration story is `smolvm machine ls --json`;
the plan is to filter on a deterministic name prefix
`claude-bottle-<slug>` + cross-reference with on-disk metadata
`bot-bottle-<slug>` + cross-reference with on-disk metadata
under `state/<slug>/`.
8. **Loopback scoping (Docker Desktop pivot).** The original
design pinned the bundle at a docker bridge IP and set TSI's
@@ -667,5 +667,5 @@ PRD 0024's bundle image is a prerequisite — this PRD assumes
needed to exercise the smolmachines path.
- PRD 0024
(`docs/prds/0024-consolidate-sidecar-bundle.md`) — defines the
single bundle image (`claude-bottle-sidecars`) this PRD
single bundle image (`bot-bottle-sidecars`) this PRD
consumes. Prerequisite for chunk 3 of this PRD.