bitbottle

module
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 27, 2026 License: MIT

README ΒΆ

bitbottle 🍢

A command-line interface for Bitbucket Cloud and Bitbucket Server / Data Center β€” built with the same philosophy as GitHub CLI: TTY-aware output, machine-readable pipes, and a clean factory model for easy testing.


✨ Features

Area Status
auth login / logout / status / token / refresh βœ… Fully working
repo list / create / delete / clone / view βœ… Fully working
pr list / create / merge / approve / view / diff / checkout / edit / decline / unapprove / ready / request-review βœ… Fully working
branch list / delete / create / checkout βœ… Fully working
tag list / create / delete βœ… Fully working
commit log / view βœ… Fully working
pipeline list / view / run (Cloud only) βœ… Fully working
completion bash|zsh|fish|powershell βœ… Fully working
mcp serve β€” MCP stdio server for AI assistants βœ… Fully working

Works identically against Bitbucket Cloud (bitbucket.org) and Bitbucket Server / Data Center (self-hosted).


πŸ“¦ Installation

go install github.com/proggarapsody/bitbottle/cmd/bitbottle@latest

Or build from source:

git clone https://github.com/proggarapsody/bitbottle
cd bitbottle
make build

Requires Go 1.21+


πŸ”‘ Authentication

Interactive login
# Bitbucket Cloud
echo "YOUR_TOKEN" | bitbottle auth login --hostname bitbucket.org --with-token

# Bitbucket Server / Data Center
echo "YOUR_TOKEN" | bitbottle auth login \
  --hostname bitbucket.example.com \
  --with-token \
  --git-protocol https \
  --skip-tls-verify        # for self-signed certs

auth login validates the token against the API, saves credentials to ~/.config/bitbottle/hosts.yml, and optionally stores the token in the system keyring.

Flags
Flag Default Description
--hostname β€” Required. Target Bitbucket host
--with-token false Read token from stdin
--git-protocol ssh ssh or https
--skip-tls-verify false Skip TLS cert check (Server/DC self-signed)
Check status
bitbottle auth status
# bitbucket.org: Logged in as alice (Token in keyring: yes)
# bitbucket.example.com: Logged in as bob (Token in keyring: no)
Logout
bitbottle auth logout --hostname bitbucket.example.com
Print stored token
bitbottle auth token
bitbottle auth token --hostname bitbucket.example.com

Prints the raw stored PAT to stdout (useful for scripting). Exits 1 if no token is stored for the host.

Refresh / re-validate token
bitbottle auth refresh
bitbottle auth refresh --hostname bitbucket.example.com

Calls the API to confirm the token is still valid. Updates the stored username if it has changed. On failure, prints an actionable error to stderr and exits 1 β€” no interactive re-auth (PATs cannot be refreshed programmatically; generate a new token from the Bitbucket UI and run auth login again).

Manual config

Edit ~/.config/bitbottle/hosts.yml directly:

# Bitbucket Cloud
bitbucket.org:
  oauth_token: <your-access-token>
  git_protocol: ssh

# Bitbucket Server / Data Center
bitbucket.example.com:
  oauth_token: <your-token>
  git_protocol: https
  skip_tls_verify: true

# Force Cloud routing for a non-bitbucket.org host
mycompany.bitbucket.example.com:
  oauth_token: <your-token>
  backend_type: cloud   # "cloud" | "server" | "" (auto)

Token scopes required:

Bitbucket Cloud Bitbucket Server / DC
account:read for auth commands PROJECT_READ
repository:read / repository:write PROJECT_READ / PROJECT_WRITE
pullrequest:read / pullrequest:write PROJECT_READ / PROJECT_WRITE

πŸš€ Usage

πŸ” Auth
# Login
echo "TOKEN" | bitbottle auth login --hostname bitbucket.org --with-token

# Show all authenticated hosts
bitbottle auth status

# Logout
bitbottle auth logout --hostname bitbucket.org

πŸ“ Repositories
List
# List repositories (auto-detects host)
bitbottle repo list

