Rule Keeper sync CLI: step-by-step manual
rule-keeper-sync is a small command-line tool that keeps Rule Keeper up to
date without pasting exports by hand. It runs on your computer or CI
runner, downloads your Jira Automation rules through Atlassian's public
Automation REST API using your API token, normalises them exactly as the
app does, and pushes a signed snapshot to the app.
What this means for security and compliance:
- Your API token never leaves the machine that runs the CLI. The app does not store any credential for your Jira site.
- The app makes no outbound network calls. It stays eligible for Atlassian's Runs on Atlassian badge.
- The app accepts a snapshot only when it is signed (HMAC-SHA256) with a secret you generate in the app. You can rotate or revoke that secret at any time.
- Only a compact summary of each rule is stored: name, state, scope, trigger type, counts of components and a fingerprint of the logic. Rule bodies, smart values and comments are not stored.
This manual is written for a Jira administrator who has never used a command line. Every step shows exactly what to type and what to expect.
1. Prerequisites
| What | Why | How to check |
|---|---|---|
| Jira administrator rights on the site | The Automation API only returns rules to admins | Jira → Settings (cog) → System opens without an error |
| Node.js 22 or newer | Runs the CLI (one file, no other dependencies) | In a terminal: node -v prints v22… or higher |
The file rule-keeper-sync.mjs |
The CLI itself | Provided by NoxDevelopment with the app, see section 3 |
| An Atlassian API token | Authenticates the CLI against Atlassian | Created in section 4 |
| A Rule Keeper sync secret | Authenticates the CLI against the app | Created in section 5 |
1.1 Install Node.js (if node -v fails)
- Open https://nodejs.org/ and download the LTS installer for your
operating system (Windows
.msi, macOS.pkg). - Run the installer with default options.
- Close every terminal window and open a new one (PowerShell on Windows, Terminal on macOS).
- Type
node -vand press Enter. You should see a version starting withv22or higher. If you see "command not found", restart the computer once and try again.
Alternative on Windows: winget install OpenJS.NodeJS.LTS.
2. Find the app in Jira
- In Jira, click the cog icon (top right) → Apps.
- In the left sidebar, under the Apps heading, click Rule Keeper.
- The page has six tabs: Cost, Inventory, Changes, Lint, Upload, Sync. Everything in this manual happens in the Sync tab.
Polish UI: Ustawienia → Aplikacje, then the Aplikacje heading in the left sidebar → Rule Keeper. The tabs are Koszty, Inwentarz, Zmiany, Lint, Wgraj, Synchronizacja.
Direct link pattern (replace the placeholders):
https://<your-site>.atlassian.net/jira/settings/apps/<app id>/<environment id>
The exact link is shown in the browser address bar when you open the page.
3. Get the CLI file
- Download
rule-keeper-sync.mjsandREADME.md(this manual) from the latest release: https://noxdevelopment.pages.dev/rule-keeper/downloads/ - Create a folder for it, for example:
- Windows:
C:\Tools\rule-keeper\ - macOS / Linux:
~/tools/rule-keeper/
- Windows:
- Copy both files into that folder.
- Open a terminal in that folder:
- Windows: open the folder in Explorer, click the address bar, type
powershell, press Enter. - macOS: right-click the folder → Services → New Terminal at Folder, or
cd ~/tools/rule-keeper.
- Windows: open the folder in Explorer, click the address bar, type
- Verify the file runs:
node rule-keeper-sync.mjs --help
You should see a usage text starting with rule-keeper-sync: push your Jira Automation rules to Rule Keeper.
4. Create an Atlassian API token
- Open https://id.atlassian.com/manage-profile/security/api-tokens while logged in as the admin account you want the CLI to use.
- Click Create API token (the classic, unscoped token). Do not choose "Create API token with scopes": scoped tokens do not cover the Automation API and the CLI will get HTTP 403.
- Label:
rule-keeper-sync. Expiry: choose according to your policy; note the date, the CLI will start failing with HTTP 401 when the token expires. - Click Create, then Copy.
- Paste the token into your password manager now. Atlassian will not show it again.
5. Generate the Rule Keeper sync secret
- In the Sync tab click Generate secret.
- A yellow box appears with the secret (starts with
rks_). Click into the box, select all, copy. - Paste it into your password manager next to the API token.
- The box disappears when you leave the page. The app keeps only an encrypted copy and cannot show the secret again. If you lose it, click Rotate secret and use the new one.
Below the buttons the tab shows Your web trigger URL. Copy it as well;
you will pass it to the CLI with --url.
6. First run (dry run)
A dry run downloads and normalises your rules but pushes nothing. It confirms that the token and the site are right before anything reaches the app.
Windows (PowerShell)
$env:ATLASSIAN_API_TOKEN = "<paste the API token>"
node rule-keeper-sync.mjs --site <your-site>.atlassian.net --email <admin e-mail> --dry-run --out rules.json
macOS / Linux (bash or zsh)
export ATLASSIAN_API_TOKEN="<paste the API token>"
node rule-keeper-sync.mjs --site <your-site>.atlassian.net --email <admin e-mail> --dry-run --out rules.json
Expected output (numbers will differ):
[rule-keeper-sync] site acme.atlassian.net, account admin@acme.example
[rule-keeper-sync] cloud id: 3f1c…
[rule-keeper-sync] page 1: 100 rule summaries (total 100)
[rule-keeper-sync] page 2: 82 rule summaries (total 182)
[rule-keeper-sync] fetched 25/182 rules
…
[rule-keeper-sync] fetched 182/182 rules
[rule-keeper-sync] normalised 182 rules (0 parser notes)
[rule-keeper-sync] wrote export-style file rules.json
dry run: 182 rules normalised, written to rules.json
rules.json has the same shape as Jira's own "Export rules" file, so you can
paste it into the Upload tab if you ever prefer a manual snapshot.
Notes:
--siteis the host name only, withouthttps://.- Secrets are read from environment variables only. Never pass them as command-line arguments; they would end up in shell history.
- If the account is not a Jira admin the API returns zero rules or HTTP 403.
7. First real sync
Windows (PowerShell)
$env:ATLASSIAN_API_TOKEN = "<paste the API token>"
$env:RULE_KEEPER_SYNC_SECRET = "<paste the secret>"
node rule-keeper-sync.mjs --site <your-site>.atlassian.net --email <admin e-mail> --url <web trigger URL from the Sync tab>
macOS / Linux
export ATLASSIAN_API_TOKEN="<paste the API token>"
export RULE_KEEPER_SYNC_SECRET="<paste the secret>"
node rule-keeper-sync.mjs --site <your-site>.atlassian.net --email <admin e-mail> --url <web trigger URL from the Sync tab>
Expected last lines:
[rule-keeper-sync] pushing 54 KB to Rule Keeper
[rule-keeper-sync] snapshot accepted
done: 182 rules pushed to Rule Keeper
Then reload the Rule Keeper page:
- the green banner shows the new snapshot with source: sync CLI;
- the Sync tab status box shows Sync active with the time of the last accepted sync and the rule count;
- after the second sync the Changes tab compares the two snapshots.
8. Schedule it
Each run creates one snapshot. The app keeps the 10 most recent snapshots. A daily run is a sensible default; hourly is fine for small sites.
8.1 Windows Task Scheduler
Create a file
C:\Tools\rule-keeper\sync.ps1:$env:ATLASSIAN_API_TOKEN = (Get-Content "C:\Tools\rule-keeper\token.txt" -Raw).Trim() $env:RULE_KEEPER_SYNC_SECRET = (Get-Content "C:\Tools\rule-keeper\secret.txt" -Raw).Trim() node "C:\Tools\rule-keeper\rule-keeper-sync.mjs" --site <your-site>.atlassian.net --email <admin e-mail> --url <web trigger URL> --quiet exit $LASTEXITCODESave the token and the secret in
token.txtandsecret.txtin that folder. Restrict the folder to your Windows account (Properties → Security) so other users cannot read it.Open Task Scheduler → Create Task.
- General: name
Rule Keeper sync, "Run whether user is logged on or not". - Triggers: New → Daily, pick a time.
- Actions: New → Program
powershell.exe, arguments-NoProfile -ExecutionPolicy Bypass -File "C:\Tools\rule-keeper\sync.ps1". - Settings: tick "Run task as soon as possible after a scheduled start is missed".
- General: name
Right-click the task → Run once and check the Sync tab in Jira.
8.2 cron (macOS, Linux)
Create
~/tools/rule-keeper/sync.sh:#!/usr/bin/env bash set -euo pipefail export ATLASSIAN_API_TOKEN="$(cat "$HOME/tools/rule-keeper/token.txt")" export RULE_KEEPER_SYNC_SECRET="$(cat "$HOME/tools/rule-keeper/secret.txt")" node "$HOME/tools/rule-keeper/rule-keeper-sync.mjs" --site <your-site>.atlassian.net --email <admin e-mail> --url <web trigger URL> --quietchmod 700 sync.sh token.txt secret.txtcrontab -eand add a daily run at 06:15:15 6 * * * /home/<you>/tools/rule-keeper/sync.sh >> /home/<you>/tools/rule-keeper/sync.log 2>&1
8.3 GitHub Actions
In a repository you control, add the secrets
ATLASSIAN_API_TOKENandRULE_KEEPER_SYNC_SECRET(Settings → Secrets and variables → Actions).Commit
rule-keeper-sync.mjsto the repository.Add
.github/workflows/rule-keeper-sync.yml:name: rule-keeper-sync on: schedule: - cron: "15 6 * * *" workflow_dispatch: jobs: sync: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 22 - run: node rule-keeper-sync.mjs --site <your-site>.atlassian.net --email <admin e-mail> --url <web trigger URL> --quiet env: ATLASSIAN_API_TOKEN: ${{ secrets.ATLASSIAN_API_TOKEN }} RULE_KEEPER_SYNC_SECRET: ${{ secrets.RULE_KEEPER_SYNC_SECRET }}Run it once from the Actions tab (workflow_dispatch) and check the Sync tab in Jira.
9. Rotating or revoking the secret
- Rotate (Sync tab → Rotate secret): the old secret stops working
immediately. Update
RULE_KEEPER_SYNC_SECRETwherever the command runs. Do this when a person who knew the secret leaves, or on your regular rotation schedule. - Revoke (Sync tab → Revoke secret): the app rejects every sync until a new secret is generated. Existing snapshots stay available.
- Rotating the Atlassian API token does not involve the app: create a
new token (section 4), replace
ATLASSIAN_API_TOKEN, revoke the old token at id.atlassian.com.
10. Reference
Command-line options
| Option | Environment variable | Meaning |
|---|---|---|
--site <host> |
RK_SITE |
Jira site, e.g. acme.atlassian.net |
--email <e-mail> |
RK_EMAIL |
Atlassian account e-mail |
--url <url> |
RK_SYNC_URL |
Web trigger URL from the Sync tab |
--cloud-id <uuid> |
RK_CLOUD_ID |
Skip the tenant lookup (optional) |
| (none) | ATLASSIAN_API_TOKEN |
API token, required |
| (none) | RULE_KEEPER_SYNC_SECRET |
App secret, required unless --dry-run |
--concurrency <n> |
Parallel rule downloads, 1 to 16, default 4 | |
--dry-run |
Download and normalise only | |
--out <file> |
Write an export-style JSON file | |
--json |
Print the summary as JSON on stdout | |
--quiet |
No progress lines on stderr | |
--help |
Usage |
Exit codes
| Code | Meaning | What to do |
|---|---|---|
| 0 | Success | Nothing |
| 2 | Configuration error | Read the message; it lists the missing flag or variable |
| 3 | Atlassian API error | See the HTTP status below |
| 4 | Rejected by the app | See the app status below |
| 5 | Unexpected error | Re-run with the full output and contact support |
Atlassian API HTTP statuses (exit code 3)
| Status | Cause | Fix |
|---|---|---|
| 401 | Wrong e-mail or token, or expired token | Create a new token (section 4) |
| 403 | Account is not a Jira admin on this site, or scoped token | Use an admin account and a classic token |
| 404 | Site name wrong or site has no Automation | Check --site |
| 429 | Rate limit | The CLI retries automatically; lower --concurrency for very large sites |
App HTTP statuses (exit code 4)
| Status | Cause | Fix |
|---|---|---|
| 401 | Wrong secret, clock skew above 5 minutes, or the same request sent twice | Check RULE_KEEPER_SYNC_SECRET; sync the computer clock |
| 403 | No secret configured in the app | Generate one in the Sync tab |
| 400 | Protocol mismatch | Update the CLI file |
| 413 | Snapshot above 4 MB | Contact support |
| 405 | URL is not the web trigger | Copy the URL from the Sync tab again |
| 402 | The Rule Keeper license on this site is not active | Renew the subscription in Jira settings → Apps → Manage apps |
What is sent to the app
One JSON document per run, signed with HMAC-SHA256:
{
"version": 1,
"source": "SyncCliSource",
"site": "acme.atlassian.net",
"cloudId": "…",
"generatedAt": "2026-10-10T21:00:00.000Z",
"rules": [
{
"id": "<rule uuid>", "name": "…", "state": "ENABLED",
"scope": { "type": "PROJECT", "projectIds": ["10010"] },
"trigger": { "type": "jira.issue.event.trigger:created", "label": "Issue created" },
"stats": { "actions": 2, "conditions": 1, "branches": 0, "depth": 2 },
"componentTypes": ["CONDITION:jira.issue.condition", "ACTION:jira.issue.edit"],
"labels": [], "authorAccountId": "…", "actorAccountId": "…",
"created": "…", "updated": "…", "notifyOnError": "FIRSTERROR",
"writeAccessType": "UNRESTRICTED", "canOtherRuleTrigger": false,
"usesConnections": false, "fingerprint": "653eed85"
}
],
"warnings": []
}
Headers: X-RuleKeeper-Version: 1, X-RuleKeeper-Timestamp: <unix seconds>,
X-RuleKeeper-Signature: v1=<hex HMAC-SHA256(secret, "<timestamp>.<body>")>.