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.
What confluence automation looks like from the CLI
Confluence automation means turning the repetitive things you do in the Confluence web UI, refreshing a status page, tagging documents, archiving stale content, and building reports, into scripts that run without a human clicking anything. The command line is where that happens. With atlassian-cli you drive Confluence through one binary, and because it is just a binary, you can drop it into cron, a systemd timer, a CI job, or a git hook.
This post is about the automation-shaped tasks specifically: scheduled updates, bulk operations across many pages, and generating report pages from data. If you want to mirror Jira issues into a Confluence page, that is a distinct workflow covered in syncing Jira to Confluence. If your goal is a full space archive you can restore later, see exporting and backing up a Confluence space. Here we stay focused on keeping live content fresh and tidy.
atlassian-cli is an independent, community open-source project. It is not Atlassian's official CLI (acli) and is not affiliated with Atlassian. Use the official acli if you want first-party vendor support. Use atlassian-cli if you want a single free Rust binary spanning Jira, Confluence, Bitbucket, and JSM with the same flags across every product.
Here is the map of common Confluence chores and the command that automates each one. Every command below is verified against the command reference.
| Task | Command |
|---|---|
| Refresh a page's content | confluence page update <id> --body report.html |
| Tag many pages at once | confluence bulk add-labels --cql "..." --labels a,b |
| Find stale pages | confluence search cql "lastmodified < now('-180d')" |
| Remove old pages | confluence bulk delete --cql "..." --dry-run |
| Pull page data for a report | confluence bulk export --cql "..." --output data.json |
| Check page traffic | confluence analytics page-views <id> --from 2026-01-01 |
Scheduled page updates with cron
atlassian-cli does not ship a scheduler, and it does not need to. The Unix ecosystem already has excellent ones. The pattern for a scheduled Confluence page update has three moving parts: a script that builds the page body into an HTML file, the confluence page update command that publishes it, and a cron entry that runs the script on a timer.
The important detail is that --body takes a file path, not an inline string. The file must contain Confluence storage-format HTML (ordinary tags like <p>, <table>, and <h2> work fine). So the update step looks like this:
# Publish new content to an existing page from a file
atlassian-cli confluence page update 12345 \
--title "Team Status (auto-updated)" \
--body ./status.html \
--profile prod
Each update creates a new page version, so the edit history stays intact and you can roll back through the Confluence UI if a run produces something unexpected. To generate the file first, pull whatever data you need and write HTML to disk. A minimal builder using a heredoc:
# build-status.sh -- regenerate the status page body
open_count=$(atlassian-cli jira issue search \
--jql "project = DEV AND status != Done" \
--format json --profile prod | jq '. | length')
cat > ./status.html <<HTML
<h2>Engineering status</h2>
<p>Open issues in DEV: <strong>${open_count}</strong></p>
<p>Last refreshed: $(date -u +"%Y-%m-%d %H:%M UTC")</p>
HTML
atlassian-cli confluence page update 12345 --body ./status.html --profile prod
Now schedule it. A crontab line that refreshes the page every weekday at 06:00 looks like this:
# crontab -e
0 6 * * 1-5 /home/ops/build-status.sh >> /var/log/confluence-status.log 2>&1
That is the whole trick. The page updates itself before anyone starts their day, and the log file gives you an audit trail. On a server without cron, a systemd timer or a scheduled CI pipeline runs the exact same script. Keep the script idempotent: it should produce the same page from the same data no matter how often it runs, so a missed or doubled execution never corrupts the result. The set -euo pipefail header matters too, because it stops the run the moment a query fails instead of publishing a half-built page.
Generating a self-refreshing report page
A scheduled update becomes a report the moment the body is built from real data instead of static text. The recipe is always the same: query with --format json, reshape the JSON into HTML, then publish. Because every atlassian-cli command speaks the same --format flag, the data source can be Jira, Bitbucket, JSM, or Confluence itself.
Suppose you want a weekly documentation-health page that lists how many pages exist in a space and which ones have not been touched recently. Pull the counts with CQL search, then feed them into the page:
# Count pages in the space and stale ones separately
total=$(atlassian-cli confluence search cql \
"space = DOCS AND type = page" --format json | jq '. | length')
stale=$(atlassian-cli confluence search cql \
"space = DOCS AND type = page AND lastmodified < now('-180d')" \
--format json | jq '. | length')
cat > ./docs-health.html <<HTML
<h2>Docs health report</h2>
<table>
<tr><th>Metric</th><th>Value</th></tr>
<tr><td>Total pages</td><td>${total}</td></tr>
<tr><td>Stale (>180 days)</td><td>${stale}</td></tr>
</table>
HTML
atlassian-cli confluence page update 45678 --body ./docs-health.html --profile prod
For the raw material behind a report, confluence bulk export dumps every matching page to JSON or CSV in one call, handling pagination for you:
# Export a space to CSV for a spreadsheet pivot
atlassian-cli confluence bulk export \
--cql "space = DOCS AND type = page" \
--output docs-inventory.csv \
--format csv
That CSV opens directly in a spreadsheet if a stakeholder prefers pivots to a Confluence table. The export here is a reporting input. If you need durable, restorable archives instead, the space backup guide covers that end of the spectrum. For a ready-made reporting script, the space report runbook has a production version with argument parsing.
Bulk labels and taxonomy
Labels are what make a large Confluence instance searchable, and they are miserable to apply one page at a time. The confluence bulk add-labels command tags every page that matches a CQL query in a single pass. As with every mutation, preview with --dry-run before committing.
# Preview which pages would be labeled
atlassian-cli confluence bulk add-labels \
--cql "space = DOCS AND type = page" \
--labels reviewed,2026-q3 \
--dry-run
# Apply for real once the match list looks right
atlassian-cli confluence bulk add-labels \
--cql "space = DOCS AND type = page" \
--labels reviewed,2026-q3
The --labels flag is comma-separated, so you can apply several at once. After tagging, that same label becomes a query handle. Finding everything marked for a quarterly review is one search:
atlassian-cli confluence search cql "label = reviewed AND label = '2026-q3'" --limit 50
For a single page you already have open, page add-label and page remove-label take the page ID and label as positional arguments:
atlassian-cli confluence page add-label 12345 needs-review
atlassian-cli confluence page remove-label 12345 outdated
Cleaning up stale pages safely
Old pages accumulate, and they poison search results long after anyone reads them. The cleanup workflow is: identify with a dated CQL query, archive if you want a record, then delete, always previewing first. CQL's lastmodified field paired with the now() function expresses "not touched in N days" cleanly.
# 1. See what qualifies as stale (read-only)
atlassian-cli confluence search cql \
"space = OLD AND type = page AND lastmodified < now('-365d')" \
--limit 100
# 2. Archive the same set to a file before deleting anything
atlassian-cli confluence bulk export \
--cql "space = OLD AND type = page AND lastmodified < now('-365d')" \
--output archive-before-delete.json --format json
# 3. Dry-run the delete to confirm the blast radius
atlassian-cli confluence bulk delete \
--cql "space = OLD AND type = page AND lastmodified < now('-365d')" \
--dry-run
# 4. Execute once you trust the list
atlassian-cli confluence bulk delete \
--cql "space = OLD AND type = page AND lastmodified < now('-365d')"
The --dry-run flag runs the same selection logic as a real delete but stops before removing anything, so you see the exact pages that would go. Bulk commands also accept --concurrency (default 4) if you need to throttle a large batch on a rate-limited instance. The full, guard-railed version of this routine, with confirmation prompts and logging, lives in the bulk cleanup runbook.
Measuring impact with analytics
Automation is easier to justify when you can show which pages actually get read. The confluence analytics commands surface view counts without leaving the terminal, so you can fold traffic numbers straight into a report page or use them to decide what to archive.
# Views for one page since a start date
atlassian-cli confluence analytics page-views 12345 --from 2026-01-01
# Rolled-up stats for an entire space
atlassian-cli confluence analytics space-stats DOCS --format json
Piped through --format json, these become inputs to the same report-building loop from earlier: a page can list its own view count, or a docs-health report can flag high-traffic pages that are also overdue for review. That combination, popular plus stale, is exactly the content worth prioritizing. Analytics also close the loop on automation itself: after a cleanup run, a week of view data tells you whether the pages you archived were genuinely dead or whether someone still needed them.
A nightly automation script
Here is a single script that ties the pieces together: refresh a status page, tag new documents, dry-run a cleanup, and export an inventory. This is the shape of a real nightly job you would drop into cron.
#!/bin/bash
# confluence-nightly.sh -- refresh, tag, audit
set -euo pipefail
PROFILE="prod"
SPACE="DOCS"
# 1. Rebuild and publish the status page
total=$(atlassian-cli confluence search cql \
"space = $SPACE AND type = page" --format json --profile "$PROFILE" | jq '. | length')
printf '<h2>Docs status</h2><p>Pages: %s</p><p>Updated: %s</p>' \
"$total" "$(date -u +%F)" > ./status.html
atlassian-cli confluence page update 45678 --body ./status.html --profile "$PROFILE"
# 2. Tag anything created in the last day for review
atlassian-cli confluence bulk add-labels --profile "$PROFILE" \
--cql "space = $SPACE AND created >= now('-1d')" \
--labels new,needs-review
# 3. Preview stale pages (never auto-delete unattended)
atlassian-cli confluence bulk delete --profile "$PROFILE" \
--cql "space = $SPACE AND lastmodified < now('-365d')" \
--dry-run
# 4. Snapshot the inventory for the record
atlassian-cli confluence bulk export --profile "$PROFILE" \
--cql "space = $SPACE AND type = page" \
--output "inventory-$(date -u +%F).json" --format json
echo "Nightly Confluence run complete."
Note the deliberate choice to keep step 3 as a dry-run. Publishing and tagging are safe to run unattended, but deletion should stay a reviewed action. The nightly job surfaces the candidates in its log so a human can approve a real cleanup during working hours.
Try atlassian-cli
One free, MIT-licensed binary for Jira, Confluence, Bitbucket, and JSM. Install it and script your first Confluence job in minutes.
Install atlassian-cliFAQ
Can I schedule Confluence page updates from the command line?
atlassian-cli has no built-in scheduler, but it is a single binary that runs cleanly under cron, systemd timers, or CI. Write a script that regenerates your page body into an HTML file, then run atlassian-cli confluence page update <id> --body report.html to publish it. Schedule that script with a cron entry (for example, 0 6 * * 1 for every Monday at 06:00) and the page refreshes on its own.
How do I bulk add labels to Confluence pages?
Use atlassian-cli confluence bulk add-labels with a CQL query and a comma-separated label list, for example: atlassian-cli confluence bulk add-labels --cql "space = DOCS AND type = page" --labels reviewed,2026-q3 --dry-run. Run it with --dry-run first to see which pages match, then remove the flag to apply. Labels are the backbone of a searchable Confluence taxonomy.
Is there a safe way to delete old Confluence pages in bulk?
Yes. Select the pages with a CQL query filtered on lastmodified, and always preview with --dry-run before deleting. For example: atlassian-cli confluence bulk delete --cql "space = OLD AND lastmodified < now('-365d')" --dry-run lists the matches without removing anything. Confirm the list, then rerun without --dry-run. Export the same query first if you want an archive.
Can atlassian-cli generate a Confluence report page automatically?
Yes. Pull data with any atlassian-cli command using --format json, transform it into Confluence storage-format HTML with a script or jq, write it to a file, and publish it with atlassian-cli confluence page update <id> --body report.html. Wrap the whole thing in a scheduled script and you get a self-refreshing dashboard page without touching the web UI.