🚀 n8n-local-sync
A lightweight, developer-first GitOps CLI for versioning, validating, and synchronizing n8n workflows.
What is it?
n8n-local-sync bridges the gap between your n8n instances and Git. By treating your n8n workflows as code, you can leverage standard software engineering practices—like version control, peer reviews, CI/CD, and automated deployments—for your automations.
Why?
Managing n8n workflows through the UI is great for building, but challenging for lifecycle management. Simple backups aren't enough. You need version-controlled workflow management.
With n8n-local-sync, you can:
- Track changes meaningfully using deterministic hashing.
- Review workflow changes in Git pull requests with clean diffs.
- Safely promote workflows across environments (dev → staging → prod) via CI/CD pipelines.
Features
- 🔄 Bidirectional Syncing: Seamlessly pull (
sync/export) and push (import) workflows using the official n8n REST API. - 🧠 Smart State Tracking: Detects
LOCAL_MODIFIED,REMOTE_MODIFIED, andCONFLICTstates before destructive actions. - 🛡️ Validation & Security: Catch invalid JSON structures and detect potential hardcoded secrets (heuristically).
- 🌲 Git-Native: Cleans workflow metadata and normalizes node order for deterministic, clean
git diffoutputs. - 🧪 Dry-Run Mode: Simulate changes (
--dry-run) across all destructive commands before applying them. - 🏷️ Tag Filtering: Target specific environments or modules during export using the
--tagflag. - 🤖 CI/CD Ready: Configure your environment dynamically using
.envfiles or environment variables.
Architecture
graph TD
A[n8n Instance] <-->|REST API| B(n8n-local-sync)
B -->|Export / Pull| C[Local Git Repository]
B -->|Validate / Diff| C
C -->|Import / Push| B
C -->|Commit / Push| D[GitHub / GitLab]
D -->|CI/CD Actions| B
Installation
You can install n8n-local-sync directly from PyPI (once published) or from the source:
pip install n8n-local-sync
Quick Start
- Initialize and export:
# Initialize project configuration
n8n-sync init
# Set your API credentials in the generated .env file
# Export workflows from your n8n instance
n8n-sync export
# Version control the results
git add n8n/workflows/ .n8n-sync.yaml
git commit -m "chore: initial workflow export"
git push
- Synchronize changes:
# See what changed between local and remote
n8n-sync diff
n8n-sync status
# Pull remote changes safely (won't overwrite local modifications)
n8n-sync sync
# Push local changes back to n8n
n8n-sync push
Configuration
Configuration resolves in the following priority:
- CLI Arguments (
--force,--dry-run) - Environment Variables (
N8N_API_KEY,N8N_BASE_URL) - Config File (
.n8n-sync.yaml)
[!IMPORTANT] Never store your
N8N_API_KEYin the.n8n-sync.yamlfile. Always use environment variables or a.envfile (which is ignored by Git).
🔄 Synching (Pulling) Remote Changes
Update your local repository with changes made directly in the n8n UI. The sync command evaluates the state of each workflow and avoids overwriting local modifications unless forced.
n8n-sync sync # or n8n-sync pull
GitOps States Handled During Pull:
UNCHANGED: Skipped safely.REMOTE_MODIFIED: Remote changes are pulled, updating the local file.LOCAL_MODIFIED: Skipped with a warning (to protect local unpushed work). Use--forceto overwrite local changes.CONFLICT(both changed): Skipped with a warning. Use--forceto overwrite local with remote.REMOTE_ONLY: New remote workflows are pulled and saved locally.LOCAL_ONLY: Ignored by pull (usepushto upload them).
Note: Deletions are not automatically synced in either direction to prevent accidental data loss. If you delete a workflow in n8n, delete the local file manually.
📤 Pushing Local Changes
Upload your local Git-versioned workflows to the remote n8n instance. Like pull, push is state-aware.
n8n-sync import # or n8n-sync push
GitOps States Handled During Push:
UNCHANGED: Skipped safely.LOCAL_MODIFIED: Pushed to remote, updating the n8n workflow.REMOTE_MODIFIED: Skipped with a warning (to protect remote changes). Use--forceto overwrite remote changes.CONFLICT(both changed): Skipped with a warning. Use--forceto overwrite remote with local.LOCAL_ONLY: Creates a new workflow in n8n. The local file is automatically updated with the new ID assigned by n8n.REMOTE_ONLY: Ignored by push (usepullto download them).
CLI Reference
n8n-sync init: Initializes a project, creating.n8n-sync.yamland.env.example.n8n-sync sync(aliaspull): Safely synchronizes remote workflows to local files. Warns on conflicts.n8n-sync import(aliaspush): Pushes local workflows to the remote n8n instance.n8n-sync export: Forces an export of all (or tagged) remote workflows to local files.n8n-sync diff: Shows a granular, structural diff between local and remote workflows.n8n-sync status: Displays a summary table of workflow synchronization states (e.g.,LOCAL_MODIFIED,CONFLICT).n8n-sync validate: Runs structural and security heuristic validations against local workflow JSON files.
Common Flags:
--dry-run: Simulate operations without modifying local files or the remote n8n instance.--force: Force overwrite conflicts or local modifications duringsync.
Git Workflow
The typical GitOps flow looks like this:
- Build a workflow in your Dev n8n instance.
- Run
n8n-sync syncto pull it down locally. - Review the structural changes using
git diff. - Create a Pull Request.
- On merge, a CI/CD pipeline runs
n8n-sync validateandn8n-sync pushto deploy the workflow to Production.
Security
- Heuristic Secret Scanning: The
validatecommand detects potential hardcoded secrets (api_key,token,password, etc.) in workflow nodes. Note: This is a heuristic detection, not a strict guarantee. - No Credentials Exposed: The CLI is designed to never output API keys or authorization headers in error logs or standard output.
n8n Compatibility
- Supported/Tested Versions: n8n
0.164.0and above. - API Requirements: Requires the n8n Public REST API (v1) to be enabled and accessible. Legacy CLI hacks are not supported.
Development
# Clone the repository
git clone https://github.com/DanielDPereira/n8n-local-sync.git
cd n8n-local-sync
# Install with development dependencies
pip install -e .[dev]
# Run linting
ruff check src/ tests/
We bundle a pre-commit hook that runs n8n-sync validate.
pre-commit install
Testing
# Run unit tests
pytest tests/
Integration Testing
You can use the provided docker-compose.yml to spin up an ephemeral n8n instance for testing:
docker compose up -d
The instance will be available at http://localhost:5678.
CI/CD
This project uses GitHub Actions for CI/CD:
- CI: Runs
pytest,ruff, andpython -m buildon all PRs and pushes tomain. - Publish: Uses PyPI Trusted Publishing (OIDC) to securely publish new releases on tag.
Roadmap
- CLI foundation
- Export/import
- Git-friendly workflow files (canonicalization)
- Validation (Heuristic secret scanning)
- Diff & Status (State tracking)
- Dry-run safe mode
- CI and PyPI packaging readiness
- Integration test suite with Docker
- Multi-environment support (
--env prod) - Workflow promotion logic
License
This project is licensed under the MIT License.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file n8n_local_sync-0.1.0.tar.gz.
File metadata
- Download URL: n8n_local_sync-0.1.0.tar.gz
- Upload date:
- Size: 19.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9a82c59d4821af21ebb269da66de9bc41ca94e689d834853194053dc24e77f8f
|
|
| MD5 |
92aa9e25e067b8b1d9d7c352367d0f22
|
|
| BLAKE2b-256 |
357276ac59f4abd85db2e5626a138968d0fb76d57de70e232b2478c445223039
|
Provenance
The following attestation bundles were made for n8n_local_sync-0.1.0.tar.gz:
Publisher:
publish.yml on DanielDPereira/n8n-local-sync
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
n8n_local_sync-0.1.0.tar.gz -
Subject digest:
9a82c59d4821af21ebb269da66de9bc41ca94e689d834853194053dc24e77f8f - Sigstore transparency entry: 2645487393
- Sigstore integration time:
-
Permalink:
DanielDPereira/n8n-local-sync@03ceb96f31651567d2365de9957c3a722af97648 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/DanielDPereira
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@03ceb96f31651567d2365de9957c3a722af97648 -
Trigger Event:
release
-
Statement type:
File details
Details for the file n8n_local_sync-0.1.0-py3-none-any.whl.
File metadata
- Download URL: n8n_local_sync-0.1.0-py3-none-any.whl
- Upload date:
- Size: 21.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0c86621cbe44da29dd00eec049de8dc04cab698c9975e823ca6252324d6fbb26
|
|
| MD5 |
6f01817792823f8810c6e5e5a2bdaf02
|
|
| BLAKE2b-256 |
10d083dc12dd8e551c85e314e3f05ffbf09b3de86f1313f4bab7167ab2394e01
|
Provenance
The following attestation bundles were made for n8n_local_sync-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on DanielDPereira/n8n-local-sync
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
n8n_local_sync-0.1.0-py3-none-any.whl -
Subject digest:
0c86621cbe44da29dd00eec049de8dc04cab698c9975e823ca6252324d6fbb26 - Sigstore transparency entry: 2645487530
- Sigstore integration time:
-
Permalink:
DanielDPereira/n8n-local-sync@03ceb96f31651567d2365de9957c3a722af97648 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/DanielDPereira
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@03ceb96f31651567d2365de9957c3a722af97648 -
Trigger Event:
release
-
Statement type: