| name | ruff-sync |
| description | Configure and operate ruff-sync to synchronize Ruff linter settings across Python projects. Use when the user wants to set up ruff-sync, sync Ruff config from an upstream source, check for configuration drift, integrate ruff-sync into CI, troubleshoot sync issues, or keep Ruff rules consistent across multiple repositories. |
ruff-sync Usage
ruff-sync pulls a canonical Ruff configuration from an upstream URL and merges it into your local project, preserving comments, whitespace, and per-project overrides.
Quick Start
uv tool install ruff-sync
ruff-sync https://github.com/my-org/standards
git diff pyproject.toml
Persist Configuration
Add to pyproject.toml so you don't need to pass CLI args every time:
[tool.ruff-sync]
upstream = "https://github.com/my-org/standards"
exclude = [
"target-version",
"lint.per-file-ignores",
"lint.ignore",
"lint.isort.known-first-party",
]
Then just run ruff-sync (no arguments needed).
See references/configuration.md for all config keys and defaults.
Common Workflows
Initial Project Setup
Setup Progress:
- [ ] 1. Install ruff-sync (uv tool install ruff-sync)
- [ ] 2. Check for `.pre-commit-config.yaml` — if present, ensure the `ruff` hook is used
- [ ] 3. Add `[tool.ruff-sync]` to `pyproject.toml` with upstream URL and exclusions
- [ ] 4. If `.pre-commit-config.yaml` exists, set `pre-commit-version-sync = true` in `[tool.ruff-sync]`
- [ ] 5. Run `ruff-sync` to pull the upstream config
- [ ] 6. Review `git diff`
- [ ] 7. Fix any new lint errors: `uv run ruff check . --fix`
- [ ] 8. Commit
Upstream Layers (multi-source)
Stack multiple upstream sources — later entries win on conflict:
[tool.ruff-sync]
upstream = [
"https://github.com/my-org/python-standards",
"https://github.com/my-org/ml-team-tweaks",
]
CI Drift Check
CI Setup Progress:
- [ ] 1. Add ruff-sync check step to CI workflow (see references/ci-integration.md)
- [ ] 2. Decide: --semantic for value-only checks, or full string comparison
- [ ] 3. Set output format: --output-format github for PR annotations
- [ ] 4. Set exit-code expectations (0 = in sync, 1 = config drift, 2 = pre-commit only)
- [ ] 5. Verify locally: `ruff-sync check --semantic`
Keep the ruff-pre-commit hook version in .pre-commit-config.yaml aligned with the project's Ruff version.
Recommendation: Always prefer the persistent TOML configuration over the ephemeral --pre-commit CLI flag.
[tool.ruff-sync]
pre-commit-version-sync = true
Then run ruff-sync — it updates the hook rev automatically. Exit code 2 means only the hook version is out of sync (Ruff config itself is fine).
Exit Codes
| Code | Meaning |
|---|
0 | In sync — no action needed |
1 | Ruff config is out of sync with upstream |
2 | Config is in sync, but pre-commit hook version is stale (only when --pre-commit is active) |
URL Formats Supported
All of these work as the upstream value:
ruff-sync https://github.com/my-org/standards
ruff-sync https://github.com/my-org/standards/tree/main/cfg
ruff-sync https://github.com/my-org/standards/blob/main/ruff.toml
ruff-sync https://raw.githubusercontent.com/my-org/standards/main/pyproject.toml
ruff-sync git@github.com:my-org/standards.git
CLI Reference (Short)
| Flag | Meaning |
|---|
--validate | Validate merged config with Ruff before writing; aborts if Ruff rejects it |
--strict | Like --validate but also treats warnings (version mismatch, deprecated rules) as failures. Implies --validate |
--output-format | text (default), json, github, gitlab, sarif (auto-detected in CI) |
--semantic | Ignore whitespace/comments in check |
--pre-commit | Sync .pre-commit-config.yaml hook version |
--save | Persist CLI args to pyproject.toml |
Gotchas
exclude uses dotted paths, not TOML paths. lint.per-file-ignores refers to the per-file-ignores key inside [tool.ruff.lint]. Do NOT write tool.ruff.lint.per-file-ignores.
--validate is opt-in. Validation is off by default. Pass --validate (or --strict) to run the merged config through Ruff before writing. The sync is aborted if Ruff rejects the config, leaving the local file untouched. This includes a Python version consistency check that compares upstream target-version against local requires-python.
- Excluding
target-version skips consistency validation. If target-version (or tool.ruff.target-version) is in the exclude list, ruff-sync will skip the version consistency check and log a warning. This is useful for projects that intentionally deviate from upstream Python versions.
--strict implies --validate. If you want warnings (like version mismatches or deprecated rules) treated as failures, only --strict is needed — don't pass both.
- Validation soft-fails if
ruff is not on PATH. If the ruff binary can't be found, a warning is logged and the sync continues normally.
- Use
--init only for new projects. ruff-sync requires an existing pyproject.toml or ruff.toml. Pass --init to scaffold one if the directory is empty. This will automatically generate a [tool.ruff-sync] configuration block for future syncs.
- Use
--save to persist CLI arguments. If you want to update an existing pyproject.toml with a new upstream URL or exclusion, pass --save to write the new configuration to the file.
--semantic ignores comments and whitespace. Use it in CI to avoid false positives from cosmetic local edits. Omit it for strict byte-for-byte checks.
- SSH URLs trigger a shallow clone.
git@github.com:... URLs use git clone --filter=blob:none --depth=1 — no git credential issues as long as SSH auth is configured.
- Later upstreams win in
upstream lists. In a multi-source list, keys set by entry 2 overwrite keys from entry 1.
- Config discovery order matters. When targeting a directory,
ruff-sync looks for ruff.toml -> .ruff.toml -> pyproject.toml in that order.
- Pre-commit exit code 2 is intentional. A
2 exit from ruff-sync check means the Ruff config is fine, only the pre-commit hook tag is stale. You may want to treat this differently from a full config drift (exit 1) in CI.
- Prefer TOML for pre-commit sync. While
--pre-commit works on the CLI, setting pre-commit-version-sync = true in pyproject.toml is the recommended way to ensure hook versioning stays consistent for all contributors.
References