Why Bulk Operations?

Moving 500 Jira issues by hand is painful. You open each ticket, click the transition button, confirm the status change, and repeat. At two minutes per issue, that's over 16 hours of clicking. For a single sprint cleanup.

The Jira web UI was designed for working with individual issues, not for mass updates. But real-world Jira administration constantly demands bulk actions: closing out a completed epic, reassigning work after a team change, exporting issues for a quarterly review, or cleaning up stale tickets at the end of a release cycle.

Jira bulk operations from the command line solve this problem. With atlassian-cli, a single command can transition, assign, label, or export hundreds of issues in seconds. The jira bulk subcommand handles concurrency, rate limiting, and error recovery automatically -- so you can process your entire backlog without babysitting the operation or hitting API throttle limits.

Bulk Transition

The most common bulk operation is transitioning issues from one workflow state to another. The pattern is always the same: preview first with dry-run, then execute.

Step 1: Preview with dry-run

Always start by seeing which issues match your JQL query. The --dry-run flag shows you exactly what would change without modifying anything:

# Preview: see which issues would be transitioned
atlassian-cli jira bulk transition \
  --jql "project = DEV AND status = 'In Progress'" \
  --transition "Done" \
  --dry-run

This queries all matching issues, displays the count and a sample list, and exits. No issues are modified. You get a clear picture of the blast radius before committing to anything.

Step 2: Execute the transition

Once you've confirmed the right issues are targeted, remove --dry-run and execute:

# Execute the transition for real
atlassian-cli jira bulk transition \
  --jql "project = DEV AND status = 'In Progress'" \
  --transition "Done" \
  --profile prod

The CLI processes issues concurrently with built-in rate-limit handling. Progress is tracked as each issue transitions. Failed transitions (e.g., issues that lack the target workflow state) are logged without halting the batch.

Bulk assign

Reassign all unassigned issues in a project to a specific team member:

# Assign all unassigned issues to a team member
atlassian-cli jira bulk assign \
  --jql "project = DEV AND assignee is EMPTY" \
  --assignee admin@example.com

This is useful after org changes, when a new engineer joins a team, or during triage sessions where you need to distribute work quickly.

Bulk Export

Exporting issues to JSON or CSV lets you analyze Jira data outside of Jira. Feed it into a spreadsheet for stakeholder reporting, pipe it to jq for custom filtering, or archive it for compliance.

# Export all project issues to JSON
atlassian-cli jira bulk export \
  --jql "project = DEV" \
  --output issues.json \
  --format json

# Export to CSV for spreadsheet analysis
atlassian-cli jira bulk export \
  --jql "project = DEV AND type = Bug AND created >= -30d" \
  --output recent-bugs.csv \
  --format csv

JSON exports preserve the full issue structure -- fields, comments, transitions, and metadata. CSV exports flatten the data into rows and columns, ready for Excel or Google Sheets. Both formats handle pagination automatically, fetching all matching issues regardless of the result count.

You can also pipe search results directly into other tools without writing to a file:

# Count bugs by priority using jq
atlassian-cli jira search \
  --jql "project = DEV AND type = Bug" \
  --format json | jq 'group_by(.fields.priority.name) | map({priority: .[0].fields.priority.name, count: length})'

Dry-Run Mode

Every destructive bulk command in atlassian-cli supports --dry-run. This is a core design principle, not an afterthought. Dry-run mode executes the same query logic as a real run -- it finds matching issues, validates transitions, and checks permissions -- but skips the actual mutation.

The safety-first pattern looks like this:

  1. Dry-run. Run the command with --dry-run. Review the output: issue count, sample keys, target states.
  2. Validate. Confirm the JQL matches the right issues. Check that the target transition exists for all matched issue types.
  3. Execute. Remove --dry-run and run again. The CLI processes changes with progress tracking.

This pattern works for transitions, assignments, label updates, and deletions. It prevents the most common mistake in bulk operations: an overly broad JQL query that catches issues you didn't intend to modify.

# Dry-run: preview which issues would get labeled
atlassian-cli jira bulk transition \
  --jql "project = DEV AND status = 'Open' AND created < -90d" \
  --transition "Closed" \
  --dry-run

