From c912eb163c0aa3ffc9d160806782194cf2e37aad Mon Sep 17 00:00:00 2001 From: Frost Ming Date: Sat, 11 Apr 2026 08:05:07 +0800 Subject: [PATCH] feat: add install and update commands to CLI and enhance documentation Signed-off-by: Frost Ming --- README.md | 5 ++++- docs/channels/cli.md | 50 +++++++++++++++++++++++++++++++++++++++++- docs/channels/index.md | 1 + docs/features.md | 2 +- src/bub/builtin/cli.py | 9 +++++--- 5 files changed, 61 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 1472213e..a9f6e8d3 100644 --- a/README.md +++ b/README.md @@ -96,11 +96,14 @@ See the [Extension Guide](https://bub.build/extension-guide/) for hook semantics | `bub chat` | Interactive REPL | | `bub run MESSAGE` | One-shot turn | | `bub gateway` | Channel listener (Telegram, etc.) | +| `bub install` | Install or sync Bub plugin deps | +| `bub update` | Upgrade Bub plugin deps | | `bub login openai` | OpenAI Codex OAuth | -| `bub hooks` | Print hook-to-plugin bindings | Lines starting with `,` enter internal command mode (`,help`, `,skill name=my-skill`, `,fs.read path=README.md`). +`bub hooks` still exists for diagnostics, but it is hidden from top-level help. `bub install` and `bub update` manage a separate uv project for Bub plugins, defaulting to `~/.bub/bub-project` or `BUB_PROJECT`. + ## Configuration | Variable | Default | Description | diff --git a/docs/channels/cli.md b/docs/channels/cli.md index 4b2a944a..ab88c56d 100644 --- a/docs/channels/cli.md +++ b/docs/channels/cli.md @@ -1,6 +1,6 @@ # CLI -`bub` exposes four main commands (`run`, `gateway`, `chat`, `login`) plus one hidden one (`hooks` for diagnostics). +`bub` exposes six public command groups: `run`, `gateway`, `chat`, `install`, `update`, and `login`. It also keeps one hidden diagnostic command: `hooks`. ## `bub run` @@ -65,6 +65,52 @@ uv run bub chat uv run bub chat --chat-id local --session-id cli:local ``` +`chat` reuses the top-level `--workspace/-w` option. By default it sets `chat_id=local`, keeps the channel as `cli`, and leaves the underlying CLI channel session id at `cli_session` unless you pass `--session-id`. + +## `bub install` + +Install packages into Bub's managed plugin project, or sync that project if no package spec is given. + +```bash +uv run bub install +uv run bub install my-plugin +uv run bub install example-owner/example-bub-plugin@main +uv run bub install https://github.com/example/bub-plugin.git +``` + +Options and behavior: + +- `--project`: path to the uv project used for Bub-managed plugins +- `BUB_PROJECT`: environment variable equivalent of `--project` +- default project path: `~/.bub/bub-project` +- if the project does not exist yet, Bub creates a bare uv app project automatically +- Bub must be installed inside a virtual environment before `install` or `update` can run + +Accepted spec forms: + +- `https://...` or `git@...`: installed as a Git requirement +- `owner/repo` or `owner/repo@ref`: expanded to a GitHub repository URL +- `name`: passed through as a normal package requirement +- `name@ref`: resolved from `bub-contrib` as `packages/` at the given Git ref + +If no package specs are provided, `install` runs a project sync instead of adding anything new. + +## `bub update` + +Update dependencies inside Bub's managed plugin project. + +```bash +uv run bub update +uv run bub update my-plugin another-plugin +``` + +Behavior: + +- with no package names, upgrades the whole project +- with package names, upgrades only the selected dependencies +- uses the same `--project` / `BUB_PROJECT` location as `install` +- creates the managed project first if it does not exist yet + ## `bub login` Authenticate with OpenAI Codex OAuth and persist the resulting credentials under `CODEX_HOME` (default `~/.codex`). @@ -98,6 +144,8 @@ BUB_MODEL=openai:gpt-5-codex BUB_API_FORMAT=responses uv run bub chat ## Notes - `--workspace` is parsed before the subcommand, for example `uv run bub --workspace /repo chat`. +- `install` and `update` operate on Bub's managed plugin project, not on the current workspace. +- `uninstall()` exists in the builtin module but is not currently exposed as a public CLI command. - `run` prints each outbound as: ```text diff --git a/docs/channels/index.md b/docs/channels/index.md index 3219df95..b1d76756 100644 --- a/docs/channels/index.md +++ b/docs/channels/index.md @@ -32,6 +32,7 @@ uv run bub gateway --enable-channel telegram - `run` command default session id: `:` - Telegram channel session id: `telegram:` - `chat` command default session id: `cli_session` (override with `--session-id`) +- `chat` command default chat id: `local` ## Outbound Delivery Surfaces diff --git a/docs/features.md b/docs/features.md index 9b81848d..2c1f4ab0 100644 --- a/docs/features.md +++ b/docs/features.md @@ -17,7 +17,7 @@ Context is reconstructed from tape records, not accumulated in session state. ## Builtin Batteries -- **CLI**: `run`, `chat`, `gateway`, `login`, `hooks` via Typer. +- **CLI**: `run`, `chat`, `gateway`, `install`, `update`, and `login` via Typer; hidden `hooks` remains available for diagnostics. - **Model runtime**: agent loop with tool use, backed by [Republic](https://github.com/bubbuild/republic). - **Comma commands**: `,help`, `,skill`, `,fs.read`, etc. Unknown commands fall back to shell. - **Channels**: `cli` and `telegram` ship as defaults. diff --git a/src/bub/builtin/cli.py b/src/bub/builtin/cli.py index f8c474a7..e2fa625c 100644 --- a/src/bub/builtin/cli.py +++ b/src/bub/builtin/cli.py @@ -148,9 +148,12 @@ def _build_requirement(spec: str) -> str: return f"git+https://github.com/{repo}.git{ref}" else: # Assume it's a package name in bub-contrib - name, *rest = spec.partition("@") - ref = "".join(rest) - return f"git+{BUB_CONTRIB_REPO}{ref}#subdirectory=packages/{name}" + name, has_ref, ref = spec.partition("@") + if has_ref: + ref = f"@{ref}" + return f"git+{BUB_CONTRIB_REPO}{ref}#subdirectory=packages/{name}" + else: # PyPI package name + return name def _ensure_project(project: Path) -> None: