Fire-and-Fuck-GET (and more) with Bitbucket.
Bitbucket CLI tool written in Ada. They didn’t make one. I had to.
GitHub has gh. GitLab has glab. Codeberg has tea. SourceHut has hut.
Bitbucket has… nothing. Atlassian, a company worth billions, couldn’t be bothered to make a CLI for their own product. So here we are.
This isn’t a passion project. This is a tool that should have existed a decade ago, built out of necessity by someone who got tired of clicking through a web UI like it’s 2005.
-
A command-line interface for Bitbucket Cloud
-
Written in Ada/SPARK for reliability (not because it’s trendy—because it works)
-
A drop-in equivalent to
gh/glab/teafor Bitbucket workflows -
AGPL-licensed, because if Atlassian wants to use it, they can open-source their improvements
-
An official Atlassian product (obviously)
-
A Bitbucket Server/Data Center client (Cloud only, for now)
-
A full reimplementation of the Bitbucket web UI
-
A replacement for
gititself -
Enterprise-grade™ with paid support tiers and a sales team
In scope:
-
Repository management (create, list, delete, clone URLs)
-
Pull request workflows (list, create, merge, review)
-
Authentication and credential management
-
Mirroring between forges
-
Pipelines status and basic management
-
Interactive TUI for common operations
Out of scope (use the web UI):
-
Bitbucket admin/workspace settings
-
Complex permission matrices
-
Jira integration configuration
-
Billing and subscription management
-
Anything that requires OAuth2 web flows
-
auth login- Authenticate with Bitbucket app password -
auth status- Show authentication status
-
repo create- Create a new repository (public or private) -
repo list- List all repositories in workspace -
repo delete- Delete a repository (with confirmation) -
repo exists- Check if repository exists
| Component | Installation |
|---|---|
GNAT (Ada compiler) |
|
GPRbuild |
|
curl |
Usually pre-installed |
git clone https://github.com/hyperpolymath/bitfuckit.git
cd bitfuckit
gprbuild -P bitfuckit.gprThe binary will be in bin/bitfuckit.
# User install
cp bin/bitfuckit ~/.local/bin/
# System install
sudo cp bin/bitfuckit /usr/local/bin/bitfuckit supports multiple credential sources, checked in priority order:
| Priority | Source | Notes |
|---|---|---|
1. RGTV (Svalinn vault) |
Post-quantum encrypted identity vault |
Recommended for security |
2. Environment variables |
|
Good for CI/CD |
3. Config file |
|
Interactive login |
4. |
|
Standard netrc format |
Store your Bitbucket credentials in the Reasonably Good Token Vault for post-quantum encrypted storage.
# Install svalinn-cli (if not already installed)
guix profile install github:hyperpolymath/reasonably-good-token-vault
# Initialize and unlock the vault
svalinn-cli init
svalinn-cli unlock
# Add your Bitbucket credentials
svalinn-cli add rest-api --name "bitbucket" --host bitbucket.org
# Enter your username and Atlassian API token when prompted
# Verify bitfuckit can see the credentials
bitfuckit auth status|
Important
|
Bitbucket uses Atlassian API Tokens with Scopes, not app passwords. Generate a token at https://id.atlassian.com/manage-profile/security/api-tokens |
export BITBUCKET_USERNAME=your-username
export BITBUCKET_API_TOKEN=your-api-token
export BITBUCKET_WORKSPACE=your-workspace # optional, defaults to username-
Get an Atlassian API token from https://id.atlassian.com/manage-profile/security/api-tokens
-
Required scopes:
-
repository:read -
repository:write -
repository:delete
-
-
Authenticate:
bitfuckit auth login
# Enter username, API token, and workspace# Create repositories
bitfuckit repo create my-new-repo
bitfuckit repo create my-private-repo --private
bitfuckit repo create my-repo --description "My awesome project"
# List repositories
bitfuckit repo list
# Check if repository exists
bitfuckit repo exists my-repo
# Delete repository (requires confirmation)
bitfuckit repo delete my-repo# List open pull requests
bitfuckit pr list my-repo
# List merged PRs
bitfuckit pr list my-repo --state MERGED
# List all PRs regardless of state
bitfuckit pr list my-repo --allOutput:
Pull Requests in my-repo:
#42 [OPEN] Fix authentication bug (John Doe)
#41 [OPEN] Add dark mode support (Jane Smith)
Total: 2 pull request(s)# From within a git repository
cd my-github-repo
bitfuckit mirror my-repo
# Creates repo on Bitbucket if needed, pushes all branchesCredentials are resolved in cascade order. The first complete set wins:
-
RGTV (Svalinn vault) — Queries
svalinn-cli get-by-host bitbucket.org. Requiressvalinn-clion PATH and an unlocked vault. -
Environment variables —
BITBUCKET_USERNAME,BITBUCKET_API_TOKEN(or legacyBITBUCKET_APP_PASSWORD),BITBUCKET_WORKSPACE. -
Config file —
~/.config/bitfuckit/config(created bybitfuckit auth login). -
~/.netrc — Standard
machine bitbucket.org/login/passwordtriple.
Use bitfuckit auth status to see which source is active.
bitfuckit/
├── src/
│ ├── bitfuckit.adb # Main CLI entry point
│ ├── config.ads/adb # Configuration & credential storage
│ ├── rgtv.ads/adb # RGTV integration & credential cascade
│ ├── bitbucket_api.ads/adb # REST API client
│ ├── tui.ads/adb # Terminal UI (SPARK verified spec)
│ └── graphql_server.ads/adb # GraphQL API server
├── graphql/
│ └── schema.graphql # Full GraphQL schema
├── bitfuckit.gpr # GPRbuild project file
└── bin/ # Build outputFire-and-Fuck-GET (and more) - everything the CLI can do, the GraphQL API can do too.
# Start GraphQL server on default port 4060
bitfuckit graphql serve
# Custom port
bitfuckit graphql serve --port 8080
# With playground enabled
bitfuckit graphql serve --playground# List repositories
query {
repositories {
nodes {
slug
name
isPrivate
links { html }
}
}
}
# Create a repository
mutation {
createRepository(input: {
name: "my-new-repo"
isPrivate: true
description: "Created via GraphQL"
}) {
success
repository {
slug
links { html }
}
}
}
# Mirror from GitHub
mutation {
mirror(input: {
source: "https://github.com/user/repo"
targetName: "repo-mirror"
allBranches: true
}) {
success
branchesPushed
}
}Every CLI command has a GraphQL equivalent:
| CLI Command | GraphQL Operation |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The full schema is in graphql/schema.graphql.
bitfuckit includes a resilient multi-forge mirroring system with automatic fallback.
┌─────────────┐
│ GitHub │ ← Primary (single source of truth)
│ (hub) │
└──────┬──────┘
│
┌─────────────────┼─────────────────┐
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ GitLab │◄─────►│SourceHut│◄─────►│Codeberg │
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
└─────────────────┴─────────────────┘
Fallback meshNormal Mode: All pushes come from GitHub (single source of truth).
Degraded Mode: If GitHub becomes unreachable, the most recently synced spoke becomes a temporary source. Clear warnings are displayed when operating in degraded mode.
Recovery: When GitHub comes back online, run forge-recover to re-establish it as the source and sync all spokes.
# Check health of all forges
just forge-health
# Mirror repository to all healthy forges (with automatic fallback)
just forge-mirror my-repo
# Sync to a specific forge
just forge-sync my-repo codeberg
# Recover from degraded mode (re-sync all from GitHub)
just forge-recover my-repo
# Mirror bitfuckit itself
just mirror-selfWhen GitHub is unreachable:
-
System automatically detects the most recently synced spoke
-
Uses that spoke as temporary source
-
Displays clear WARNING banner about degraded operation
-
Tracks sync timestamps for recovery
╔════════════════════════════════════════════════════════════════╗
║ WARNING: OPERATING IN DEGRADED MODE ║
║ ║
║ Primary source (GitHub) is unreachable. ║
║ Using fallback: gitlab ║
║ ║
║ Data may be stale. Will auto-recover when GitHub is back. ║
╚════════════════════════════════════════════════════════════════╝bitfuckit also works with the simpler forge-mirror script for basic multi-forge workflows:
# Check status of all forges
forge-mirror status
# Push to all forges including Bitbucket
forge-mirror push my-repo --forges github,gitlab,bitbucket,codeberg,radiclebitfuckit uses the Bitbucket REST API v2.0:
-
Base URL:
https://api.bitbucket.org/2.0 -
Authentication: Basic Auth with Atlassian API token
-
Endpoints:
-
GET /repositories/{workspace}- List repos -
POST /repositories/{workspace}/{repo}- Create repo -
DELETE /repositories/{workspace}/{repo}- Delete repo -
GET /repositories/{workspace}/{repo}- Get repo details -
GET /repositories/{workspace}/{repo}/pullrequests- List pull requests
-
-
✓ Authentication (login/status)
-
✓ Repository CRUD operations
-
✓ GitHub mirror
-
✓ Interactive TUI
-
✓ Pull request listing (
pr list)
-
❏ Pull request create/merge/decline
-
❏ Issue tracking
-
❏ Pipeline status
-
❏ Webhook management
Contributions welcome! Please:
-
Fork the repository
-
Create a feature branch
-
Ensure code compiles with GNAT
-
Submit a pull request
SPDX-License-Identifier: CC-BY-SA-4.0
Copyright © 2025-2026 Jonathan D.A. Jewell (hyperpolymath)
This program is free software: you can redistribute it and/or modify it under the terms of the Palimpsest-MPL License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
-
Reasonably Good Token Vault (RGTV) - Secure credential storage
-
forge-mirror - Universal git forge mirror script
|
Note
|
This is an unofficial community tool. It is not affiliated with, endorsed by, or supported by Atlassian Pty Ltd. Bitbucket® is a registered trademark of Atlassian Pty Ltd. All product and company names are trademarks™ or registered® trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them. |
|
Important
|
A note on corporate priorities Atlassian—a company valued at over $50 billion USD—has provided no official command-line interface for Bitbucket. Not in 2015. Not in 2020. Not now. Every other major git forge recognized that developers live in the terminal and provided first-class CLI tooling. Atlassian apparently disagrees, or simply doesn’t care enough to allocate engineering resources to what has become a basic expectation for modern developer tooling. This tool exists because the gap in functionality was too large to ignore. It was built out of necessity, not passion. The PMPL license ensures that if Atlassian ever decides to incorporate any of this work, they must contribute back to the community they have thus far neglected to serve. We remain hopeful that Atlassian will eventually prioritize developer experience over enterprise feature bloat and provide an official CLI. Until then, |