CLI
This page lists every command exposed by the bub CLI entry point. Commands are registered through the builtin register_cli_commands hook (src/bub/builtin/hook_impl.py); plugins may add more.
Global options
Section titled “Global options”bub [OPTIONS] COMMAND [ARGS]...
| Option | Type | Default | Description |
|---|---|---|---|
--workspace, -w | TEXT | current working directory | Path to the workspace; sets BubFramework.workspace. |
--help | flag | — | Show help and exit. |
The framework is created in bub/__main__.py, which calls BubFramework().load_hooks() and then create_cli_app(). The active framework is stored on ctx.obj.
bub run
Section titled “bub run”Run one inbound ChannelMessage through BubFramework.process_inbound and print every outbound to stdout.
bub run [OPTIONS] MESSAGE
| Option | Type | Default | Description |
|---|---|---|---|
MESSAGE (arg) | TEXT | required | Inbound message content. |
--channel | TEXT | cli | Channel name attached to the inbound envelope. |
--chat-id | TEXT | local | Chat id attached to the inbound envelope. |
--sender-id | TEXT | human | Sender id; stored under context.sender_id. |
--session-id | TEXT | {channel}:{chat_id} | Override the session id. |
Behavior notes:
- Opens
framework.running()for the duration of one turn —provide_tape_storeis entered and exited around the call. - Outbounds are formatted as
[channel:chat_id]\n<content>. - Streaming output is not enabled; the model hook is invoked through
HookRuntime.run_model.
bub chat
Section titled “bub chat”Start an interactive REPL backed by the cli channel.
bub chat [OPTIONS]
| Option | Type | Default | Description |
|---|---|---|---|
--chat-id | TEXT | local | Chat id reported by the CLI channel. |
--session-id | TEXT | none | Optional explicit session id. |
Behavior notes:
- Constructs a
ChannelManagerwithenabled_channels=["cli"]andstream_output=True, then callsmanager.listen_and_run(). - Exits with code
1if no plugin provides a channel namedcli. - The CLI channel uses
prompt_toolkitandrichto render streamed events.
bub gateway
Section titled “bub gateway”Start every enabled channel listener (Telegram, custom plugin channels, …).
bub gateway [OPTIONS]
| Option | Type | Default | Description |
|---|---|---|---|
--enable-channel | TEXT (repeatable) | empty list (use BUB_ENABLED_CHANNELS) | Restrict gateway to the listed channel names. Pass multiple times. |
Behavior notes:
- When
--enable-channelis omitted the manager readsChannelSettings.enabled_channels(BUB_ENABLED_CHANNELS, defaultall). allexcludes theclichannel automatically to avoid stdout contention.framework.running()is held open until the manager loop exits;provide_tape_storecleanup runs on shutdown.
See Operate › Channels for per-channel deployment notes.
bub onboard
Section titled “bub onboard”Interactively collect plugin configuration via onboard_config hooks and write the result to ~/.bub/config.yml (or whatever framework.config_file resolves to).
bub onboard [OPTIONS]
| Option | Type | Default | Description |
|---|---|---|---|
--help | flag | — | Show help and exit. |
Behavior notes:
- The builtin onboarding fragment prompts for: provider (one of
openrouter,openai,anthropic,gemini,azure,bedrock,ollama,groq,mistral,deepseek, pluscustom), model name, optional API key, optional API base, API format (completion/responses/messages), enabled channels, and stream output. - Each plugin’s
onboard_confighook receives the accumulated dict so far; non-dict returns abort withTypeError. - The merged dict is validated through
configure.validatebefore being written.
Exit codes:
| Code | Meaning |
|---|---|
0 | Config saved. |
1 | Validation or write error; message printed to stderr. |
bub install
Section titled “bub install”Install a plugin into Bub’s managed uv project (BUB_HOME/bub-project, or ~/.bub/bub-project when BUB_HOME is unset), or sync the project when no specs are passed.
bub install [OPTIONS] [SPECS]...
| Option | Type | Default | Description |
|---|---|---|---|
SPECS (args) | one or more strings | empty list | Package specs: PyPI name, owner/repo[@ref], git+..., or a bub-contrib package as name@ref resolved against https://github.com/bubbuild/bub-contrib.git. |
--project | PATH | BUB_HOME/bub-project, or ~/.bub/bub-project when BUB_HOME is unset (env: BUB_PROJECT) | Path to the Bub plugin project directory. |
Behavior notes:
- Requires
uvonPATHand that Bub itself runs inside a virtualenv (sys.prefix != sys.base_prefix); otherwise exits with1. - Initializes the project on first use via
uv init --bare --name bub-project --appand adds Bub to it as a dependency (matching the local install: editable, file://, VCS, or PyPI). - The default project directory is created automatically. When
--projectis provided explicitly, the directory must already exist. - With no specs, runs
uv sync --active --inexact. - With specs, runs
uv add --active <requirements>.
Exit codes mirror uv — non-zero from the underlying subprocess.run is propagated.
bub uninstall
Section titled “bub uninstall”bub uninstall [OPTIONS] PACKAGES...
| Option | Type | Default | Description |
|---|---|---|---|
PACKAGES (args) | one or more strings | required | Package names as recorded in the project’s pyproject.toml. |
--project | PATH | BUB_HOME/bub-project, or ~/.bub/bub-project when BUB_HOME is unset (env: BUB_PROJECT) | Plugin project directory. |
Calls uv remove --active <packages> inside --project.
bub update
Section titled “bub update”bub update [OPTIONS] [PACKAGES]...
| Option | Type | Default | Description |
|---|---|---|---|
PACKAGES (args) | zero or more strings | empty list | Package names to upgrade; empty means all. |
--project | PATH | BUB_HOME/bub-project, or ~/.bub/bub-project when BUB_HOME is unset (env: BUB_PROJECT) | Plugin project directory. |
Behavior notes:
- No packages →
uv sync --active --upgrade --inexact. - With packages →
uv sync --active --inexact --upgrade-package <name>for each.
bub login
Section titled “bub login”Top-level group for authentication subcommands.
bub login [OPTIONS] COMMAND [ARGS]...
| Option | Type | Default | Description |
|---|---|---|---|
--help | flag | — | Show help and exit. |
bub login openai
Section titled “bub login openai”Run the Codex OAuth flow to obtain OpenAI credentials, then save them under the resolved Codex home.
bub login openai [OPTIONS]
| Option | Type | Default | Description |
|---|---|---|---|
--codex-home | PATH | $CODEX_HOME or ~/.codex | Directory to store the resulting auth.json. |
--browser / --no-browser | flag | --browser | Open the OAuth authorize URL in the default browser. |
--manual | flag | off | Skip the local callback server and prompt for the callback URL or code. |
--timeout | FLOAT | 300.0 | OAuth wait timeout in seconds. |
Behavior notes:
- On success prints
login: ok, the account id, the auth file path, and a usage hint to setBUB_MODEL=openai:gpt-5-codexand omitBUB_API_KEY. - On
CodexOAuthLoginErrorexits with code1.
bub hooks
Section titled “bub hooks”Hidden diagnostic command that prints the hook → adapters map.
bub hooks
The command is registered with hidden=True, so it does not appear in the top-level --help listing. Output is one line per hook: hook_name: adapter1, adapter2, …. Use it to verify discovery; see Hooks › How hooks are invoked before inferring firstresult precedence from the printed order.