# Limit results
bitbottle repo list --limit 10

# Target a specific host
bitbottle repo list --hostname bitbucket.example.com

# JSON output (specify comma-separated fields)
bitbottle repo list --json slug,project,scm

TTY output (aligned table):

SLUG              PROJECT     TYPE
my-service        MYPROJ      git
payments-api      MYPROJ      git
infra-tools       PLATFORM    git

Piped / non-TTY output (tab-separated, no header):

bitbottle repo list | awk '{print $1}'   # β†’ slugs only
bitbottle repo list | cut -f2            # β†’ projects only
Create
bitbottle repo create my-service --project MYPROJ
bitbottle repo create my-service --project MYPROJ --description "Core service" --private=false
Flag Default Description
--project β€” Required. Project key
--description β€” Repository description
--private true Make repository private
Delete
# With confirmation prompt (TTY)
bitbottle repo delete MYPROJ/my-service

# Skip prompt
bitbottle repo delete MYPROJ/my-service --confirm
Clone
# Clone into ./my-service
bitbottle repo clone MYPROJ/my-service

# Clone into custom directory
bitbottle repo clone MYPROJ/my-service ~/projects/my-service

Uses SSH or HTTPS based on git_protocol in your config.

View
bitbottle repo view MYPROJ/my-service

# Open in browser
bitbottle repo view MYPROJ/my-service --web

🌿 Branches
List
bitbottle branch list MYPROJ/my-service

# Limit results
bitbottle branch list MYPROJ/my-service --limit 10

# JSON output
bitbottle branch list MYPROJ/my-service --json name,default,hash

# jq filter
bitbottle branch list MYPROJ/my-service --json name --jq .

TTY output:

NAME        DEFAULT   HASH
main        true      a1b2c3d4
feature/x   false     e5f6a7b8
develop     false     c9d0e1f2
Delete
bitbottle branch delete MYPROJ/my-service feature/my-branch
Create
bitbottle branch create MYPROJ/my-service feature/my-branch --start-at main
bitbottle branch create MYPROJ/my-service hotfix/issue-42 --start-at abc123def456
Flag Default Description
--start-at β€” Required. Branch name or commit hash to branch from
Checkout
# Fetch from origin and check out locally
bitbottle branch checkout feature/my-branch

Equivalent to git fetch origin feature/my-branch && git checkout feature/my-branch.


🏷️ Tags
List
bitbottle tag list MYPROJ/my-service
bitbottle tag list MYPROJ/my-service --limit 10
bitbottle tag list MYPROJ/my-service --json name,hash

TTY output:

NAME       HASH
v1.2.0     a1b2c3d4
v1.1.0     e5f6a7b8
v1.0.0     c9d0e1f2
Create
# Lightweight tag
bitbottle tag create MYPROJ/my-service v1.3.0 --start-at main

# Annotated tag
bitbottle tag create MYPROJ/my-service v1.3.0 --start-at main --message "Release 1.3.0"
Flag Default Description
--start-at β€” Required. Branch name or commit hash to tag
--message β€” Tag message (creates annotated tag when non-empty)
Delete
bitbottle tag delete MYPROJ/my-service v1.3.0

πŸ“ Commits
Log
bitbottle commit log MYPROJ/my-service

# Specific branch
bitbottle commit log MYPROJ/my-service --branch feature/x

# Limit results
bitbottle commit log MYPROJ/my-service --limit 10

# JSON output
bitbottle commit log MYPROJ/my-service --json hash,message,author

Branch resolution order: --branch flag β†’ current local branch (git rev-parse --abbrev-ref HEAD) β†’ main.

TTY output:

HASH     MESSAGE                           AUTHOR   DATE
abc1234  Fix null pointer in auth          alice    2 days ago
def5678  Bump lodash to 4.17.21            bob      3 days ago
c9d0e1f  Add retry logic to payments       charlie  5 days ago

Pipe output (tab-separated, no header, full hash + RFC3339 date):

