Skip to content

Bitbucket forge viewer

mnml-forge-bitbucket is a terminal Bitbucket Cloud viewer. Runs standalone in any terminal. It’s the first shipped member of the forge integration class — sibling repos mnml-forge-github and a future mnml-forge-gitlab follow the same shape. See Building integrations for the model.

┌─ bitbucket PRs ──────────────────────────────────────────────────┐
│ ▸1.Mine (3) 2.Reviewing (7) 3.example-api PRs (12) │
└──────────────────────────────────────────────────────────────────┘
┌─ Mine ───────────────────────────────────────────────────────────┐
│ REPO │ PR │ STATE │ AUTHOR │ BRANCH → DEST │
│ acme/api │ #1234 │ OPEN │ Chris │ chris/fix → main │
│ acme/web │ #821 │ OPEN │ Chris │ chris/redesign… │
│ … │
└──────────────────────────────────────────────────────────────────┘
1-9 tab · ↑↓/jk move · Enter/o open · r refresh · q quit
Terminal window
cargo install --git https://github.com/chris-mclennan/mnml-forge-bitbucket mnml-forge-bitbucket
mnml-forge-bitbucket --install

Homebrew tap + binary releases will follow once the binary stabilises.

  1. Create a Bitbucket app password at https://bitbucket.org/account/settings/app-passwords/.

    Minimum scopes: Pull requests: Read. Add Account: Read if you want mode = "mine" / mode = "reviewing" tabs (those need /2.0/user to resolve your account_id) or the a approve toggle.

  2. Point the tool at your app password. Two options — env var or on-disk file.

    Env var (preferred if your shell already exports Bitbucket credentials):

    Terminal window
    export BITBUCKET_APP_PASSWORD="ATATT-…" # bare app password
    # OR
    export BITBUCKET_PERSONAL_TOKEN="[email protected]:ATATT-…" # email:token combined form

    BITBUCKET_APP_PASSWORD wins over BITBUCKET_PERSONAL_TOKEN; the latter accepts either the bare token or the email:token combined form (only the after-colon portion is used).

    On-disk file (chmod 600):

    Terminal window
    mkdir -p ~/.config/mnml-forge-bitbucket
    pbpaste > ~/.config/mnml-forge-bitbucket/token # or paste it in $EDITOR
    chmod 600 ~/.config/mnml-forge-bitbucket/token

    Resolution order at startup: BITBUCKET_APP_PASSWORDBITBUCKET_PERSONAL_TOKEN~/.config/mnml-forge-bitbucket/token.

  3. Run once to scaffold the config template:

    Terminal window
    mnml-forge-bitbucket

    On first launch with no config, it writes ~/.config/mnml-forge-bitbucket.toml and exits with instructions. Edit email, workspace, and the [[tabs]] list.

  4. Re-run — the TUI launches with your configured tabs.

  5. Verify the resolved config + auth state without launching the TUI:

    Terminal window
    mnml-forge-bitbucket --check

    Hits /2.0/user to confirm the app password works. The output reports the token source (env: BITBUCKET_APP_PASSWORD / env: BITBUCKET_PERSONAL_TOKEN / the file path) so you can confirm which credential path is authoritative when both a file and an env var are set.

Each [[tabs]] entry is one tab. The kind field (defaults to pull_requests) decides what the tab shows:

kindWhat it showsRequired fields
pull_requests (default)PR list, with state filter + optional mine/reviewing modesone of repo / mode / q
pipelinesRecent builds for a repo, newest-firstrepo
branchesBranches in a repo, sorted by latest commitrepo

PR-specific fields (state, mode, q) are ignored on pipelines and branches tabs.

[[tabs]]
name = "Reviewing"
mode = "reviewing" # kind defaults to pull_requests
[[tabs]]
name = "example-api pipelines"
kind = "pipelines"
repo = "example-api"
[[tabs]]
name = "example-api branches"
kind = "branches"
repo = "example-api"

Three shapes for kind = "pull_requests":

[[tabs]]
name = "example-api PRs"
repo = "example-api"
state = "OPEN" # OPEN / MERGED / DECLINED / SUPERSEDED

Uses the default workspace from the top of the config. Override per-tab with workspace = "otherws" if needed.

[[tabs]]
name = "Mine"
mode = "mine"