# Output shows count and sample issues
# [DRY-RUN] Found 147 issues matching criteria
# Sample: DEV-401, DEV-388, DEV-372, DEV-365, ...
# Would transition 147 issues to: Closed

Concurrency Control

Bulk operations run concurrently by default, processing multiple issues in parallel to save time. The --concurrency flag controls how many API requests are made simultaneously.

# Default concurrency (4 parallel requests)
atlassian-cli jira bulk transition \
  --jql "project = DEV AND status = 'Open'" \
  --transition "In Progress"

# Lower concurrency for rate-limited instances
atlassian-cli jira bulk transition \
  --jql "project = DEV AND status = 'Open'" \
  --transition "In Progress" \
  --concurrency 2

# Higher concurrency for large batches
atlassian-cli jira bulk transition \
  --jql "project = DEV AND status = 'Open'" \
  --transition "In Progress" \
  --concurrency 8

The default concurrency of 4 works well for most Atlassian Cloud instances. If you're on a plan with stricter rate limits, reduce it to 2. For enterprise instances with higher API quotas, you can push it to 8 or higher. The CLI automatically backs off when it receives a 429 (Too Many Requests) response, so even aggressive concurrency settings won't cause permanent failures.

Rate limiting is handled transparently. When the Atlassian API returns a rate-limit response, the CLI waits the required interval and retries. This means you can queue up a 2,000-issue transition and walk away -- it will complete without manual intervention, throttling itself as needed.

Real-World Example: Sprint Cleanup

Here's a complete sprint cleanup workflow that combines multiple bulk operations. This is the kind of script you'd run at the end of every sprint to keep your Jira board clean.

#!/bin/bash
# Sprint cleanup: close stale issues, reassign, export report
set -euo pipefail

PROFILE="prod"
PROJECT="DEV"

# Step 1: Close issues that have been "Done" for 7+ days
atlassian-cli jira bulk transition \
  --profile "$PROFILE" \
  --jql "project = $PROJECT AND status = 'Done' AND updated < -7d" \
  --transition "Closed" \
  --dry-run

# Step 2: Reassign unassigned bugs to the triage lead
atlassian-cli jira bulk assign \
  --profile "$PROFILE" \
  --jql "project = $PROJECT AND type = Bug AND assignee is EMPTY" \
  --assignee triage-lead@company.com

# Step 3: Export the sprint's completed work for the retro
atlassian-cli jira bulk export \
  --profile "$PROFILE" \
  --jql "project = $PROJECT AND sprint in closedSprints() AND status = Done" \
  --output sprint-report.json \
  --format json

# Step 4: Count remaining open issues
atlassian-cli jira search \
  --profile "$PROFILE" \
  --jql "project = $PROJECT AND status != Done AND status != Closed" \
  --format json | jq '. | length'

echo "Sprint cleanup complete."

This script runs in under a minute for most projects. The dry-run on step 1 lets you verify the transition targets before removing the flag for a live run. The export in step 3 gives you data for your retrospective. And the final count tells you how much work is still open.

For the full production-ready version of this script with argument parsing, confirmation prompts, and error handling, see the Jira Bulk Transition Runbook.

FAQ

How do I bulk transition Jira issues from the command line?

Use atlassian-cli jira bulk transition with a JQL query. Start with --dry-run to preview affected issues, then remove the flag to execute. Example: atlassian-cli jira bulk transition --jql "project = DEV AND status = 'In Progress'" --transition "Done" --dry-run. The CLI handles concurrency and rate limiting automatically.

Can I preview bulk Jira changes before applying them?

Yes. Every bulk command in atlassian-cli supports a --dry-run flag. Dry-run mode queries the matching issues, shows you exactly what would change -- issue count, sample keys, target states -- and exits without modifying anything. This safety-first approach prevents accidental mass updates across your Jira instance.

Does bulk Jira CLI handle API rate limits?

Yes. atlassian-cli has built-in rate-limit handling with automatic backoff. You can control parallelism with the --concurrency flag (default: 4 concurrent requests). When the Atlassian Cloud API returns a 429 response, the CLI waits the required interval and retries automatically. This prevents throttle failures even when processing thousands of issues.

Related Resources