bitbottle commit log MYPROJ/my-service | cut -f1   # β†’ full hashes
Flag Default Description
--branch / -b (current branch β†’ main) Branch to list commits from
--limit 30 Maximum number of results
--json β€” Comma-separated fields
--jq β€” jq filter applied to JSON output
--hostname β€” Target Bitbucket host
View
bitbottle commit view MYPROJ/my-service abc1234def456abc1234def456abc1234def456ab

# Open in browser
bitbottle commit view MYPROJ/my-service abc1234 --web

# JSON output
bitbottle commit view MYPROJ/my-service abc1234 --json hash,message,author,timestamp

TTY output:

commit abc1234def456abc1234def456abc1234def456ab

Fix null pointer in auth middleware

Author:  alice
Date:    2026-04-24 10:00:00 +0000 UTC
Web:     https://bitbucket.org/myws/my-service/commits/abc1234def456

πŸ”€ Pull Requests
List
# List open PRs (auto-detects repo from git remote)
bitbottle pr list

# Explicit PROJECT/REPO
bitbottle pr list MYPROJECT/my-service

# Filter by state
bitbottle pr list --state merged
bitbottle pr list --state closed --limit 5

# Specific host
bitbottle pr list --hostname bitbucket.example.com

# JSON output
bitbottle pr list --json id,title,author,state

TTY output:

TITLE                        AUTHOR     STATE
Fix null pointer in auth     alice      OPEN
Bump lodash to 4.17.21       bob        OPEN
Add retry logic to payments  charlie    OPEN

Piped:

# Count open PRs
bitbottle pr list | wc -l

# Get all open PR titles
bitbottle pr list | awk '{print $1}'
Create
bitbottle pr create --title "Fix auth bug" --base main

# With description and draft flag
bitbottle pr create \
  --title "Add retry logic" \
  --body "Implements exponential backoff for all HTTP calls." \
  --base main \
  --draft
Flag Default Description
--title β€” Required. PR title
--base β€” Required. Target branch
--body β€” PR description
--draft false Mark as draft PR

Branch is auto-detected from git rev-parse --abbrev-ref HEAD.

Merge
# Default merge strategy
bitbottle pr merge 42

# Explicit strategy
bitbottle pr merge 42 --merge      # merge commit
bitbottle pr merge 42 --squash     # squash merge

# Delete source branch after merge
bitbottle pr merge 42 --squash --delete-branch
Flag Default Description
--merge false Merge commit strategy
--squash false Squash merge strategy
--delete-branch false Delete source branch after merge
Approve
bitbottle pr approve 42
View
bitbottle pr view 42

# Open in browser
bitbottle pr view 42 --web
Diff
# Stream diff to terminal
bitbottle pr diff 42

# Pipe to a pager or diff tool
bitbottle pr diff 42 | less
bitbottle pr diff 42 | delta
Checkout
# Fetch and checkout the PR's source branch
bitbottle pr checkout 42
Edit
# Update title
bitbottle pr edit 42 --title "Fix auth bug (updated)"

# Update description
bitbottle pr edit 42 --body "New description"

# Update both
bitbottle pr edit 42 --title "New title" --body "New body"
Decline
bitbottle pr decline 42
Unapprove
bitbottle pr unapprove 42
Ready
# Promote a draft PR to ready for review
bitbottle pr ready 42
Request Review
# Add reviewers (comma-separated usernames/account IDs)
bitbottle pr request-review 42 --reviewer alice --reviewer bob

# Or comma-separated
bitbottle pr request-review 42 --reviewer alice,bob
Flag Default Description
--reviewer β€” Required. Reviewer username(s); repeatable or comma-separated

βš™οΈ Pipelines (Bitbucket Cloud only)
List
bitbottle pipeline list MYWORKSPACE/my-service

# Limit results
bitbottle pipeline list MYWORKSPACE/my-service --limit 10

# JSON output
bitbottle pipeline list MYWORKSPACE/my-service --json buildNumber,state,refName,duration

