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
+24 -24
View File
@@ -14,7 +14,7 @@ second backend ships in this PRD.
## Problem
Today, "how to launch a bottle" is spread across roughly six modules
(`claude_bottle/cli/start.py`, `pipelock.py`, `network.py`, `ssh.py`,
(`bot_bottle/cli/start.py`, `pipelock.py`, `network.py`, `ssh.py`,
`skills.py`, `docker.py`), each shelling out to `docker` directly via
`subprocess.run(["docker", ...])`. That coupling means:
@@ -57,22 +57,22 @@ The feature works when all of the following are observable:
The feature is **done** when all of the following ship:
- A new `claude_bottle/backend/` package exists with abstract base
- A new `bot_bottle/backend/` package exists with abstract base
classes (`BottleBackend`, `BottlePlan`, `BottleCleanupPlan`,
`Bottle`) plus a `claude_bottle/backend/docker/` subpackage
`Bottle`) plus a `bot_bottle/backend/docker/` subpackage
containing the `DockerBottleBackend` implementation.
- `DockerBottleBackend.launch(plan)` returns a context manager
yielding a `Bottle` handle exposing `exec_claude(argv, *, tty=True)`,
`cp_in(host, ctr)`, and teardown on context exit.
- Every existing `subprocess.run(["docker", ...])` call in
`cli/start.py`, `pipelock.py`, `network.py`, `ssh.py`, and
`skills.py` either moves into `claude_bottle/backend/docker/` or is
`skills.py` either moves into `bot_bottle/backend/docker/` or is
called from it. No top-level CLI code references `docker` directly.
- `bottles[].runtime` is removed from the manifest schema, the
dataclass in `manifest.py`, the example manifest, and any README /
docs references. `require_runsc()` in the old top-level
`claude_bottle/docker.py` is deleted.
- A single env var, `CLAUDE_BOTTLE_BACKEND` (default `"docker"`),
`bot_bottle/docker.py` is deleted.
- A single env var, `BOT_BOTTLE_BACKEND` (default `"docker"`),
selects the backend. Unknown values die at startup with a list of
known backends.
- The y/N preflight in `cli.py` includes the resolved Docker runtime
@@ -97,8 +97,8 @@ The feature is **done** when all of the following ship:
### In scope
- New `claude_bottle/backend/` package containing the abstract types
and the registry, plus a `claude_bottle/backend/docker/` subpackage
- New `bot_bottle/backend/` package containing the abstract types
and the registry, plus a `bot_bottle/backend/docker/` subpackage
containing the Docker implementation.
- The `Bottle`, `BottleBackend`, `BottlePlan`, and `BottleCleanupPlan`
abstract base classes; `BottleSpec` data carrier; and
@@ -136,10 +136,10 @@ The feature is **done** when all of the following ship:
### New services / components
A new package, `claude_bottle/backend/`, with an abstract base layer
A new package, `bot_bottle/backend/`, with an abstract base layer
and a Docker subpackage:
- **`claude_bottle/backend/__init__.py`** — Defines the abstract base
- **`bot_bottle/backend/__init__.py`** — Defines the abstract base
classes and the backend registry. `BottleSpec` carries the
CLI-supplied intent; the abstract `BottlePlan` and
`BottleCleanupPlan` are the prepared-but-not-launched outputs of
@@ -165,14 +165,14 @@ and a Docker subpackage:
`provision_git`); subclasses implement those four rather than
overriding `provision` itself.
Selection reads `CLAUDE_BOTTLE_BACKEND` (default `"docker"`).
Selection reads `BOT_BOTTLE_BACKEND` (default `"docker"`).
Unknown values call `die()` with the list of known backends:
```python
def get_bottle_backend() -> BottleBackend: ...
```
- **`claude_bottle/backend/docker/`** — Subpackage with the Docker
- **`bot_bottle/backend/docker/`** — Subpackage with the Docker
implementation, split into:
- `backend.py` — `DockerBottleBackend`, owning all five abstract
methods (`prepare`, `launch`, `prepare_cleanup`, `cleanup`,
@@ -196,49 +196,49 @@ and a Docker subpackage:
- `pipelock.py` — `DockerPipelockProxy` (the sidecar start/stop
lifecycle) and Docker-specific naming helpers. The backend-neutral
yaml + allowlist resolution stays in the top-level
`claude_bottle/pipelock.py`.
`bot_bottle/pipelock.py`.
- `util.py` — Docker-specific helpers (slugify, image/container
existence checks, `runsc_available`).
### Existing code touched
- **`claude_bottle/cli/start.py`** — replace the inline docker
- **`bot_bottle/cli/start.py`** — replace the inline docker
orchestration with `backend = get_bottle_backend(); plan =
backend.prepare(spec, stage_dir=...); with backend.launch(plan) as
bottle: bottle.exec_claude(...)`. The y/N preflight is rendered by
`plan.print(...)`.
- **`claude_bottle/manifest.py`** — drop the `runtime` field from the
- **`bot_bottle/manifest.py`** — drop the `runtime` field from the
Bottle dataclass and its validation. Existing manifests with
`runtime: "runsc"` produce a clear "no longer supported; gVisor is
now auto-detected by the backend; remove the 'runtime' field" error.
- **`claude_bottle/docker.py`** — module deleted. `require_runsc()`,
- **`bot_bottle/docker.py`** — module deleted. `require_runsc()`,
`slugify()`, `image_exists()`, `container_exists()`, the
`build_image` / `build_image_with_cwd` helpers, and `require_docker`
all migrate into `claude_bottle/backend/docker/util.py` (or
all migrate into `bot_bottle/backend/docker/util.py` (or
`backend.py`).
- **`claude_bottle/pipelock.py`** — keeps the allowlist resolution and
- **`bot_bottle/pipelock.py`** — keeps the allowlist resolution and
YAML generation. Becomes a thin abstract class (`PipelockProxy`)
exposing `prepare` (writes the yaml) plus abstract `start` / `stop`
methods. The Docker-specific subclass `DockerPipelockProxy` lives
under `backend/docker/pipelock.py`.
- **`claude_bottle/network.py`** — folds entirely into
- **`bot_bottle/network.py`** — folds entirely into
`backend/docker/network.py`. No top-level network module remains.
- **`claude_bottle/ssh.py`** and **`claude_bottle/skills.py`** —
- **`bot_bottle/ssh.py`** and **`bot_bottle/skills.py`** —
absorbed into `DockerBottleBackend` as `provision_ssh` and
`provision_skills`. The host-side file-tree generation stays as
private helpers on the backend class.
- **`claude_bottle/env.py`** (renamed from `env_resolve.py`) —
- **`bot_bottle/env.py`** (renamed from `env_resolve.py`) —
`resolve_env(manifest, agent) -> ResolvedEnv` returns
`forwarded: list[str]` (names whose values were exported into
`os.environ` for inheritance) and `literals: dict[str, str]` (name
→ verbatim value). The Docker backend translates the result into
`--env-file` content + `-e NAME` argv fragments.
- **`claude_bottle/util.py`** — top-level cross-backend helpers
- **`bot_bottle/util.py`** — top-level cross-backend helpers
(`expand_tilde`, `is_ipv4_literal`). Backend-specific helpers live
in their backend's `util.py`.
- **`claude-bottle.example.json`** — remove the `runtime` field from
- **`bot-bottle.example.json`** — remove the `runtime` field from
any example bottle.
- **`README.md`** — note `CLAUDE_BOTTLE_BACKEND` and the runsc
- **`README.md`** — note `BOT_BOTTLE_BACKEND` and the runsc
auto-detect; remove any mention of `runtime: "runsc"` as a manifest
field.