Skip to content

CLI reference

Commands: check, fix, new, baseline, explain, init.

shapelint check

Loads the nearest config, checks every file claimed by a rule, prints the findings, and exits with a status code.

bash
shapelint check
  • Config discovery walks up from the current directory looking for shapelint.config.ts, .js, or .mjs. You can run it from any subfolder.
  • Globs in each rule's files are resolved relative to the config's root.
  • First-match-wins: a file claimed by an earlier rule is not re-checked by a later one.

Exit codes

CodeMeaning
0No violations (or warn-severity findings only).
1One or more error-severity findings.
2Operational failure, no config, invalid config, no rules, or a bad pattern.

Exit 2 is distinct from 1 on purpose: it means Shapelint could not do its job, not that your code failed. CI should treat both as failures but can message them differently.

--format

Overrides the config output field:

FormatUse
humanDefault. Colorized, self-contained diagnostics.
agentSame text, color stripped, for piping into an AI agent.
jsonStructured (version: 1, summary, full diagnostics array).
githubGitHub Actions workflow annotations (::error file=…,line=…::…).
bash
shapelint check --format json
shapelint check --format github   # inline annotations in a PR

--semantic

Runs the AI/semantic tier in addition to the deterministic checks. Requires a judge in the config; without one, Shapelint warns and skips the pass. Semantic findings are warnings unless a rule opts into blocking.

bash
shapelint check --semantic

--cache

Persists a content-hash cache in .shapelint/check-cache.json so unchanged files skip the parse/match work on the next run, useful in CI (restore the cache between runs) and pre-commit.

bash
shapelint check --cache

Correctness is preserved by construction: only the pure, content-derived checks (pattern, filename, imports, usage) are cached, keyed by the file's content hash and a hash of the config. Filesystem-dependent checks (requires, belongsHere, unmatched) are always recomputed, and any config change invalidates the whole cache. Commit .shapelint/check-cache.json or not, as you prefer, it is safe to delete at any time.

Running without installing

If Shapelint isn't a dependency of the target project, use a plain-object config and invoke the built CLI by path:

bash
node /path/to/shapelint/dist/cli.js check

shapelint init

Writes a starter shapelint.config.ts with one example rule to edit. It detects whether your project uses a src/ directory (to set root), nothing else is inferred from your code; the rules are yours to write. Refuses to overwrite an existing config.

bash
shapelint init

Inferring a config from your actual code (a full-repo scan that proposes rules from the shapes it finds) is a v2 idea, not what init does today.

shapelint baseline

Turning Shapelint on in an existing repo can surface hundreds of violations at once. baseline records the current failures so they stop failing the build, new violations still fail, and you fix the grandfathered ones over time.

bash
shapelint baseline          # grandfather every current error
shapelint baseline --prune  # drop entries that no longer fail

Writes .shapelint/baseline.json (commit it). A baseline entry is a fingerprint of file + rule + code, deliberately excluding line numbers, so editing elsewhere in a file doesn't churn the baseline. check then suppresses matching errors and reports them as N grandfathered.

shapelint new <rule> <Name>

Scaffolds a conforming file from a rule's pattern, the file is correct by construction, so the agent starts from the right shape instead of being corrected afterwards. Prevention beats correction.

bash
shapelint new ui-component Card
# → src/components/ui/Card.tsx, matching the ui-component pattern

The target directory comes from the rule's files glob (its literal prefix), and the filename from the rule's filename spec. $Name / $name / $NAME placeholders in the pattern are substituted from <Name> (given in PascalCase). Refuses to overwrite an existing file.

shapelint explain <file>

Prints which rule claims a file and why (the matched glob, filename spec, import and usage rules), then runs that rule against the file and reports whether it conforms. This answers "why did / didn't this fire".

bash
shapelint explain src/components/ui/Button.tsx

shapelint fix

Applies the mechanical, judgment-free fixes Shapelint can make with certainty. Anything requiring a naming or decomposition decision is left for you (or the agent), those are reported by check as usual.

bash
shapelint fix            # dry run: list what would change, write nothing
shapelint fix --write    # apply the fixes
shapelint fix --write --force   # apply even if the git tree is dirty

Currently fixes:

DiagnosticFix
ARCH_NAME_MISMATCH (literal or filename-bound target)Rename the symbol and every reference.
ARCH_EXPORT_FORMConvert between named and default export, and rewrite importers.
ARCH_FILENAME_MISMATCH (a kebab-case / PascalCase / camelCase convention)Rename the file and rewrite import specifiers.
ARCH_MISPLACED_FILE (belongsHere)Move the file into the governed folder and rewrite import specifiers.

Safety guarantees:

  • Dry run by default. Nothing is written unless you pass --write.
  • Verify-and-rollback. All edits are applied in memory, then the whole project is re-checked. If the fixes wouldn't reduce errors, or would make a previously-clean file fail, nothing is written.
  • Refuses a dirty tree. --write aborts if git status is dirty, unless you pass --force, so a fix is always its own reviewable diff.

Exit code is 0 when the tree is clean (or fully fixed), 1 when unfixable errors remain.

Move safety. When a fix moves or renames a file, verification re-checks the project with the moved-away path treated as gone and the new path in place, so the same converge-or-discard guarantee applies to moves. Path-alias imports (@/…) aren't rewritten automatically yet, the verify step will refuse the move if that would break a build.

Released under the MIT License.