A fast, native architecture linter for Feature-Sliced Design projects.
Steiger for Rust is a Node.js-free rewrite of feature-sliced/steiger. It checks the architecture of JavaScript and TypeScript projects that use Feature-Sliced Design while keeping startup and analysis inside a native Rust executable.
- Compatible with Steiger 0.6 and
@feature-sliced/steiger-plugin0.7 behavior. - Includes all 20 FSD rules and enables the same 17-rule recommended preset.
- Uses Oxc for JavaScript and TypeScript parsing and Rayon for parallel work.
- Supports checked-in diagnostic baselines for gradual adoption in CI and pre-push hooks.
Install the npm package and lint the directory that contains your FSD layers:
npm install --save-dev steiger-rust
npx steiger ./srcA project without diagnostics prints:
✓ No problems found!
The steiger-rust meta-package installs the native package for the current
operating system and architecture. Its steiger entry points directly to the
Rust executable: npm installs and resolves the command, but the linter itself
does not start Node.js or a JavaScript launcher.
Important
Do not install with --omit=optional. The platform-specific native binary is
delivered as an optional dependency.
The following end-to-end CLI benchmark was measured on July 21, 2026, using
a large production PWA: a 64 MB source tree containing 10,378 JavaScript,
TypeScript, and component files. All 20 built-in FSD rules were enabled as
errors in both implementations. They returned the same 1,362 diagnostics and
1,158 unique (rule, path) pairs.
| Implementation | Version | Runs | Median wall time | Relative |
|---|---|---|---|---|
| JavaScript Steiger | steiger 0.6.0 + plugin 0.7.0 |
3 | 31.49 s | 1× |
| Steiger for Rust | 0.1.0 release build |
10 | 0.53 s | ~59× faster |
Environment: Apple M2 Max, macOS, Node.js 22.14.0. Runs used a warm filesystem
cache, the JSON reporter, and discarded reporter output. The JavaScript process
was run with CHOKIDAR_USEPOLLING=1; its default watcher mode stopped with
EMFILE: too many open files even with ulimit -n 120000.
Raw wall times were 31.35, 31.49, 31.59 s for JavaScript and
0.80, 0.53, 0.53, 0.53, 0.52, 0.52, 0.54, 0.54, 0.53, 0.53 s for Rust.
These are project-specific results rather than a universal performance
guarantee; filesystem, enabled rules, project shape, and cache state all affect
runtime.
Use Steiger for Rust in local development, pre-push validation, or CI for FSD projects whose source is JavaScript, TypeScript, Vue, Svelte, or Astro. Linting does not require authentication or a network connection after installation.
| Area | Supported targets |
|---|---|
| Operating systems | macOS, Linux, Windows |
| Architectures | x64 and arm64 |
| npm Linux variants | glibc and musl |
| Source files | JS, JSX, TS, TSX, MJS, CJS, MTS, CTS |
| Embedded scripts | Vue, Svelte, Astro |
| Configuration | TOML and JSON |
| Source builds | Rust 1.89 or newer |
GitHub Releases and npm publish native binaries for these targets:
| Operating system | Architecture | Target family |
|---|---|---|
| macOS | x64, arm64 | Darwin |
| Linux | x64, arm64 | GNU/glibc and musl |
| Windows | x64, arm64 | MSVC |
Other Rust targets can be built from source when all dependencies support the target.
When PATH is omitted, Steiger selects ./src, then ./app, then the current
directory.
steiger [OPTIONS] [PATH]| Option | Purpose |
|---|---|
-w, --watch |
Re-run when project files change |
--fix |
Apply available automatic fixes |
--fail-on-warnings |
Return a failing status when warnings remain |
--reporter pretty|json |
Select human-readable or JSON output |
--config FILE |
Use an explicit TOML or JSON configuration |
--baseline FILE |
Fail only on diagnostics absent from a baseline |
--fsd-errors FILE |
Alias for --baseline |
--list-rules |
Print every built-in rule and its default state |
Common commands:
steiger ./src --watch
steiger ./src --fix
steiger ./src --reporter json
steiger ./src --fail-on-warnings
steiger ./src --baseline ./fsd-errors.json
steiger --list-rules| Code | Meaning |
|---|---|
0 |
Validation passed |
1 |
Errors remain, warnings fail, or new baseline diagnostics were found |
2 |
The path, configuration, or another CLI input is invalid |
--baseline lets a project commit its known FSD diagnostics and reject only
new (rule, path) pairs. The file is a JSON object keyed by rule name; every
path is resolved relative to the baseline file.
{
"fsd/insignificant-slice": [
"src/entities/user"
]
}Run the validation from a hook or CI job:
steiger ./src --baseline ./fsd-errors.jsonKnown diagnostics are hidden. The command returns 0 when there are no new
pairs and 1 when current output contains a pair absent from the baseline. A
reduction in existing diagnostics succeeds without modifying the committed
file.
For an npm project, the same validation can be exposed as a package script:
{
"scripts": {
"fsd:check": "steiger ./src --baseline ./fsd-errors.json"
}
}npm run fsd:checkWithout --config, Steiger searches the current directory and its parents for:
steiger.toml.steiger.tomlsteiger.config.tomlsteiger.json.steiger.jsonsteiger.config.json
Important
JavaScript and TypeScript configuration files such as steiger.config.js
are not evaluated. Executing them would add a Node.js runtime dependency.
Move the rule and override settings to TOML or JSON; plugin objects are not
needed because every supported FSD rule is built into the binary.
Example steiger.toml:
global_ignores = ["**/__mocks__/**"]
[rules]
"fsd/no-processes" = "warn"
[[overrides]]
files = ["./src/shared/**"]
[overrides.rules]
"fsd/public-api" = "off"
[[overrides]]
files = ["./src/widgets/**"]
ignores = ["**/discount-offers/**"]
[overrides.rules]
"fsd/no-segmentless-slices" = "off"JSON also accepts a Steiger-style flat array:
[
{ "ignores": ["**/__mocks__/**"] },
{
"files": ["./src/shared/**"],
"rules": { "fsd/public-api": "off" }
}
]Later matching overrides take precedence. A folder diagnostic receives the highest effective severity of the files below that folder, matching upstream Steiger's file-glob behavior.
- JavaScript, JSX, TypeScript, TSX, MJS, CJS, MTS, and CTS through Oxc.
import,import(), andrequire()dependencies.- Vue and Svelte
<script>blocks. - Astro frontmatter.
- Relative imports, directory indexes, TypeScript
baseUrl/paths,extends, and project references throughoxc_resolver. .gitignore,.ignore,.git,node_modules, and Rusttargetexclusions.
The recommended preset enables these 17 rules:
fsd/ambiguous-slice-namesfsd/excessive-slicingfsd/forbidden-importsfsd/inconsistent-namingfsd/insignificant-slicefsd/no-layer-public-apifsd/no-processesfsd/no-public-api-sidestepfsd/no-reserved-folder-namesfsd/no-segmentless-slicesfsd/no-segments-on-sliced-layersfsd/no-ui-in-appfsd/public-apifsd/repetitive-namingfsd/segments-by-purposefsd/shared-lib-groupingfsd/typo-in-layer-name
The upstream-compatible split rules fsd/no-cross-imports,
fsd/no-higher-level-imports, and fsd/import-locality are built in but
disabled by default. Run steiger --list-rules for the machine-readable list.
cargo install --path . --locked
steiger ./srcPrebuilt archives and SHA-256 checksums are also available on the GitHub Releases page.
cargo fmt --all -- --check
cargo clippy --locked --all-targets --all-features -- -D warnings
cargo test --locked --all-features
cargo build --locked --releaseThe npm integration test verifies that .bin/steiger resolves directly to a
native Mach-O, ELF, or PE executable:
node --test tests/npm_native_cli.mjs
node scripts/prepare-npm-release.mjs --check v0.1.0| Path | Purpose |
|---|---|
src/main.rs |
CLI arguments, reporters, exit codes, and watch mode |
src/config.rs |
TOML/JSON discovery, parsing, and override scoping |
src/rules/ |
Built-in structural and import rules |
tests/ |
CLI, configuration, compatibility, and npm integration tests |
npm/ |
Meta-package and eight platform-specific packages |
.github/workflows/ |
Multi-platform CI and tag-based release publishing |
See CONTRIBUTING.md for pull request guidance and RELEASING.md for the tag-based GitHub and npm release process.
This project is an independent Rust implementation derived from the behavior and tests of the MIT-licensed upstream Steiger project. It is released under the MIT License.