Skip to content

Sync & Status ​

The everyday pair: status looks at drift without writing anything, sync applies the safe part of it.

Checking status ​

lintsync status shows drift from the preset without ever writing anything — the read-only sibling of sync --dry-run.

bash
lintsync status [options]
bash
lintsync status
lintsync status --all --tag type:npm-package

Unlike sync, a conflict here is just a state of the project, not a failure of the command: status exits 0 as long as it could actually read the config and find the preset, even if there's a conflict to look at. Only a genuine execution error (bad manifest, unknown preset, unreadable file) is non-zero.

Options ​

--cwd <path> ​

Project directory. Default: the current directory.

--tool <name> ​

Restrict the check to one tool (eslint, prettier, or stylelint).

--all ​

Run across every project in the registry instead of one --cwd — see Projects & Batch Mode.

--tag <tag> ​

Combined with --all, restricts the batch to projects carrying this tag. Has no effect without --all.

--registry <path> ​

Combined with --all, use a project registry file somewhere other than the default — see Projects & Batch Mode.

--json ​

Machine-readable output.

--quiet ​

Suppress output on success.

--verbose ​

Also print the manifest's recorded value for each conflict, not just the local and preset values.

Applying changes ​

lintsync sync compares the current project against its preset and applies the safe changes.

bash
lintsync sync [options]
bash
lintsync sync                # preview: shows what would change, writes nothing without --yes
lintsync sync --yes          # apply non-conflicting changes
lintsync sync --dry-run      # explicit preview, never writes even with --yes
lintsync sync --tool eslint  # restrict to one tool

Example output — a real run with one conflict, in the default (non-quiet, non-verbose) view:

eslint (eslint.config.mjs) — preset npm-lib@0.1.0
  ✗ 1 conflict:
      rules.no-console (local: "warn", preset: "error")

prettier (.prettierrc.json) — preset npm-lib@0.1.0
  ✓ up to date

Total: 2 tools, 1 conflict. Exit code: 1

When run in a real terminal without --dry-run/--yes/--json, a conflict opens an interactive TUI instead of just reporting it — see Resolving a conflict below. In CI (no TTY) or with --json, a conflict is reported and left completely untouched.

A conflict on one key withholds all pending changes for that tool's file until it's resolved — nothing is written half-way. "Keep local" or a manual value from the TUI is a per-run decision, not a permanent pin: the manifest has no field for "intentionally diverges forever," so the same conflict can resurface on a later sync if the file or the preset changes again.

Options ​

--tool <name> ​

Restrict the sync to one tool.

--dry-run ​

Preview only — never writes, even together with --yes.

-y, --yes ​

Apply non-conflicting changes. Required to actually write anything; without it (and without --dry-run), sync still only previews.

--all ​

Run across every project in the registry — see Batch mode below.

--tag <tag> ​

Combined with --all, restricts the batch to projects carrying this tag.

--registry <path> ​

Combined with --all, use a project registry file somewhere other than the default.

--cwd <path> ​

Project directory. Default: the current directory.

--json ​

Machine-readable output.

--quiet ​

Suppress output on success.

--verbose ​

Print every changed key individually (one per line) instead of a single comma-joined summary line, and also print the manifest's recorded value for each conflict.

Batch mode ​

Pass --all to run sync across every project in the registry (see Projects & Batch Mode) instead of one --cwd:

bash
lintsync sync --all                    # every registered project
lintsync sync --all --tag type:site    # only projects tagged type:site
lintsync sync --all --yes

Batch runs are always non-interactive — a conflict is reported per project, never opens the TUI.

Resolving a conflict (the TUI) ​

In a real terminal, without --dry-run/--yes/--json, a sync conflict opens an interactive resolver instead of failing:

  • Left/Right arrow — page between conflicts, without requiring a resolution first.
  • Up/Down arrow — move the cursor between the three choices: Accept preset, Keep local, Edit manually.
  • Enter — commit the highlighted choice. Choosing Edit manually instead enters a text-input mode, seeded with the file's current value.
  • Inside manual-edit mode: typing edits the buffer, Enter commits it (parsed as JSON when it's valid JSON, a plain string otherwise — the same rule set uses), Escape cancels back to the option list without recording anything, Backspace deletes the last character.

A live preview line always shows what the currently-highlighted (or currently-typed) choice would actually produce. The resolver shows a three-way diff for the page's conflict — the local file's value, the manifest's last-applied value, and what the preset currently wants:

Conflict 1/2: rules.no-console
 Local: "warn"
 Manifest (was): "off"
 Preset (would be): "error"

  ▸ Accept preset
    Keep local
    Edit manually

Preview: "error"

Resolving every page's conflict applies the whole batch (both your resolutions and any already-planned non-conflicting changes for that tool) in one write — a tool you touched here ends up fully in sync, never half-applied.

Exit codes ​

CodeMeaning
0Success — no changes needed, changes applied, or (for status) just observed
1Unresolved conflict (sync only) — also the exit code for an ordinary command-line usage mistake (an unknown flag, a missing required argument) on any command, not just a sync conflict
2Execution error — file/preset not found, unsupported format, parse failure, an edit that can't be made safely
3Batch mode only (--all): projects disagreed on their exit code

The same table applies to sync, status, init, get, set, unset, and migrate — though in practice get/set/unset/migrate only ever return 0 or 2 (they have no notion of a "conflict" or a batch run).