feat: add quick install script and packaging (#197)
Give bot-bottle a real distribution path so new users can install
without cloning the repo:
- pyproject.toml: full project metadata, a `bot-bottle` console-script
entry point (bot_bottle.cli:main), and package-data for the runtime
assets (Dockerfiles, egress entrypoint, netpool defaults, macos init).
Still zero runtime pip dependencies.
- install.sh: POSIX, sudo-free, idempotent bootstrapper — checks Python
>= 3.11, creates ~/.bot-bottle/{agents,bottles,contrib}, installs via
pipx (pip --user fallback), then runs `bot-bottle doctor`.
- `bot-bottle doctor`: new store-free subcommand reporting Python
version, backend availability (reuses is_backend_available rather than
hardcoding Docker), and config-dir presence. Exits non-zero when a hard
prerequisite is unmet.
- PRD prd-new-install-script and unit tests for doctor, the packaging
contract, and the install script.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
# PRD prd-new: Quick install script
|
||||
|
||||
- **Status:** Draft
|
||||
- **Author:** claude
|
||||
- **Created:** 2026-07-25
|
||||
- **Issue:** #197
|
||||
|
||||
## Summary
|
||||
|
||||
Add a proper Python package distribution (`pyproject.toml` with a
|
||||
`bot-bottle` entry point) plus a thin `install.sh` bootstrapper, so users
|
||||
can install bot-bottle with a single command instead of cloning the repo
|
||||
and invoking `cli.py` directly. A new `bot-bottle doctor` subcommand
|
||||
verifies host prerequisites after install.
|
||||
|
||||
## Problem
|
||||
|
||||
There is currently no install path for new users. The only way to run
|
||||
bot-bottle is to clone the repo and invoke `./cli.py`. This blocks any
|
||||
public demo: readers want `curl | sh` or `pipx install`, not a manual
|
||||
clone-and-configure flow. There is also no single command that tells a
|
||||
user whether their host is actually ready to run a bottle.
|
||||
|
||||
## Goals / Success Criteria
|
||||
|
||||
- `curl -fsSL <raw-url>/install.sh | sh` leaves a working `bot-bottle`
|
||||
command on PATH.
|
||||
- Python-native users can install with `pipx install bot-bottle` or
|
||||
`uv tool install bot-bottle` (once published) — or from a local
|
||||
checkout today.
|
||||
- `install.sh` validates prerequisites (Python ≥ 3.11), creates the
|
||||
`~/.bot-bottle/` config tree, installs the package, and runs
|
||||
`bot-bottle doctor`. It never installs Docker or a VM backend silently
|
||||
and never uses `sudo`.
|
||||
- `install.sh` is idempotent — safe to re-run.
|
||||
- `bot-bottle doctor` reports Python version, backend availability, and
|
||||
config-dir presence, exiting non-zero when a hard prerequisite is unmet.
|
||||
- The package keeps **zero runtime pip dependencies** (stdlib-only,
|
||||
matching the existing constraint in `AGENTS.md`).
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Bundling a Python runtime or producing a standalone binary.
|
||||
- Automatic Docker / VM-backend installation.
|
||||
- Plugin-architecture changes (issue #197 floats a containerized-plugin
|
||||
direction; that's a separate feature).
|
||||
- Publishing to a package index in this PR — the package *structure* is
|
||||
the deliverable; publishing is a follow-up step.
|
||||
|
||||
## Design
|
||||
|
||||
### Package structure (`pyproject.toml`)
|
||||
|
||||
Fill out the previously-stub `pyproject.toml` with project metadata, a
|
||||
console-script entry point, and package-data for the non-Python assets the
|
||||
runtime reads from inside the package:
|
||||
|
||||
```toml
|
||||
[project]
|
||||
name = "bot-bottle"
|
||||
version = "0.1.0"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = []
|
||||
|
||||
[project.scripts]
|
||||
bot-bottle = "bot_bottle.cli:main"
|
||||
```
|
||||
|
||||
`bot_bottle.cli:main` already exists (the `cli.py` shim calls it), so no
|
||||
refactor of the entry point is needed. `package-data` ships the container
|
||||
Dockerfiles, `egress_entrypoint.sh`, the firecracker netpool defaults, and
|
||||
the macos-container init script so an installed wheel can still build its
|
||||
sidecar/agent images.
|
||||
|
||||
### `install.sh`
|
||||
|
||||
A POSIX `sh` bootstrapper that:
|
||||
|
||||
1. Checks `python3` is present and ≥ 3.11; exits with a clear message
|
||||
otherwise.
|
||||
2. Creates `~/.bot-bottle/{agents,bottles,contrib}`.
|
||||
3. Installs via `pipx` if available, else `python3 -m pip install --user`.
|
||||
The spec defaults to the git URL and is overridable via
|
||||
`BOT_BOTTLE_INSTALL_SPEC` (used by tests / local installs).
|
||||
4. Locates the `bot-bottle` entry point (PATH or `~/.local/bin`).
|
||||
5. Runs `bot-bottle doctor` and reports the result.
|
||||
|
||||
It is idempotent and never calls `sudo`.
|
||||
|
||||
### `bot-bottle doctor`
|
||||
|
||||
A new store-free subcommand (no DB migration required) that checks and
|
||||
reports:
|
||||
|
||||
- **python** — interpreter version (hard requirement: ≥ 3.11).
|
||||
- **backend** — at least one backend available on this host
|
||||
(macos-container / firecracker / docker), reusing
|
||||
`is_backend_available()` rather than hardcoding Docker, since the
|
||||
default backend is now a VM backend. Hard requirement.
|
||||
- **config** — whether `~/.bot-bottle/` exists (advisory only; `start`
|
||||
provisions on first run).
|
||||
|
||||
Exits 0 when both hard requirements pass, non-zero otherwise.
|
||||
|
||||
## Testing strategy
|
||||
|
||||
- Unit test `bot-bottle doctor` success/failure paths with backend
|
||||
availability and Python version mocked.
|
||||
- Unit test that `pyproject.toml` parses, declares the entry point and an
|
||||
empty `dependencies` list, and that every `package-data` glob resolves
|
||||
to a file that exists on disk (guards against drift).
|
||||
- Unit test that `install.sh` is executable, POSIX-ish (`set -eu`), never
|
||||
calls `sudo`, and runs `doctor` after install.
|
||||
|
||||
## Open questions
|
||||
|
||||
- Should `version` be derived from a git tag at build time (e.g.
|
||||
`hatch-vcs`) or kept static? Static (`0.1.0`) is simpler for now.
|
||||
- Publishing target (PyPI vs. a self-hosted index) is deferred.
|
||||
Reference in New Issue
Block a user