Two n8n environments drift apart, someone promotes the wrong version by hand, and a client’s automation stops at 2am.
$ chiral push --source dev --target prod
Credential map:
dev_postgres → prod_postgres ✓ found
dev_sendgrid → prod_sendgrid ✓ found
+ My New Workflow (will be created)
+ Invoice Sync [DEV] (will be created as "Invoice Sync")
~ Updated Workflow (active - will be paused briefly)
─ Unchanged Workflow (already up to date - skipped)
⚠ Pushing to prod - review changes above carefully.
? Type "prod" to confirm: prod
✓ Snapshot saved → .chiral/snapshots/20240101T120000Z-a3f2b9c1/
✓ Created My New Workflow
✓ Created Invoice Sync (mapped from "Invoice Sync [DEV]")
✓ Updated Updated Workflow (reactivated)
─ Skipped Unchanged Workflow (already up to date)
✓ Push complete - 2 changes
Deployment: 20240101T120000Z-a3f2b9c1
Next: chiral pull --env prodsh -c "$(curl -sSfL https://chiral.sh/install)" Every import to prod was a guess. You'd find out if it was wrong from the errors.
n8n assigns a new versionId on every save. Chiral diffs the content, so it only flags what actually changed.
Comparing dev → prod
+ New Workflow (will be created - wrong name? run: chiral workflow map)
+ Invoice Sync [DEV] (mapped to "Invoice Sync" in prod but not found - does it exist?)
- Deprecated Workflow (in prod, not in dev)
~ Updated Workflow (modified - versionId differs)
2 added, 1 modified, 1 removed.
Run 'chiral push --source dev --target prod --dry-run' to preview. Comparing dev → prod + New Workflow (will be created - wrong name? run: chiral workflow map) + Invoice Sync [DEV] (mapped to "Invoice Sync" in prod but not found - does it exist?) - Deprecated Workflow (in prod, not in dev) ~ Updated Workflow (modified - versionId differs) 2 added, 1 modified, 1 removed. Run 'chiral push --source dev --target prod --dry-run' to preview.
Same versionId, or a matching content hash after a push, reads as unchanged, and the diff stops crying wolf.
The import looked clean. The workflow ran. The credential wasn't there.
When a remapped credential is missing in the target, the push aborts before touching anything, and prints the exact command to fix it.
Credential map:
dev_postgres → prod_postgres ✓ found
dev_sendgrid → (not mapped) ✗ missing in prod
Cannot push - 1 credential not found in prod. Create it first or run:
chiral credential add sendgrid prod=prod_sendgrid Credential map:
dev_postgres → prod_postgres ✓ found
dev_sendgrid → (not mapped) ✗ missing in prod
Cannot push - 1 credential not found in prod. Create it first or run:
chiral credential add sendgrid prod=prod_sendgrid Chiral migrates credential names between environments, not their secret values. It refuses rather than push a workflow pointed at a credential that is not there.
The last import wins. There's no warning.
It reads the shared audit log and warns when a teammate pushed to prod after your last pull, before you overwrite their work.
⚠ prod was last pushed by alice@example.com 2 hours ago.
You may be overwriting their changes.
Run 'chiral diff --source prod --target dev' to check.
? Push anyway? [y/N]: ⚠ prod was last pushed by alice@example.com 2 hours ago.
You may be overwriting their changes.
Run 'chiral diff --source prod --target dev' to check.
? Push anyway? [y/N]: Detection runs against .chiral/audit.jsonl. It is a warning, not a hard block: you decide whether to continue.
The import broke it. There was no previous version to restore.
Before touching a single workflow, Chiral snapshots the target. If the push breaks something, you have an exact restore point from before it started.
✓ Created My New Workflow
✓ Updated Billing Pipeline
✗ Failed Order Processor (connection timeout)
─ Skipped (2 remaining - not attempted)
✗ Push incomplete - 2 of 5 workflows applied.
Pre-push snapshot saved at .chiral/snapshots/20240101T120000Z-a3f2b9c1/
Upgrade to the paid tier for one-command rollback, or restore manually from the snapshot. ✓ Created My New Workflow
✓ Updated Billing Pipeline
✗ Failed Order Processor (connection timeout)
─ Skipped (2 remaining - not attempted)
✗ Push incomplete - 2 of 5 workflows applied.
Pre-push snapshot saved at .chiral/snapshots/20240101T120000Z-a3f2b9c1/
Upgrade to the paid tier for one-command rollback, or restore manually from the snapshot. The snapshot is written before the first workflow is touched. One-command rollback is a paid feature; the snapshot itself is always yours.
Four failure modes. All of them silent. None of them recoverable without starting over.
Concept: why it’s called Chiral
What it is
A command-line tool that promotes n8n workflows between your own environments.
Chiral runs against the n8n REST API on instances you host. It reads both environments, shows you the real diff, takes a snapshot of the target, and applies only what changed. It never deletes a workflow unless you ask, and it stops when a credential is missing.
The free tier covers diff, push, snapshots, and concurrency detection.
The paid tier adds one-command rollback, gated pushes, and
--delete-removed. Pricing is flat per team, with no per-seat
metering and no usage billing.
tier price notes
─────────────────────────────────────────────────────
free $0 / forever diff, push, snapshots, dry-run
team $79 / month + rollback, gated pushes, audit
─────────────────────────────────────────────────────
n8n Source Control: €800/month · Business plan only.
Chiral runs on CE. tier price notes ───────────────────────────────────────────────────── free $0 / forever diff, push, snapshots, dry-run team $79 / month + rollback, gated pushes, audit ───────────────────────────────────────────────────── n8n Source Control: €800/month · Business plan only. Chiral runs on CE.
Follow CLI releases
Track Chiral releases without polling GitHub.
Feature updates and release notes. No pitch emails. Unsubscribe any time.