# jq filter β€” show only failed
bitbottle pipeline list MYWORKSPACE/my-service --json state --jq 'select(. == "FAILED")'

TTY output:

BUILD   STATE       BRANCH/TAG   DURATION
42      SUCCESSFUL  main         87s
41      FAILED      feature/x    12s
40      SUCCESSFUL  main         91s
View
bitbottle pipeline view MYWORKSPACE/my-service {uuid}

# Open in browser
bitbottle pipeline view MYWORKSPACE/my-service {uuid} --web

# JSON output
bitbottle pipeline view MYWORKSPACE/my-service {uuid} --json buildNumber,state,refName,duration,webURL
Run
# Trigger a pipeline on a branch (--branch is required)
bitbottle pipeline run MYWORKSPACE/my-service --branch main

# Trigger on a feature branch
bitbottle pipeline run MYWORKSPACE/my-service --branch feature/my-feature
Flag Default Description
--branch β€” Required. Branch to run the pipeline on

Note: Pipelines are a Bitbucket Cloud feature. Running any pipeline command against a Server / Data Center host returns an error.


πŸ€– MCP Server (AI Assistant Integration)

bitbottle mcp serve starts a Model Context Protocol server over stdio. Claude Desktop, Claude Code, and any MCP-compatible client can call Bitbucket operations as native tools β€” no raw API requests, no output parsing.

Tools exposed
Tool Description
list_hosts List all configured Bitbucket hosts
list_repos List repositories
get_repo Get a single repository
create_repo Create a repository
delete_repo Delete a repository
list_prs List pull requests
get_pr Get a single pull request
create_pr Create a pull request
merge_pr Merge a pull request
approve_pr Approve a pull request
get_pr_diff Get the unified diff for a pull request
list_branches List branches in a repository
create_branch Create a new branch
delete_branch Delete a branch
list_tags List tags in a repository
create_tag Create a tag
delete_tag Delete a tag
update_pr Update PR title and/or description
decline_pr Decline a pull request
unapprove_pr Remove approval from a pull request
ready_pr Mark a draft PR as ready for review
request_review Add reviewers to a pull request
list_commits List commits for a repository
get_commit Get a single commit by hash
list_pipelines List pipelines (Cloud only)
get_pipeline Get a single pipeline by UUID (Cloud only)
run_pipeline Trigger a pipeline on a branch (Cloud only)
get_current_user Get the authenticated user

Every tool accepts an optional hostname parameter. When only one host is configured, hostname can be omitted.

Setup

Claude Desktop β€” add to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "bitbottle": {
      "command": "bitbottle",
      "args": ["mcp", "serve"]
    }
  }
}

Claude Code β€” add to .mcp.json in your project root:

{
  "mcpServers": {
    "bitbottle": {
      "command": "bitbottle",
      "args": ["mcp", "serve"]
    }
  }
}

The MCP server uses the same ~/.config/bitbottle/hosts.yml config and credentials as the CLI β€” no separate auth setup needed.


🐚 Shell Completion

# bash
bitbottle completion --shell bash >> ~/.bash_profile

# zsh
bitbottle completion --shell zsh >> ~/.zshrc

# fish
bitbottle completion --shell fish > ~/.config/fish/completions/bitbottle.fish

# PowerShell
bitbottle completion --shell powershell >> $PROFILE
Flag Short Required Values
--shell -s yes bash, zsh, fish, powershell

βš™οΈ Backend Routing

bitbottle automatically routes API calls to the correct backend:

Hostname backend_type in config Routes to
bitbucket.org (any / empty) ☁️ Bitbucket Cloud
anything else (empty) 🏒 Server / Data Center
any hostname cloud ☁️ Bitbucket Cloud (forced)
any hostname server 🏒 Server / DC (forced)

Same commands, same output format β€” regardless of backend.

