atlassian-cli is an independent, community open-source project, not affiliated with, endorsed by, or sponsored by Atlassian, and is not Atlassian's official CLI (acli). Product names are used only to identify compatibility.

Why script Atlassian at all

The fastest route to automation for Jira and the rest of the Atlassian suite is not a rules engine or a third-party integration platform. It is a shell script that calls one command-line tool. With atlassian-cli, a single free binary spans Jira, Confluence, Bitbucket, and Jira Service Management, so the same script can query issues, publish a wiki page, open a pull request, and comment on a support ticket without ever leaving the terminal.

This is a cross-product playbook. It is deliberately different from the rule-by-rule recipes in Jira automation examples: instead of focusing on one product, it covers the handful of scripting patterns that stay identical no matter which Atlassian product you point them at. Learn them once and you can wire the four products together into pipelines that run on a schedule, in CI, or on demand.

A note on what this tool is. atlassian-cli is an independent, community open-source project under the MIT license. It is not Atlassian's official CLI (acli) and is not affiliated with, endorsed by, or sponsored by Atlassian. Use the official acli when you need first-party vendor support; use atlassian-cli when you want a single binary spanning Jira, Confluence, Bitbucket, and JSM with consistent JSON, CSV, and YAML output built for scripting.

The building blocks every script shares

Before writing any automation, it helps to know the small vocabulary that every atlassian-cli script reuses. Almost every playbook you will ever build is a combination of these five ideas.

Goal Pattern Why it matters
Target the right site --profile prod One saved profile per Atlassian site keeps credentials out of the script.
Machine-readable output --format json Pipe straight into jq and feed the result to the next command.
Stable list parsing --envelope Wraps list output as {"data": [...], "count": N} so paths never shift.
Fail fast in CI --format quiet Emits an exit code only, so you can gate a pipeline on &&.
Preview destructive ops --dry-run Every bulk command shows what would change before you commit.

Two of these deserve a closer look. First, profiles. Authenticate once per site and mark a default, then reference it by name from any script:

# Save a profile once (token comes from an env var, never inline)
atlassian-cli auth login --profile prod \
  --base-url https://acme.atlassian.net \
  --email you@acme.com \
  --token "$ATLASSIAN_TOKEN" --default

# Confirm it works before a script does anything else
atlassian-cli auth test --profile prod --format quiet

Second, JSON plus jq. Because every product returns the same structured output, one mental model works everywhere. The --envelope flag makes the shape predictable, so your jq filters read .data[] instead of guessing at the top-level structure.

# List issue keys, one per line
atlassian-cli jira issue search \
  --jql "project = ENG AND status = Done" \
  --format json --envelope | jq -r '.data[].key'

For the full flag catalogue, keep the command reference and authentication guide open in another tab. Everything below is built from these primitives.

Automation for Jira: the entry point

Most teams start their automation for Jira before anything else, because Jira is where the work lives. A good first script does nothing dangerous: it reads. Turn a JQL query into a formatted digest you can drop into a standup message or a report.

#!/usr/bin/env bash
set -euo pipefail
PROFILE=prod

# Everything closed in the active sprint, as a bullet list
atlassian-cli jira issue search \
  --profile "$PROFILE" \
  --jql "project = ENG AND sprint in openSprints() AND status = Done" \
  --format json --envelope \
  | jq -r '.data[] | "- \(.key): \(.fields.summary)"'

Once the read side behaves, add writes. The single-issue verbs mirror the bulk ones, so you can prototype against one ticket, then scale the exact same logic to a JQL result set with the jira bulk family. The golden rule for anything that mutates data: dry-run first, then execute.

# Preview a bulk transition (no changes made)
atlassian-cli jira bulk transition \
  --profile prod \
  --jql "project = ENG AND status = 'In Review' AND updated < -14d" \
  --transition "Done" \
  --dry-run

# Reassign stale unassigned bugs to the triage lead
atlassian-cli jira bulk assign \
  --profile prod \
  --jql "project = ENG AND type = Bug AND assignee is EMPTY" \
  --assignee triage-lead@acme.com

Individual updates use the same shape, which is handy when a script needs to react to one specific issue rather than a query:

atlassian-cli jira issue transition ENG-482 --transition "In Progress"
atlassian-cli jira issue update ENG-482 --summary "Rename service to billing-api"
atlassian-cli jira issue assign ENG-482 --assignee you@acme.com

For a production-hardened version of a bulk workflow with argument parsing and confirmation prompts, see the bulk transition runbook.

Chaining products in one script

This is where a single binary earns its keep. Because Jira, Confluence, Bitbucket, and JSM all live behind the same command, a script can hand data from one product to the next with a plain shell variable. No API clients, no glue code, no juggling auth libraries.

Jira to Confluence: an automated release note

Collect the issues shipped in a release, then publish them as a Confluence page in one pass:

#!/usr/bin/env bash
set -euo pipefail
PROFILE=prod
SPACE=ENG
VERSION="2026.7"

# 1. Pull completed issues for the release version
items=$(atlassian-cli jira issue search \
  --profile "$PROFILE" \
  --jql "project = ENG AND fixVersion = \"$VERSION\" AND status = Done" \
  --format json --envelope \
  | jq -r '.data[] | "<li>\(.key): \(.fields.summary)</li>"')

# 2. Publish them as a Confluence page
atlassian-cli confluence page create \
  --profile "$PROFILE" \
  --space "$SPACE" \
  --title "Release notes $VERSION" \
  --body "<h2>Shipped in $VERSION</h2><ul>$items</ul>"

