Skip to content

LintSync ​

Keep ESLint, Prettier, and Stylelint configs in sync with a shared preset, across one project or many — without losing local overrides.

Features ​

  • Point edits, not full-file rewrites — LintSync writes preset rules directly into your existing config files (no extends package to install); your comments, quote style, and formatting outside the touched keys are preserved.
  • Per-key ownership — a small .lintsync/manifest.json tracks which keys the preset last applied, so a plain preset update and a rule you changed by hand are never confused with each other.
  • Conflict resolution, not silent overwrites — a key that differs from both the manifest and the current preset is a conflict: LintSync opens an interactive TUI to resolve it (or fails safely in CI), and never writes it half-way.
  • Four built-in presets — vue-app, react-app, npm-lib, and a generic base, each bundling ESLint/Prettier/Stylelint rules plus the dependencies to install. Presets live inside LintSync itself, so npm update -g lintsync is how you get preset updates — no separate config package to publish or version.
  • Build and save your own preset — an interactive constructor pulls Prettier's live option list and roughly 80 Stylelint rules straight from the official -recommended/-standard configs, and saves the result locally for reuse across every project on the machine.
  • Batch mode across many projects — a registry of known projects, taggable and filterable, lets sync/status run with --all across every one of them at once, with a single aggregate exit code for CI.
  • JSON/JSONC, YAML, and JS/TS config files — including modern ESLint flat config arrays (export default [...]) and CommonJS module.exports.
  • Migrate legacy configs — migrate eslint --to flat and its Prettier/Stylelint equivalents convert a config to a new format or location without ever deleting the source or overwriting an existing target.

How It Works ​

A preset is a built-in (or locally-saved custom) bundle of rules per tool, plus the dependencies it needs and the list of keys it considers its own (managedKeys). lintsync init installs those dependencies, writes each tool's config file from the preset, and records a manifest entry per tool — commit this file.

The manifest is not a source of truth; it's a record of "what the preset last applied." Every sync/status run re-reads the actual config file and compares it against both the manifest and the current preset:

  • File matches the manifest (you haven't touched the key) → quietly update it to the preset's current value.
  • File already matches the preset → nothing to do.
  • File differs from both → conflict. Nothing is written until it's resolved.

get/set/unset edit a config field directly and deliberately leave the manifest untouched — a manual edit is exactly the kind of thing that should show up as a conflict on the next sync, not be silently overwritten.