Cloud vs Server/DC differences (handled internally)
Concern Cloud Server / DC
REST base api.bitbucket.org/2.0 HOST/rest/api/1.0
Repo path /repositories/{workspace}/{slug} /projects/{key}/repos/{slug}
PR path /pullrequests/{id} (no hyphen) /pull-requests/{id}
Approve PR POST .../approve PUT .../participants/~
Delete branch DELETE .../refs/branches/{branch} DELETE .../branches (JSON body)
Pagination Cursor (next URL) Keyset (isLastPage + nextPageStart)
Error shape {"type":"error","error":{"message":".."}} {"errors":[{"message":".."}]}
Current user GET /user GET /users/~

πŸ—‚οΈ Configuration Reference

Config file: ~/.config/bitbottle/hosts.yml

Field Type Default Description
oauth_token string β€” Bearer token (preferred)
user string β€” Username (populated automatically on login)
git_protocol string ssh ssh or https
skip_tls_verify bool false Skip TLS cert check (Server/DC self-signed)
backend_type string "" "" (auto), cloud, or server

Auth header precedence: Bearer <oauth_token> β†’ Basic <user>:<empty> β†’ none.


πŸ”Œ Architecture

bitbottle
β”œβ”€β”€ api/backend/        # Shared domain types + Client interface (12 capabilities)
β”œβ”€β”€ api/cloud/          # Bitbucket Cloud adapter (api.bitbucket.org)
β”œβ”€β”€ api/server/         # Bitbucket Server/DC adapter
β”œβ”€β”€ api/internal/httpx/ # Shared HTTP transport (internal – not importable externally)
β”œβ”€β”€ internal/bbinstance # Host detection, URL builders, version helpers
β”œβ”€β”€ internal/config     # hosts.yml read/write
└── pkg/cmd/            # CLI commands (cobra)
    β”œβ”€β”€ auth/           # auth login / logout / status / token / refresh
    β”œβ”€β”€ branch/         # branch list / delete / create / checkout
    β”œβ”€β”€ commit/         # commit log / view
    β”œβ”€β”€ completion/     # completion --shell bash|zsh|fish|powershell
    β”œβ”€β”€ mcp/            # mcp serve β€” MCP stdio server
    β”œβ”€β”€ pipeline/       # pipeline list / view / run (Cloud only)
    β”œβ”€β”€ pr/             # pr list / create / merge / approve / view / diff / checkout / edit / decline / unapprove / ready / request-review
    β”œβ”€β”€ repo/           # repo list / create / delete / clone / view
    └── tag/            # tag list / create / delete

The Backend factory returns a backend.Client β€” a composite of single-method interfaces. Commands depend only on the methods they use, so they work identically against Cloud and Server with no if cloud { ... } branching. Pipeline commands additionally require a backend.PipelineClient, which is only implemented by the Cloud adapter. pr request-changes uses the Cloud-only optional-interface pattern (type assertion). The MCP server is a thin translation layer on top of the same factory and client.


πŸ§ͺ Testing

# All tests
go test ./...

# With race detector
go test -race ./...

# Benchmarks (Cloud and Server JSON decode, N=100)
go test -bench=. ./api/cloud/ ./api/server/

# Coverage
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out

Coverage targets: β‰₯ 80% on api/cloud, api/server, and pkg/cmd/*.


πŸ› οΈ Contributing

See CONTRIBUTING.md.


πŸ“„ License

MIT

Directories ΒΆ

Path Synopsis
api
cloud
Package cloud is the Bitbucket Cloud adapter for the backend.Client interface.
Package cloud is the Bitbucket Cloud adapter for the backend.Client interface.
internal/httpx
Package httpx is the shared HTTP transport used by the Bitbucket Server/DC and Cloud API adapters.
Package httpx is the shared HTTP transport used by the Bitbucket Server/DC and Cloud API adapters.
server
Package server is the Bitbucket Data Center (a.k.a.
Package server is the Bitbucket Data Center (a.k.a.
cmd
bitbottle command
Package git wraps internal/run.Runner to provide git-specific operations.
Package git wraps internal/run.Runner to provide git-specific operations.
internal
run
pkg
test

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL