Recipes¶
Copy-paste setups, top to bottom — swap the < > placeholders for your own
values. Codex is the bundled default; Claude covers reviewing with
Claude instead.
Codex or Claude
Bubo runs the review through a small wrapper around your agent CLI. Codex is bundled and works out of the box, so the recipes below use it. Prefer Claude? See Claude.
Codex (OpenAI) — GitLab¶
The fastest path to a first review on a GitLab merge request.
1. Prerequisites¶
Install these once and put them on PATH (see
prerequisites for platform-specific commands):
- uv, Python 3.14+, Git
- Codex CLI, authenticated to OpenAI
- Superpowers + the
code-reviewerskill in your Codex config - glab (GitLab CLI) — for cloning/fetching MRs
2. Install Bubo¶
uv tool install bubo
bubo init # writes ~/.codex/config.toml (with [profiles.bubo]),
# ~/.claude/settings.json, the workspace, and the SQLite DB
Want the bleeding edge? Track main instead:
uv tool install git+https://github.com/mountainowl/bubo.
3. Configure¶
bubo init seeds the config at
~/.local/share/bubo/config/env.toml. Open it and fill in the minimum:
[scm]
provider = "gitlab"
[gitlab]
token = "<glpat-your-token>" # GitLab token with `api` scope
[agents]
llm_model = "gpt-5.5" # any model your Codex profile drives
llm_api_key = "<sk-your-openai-key>"
llm_api_key_env = "OPENAI_API_KEY" # the env var the OpenAI/Codex CLI reads
[[projects]]
path = "<your-group>/<your-repo>" # repos Bubo should watch
enabled = true
4. Verify and run¶
bubo doctor # checks workspace, config, DB, and the Codex profile block
bubo-poller # one poll cycle; reviews open MRs, then exits
The first run is dry-run by default ([review].dry_run = true): Bubo
plans findings and writes them to SQLite but posts nothing. Read a
transcript under ~/.local/share/bubo/var/reports/. When it looks right,
flip [review].dry_run = false to start posting inline review threads.
5. Schedule it (optional)¶
bubo init rendered ready-to-install cron + systemd units under
~/.local/share/bubo/deploy/templates/. See operate for
the install steps.
Codex (OpenAI) — GitHub¶
Same as the GitLab recipe, with three changes:
- Install the
ghCLI instead ofglab, authenticated to GitHub. - Use a GitHub token with pull-request read+write.
- Set the provider to GitHub:
[scm]
provider = "github"
[github]
token = "<ghp-your-token>"
[agents]
llm_model = "gpt-5.5"
llm_api_key = "<sk-your-openai-key>"
llm_api_key_env = "OPENAI_API_KEY"
[[projects]]
path = "<owner>/<repo>"
enabled = true
Run bubo-poller once [scm].provider = "github" is set, or force the
provider for a single run with BUBO_PROVIDER=github bubo-poller.
Self-hosted / in-house model (OpenAI-compatible)¶
The strongest version of Bubo's compliance story: when your org runs its own OpenAI-compatible gateway — Azure OpenAI, vLLM/TGI, LiteLLM, or an internal proxy — code, diffs, review state, and the model call all stay on your infrastructure. Nothing leaves.
The one thing to know: Bubo never calls the model directly. It shells out to
an agent CLI (Codex by default), so the in-house endpoint is configured in the
agent's profile, not Bubo's env.toml. A bare bubo init ships a
stock-OpenAI profile (model = "gpt-5.5", no provider block), so pointing at an
internal endpoint is one explicit edit — uv tool install bubo && bubo init
alone will not redirect it.
1. Install Bubo (unchanged)¶
uv tool install bubo
bubo init # writes ~/.codex/config.toml [profiles.bubo], the env.toml seed, the DB
bubo doctor
2. Point the Codex profile at your gateway (the load-bearing step)¶
Edit ~/.codex/config.toml. Add a model-provider block and reference it from the
[profiles.bubo] profile bubo init created:
[profiles.bubo]
model = "<internal-model-name>"
model_provider = "inhouse" # references the block below
sandbox_mode = "read-only"
[model_providers.inhouse]
name = "In-house gateway"
base_url = "https://llm.corp.internal/v1" # your OpenAI-compatible endpoint
env_key = "OPENAI_API_KEY" # env var Codex reads the key from
wire_api = "chat" # "chat" or "responses" — match your gateway
These are Codex's config keys, not Bubo's — confirm the exact field names against your Codex version.
3. Tell Bubo the label + key plumbing¶
In $BUBO_ROOT/config/env.toml:
[agents]
llm_model = "<internal-model-name>" # must match the profile; used for the cost label only
llm_api_key = "${LLM_API_KEY}" # Bubo exports this under llm_api_key_env
llm_api_key_env = "OPENAI_API_KEY" # the env var your gateway/CLI reads
codex_profile = "bubo"
If you track cost, set the [telemetry] *_per_1m rows to your gateway's rates
(see the configuration reference).
4. Pre-flight the sandbox (the enterprise Linux gotcha)¶
On hardened Linux hosts — Ubuntu with the AppArmor unprivileged-user-namespace
restriction — Codex's default read-only sandbox uses bubblewrap and can fail to
initialize, and a failed sandbox can surface as a misleading clean "no findings"
review. Enterprise hosts are exactly where this bites. Fix it once during
bring-up: see Troubleshooting.
5. Verify before going live¶
Keep [review].dry_run = true, run bubo-poller once, and read a transcript
under var/reports/ to confirm findings come through your in-house model. Then
flip dry_run = false.
Not OpenAI-compatible?
The escape hatch is [agents].reviewer_command — override the whole command
with any CLI that takes the prompt and returns Bubo's JSON findings contract.
You're locked to neither Codex nor OpenAI.
Claude¶
Bubo runs the review through a wrapper around your agent CLI, so Claude works
like Codex — only the CLI it calls and the key it uses change.
Install the Claude CLI, then set Claude as your agent in [agents]:
[agents]
llm_model = "<your-claude-model>"
llm_api_key = "<your-anthropic-key>"
llm_api_key_env = "ANTHROPIC_API_KEY" # the env var the Claude CLI reads
Codex ships pre-wired, so reviewing with Claude takes one extra step: point
the wrapper at the Claude CLI for the review. Verify it like Codex — keep
[review].dry_run = true, run bubo-poller once, and read the transcript
under var/reports/ to confirm findings come through before you flip
dry_run to false.