The whole flow is two commands joined by a variable. Swap confluence page create for confluence blog create if you prefer a dated blog post instead of a page.

Bitbucket and JSM in the same loop

Reviewing what is open across repositories is another read-first pattern. List pull requests, then act on them:

# Open PRs on a repo, newest activity first
atlassian-cli bitbucket --workspace acme pr list api-service \
  --state OPEN --limit 20

# Comment on a specific PR from a script
atlassian-cli bitbucket --workspace acme pr comment api-service 123 \
  --text "Automated check passed. Ready for human review."

Jira Service Management fits the same way. When an automated deploy check fails, open a request so the incident is tracked from the start:

atlassian-cli jsm request create \
  --servicedesk-id 10 \
  --request-type-id 7 \
  --summary "Deploy failed: api-service on main" \
  --description "Pipeline failed at the integration stage. Investigating."

# Later, add a public update on the same request
atlassian-cli jsm request add-comment SD-123 \
  --body "Root cause found, fix deploying now." --public

None of these commands know about each other, and that is the point. Each returns predictable output, so the shell is the only orchestration you need to stitch a Jira query to a Confluence page to a Bitbucket comment to a JSM ticket.

Safety rails for unattended runs

A script you run by hand and watch is forgiving. A script on a schedule is not. Three habits keep automation safe when nobody is looking.

  1. Gate on auth. Start every script with atlassian-cli auth test --profile prod --format quiet. If the token expired, the script stops before it touches data instead of failing halfway through a batch.
  2. Dry-run destructive commands. Every bulk command across Jira, Confluence, and Bitbucket supports --dry-run. Run it, read the count, and only remove the flag when the number matches your intent. An overly broad query is the most common cause of a bad mass update.
  3. Fail fast. Begin scripts with set -euo pipefail so a single failed command halts the pipeline rather than letting errors cascade into later steps.

Concurrency is a fourth lever. Bulk operations run several requests in parallel by default; the --concurrency flag lets you dial that up for large batches or down for rate-limited sites. The CLI backs off automatically when the API returns a throttle response, so even aggressive settings will not cause permanent failures.

# Preview first, then run with lower concurrency on a strict plan
atlassian-cli confluence bulk add-labels \
  --cql "space = DOCS AND type = page" \
  --labels reviewed \
  --dry-run

atlassian-cli confluence bulk add-labels \
  --cql "space = DOCS AND type = page" \
  --labels reviewed \
  --concurrency 2

Scheduling: cron and CI

Because atlassian-cli is a single binary that reads its token from an environment variable, it drops into any scheduler without extra setup. A cron entry that runs a nightly cleanup script looks like this:

# crontab -e : run the sprint digest every weekday at 09:00
0 9 * * 1-5  ATLASSIAN_TOKEN=... /home/ci/scripts/sprint-digest.sh >> /var/log/atlassian.log 2>&1

In CI, the same idea applies. Store the API token as a masked secret, expose it as ATLASSIAN_TOKEN, and gate the job on the quiet auth check so the pipeline fails cleanly if credentials are wrong:

# A CI step: block the job unless auth succeeds
atlassian-cli auth test --profile prod --format quiet \
  && ./scripts/publish-release-notes.sh

The --format quiet and --format json outputs are what make this reliable: quiet gives you a clean exit code for gating, and JSON gives downstream steps something machine-readable to parse. For a printable summary of every command used here, the atlassian-cli cheat sheet collects them in one place, and the broader atlassian-cli guide covers installation and first-run setup.

Try atlassian-cli

One free, MIT-licensed binary for Jira, Confluence, Bitbucket, and JSM. Install it and start scripting in minutes.

Install atlassian-cli

FAQ

What is the easiest way to start automation for Jira with scripts?

Save one auth profile, then call atlassian-cli from a shell script. Start with a read-only query like atlassian-cli jira issue search --jql "project = ENG AND status = Done" --format json and pipe it to jq. Once the query returns what you expect, wrap it in a bash script with set -euo pipefail and add write operations. Every product uses the same binary, flags, and output formats, so one pattern scales from Jira to Confluence, Bitbucket, and JSM.

Can one script touch Jira, Confluence, Bitbucket, and JSM together?

Yes. atlassian-cli is a single binary with subcommands for all four products, so a script can query Jira, publish to Confluence, open a Bitbucket pull request, and comment on a JSM request in sequence. The shared --format json output means you can pipe the result of one command into jq and feed it as an argument to the next. Use one profile per site with the --profile flag to keep credentials consistent across the whole pipeline.

How do I make Atlassian automation scripts safe to run unattended?

Use three habits. First, gate the script on auth with atlassian-cli auth test --profile prod --format quiet so it exits before touching data if credentials are stale. Second, preview every destructive bulk command with --dry-run and only remove the flag once the count looks right. Third, run scripts with set -euo pipefail so a failed command stops the pipeline instead of cascading. For scheduled jobs, read the API token from an environment variable rather than hard-coding it.

Should I use atlassian-cli or Atlassian's official acli for scripting?

They are different tools. acli is Atlassian's official first-party CLI and is the right choice when you need vendor support. atlassian-cli is an independent, community, MIT-licensed open-source project. Reach for it when you want a single free binary that spans Jira, Confluence, Bitbucket, and Jira Service Management with consistent JSON, CSV, and YAML output for scripting. It is not affiliated with Atlassian.

Related Resources