Bitbucket Cloud has no workspace-scoped PR endpoint that accepts BBQL, so mode = "mine" enumerates every repo you have access to in the workspace and fans out per-repo BBQL queries (author.account_id = "<your-id>") with a concurrency cap of 8. Results are merged + sorted by updated_on descending. On a 100-repo workspace this typically completes in a few seconds; per-repo errors (e.g. a 403 on an archived repo) are dropped silently rather than blanking the tab.

Requires Account: Read on the app password. Same enumeration shape powers mode = "reviewing" — the per-repo BBQL swaps to reviewers.account_id = "<your-id>".

mode = "reviewing" — PRs you’re a reviewer on

Section titled “mode = "reviewing" — PRs you’re a reviewer on”
[[tabs]]
name = "Reviewing"
mode = "reviewing"

Same as mine but with reviewers.account_id = "<your-id>".

For finer-grained control you can supply a raw Bitbucket Query Language string via q. Either as the only filter (no mode, no repo) or layered on top of an auto-mode tab:

[[tabs]]
name = "Stale PRs"
repo = "example-api"
state = "OPEN"
q = "updated_on <= 2026-05-01T00:00:00+00:00"

BBQL reference: https://developer.atlassian.com/cloud/bitbucket/rest/intro/#filtering-and-sorting-results

The first-run template ships with 5 tabs:

TabKindNotes
Minepull_requestsmode = "mine"
Reviewingpull_requestsmode = "reviewing"
your-repo PRspull_requestsper-repo, state OPEN
your-repo pipelinespipelinesnewest-first builds
your-repo branchesbranchessorted by latest commit

Edit or replace freely; you’re not locked in.

ChordAction
1-9Switch to that tab
Tab / BackTabCycle tabs forward / back
/ k, / jMove selection
PgUp / PgDnJump 10 rows
g / GTop / bottom
Enter / oOpen focused PR (or pipeline / branch) in your browser
yYank focused row’s URL to the OS clipboard
dToggle right-half PR detail panel
Ctrl+U / Ctrl+DScroll detail panel up / down (when open)
aToggle your approval on the focused PR (detail panel must be open)
rRefresh active tab (+ detail if open)
q / Esc / Ctrl+CQuit

Auto-refresh runs every refresh_interval_secs seconds (default 60, set to 0 to disable).

d opens a right-half panel for the focused PR: header (state · branches · author · updated · approval chip), then title, description, then up to the last 20 comments (most-recent first). Detail content is lazy-loaded on first focus and cached per (workspace, repo, id) — arrow-keying through a long list only fetches once per PR.

r while the detail panel is open invalidates the cached detail for the focused PR and re-fetches both the list and the detail — useful after a new comment landed server-side.

The approval chip shows either ✓ you approved · N total or ○ not approved · N total. N is the count of approving participants on the PR (including you).

a (with the detail panel open) toggles your approval. The viewer reads the current state from the cached participant record and POSTs or DELETEs /pullrequests/{id}/approve accordingly, then drops the cache so a re-fetch picks up the new state. Requires Account: Read on the app password — otherwise the viewer can’t resolve your account_id and the toggle is a no-op with an explanatory toast.

Just run mnml-forge-bitbucket in any terminal. The TUI takes over until you q.

:term mnml-forge-bitbucket

mnml spawns it in a Pty pane — splittable, focusable, key-routed like any other pane.

To get a one-click chip in mnml’s rail under INTEGRATIONS (alongside Claude Code / Codex / Jira / HTTP / etc.), drop this into your ~/.config/mnml/config.toml:

[[ui.integration_icon]]
id = "bitbucket"
glyph = "\U000F0093" # nf-md-bitbucket (TOML 8-digit form)
fallback = "B"
command = ":term mnml-forge-bitbucket"
color = "blue"
tooltip = "Open Bitbucket PRs"

Setting [[ui.integration_icon]] replaces the built-in defaults (Claude Code / Codex / Bitbucket / HTTP / CodeBuild / GitHub), so copy the defaults from src/config.rs into your config first if you want to extend rather than replace. See the launcher-icon strips for the field reference and the \UXXXXXXXX Nerd-Font escape convention.

The viewer lives in its own sibling repo: github.com/chris-mclennan/mnml-forge-bitbucket. MIT-licensed and built around the same ratatui substrate mnml uses, so most of its UI patterns will look familiar. See Building integrations for the anatomy of an integration, or Community integrations for the directory of siblings.