Read-only Bitbucket Cloud access (with one opt-in write) as an Agent Skill. One codebase, works in Claude Code and Codex CLI and PI.
Thin Node wrapper over the Bitbucket Cloud v2 REST API. Replaces ad-hoc curl calls and keeps the API token out of shell history. Auto-detects workspace/slug from git remote.
- Single Node CLI:
bin/bb.mjs - Pull requests:
pr list,pr get,pr diff,pr activity,pr create - PR comments:
pr comments(list),pr comment add(with--parentfor threaded replies),pr comment edit,pr comment resolve,pr comment unresolve - Pipelines:
pipeline list,pipeline get,pipeline steps,pipeline log - Auto-detects
<workspace>/<slug>fromgit remote get-url origin - Basic auth (scoped Atlassian API token + email) and Bearer auth (OAuth / workspace / repo / project access tokens) via the same
.bbfile - JSON output stays pure (no trailers); text output gets a divider-block hint when the skill emits a notice
- Inline
_hintfield in JSON object output makes skill-emitted messages obvious vs. Bitbucket API responses - Zero third-party dependencies; uses native
fetchandgit
Pick the location for the tool you use. Both tools read the exact same files.
# personal (available in every project)
git clone https://github.com/omvmike/bitbucket-skill ~/.claude/skills/bitbucket
# or project-scoped (committed with your repo)
git clone https://github.com/omvmike/bitbucket-skill .claude/skills/bitbucketInvoke with /bitbucket or let Claude trigger it automatically when you ask about a PR or pipeline.
# personal
git clone https://github.com/omvmike/bitbucket-skill ~/.agents/skills/bitbucket
# or project-scoped
git clone https://github.com/omvmike/bitbucket-skill .agents/skills/bitbucketInvoke with $bitbucket or let Codex trigger it automatically.
# personal (available in every project)
git clone https://github.com/omvmike/bitbucket-skill ~/.pi/agent/skills/bitbucketProject-scoped variant isn't tested but should work as well.
Invoke with /skill:bitbucket or let Pi trigger it automatically
cd <install-dir> && git pullNode 18+ (uses native fetch, node:fs, node:child_process). No npm install required — zero third-party dependencies. git must be available on PATH for workspace/slug auto-detection.
-
Create a scoped Atlassian API token at:
https://id.atlassian.com/manage-profile/security/api-tokens?autofillToken=&appId=bitbucket
On that page, tick these scopes (read-only profile — covers everything except
bb pr create):read:user:bitbucket(required for--whoami; also surfaces embedded user display names)read:repository:bitbucketread:pullrequest:bitbucketread:pipeline:bitbucket
Also tick
write:pullrequest:bitbucketforbb pr create,pr comment add, orpr comment edit. -
Save credentials at the project root:
umask 077 cat > .bb <<'EOF' BB_USER=<your-atlassian-email> BB_TOKEN=<paste-api-token> EOF chmod 600 .bb echo .bb >> .gitignore
For OAuth 2.0 / workspace / repository / project access tokens (Bearer auth), omit
BB_USER. -
Verify:
node ~/.claude/skills/bitbucket/bin/bb.mjs --whoami
Replace the install path with wherever you cloned.
# List open PRs
node ~/.claude/skills/bitbucket/bin/bb.mjs pr list
# My open PRs as markdown table (default is JSON)
node ~/.claude/skills/bitbucket/bin/bb.mjs pr list --mine --format table
# PR detail + diff
node ~/.claude/skills/bitbucket/bin/bb.mjs pr get 42
node ~/.claude/skills/bitbucket/bin/bb.mjs pr diff 42 > /tmp/pr42.diff
# Activity (comments, approvals, updates) as a single mixed feed
node ~/.claude/skills/bitbucket/bin/bb.mjs pr activity 42 --format table
# Comments only (newest first)
node ~/.claude/skills/bitbucket/bin/bb.mjs pr comments 42 --format table
# Add a comment (requires write:pullrequest:bitbucket scope)
node ~/.claude/skills/bitbucket/bin/bb.mjs pr comment add 42 --body 'LGTM, merging after CI' --yes
# Add a comment from a file
node ~/.claude/skills/bitbucket/bin/bb.mjs pr comment add 42 --body '@review-notes.md' --yes
# Edit an existing comment (overwrites the body)
node ~/.claude/skills/bitbucket/bin/bb.mjs pr comment edit 42 12345 --body 'Updated review notes' --yes
# Threaded reply to an existing comment (anchor is inherited)
node ~/.claude/skills/bitbucket/bin/bb.mjs pr comment add 42 --parent 12345 --body 'Verified — resolving.' --yes
# Resolve / reopen a thread (top-level comment id)
node ~/.claude/skills/bitbucket/bin/bb.mjs pr comment resolve 42 12345 --yes
node ~/.claude/skills/bitbucket/bin/bb.mjs pr comment unresolve 42 12345 --yes
# Pipelines for master
node ~/.claude/skills/bitbucket/bin/bb.mjs pipeline list --branch master --limit 5
# Failed step log
node ~/.claude/skills/bitbucket/bin/bb.mjs pipeline steps '{pipeline-uuid}'
node ~/.claude/skills/bitbucket/bin/bb.mjs pipeline log '{pipeline-uuid}' '{step-uuid}'
# Open a PR (requires write:pullrequest:bitbucket scope)
node ~/.claude/skills/bitbucket/bin/bb.mjs pr create \
--source feat/foo --target master \
--title 'feat: foo' --body '@CHANGES.md' \
--reviewer '{uuid-of-reviewer}' --yes
# Identity / auth check
node ~/.claude/skills/bitbucket/bin/bb.mjs --whoami
# Where am I reading config from?
node ~/.claude/skills/bitbucket/bin/bb.mjs --list-targetsconfig.json in the skill directory holds the runtime defaults.
| Key | Default | Notes |
|---|---|---|
defaultFormat |
json |
Output format when --format is not passed (json or table). pr diff and pipeline log always return raw text. |
defaultLimit |
10 |
Pagination limit for list endpoints |
timeoutMs |
15000 |
HTTP timeout per request |
maxRowsPerPage |
50 |
Bitbucket API page size cap |
| Code | Meaning |
|---|---|
| 0 | Success |
| 2 | Config / auth (missing .bb, invalid token, 401/403) |
| 3 | Not found (404) |
| 4 | Validation (bad flags, unknown command) |
| 5 | Network / timeout / 5xx |
| 6 | Rate-limited (429) |
The script walks up from process.cwd() (the directory you ran claude / codex from) and stops at the first directory containing a .git folder. If .bb isn't there, it falls back to ~/.config/bitbucket/.bb. The resolved path is shown by --list-targets and --whoami.
Workspace/slug are detected by parsing git remote get-url origin for SSH (git@bitbucket.org:<workspace>/<slug>) and HTTPS (https://bitbucket.org/<workspace>/<slug>) Bitbucket Cloud URLs. Override with --repo <workspace>/<slug> or set BB_WORKSPACE in .bb.
- Scoped API tokens — set
BB_USER(your Atlassian email) +BB_TOKEN. Auth header isBasic base64(email:token), routed againstapi.bitbucket.org/2.0/...directly (no API gateway needed for Bitbucket). - OAuth 2.0 / workspace / repository / project access tokens — omit
BB_USER, set onlyBB_TOKEN. Auth header isBearer <token>, same direct routing.
The skill requests the minimum scopes needed for each operation. Generated tokens land at https://api.bitbucket.org/2.0/... directly — no gateway routing.
Read-only profile (recommended default — 4 scopes):
| Scope | Justification |
|---|---|
read:user:bitbucket |
--whoami (calls GET /2.0/user) — Bitbucket rejects this endpoint without it. Also surfaces embedded user display_name fields in PR/pipeline responses. |
read:repository:bitbucket |
All /repositories/{w}/{s}/... paths require this |
read:pullrequest:bitbucket |
pr list, pr get, pr diff, pr activity, pr comments |
read:pipeline:bitbucket |
pipeline list, pipeline get, pipeline steps, pipeline log |
Write profile (adds 1 scope, total 5) — required for pr create, pr comment add / pr comment edit, and pr comment resolve / pr comment unresolve:
| Scope | Justification |
|---|---|
write:pullrequest:bitbucket |
POST /pullrequests (pr create), POST /pullrequests/{id}/comments (pr comment add, including threaded replies via parent.id), PUT /pullrequests/{id}/comments/{cid} (pr comment edit), POST /pullrequests/{id}/comments/{cid}/resolve (pr comment resolve), DELETE /pullrequests/{id}/comments/{cid}/resolve (pr comment unresolve) |
Explicitly NOT needed. Compared to the older selectedScopes=all link, this drops 35 scopes:
- All 4
admin:*scopes — the skill never modifies repo/project/workspace/pipeline settings - All 8
delete:*scopes — the skill never deletes anything - All other
write:*scopes — onlywrite:pullrequest:bitbucketis used (and only forpr create) read:project:bitbucket,read:workspace:bitbucket— the skill doesn't query project or workspace resources directlyread:gpg-key,read:ssh-key,read:webhook,read:wiki,read:snippet,read:issue,read:runner,read:test,read:package,read:permission— none of these resources are touchedmanage:org— irrelevantread:account,read:me— these are legacy classic-token scopes. Atlassian's modern scoped API tokens enforceread:user:bitbucketinstead (it's in the recommended profile above), so the legacy ones are inert here.
MIT