Unified CLI for Jira, Confluence, Bitbucket & JSM
Automate your entire Atlassian Cloud stack from the terminal. Bulk operations, dry-run mode, multiple output formats (JSON/CSV/YAML/table), and profile-based multi-instance support.
Independent open-source project.
atlassian-cliis not affiliated with, endorsed by, sponsored by, or maintained by Atlassian. Atlassian maintains its own separate official CLI (acli). Atlassian, Jira, Confluence, Bitbucket, and Jira Service Management are trademarks of Atlassian Pty Ltd; product names are used here only to identify compatibility.
Full documentation, command references, and how-to guides live on the project site:
- Jira guide: issues, projects, bulk operations, workflows
- Confluence guide: spaces, pages, blog posts, attachments
- Bitbucket guide: repos, branches, pull requests, pipelines
- Jira Service Management guide: service desks and requests
- Installation guide: Homebrew, Cargo, and pre-built binaries
- Blog: release notes, tips, and workflow recipes
# Add the tap (first time only)
brew tap omar16100/atlassian-cli
# Install
brew install atlassian-cli
# Verify installation
atlassian-cli --versionRecent Homebrew releases refuse to load a formula from a third-party tap until the tap is trusted. If Homebrew reports "Refusing to load formula ... from untrusted tap", trust the tap, then install or upgrade:
brew trust omar16100/atlassian-cli
brew upgrade atlassian-clicargo install atlassian-cligit clone https://github.com/omar16100/atlassian-cli
cd atlassian-cli
cargo install --path crates/cliDownload the latest release for your platform from the Releases page.
Binaries are built for macOS (Apple Silicon and Intel) and Linux x86_64 (glibc and
musl); see targets in dist-workspace.toml. There are no Windows binaries.
crates/
cli/ # Clap-based binary entry point
api/ # Thin HTTP client wrapper (reqwest)
auth/ # Encrypted credential storage (AES-256-GCM)
config/ # YAML profile loader + config-directory resolution
output/ # Output formatting helpers (table/json/yaml/csv/quiet)
bulk/ # Concurrency + dry-run aware executor
- Install the Rust toolchain (rustup) and ensure
cargois on your PATH. - Fetch dependencies and verify the workspace compiles:
cargo check
- Install the CLI locally so the
atlassian-clibinary is available (ensure~/.cargo/binis in your PATH):cargo install --path crates/cli
- Run the CLI help to inspect current subcommands:
atlassian-cli --help atlassian-cli jira --help atlassian-cli confluence --help atlassian-cli bitbucket --help # or use 'bb' alias atlassian-cli bb --help - Add a profile and API token:
atlassian-cli auth login \ --profile personal \ --base-url https://example.atlassian.net \ --email you@example.com \ --token $ATLASSIAN_API_TOKEN \ --default - List configured profiles (reads
~/.config/atlassian-cli/config.yamlif present):Tip: Useatlassian-cli auth list
cp configs/config.example.yaml ~/.config/atlassian-cli/config.yamlas a starting point before running the login command. - Try the Jira, Confluence, Bitbucket, and JSM commands (requires real data):
# Jira - Issues atlassian-cli jira issue search --jql "project = DEV order by created desc" --limit 5 atlassian-cli jira issue get DEV-123 # Pick the fields you want, by id or by the display name from `jira fields list`. # Columns come back in the order you ask for them; `all` returns everything. atlassian-cli jira issue get DEV-123 --fields summary,status atlassian-cli jira issue get DEV-123 --fields "Story Points" --format json atlassian-cli jira issue get DEV-123 --fields all --format json atlassian-cli jira issue search --project DEV --fields status,"Story Points" --format csv atlassian-cli jira issue create --project DEV --issue-type Task --summary "Test task" # Custom fields: discover IDs via `jira fields list`: atlassian-cli jira issue create --project DEV --issue-type Task --summary "cf test" \ --field 'customfield_10010={"value":"Internal"}' \ --field 'customfield_10020={"formula":"a=b"}' atlassian-cli jira issue update DEV-123 --summary "Updated summary" atlassian-cli jira issue transition DEV-123 --transition "In Progress" atlassian-cli jira issue assign DEV-123 --assignee user@example.com atlassian-cli jira issue delete DEV-123 --force # Jira - Attachments atlassian-cli jira attachment list DEV-123 atlassian-cli jira attachment get 10001 atlassian-cli jira attachment download 10001 # -> ./<server filename> atlassian-cli jira attachment download 10001 --output ./logo.png atlassian-cli jira attachment download 10001 --output - | file - # stream to stdout atlassian-cli jira attachment download --issue DEV-123 --dir ./attachments atlassian-cli jira attachment upload DEV-123 --file ./report.pdf atlassian-cli jira attachment delete 10001 --force # Jira - Raw API access (any endpoint, using the configured profile) atlassian-cli jira api /rest/api/3/myself atlassian-cli jira api /rest/api/3/search/jql --query 'jql=project = DEV' --query maxResults=5 atlassian-cli jira api /rest/api/3/issue/DEV-123 -X PUT -d '{"fields":{"summary":"New"}}' atlassian-cli jira api /rest/api/3/issue/DEV-123 -X PUT -d @payload.json atlassian-cli jira api /rest/api/3/issue/DEV-123 -X DELETE --dry-run # Note: `jira api` stops at cross-origin redirects by design. For attachment # bytes, which redirect to Atlassian's media host, use `jira attachment download`. # Jira - Projects atlassian-cli jira project list atlassian-cli jira project get DEV atlassian-cli jira components list DEV atlassian-cli jira versions list DEV # Jira - Roles atlassian-cli jira roles list DEV atlassian-cli jira roles get DEV 10002 atlassian-cli jira roles actors DEV 10002 atlassian-cli jira roles add-actor DEV 10002 --user user@example.com atlassian-cli jira roles remove-actor DEV 10002 --user user@example.com # Jira - Custom Fields & Workflows atlassian-cli jira fields list atlassian-cli jira workflows list atlassian-cli jira workflows export "Software Simplified Workflow" # Jira - Bulk Operations atlassian-cli jira bulk transition --jql "project = DEV AND status = Open" --transition "In Progress" --dry-run atlassian-cli jira bulk assign --jql "project = DEV AND assignee is EMPTY" --assignee admin@example.com atlassian-cli jira bulk export --jql "project = DEV" --output issues.csv --export-format csv # Jira - Automation & Webhooks atlassian-cli jira automation list atlassian-cli jira webhooks list atlassian-cli jira audit list --from 2025-01-01 --limit 100 # Confluence - Search atlassian-cli confluence search cql "space = DEV and type = page" --limit 5 atlassian-cli confluence search text "meeting notes" --limit 10 atlassian-cli confluence search in-space DEV "api docs" # Confluence - Spaces atlassian-cli confluence space list --limit 10 atlassian-cli confluence space get DEV atlassian-cli confluence space create --key DOCS --name "Documentation" --description "Team docs" atlassian-cli confluence space update DEV --name "Development Space" atlassian-cli confluence space delete OLD --force atlassian-cli confluence space permissions DEV atlassian-cli confluence space add-permission DEV --permission read --subject-type user --subject-id 5b10a2844c20165700ede21g # Confluence - Pages atlassian-cli confluence page list --space DEV --limit 25 atlassian-cli confluence page get 12345 atlassian-cli confluence page create --space DEV --title "New Page" --body "<p>Content</p>" atlassian-cli confluence page update 12345 --title "Updated Title" atlassian-cli confluence page delete 12345 atlassian-cli confluence page versions 12345 atlassian-cli confluence page add-label 12345 documentation atlassian-cli confluence page remove-label 12345 outdated atlassian-cli confluence page comments 12345 atlassian-cli confluence page comments 12345 --replies # walk each thread atlassian-cli confluence page add-comment 12345 "Great work!" atlassian-cli confluence page add-comment 12345 "Agreed" --parent 98765 --kind inline atlassian-cli confluence page get-restrictions 12345 atlassian-cli confluence page add-restriction 12345 --operation update --subject-type user --subject-id 5b10a2844c20165700ede21g atlassian-cli confluence page remove-restriction 12345 --operation update --subject-type user --subject-id 5b10a2844c20165700ede21g # Confluence - Blog Posts atlassian-cli confluence blog list --space DEV --limit 10 atlassian-cli confluence blog get 67890 atlassian-cli confluence blog create --space DEV --title "Sprint Recap" --body "<p>Summary</p>" atlassian-cli confluence blog update 67890 --title "Updated Recap" atlassian-cli confluence blog delete 67890 # Confluence - Attachments atlassian-cli confluence attachment list 12345 atlassian-cli confluence attachment get 11111 atlassian-cli confluence attachment upload 12345 --file ./diagram.png atlassian-cli confluence attachment download 11111 --output ./download.png atlassian-cli confluence attachment delete 11111 --force # Confluence - Bulk Operations atlassian-cli confluence bulk delete --cql "space = OLD AND type = page" --dry-run atlassian-cli confluence bulk add-labels --cql "space = DEV" --labels docs,reviewed --dry-run atlassian-cli confluence bulk export --cql "space = DEV" --output backup.json --export-format json # Confluence - Analytics atlassian-cli confluence analytics page-views 12345 --from 2025-01-01 atlassian-cli confluence analytics space-stats DEV # Bitbucket Commands # Note: You can use 'bb' as a shorthand alias for 'bitbucket' in all commands below # Examples: atlassian-cli bb whoami OR atlassian-cli bitbucket whoami # Bitbucket - User Info atlassian-cli bitbucket whoami # Bitbucket - Repositories atlassian-cli bitbucket --workspace myteam repo list --limit 10 atlassian-cli bitbucket --workspace myteam repo get api-service atlassian-cli bitbucket --workspace myteam repo create newrepo --name "New Repo" --private atlassian-cli bitbucket --workspace myteam repo update api-service --description "Updated description" atlassian-cli bitbucket --workspace myteam repo delete oldrepo --force # Bitbucket - Branches atlassian-cli bitbucket --workspace myteam branch list api-service atlassian-cli bitbucket --workspace myteam branch create api-service feature/new --from main atlassian-cli bitbucket --workspace myteam branch delete api-service feature/old --force atlassian-cli bitbucket --workspace myteam branch protect api-service --pattern "main" --kind restrict_merges --approvals 2 atlassian-cli bitbucket --workspace myteam branch restrictions api-service # Bitbucket - Pull Requests atlassian-cli bitbucket --workspace myteam pr list api-service --state OPEN --limit 5 atlassian-cli bitbucket --workspace myteam pr get api-service 123 atlassian-cli bitbucket --workspace myteam pr create api-service --title "Add feature" --source feature/new --destination main atlassian-cli bitbucket --workspace myteam pr update api-service 123 --title "Updated title" atlassian-cli bitbucket --workspace myteam pr approve api-service 123 atlassian-cli bitbucket --workspace myteam pr merge api-service 123 --strategy merge_commit atlassian-cli bitbucket --workspace myteam pr comments api-service 123 atlassian-cli bitbucket --workspace myteam pr comment api-service 123 --text "Looks good!" # Inline comment anchored to a line on the new (destination) side of the diff atlassian-cli bitbucket --workspace myteam pr comment api-service 123 --text "Nit: rename" --path src/main.rs --line 42 # Inline comment anchored to a removed line on the old (source) side atlassian-cli bitbucket --workspace myteam pr comment api-service 123 --text "Why remove this?" --path src/main.rs --line 17 --side old # Whole-file inline comment (no --line) atlassian-cli bitbucket --workspace myteam pr comment api-service 123 --text "See README" --path README.md atlassian-cli bitbucket --workspace myteam pr reviewers api-service 123 atlassian-cli bitbucket --workspace myteam pr reviewers api-service 123 --all # Replace the reviewers (account UUIDs); title and description are kept atlassian-cli bitbucket --workspace myteam pr update api-service 123 --reviewers {uuid-1},{uuid-2} # Trace every request and response on stderr (tokens and request bodies are never logged) atlassian-cli --debug jira issue get PROJ-123 # Bitbucket - Workspaces & Projects atlassian-cli bitbucket workspace list --limit 10 atlassian-cli bitbucket workspace get myteam atlassian-cli bitbucket --workspace myteam project list atlassian-cli bitbucket --workspace myteam project create PROJ --name "My Project" --private atlassian-cli bitbucket --workspace myteam project delete PROJ --force # Bitbucket - Pipelines (the repository is an argument, --repo, or the git remote) atlassian-cli bitbucket --workspace myteam pipeline list api-service atlassian-cli bitbucket --workspace myteam pipeline get api-service 42 --steps atlassian-cli bitbucket --workspace myteam pipeline steps api-service 42 atlassian-cli bitbucket --workspace myteam pipeline trigger api-service --ref-name main atlassian-cli bitbucket --workspace myteam pipeline stop --repo api-service 42 # status and watch exit 0 successful, 1 failed, 2 in progress or timed out, 3 paused on a manual step atlassian-cli bitbucket --workspace myteam pipeline status api-service --wait # Bitbucket - Webhooks & SSH Keys atlassian-cli bitbucket --workspace myteam webhook list api-service atlassian-cli bitbucket --workspace myteam webhook create api-service --url https://example.com/hook --events repo:push atlassian-cli bitbucket --workspace myteam ssh-key list api-service atlassian-cli bitbucket --workspace myteam ssh-key add api-service --label deploy --key "ssh-rsa ..." # Bitbucket - Permissions & Commits atlassian-cli bitbucket --workspace myteam permission list api-service atlassian-cli bitbucket --workspace myteam permission grant api-service --user-uuid {uuid} --permission write atlassian-cli bitbucket --workspace myteam commit list api-service --branch main atlassian-cli bitbucket --workspace myteam commit diff api-service abc123 atlassian-cli bitbucket --workspace myteam commit browse api-service --commit main --path src/ # Bitbucket - Bulk Operations (list candidates only; --execute applies) # archive-repos disables issues and wiki, it does not archive. # delete-branches does not check whether a branch was merged. atlassian-cli bitbucket --workspace myteam bulk archive-repos --days 180 atlassian-cli bitbucket --workspace myteam bulk delete-branches api-service --exclude feature/keep # JSM atlassian-cli jsm service-desk list --limit 10 atlassian-cli jsm request list --limit 10 atlassian-cli jsm request get SD-123
config.yaml and the encrypted credentials live in one directory, chosen in this
order:
$ATLASSIAN_CLI_CONFIG_DIR, or--config-dir$XDG_CONFIG_HOME/atlassian-cli~/.config/atlassian-cli~/.atlassian-cli(or the older~/.atlcli) if either still holds your files
~/.config is used on macOS as well as Linux. On Windows the default is
%LOCALAPPDATA%\atlassian-cli.
# Move everything, including credentials
export ATLASSIAN_CLI_CONFIG_DIR=/tmp/ci-atlassian
atlassian-cli --config-dir ./scratch auth list
# Move just the config file; credentials stay in the config directory
atlassian-cli --config ./team-config.yaml jira issue search --jql "project = DEV"A relative $XDG_CONFIG_HOME is ignored, as the XDG base directory spec
requires. A relative $ATLASSIAN_CLI_CONFIG_DIR is honoured, since that variable
is this tool's own and ./ci-config is a reasonable thing to write in a job with
a fixed working directory.
An existing install is moved the first time you run any command: the files are
copied to the new location and the old directory is renamed to
~/.atlassian-cli.migrated. Nothing is deleted, and you are told where things
went. The rename is deliberate: a lingering copy that is silently ignored is a
trap, because anything you edit there later has no effect.
Setting $ATLASSIAN_CLI_CONFIG_DIR skips the move entirely: an explicit choice
is taken at face value.
On Unix the directory is created 0700 and both files 0600.
For convenience, the following command aliases are available:
| Full Command | Alias | Description |
|---|---|---|
bitbucket |
bb |
Bitbucket commands |
Example usage:
# Full command
atlassian-cli bitbucket pipeline list --workspace myworkspace
# Using alias (shorter and faster to type)
atlassian-cli bb pipeline list --workspace myworkspace
# Both commands work identically
atlassian-cli bitbucket repo list --workspace myteam
atlassian-cli bb repo list --workspace myteamBitbucket requires a separate scoped API token from Jira/Confluence.
| Product | Token Type | Creation Method |
|---|---|---|
| Jira/Confluence | Regular API token | "Create API token" |
| Bitbucket | Scoped API token | "Create API token with scopes" → select Bitbucket |
Atlassian deprecated Bitbucket app passwords in favor of scoped API tokens. These tokens must be created specifically for Bitbucket with explicit permission scopes.
- Go to https://id.atlassian.com/manage-profile/security/api-tokens
- Click "Create API token with scopes" (not regular "Create API token")
- Select Bitbucket as the app
- Add required scopes:
read:repository:bitbucket- list/view reposwrite:repository:bitbucket- create/update reposread:pullrequest:bitbucket- view PRsadmin:repository:bitbucket- admin operations
- Copy the token
Note: Bitbucket admin:* scopes do NOT include read:* permissions - add both if needed.
The CLI checks these environment variables in order:
| Priority | Variable | Description |
|---|---|---|
| 1 | ATLASSIAN_CLI_BITBUCKET_TOKEN_{PROFILE} |
Profile-specific Bitbucket token |
| 2 | ATLASSIAN_BITBUCKET_TOKEN |
Generic Bitbucket token |
| 3 | BITBUCKET_TOKEN |
Simple fallback |
| 4 | ATLASSIAN_CLI_TOKEN_{PROFILE} |
Falls back to regular token |
# Option 1: Profile-specific (recommended for multiple profiles)
export ATLASSIAN_CLI_BITBUCKET_TOKEN_WORK=your-bitbucket-scoped-token
# Option 2: Generic Bitbucket token (simpler for single profile)
export ATLASSIAN_BITBUCKET_TOKEN=your-bitbucket-scoped-token
# Option 3: Simple fallback
export BITBUCKET_TOKEN=your-bitbucket-scoped-token
# The CLI will use this token for Bitbucket commands
atlassian-cli bitbucket repo list --workspace myteamIf no Bitbucket-specific token is found, commands fall back to the regular ATLASSIAN_CLI_TOKEN_{PROFILE} token.
make fmt/make clippy/make testkeep the workspace tidy using the standard Rust tooling stack (mirrored injust fmt,just clippy, etc.).make install(orjust install) compiles and installs the CLI locally fromcrates/cli.
Unit tests live beside the code in each crate. Integration tests in
crates/cli/tests/ exercise the API client and the built CLI, most of them
against mocked Atlassian APIs (wiremock).
# Run all tests
cargo test --workspace
# Run tests for specific crate
cargo test -p atlassian-cli-config
cargo test -p atlassian-cli-output
cargo test -p atlassian-cli-bulk
# Run integration tests
cargo test --test cli_integration
cargo test --test jira_integration
cargo test --test bitbucket_integration
cargo test --test confluence_integration
# Run tests with output
cargo test -- --nocapturecargo test --workspace on 27 Sep 2026 (commit e3dc5b1, macOS): 927 passed,
0 failed, 1 ignored. The ignored test is a manual check that decrypts a copy of
a real credentials.enc.
| Test target | Tests |
|---|---|
atlassian-cli unit tests (crates/cli/src) |
430 |
CLI integration and end-to-end tests (23 files in crates/cli/tests/) |
260 |
atlassian-cli-api |
84 |
atlassian-cli-config |
65 |
atlassian-cli-output |
56 |
atlassian-cli-auth |
22 (+1 ignored) |
atlassian-cli-bulk |
10 |
The integration files include per-product suites for Jira (24), Bitbucket (23), Bamboo (22), Confluence (20), Opsgenie (14) and JSM (11).
GitHub Actions runs on every pull request and on pushes to main
(.github/workflows/):
ci.yml:cargo fmt --all -- --checkandcargo clippy --all-targets --all-features -- -D warningson Ubuntu, andcargo test --all --no-fail-faston Ubuntu and macOSsecurity.yml:cargo audit(advisory warnings do not fail the job) andcargo denychecks for licenses, bans, sources and advisories, also weeklyrelease.yml: cargo-dist builds the release binaries (macOS and Linux) when a version tag is pushed, and updates the Homebrew tap
Windows is neither built nor tested in CI.
Phase 1 - Foundation (100% complete)
- ✅ Cargo workspace with modular crate structure
- ✅ Config loader with profile support (~/.config/atlassian-cli/config.yaml)
- ✅ API token authentication (Basic auth with email+token)
- ✅ HTTP client with retry, rate limiting, and pagination
- ✅ Multi-format output (table/JSON/CSV/YAML/quiet)
- ✅ Bulk operation executor with concurrency control
- ✅ Unit tests for every crate
- ✅ CI/CD with GitHub Actions
Phase 2 - Jira CLI (100% complete)
- ✅ Issue CRUD operations (create/read/update/delete/search/transition)
- ✅ Issue management (assign/unassign, watchers, links, comments)
- ✅ Project lifecycle (list/get/create/update/delete)
- ✅ Components and versions management
- ✅ Custom fields (list/get/create/delete)
- ✅ Workflows (list/get/export)
- ✅ Bulk operations (transition/assign/label/export/import)
- ✅ Automation rules (list/get/create/update/enable/disable)
- ✅ Webhooks (full CRUD + test)
- ✅ Audit log access (list/export)
- ✅ Role management (list/get/actors/add-actor/remove-actor)
- ✅ Integration tests with API mocking
Phase 4 - Bitbucket CLI (100% complete)
- ✅ Repository CRUD operations (list/get/create/update/delete)
- ✅ Branch management (list/get/create/delete/protect/unprotect)
- ✅ Pull request workflow (list/get/create/update/merge/decline)
- ✅ PR approvals, comments (top-level and inline), and reviewers
- ✅ Branch protection and restrictions
- ✅ Workspace operations (list/get)
- ✅ Project management (list/get/create/update/delete)
- ✅ Pipeline operations (list/get/trigger/stop/logs)
- ✅ Webhooks (list/create/delete)
- ✅ SSH deploy keys (list/add/delete)
- ✅ Repository permissions (list/grant/revoke)
- ✅ Commit operations (list/get/diff/browse)
- ✅ Bulk operations:
archive-reposdisables the issue tracker and wiki on stale repos (Bitbucket Cloud has no archive API),delete-branchesdeletes branches by name without checking merge status. Both only list candidates unless given--execute - ✅ User info (whoami)
- ✅ Integration tests with API mocking
Phase 3 - Confluence CLI (100% complete)
- ✅ Space operations (list/get/create/update/delete/permissions)
- ✅ Page management (CRUD, versions, labels, comments, restrictions)
- ✅ Blog posts (list/get/create/update/delete)
- ✅ Attachments (list/get/upload/download/delete)
- ✅ Search (CQL, text, in-space)
- ✅ Bulk operations (delete, add-labels, export)
- ✅ Analytics (page-views, space-stats)
- ✅ Integration tests with API mocking
Additional Products (Partial)
- ✅ JSM CLI: service desks, requests, queues, approvals, SLAs, customers, organizations, request types, knowledge base and feedback
- ✅ Opsgenie CLI: alerts, incidents, schedules and on-call, teams, escalations, services and heartbeats, US and EU regions
- ✅ Bamboo CLI: projects, plans, plan branches, builds (run, stop, logs, comments, labels), deployments, agents, artifacts, server info and queue
- Opsgenie and Bamboo are covered by mocked-API integration tests
(
crates/cli/tests/opsgenie_integration.rs,bamboo_integration.rs). Remaining roadmap items for all three are in docs/todo.md (Phases 5 to 7).
- JSM: Insight / Assets commands
- Remaining Opsgenie and Bamboo roadmap items (Phases 6 and 7 in docs/todo.md)
- Add recipe documentation for common workflows
- Docker image (release binaries ship on GitHub Releases, and Homebrew via the omar16100/homebrew-atlassian-cli tap)