Skip to content

CLI Reference

fensu check

Evaluate the configured rules against your repository and report every fault.

fensu check is the core command. It loads your configuration, discovers the files in each scope, runs the selected rules, and reports every fault it finds. It is the command you wire into CI.

fensu check [paths...] [--warn] [--no-color]
[--cache | --no-cache] [--cache-stats] [--target TARGET]

Run against the repository described by your fensu.toml or [tool.fensu]:

fensu check

Fensu finds your configuration by searching upward from the current directory, sorts files into the product, test, and tooling scopes, and applies each scope’s rules. An explicit multi-target configuration runs every target and produces one report. Selected repository rules then run exactly once over that complete target registry.

ArgumentDescription
paths...Optional for Python and web targets. Use these paths instead of configured roots. Rust targets use Cargo discovery and reject positional paths.
--warnAlso evaluate and report rules configured in warn. Warnings never make the command fail.
--no-colorDisable ANSI color in the output.
--cache / --no-cacheEnable or disable persistent result caching for this run.
--cache-statsWrite cache operation counts to stderr.
--target TARGETEvaluate only one named analyzer target; repository rules are skipped.

Passing paths replaces the configured roots for that run. The rest of the configuration, including evaluation targeting, still applies. Color is enabled automatically when the output is a terminal and disabled otherwise, and --no-color forces it off. With several configured targets, positional paths require --target TARGET so their owner is unambiguous.

fensu check src/my_package/main

When the repository conforms, Fensu prints a summary and nothing else:

Found 0 faults

When evaluation targeting is configured, the command also reports how many discovered files received direct evaluation:

Evaluation: 412 of 2,153 Python files (1,741 excluded by config)

When it finds problems, it prints one diagnostic per fault, then the summary. Each diagnostic has a stable, editor-friendly shape:

FFA002 function 'run' must define a return type annotation
--> src/my_package/main/run.py:5:0
|
5 | def run(a, b):
| ^
|
= help: Declare the returned value type, using None when the function returns no value.
  • The first line is the rule code and the message: the concrete contract that was violated.
  • The --> line is the location as path:line:column, repository-relative so an editor can make it clickable. A file-level fault with no specific line shows - for the line and column.
  • The source excerpt shows the offending line with a caret under the exact column.
  • The = help: line is the remediation: the normal correction, wrapped at 100 columns.

This two-level message contract (what is wrong, and how to fix it) is the same whether the fault comes from a core rule or a custom rule, and the text is written to be read at the moment of violation by a person or an agent.

Rules listed in warn are evaluated only when you pass --warn:

fensu check --warn

Warning diagnostics appear after blocking faults, and the summary reports both tiers:

Found 0 faults and 3 warnings

Warnings never affect the exit code. See the warn key for how to configure them.

CodeMeaning
0No blocking faults found, even if --warn reports warnings.
1One or more blocking faults found.
2Configuration or evaluation setup failed.

Because a non-zero exit fails a CI job, adding fensu check to your pipeline turns architectural drift into a build failure.

fensu check runs the rules resolved from your select and ignore configuration. Both take rule-code prefixes: FF is every core rule, FFR a family, FFR3 a hundreds bucket, FFR301 one rule; X is every custom rule, XDB a custom namespace, XDB001 one custom rule. Activated native packs use the reserved FP namespace: FPDG selects the complete Dagster policy and FPDG022 selects one Dagster-native rule; FPRS selects the complete Rust policy. To narrow a run, adjust those keys rather than the command:

select = ["FFL", "FFR"] # only layers and roles
ignore = ["FFH007"] # minus one rule

Pack selectors are available only after activation with rule_packs; see Native rule packs.

There is no inline suppression comment. When a rule genuinely does not fit, disable it globally, add an exact rule exception, add a path-scoped rule ignore, or replace it with a custom rule. Use evaluation targeting when a whole region is outside the current adoption boundary. See Philosophy for why.

After either a native or custom-rule check, Fensu removes empty subdirectories under configured product, test, and tooling roots. It also removes a bytecode-only subtree when deleting regular .pyc or .pyo files beneath __pycache__ makes that subtree empty. It does not purge caches from active source trees.

Configured roots, source and unknown files, non-empty directories, symlinks, concurrent additions, and paths outside configured roots are preserved. Cleanup is best-effort and never changes the check’s output or exit code.

fensu check keeps a persistent result cache, on by default, in a SQLite database at .fensu/cache/v2.db in the repository root. Add .fensu/cache/ to your .gitignore. The [cache] table configures it; these flags override the configuration for one run:

OptionDescription
--cacheForce caching on.
--no-cacheForce caching off; never opens or creates cache storage.
--cache-statsWrite one line of cache statistics to stderr.

The --cache-stats line reports hits, misses, invalidations, writes, non_cacheable, and storage_failed. When caching was requested but unavailable, it reports Cache: disabled (<reason>) instead.

Caching never changes output: a cached run is byte-identical to an uncached run, and any cache failure degrades to fresh computation. See Caching for the invalidation model, the correctness contract, and how custom rules stay cacheable.

When Fensu finds an installed project skill that no longer matches the active policy, it writes a non-failing notice to stderr:

Fensu skill files are out of date; run `fensu skills`.

Use fensu skills --check when freshness must be enforced in CI.