Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down
50 changes: 49 additions & 1 deletion docs/channels/cli.md
Original file line number Diff line number Diff line change
@@ -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`

Expand Down Expand Up @@ -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/<name>` 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`).
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions docs/channels/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ uv run bub gateway --enable-channel telegram
- `run` command default session id: `<channel>:<chat_id>`
- Telegram channel session id: `telegram:<chat_id>`
- `chat` command default session id: `cli_session` (override with `--session-id`)
- `chat` command default chat id: `local`

## Outbound Delivery Surfaces

Expand Down
2 changes: 1 addition & 1 deletion docs/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
9 changes: 6 additions & 3 deletions src/bub/builtin/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Loading