sliderule is the command SlideRule installs as a .NET global tool, and this page is its reference. Each command's help appears as the tool prints it, followed by what the help has no room for. The topics that span several commands come after the commands, from how a command finds its solution to the environment variables SlideRule reads.
The install and what the machine needs are in Getting started. Writing rules is covered in Writing specs, with the whole vocabulary in GRAMMAR.md. Running the check in CI, working a ratchet down and upgrading are in Operating SlideRule. The help on this page is printed at a width of 100 columns, and a terminal wraps it to its own.
Every command that takes a solution finds it, and its spec, the same way, as Solution and spec resolution describes. A repository that commits a settings file can leave both out of every command.
A token that begins with - where a solution goes, or where explain takes its rule ID, is rejected with Unrecognized option '<token>'. Write a path that begins with a dash as ./-name. A -- in front of it does not help, because the refusal applies after -- as well.
Description:
SlideRule is a .NET architecture checker that enforces one C# spec and renders the same rules for
coding agents.
Usage:
sliderule [command] [options]
Options:
-?, -h, --help Show help and usage information
--version Show version information
Commands:
check <solution> Evaluate rules against a target solution; a project that fails to
load, or whose NuGet packages did not resolve, fails the run (exit
2) unless --allow-workspace-diagnostics is passed.
explain <rule-id> <solution> Print a rule's because, fix, citation, exemplar, posture payload,
and linked prose; or, with --type or --path, which layers, rules
and scopes claim a type, and why.
render <solution> Render the managed AGENTS.md block(s) from the spec, and
sliderule.model.json where --model is passed or the file exists; a
project that fails to load, or whose NuGet packages did not
resolve, refuses the command (exit 2) unless
--allow-workspace-diagnostics is passed.
baseline Grandfather, shrink, add one attributed exception to, or rename the
ratcheted baselines. init, accept-reductions and add refuse (exit
2) when a project fails to load or its NuGet packages did not
resolve, unless --allow-workspace-diagnostics is passed; rename
reads only the spec and the baseline files.
status <solution> Report per-rule burndown and promotion suggestions; red rules never
fail the run, but a project that fails to load or to restore does
(exit 2) unless --allow-workspace-diagnostics is passed.
graph <solution> Summarize the codebase: projects, declared vs observed project
references, namespace inventory, and grouped external references.
Needs no spec; a project that fails to load or to restore refuses
the survey (exit 2) unless --allow-workspace-diagnostics is passed.
mcp <solution> Run the MCP stdio server bound to a solution and spec.
hook <solution> Run as a Claude Code hook: read the event's payload on stdin, check
the working tree when an agent's turn ends, and answer in Claude
Code's exit codes. 0 lets the stop stand, with any tripwire
warnings on stdout as context for the agent; 2 refuses it, with the
report on stderr; 1 is SlideRule's own error, reported on stderr
without blocking.
Description:
Evaluate rules against a target solution; a project that fails to load, or whose NuGet packages
did not resolve, fails the run (exit 2) unless --allow-workspace-diagnostics is passed.
Usage:
sliderule check [<solution>] [options]
Arguments:
<solution> Solution file, a directory to search, or omitted to walk up from the working
directory.
Options:
--spec <spec> A built spec DLL, or a csproj that is a member of the
target solution. Omit to use the convention.
--json Emit the machine-readable JSON document instead of
human-readable output.
--diff-base <diff-base> A git ref; files changed since it are checked against
quarantined and cautioned scopes (the scope tripwire) —
warnings only, never failures.
--allow-workspace-diagnostics Check against the partial model even when some projects
fail to load or to restore, instead of failing the run
with exit 2.
--sarif <sarif> Write a SARIF 2.1.0 report to <path> (GitHub code
scanning et al.); human/--json output is unchanged.
--rules <rules> Check only the rules whose ID matches these globs
(semicolon-separated, '*' allowed and it spans '/'); the
report, the summary counts and the 0/1 verdict then cover
that subset alone. A filter matching no rule refuses the
run (exit 2) and lists the available rule IDs.
--grain <full|overview|skeleton|index> How much of the --json report to keep, each rung coarser
than the one before it and never narrower: full (the
default); overview, every rule and violation with each
violation's sites replaced by their count; skeleton,
every rule with its prose, status, baseline and warnings
and its violations replaced by their count; index, a
verdict per rule ID with the prose, the NuGet audit
advisories and the workspace diagnostics elided
(packageAuditCount and workspaceDiagnosticCount say how
many) and every trust stamp kept, which is the menu
--rules globs pick from.
--no-cache Bypass the persisted caches (extraction fragments and the
build capture): always load and extract fresh, and write
nothing back.
--binlog <binlog> A .binlog from a real build of this solution on this
machine. Replays the captured structure instead of a
design-time build; the capture persists, and later runs
replay it automatically while structurally valid.
-?, -h, --help Show help and usage information
Without --diff-base every tripwire reports skipped, which is not the same as clean. A pull-request check therefore passes the pull request's base ref, and the checkout has to be deep enough for that ref to resolve. A tripwire touch is one of the warnings a check can raise, and a warning never fails the run.
Five options have a section of their own below. --sarif is under SARIF, --grain under Grains, and --binlog and --no-cache under Caching. What --allow-workspace-diagnostics accepts is under Wrong and smaller models.
Description:
Print a rule's because, fix, citation, exemplar, posture payload, and linked prose; or, with
--type or --path, which layers, rules and scopes claim a type, and why.
Usage:
sliderule explain [<rule-id> [<solution>]] [options]
Arguments:
<rule-id> The rule ID to explain (a post-desugar ID, e.g. legacy/billing/containment). Omit it
with --type or --path.
<solution> Solution file, a directory to search, or omitted to walk up from the working
directory.
Options:
--spec <spec> A built spec DLL, or a csproj that is a member of the target solution. Omit to
use the convention.
--no-cache Bypass the persisted caches (extraction fragments and the build capture): always
load and extract fresh, and write nothing back.
--type <name> Explain a type instead of a rule: which layers, rules and scopes claim it, and
why. A full name as check reports it, or a simple name.
--path <path> Explain every type a file or directory declares instead of a rule, absolute or
relative to the solution.
-?, -h, --help Show help and usage information
explain prints one rule whole, and arch_explain returns the same text over MCP. The rule ID is the one check prints. A rule that a scope contributes has the scope's ID in front of its own, such as <scope-id>/containment.
With --type or --path in place of the rule ID, explain answers which layers, rules and scopes claim a type, and why. --type takes a full name as check prints it, or a simple name, which explains every type that has it. An unknown name fails with the closest full names. --path explains every type declared in a file or under a directory. With either option, a lone positional argument is the solution.
Under each claim, indented lines give the facts that admitted the type, such as the glob its namespace matched or the project that declares it. The excepted by group lists the rules and scopes whose Except removed the type, with the reason the type matched it. A rule that drops the type for any other reason is not listed. A type that no layer, rule or scope claims gets the line claimed by: no layer, rule or scope. A framework or package type the solution references, named in full, gets the line claimed by: nothing; it is declared outside the solution, and every selection ranges over the types the solution declares. This form extracts the solution as check does, so it uses the extraction cache. A project that fails to load is named at the top of the answer, and the command still exits 0. arch_explain takes type or path for the same answer.
Description:
Render the managed AGENTS.md block(s) from the spec, and sliderule.model.json where --model is
passed or the file exists; a project that fails to load, or whose NuGet packages did not resolve,
refuses the command (exit 2) unless --allow-workspace-diagnostics is passed.
Usage:
sliderule render [<solution>] [options]
Arguments:
<solution> Solution file, a directory to search, or omitted to walk up from the working
directory.
Options:
--spec <spec> A built spec DLL, or a csproj that is a member of the target
solution. Omit to use the convention.
--allow-workspace-diagnostics Render from the partial model even when some projects fail
to load or to restore, instead of refusing the command with
exit 2.
--model Write sliderule.model.json, the built model as data, beside
the root AGENTS.md. Needed once: any later render refreshes
a model file that exists.
--diagram <diagram> Also render two Mermaid diagrams into <path>'s managed
block: the codebase graph (projects and their cross-project
references; solid = observed, dotted = declared but
unobserved), then the spec's law (the places it names, what
they must not reference, and the debt it grandfathers). The
graph draws the projects the solution file declares, so a
project a ProjectReference dragged into the build is not
drawn; `graph` lists every loaded project and says which is
which.
--diagram-only <diagram-only> Draw only the declared projects matching these name globs
(semicolon-separated, '*' allowed) — for legibility on a
large solution, not to keep a foreign project out. Scopes
the codebase survey fence only, never the law fence. With
--diagram.
--diagram-exclude <diagram-exclude> Drop the declared projects matching these name globs
(semicolon-separated, '*' allowed) — for legibility on a
large solution, not to keep a foreign project out. Scopes
the codebase survey fence only, never the law fence. With
--diagram.
--check Write nothing: compare every file this render would write
with the one on disk, name each that differs, and exit 1 if
any does. For CI, in place of a render followed by git diff.
--no-cache Bypass the persisted caches (extraction fragments and the
build capture): always load and extract fresh, and write
nothing back.
-?, -h, --help Show help and usage information
render writes the managed block into the AGENTS.md in the solution's directory. It also writes a card into each scope's directory and into the directory of each layer a rule governs. Everything outside a block's markers stays as it was. The Coding agents page explains which agents read these files, and why render names a CLAUDE.md on stderr when it finds one.
render adds and updates files, and never deletes one. When a spec change moves a rule, the card in the directory the rule left stays on disk until you delete it, and render --check does not report it. Under --check, each file a render would write is listed as current or stale, including a card the spec now places where none is committed.
The build analyzer reads the model file --model writes. The model file is never written while a project has failed to load. Under --allow-workspace-diagnostics, such a render fails whole when --model or the settings file asks for the model file. One that would only refresh an existing model file leaves it as it was, with a warning. A settings file can ask for the model file or the diagram without the option. A --diagram on the command line replaces the settings file's whole diagram entry, its only and exclude lists included.
Description:
Grandfather, shrink, add one attributed exception to, or rename the ratcheted baselines. init,
accept-reductions and add refuse (exit 2) when a project fails to load or its NuGet packages did
not resolve, unless --allow-workspace-diagnostics is passed; rename reads only the spec and the
baseline files.
Usage:
sliderule baseline [command] [options]
Options:
-?, -h, --help Show help and usage information
Commands:
init <solution> Grandfather each uncaptured ratcheted rule's current violations
into its baseline. Always extracts fresh, because a rule it cannot
see would be recorded as zero debt.
accept-reductions <solution> Remove baseline entries whose violations no longer occur and lower
recorded site counts; never adds. Always extracts fresh, because a
violation it cannot see would be deleted as fixed.
add <solution> Grandfather exactly one currently observed violation of a captured
rule, with attribution: an edge (--source with --target) or a shape
(--subject).
rename <solution> Move a renamed rule's baseline section from its old rule ID to its
new one, with every entry kept and re-sealed. Reads the spec and
the baseline files, never the code.
A baseline records a ratcheted rule's current violations, so that only new ones fail. The ratcheted rules are the Migrate rules and each Quarantine scope's containment. A rule's baseline is the file arch/baselines/<rule-id>.json under the solution directory, unless the rule names a path of its own with .Baseline(path). Commit the files baseline writes along with the spec.
Each entry in a baseline file is one line with a seal of its own, so an edit by hand is caught. A file whose entry no longer matches its seal fails its integrity check. Every command that reads it then exits 2, naming the file and the entry. Restore that line from version control, and resolve a merge conflict in a baseline file by keeping whole entry lines from either side. A baseline shrinks through baseline accept-reductions and grows only through baseline add, one attributed entry at a time.
baseline is yours to run. A baseline turns a red rule green without fixing anything. The MCP server therefore has no tool that writes one, and the hook settings deny the command to an agent.
Description:
Grandfather each uncaptured ratcheted rule's current violations into its baseline. Always
extracts fresh, because a rule it cannot see would be recorded as zero debt.
Usage:
sliderule baseline init [<solution>] [options]
Arguments:
<solution> Solution file, a directory to search, or omitted to walk up from the working
directory.
Options:
--spec <spec> A built spec DLL, or a csproj that is a member of the target
solution. Omit to use the convention.
--allow-workspace-diagnostics Write baselines from the partial model even when some projects
fail to load or to restore, instead of refusing the command with
exit 2.
-?, -h, --help Show help and usage information
Description:
Remove baseline entries whose violations no longer occur and lower recorded site counts; never
adds. Always extracts fresh, because a violation it cannot see would be deleted as fixed.
Usage:
sliderule baseline accept-reductions [<solution>] [options]
Arguments:
<solution> Solution file, a directory to search, or omitted to walk up from the working
directory.
Options:
--spec <spec> A built spec DLL, or a csproj that is a member of the target
solution. Omit to use the convention.
--allow-workspace-diagnostics Write baselines from the partial model even when some projects
fail to load or to restore, instead of refusing the command with
exit 2.
-?, -h, --help Show help and usage information
Description:
Grandfather exactly one currently observed violation of a captured rule, with attribution: an
edge (--source with --target) or a shape (--subject).
Usage:
sliderule baseline add [<solution>] [options]
Arguments:
<solution> Solution file, a directory to search, or omitted to walk up from the working
directory.
Options:
--spec <spec> A built spec DLL, or a csproj that is a member of the target
solution. Omit to use the convention.
--rule <rule> The ratcheted rule ID to add the entry to.
--because <because> Why this entry is grandfathered — recorded in the baseline entry
(single line).
--source <source> The referencing type of the edge to grandfather — a full type name
or 'T:' symbol ID — or the project a package, framework or
property violation names.
--target <target> The referenced type of the edge to grandfather — a full type name
or 'T:' symbol ID, or a banned member's full name
(System.DateTime.Now) or member symbol ID (P:System.DateTime.Now),
or the project's package, target framework, or property with its
framework (Serilog, net48, Nullable@net8.0).
--subject <subject> The offending type of the shape violation to grandfather — a full
type name or 'T:' symbol ID.
--allow-workspace-diagnostics Write baselines from the partial model even when some projects
fail to load or to restore, instead of refusing the command with
exit 2.
--no-cache Bypass the persisted caches (extraction fragments and the build
capture): always load and extract fresh, and write nothing back.
-?, -h, --help Show help and usage information
The reason given with --because is kept in the entry, and SARIF repeats it on the alert for that site.
Description:
Move a renamed rule's baseline section from its old rule ID to its new one, with every entry kept
and re-sealed. Reads the spec and the baseline files, never the code.
Usage:
sliderule baseline rename [<solution>] [options]
Arguments:
<solution> Solution file, a directory to search, or omitted to walk up from the working
directory.
Options:
--spec <spec> A built spec DLL, or a csproj that is a member of the target solution.
Omit to use the convention.
--from <from> (REQUIRED) The rule ID the baseline section is filed under: the rule's old ID,
which the spec no longer declares.
--to <to> (REQUIRED) The rule's new ID: a ratcheted rule in the spec with no baseline
section yet.
-?, -h, --help Show help and usage information
status lists a baseline section filed under an ID the spec no longer declares, with the rename that would move it. That rename ends --to <new-id> for you to fill in, and check names it with the failing rule's ID as --to.
Description:
Report per-rule burndown and promotion suggestions; red rules never fail the run, but a project
that fails to load or to restore does (exit 2) unless --allow-workspace-diagnostics is passed.
Usage:
sliderule status [<solution>] [options]
Arguments:
<solution> Solution file, a directory to search, or omitted to walk up from the working
directory.
Options:
--spec <spec> A built spec DLL, or a csproj that is a member of the target
solution. Omit to use the convention.
--json Emit the machine-readable JSON burndown document instead of
human-readable output.
--allow-workspace-diagnostics Report the burndown from the partial model even when some projects
fail to load or to restore, instead of exiting 2 after rendering
it.
--no-cache Bypass the persisted caches (extraction fragments and the build
capture): always load and extract fresh, and write nothing back.
--binlog <binlog> A .binlog from a real build of this solution on this machine.
Replays the captured structure instead of a design-time build; the
capture persists, and later runs replay it automatically while
structurally valid.
-?, -h, --help Show help and usage information
status suggests Enforce for a Migrate rule whose baseline has reached zero. --json writes the burndown document arch_status returns.
Description:
Summarize the codebase: projects, declared vs observed project references, namespace inventory,
and grouped external references. Needs no spec; a project that fails to load or to restore
refuses the survey (exit 2) unless --allow-workspace-diagnostics is passed.
Usage:
sliderule graph [<solution>] [options]
Arguments:
<solution> Solution file, a directory to search, or omitted to walk up from the working
directory.
Options:
--json Emit the machine-readable JSON survey document instead of
human-readable output.
--allow-workspace-diagnostics Survey the partial model even when some projects fail to
load or to restore, instead of refusing with exit 2.
--no-cache Bypass the persisted caches (extraction fragments and the
build capture): always load and extract fresh, and write
nothing back.
--binlog <binlog> A .binlog from a real build of this solution on this
machine. Replays the captured structure instead of a
design-time build; the capture persists, and later runs
replay it automatically while structurally valid.
--grain <full|overview|skeleton|index> How much of the survey to keep, each rung coarser than
the one before it and never narrower: full (the default);
overview, the whole survey with each project's namespace
inventory elided; skeleton, the structural spine, every
project with its frameworks, packaging facts, declared
project references and type count and the observed
project edges, with its package references elided and the
external references, multiply declared types and shadowed
types each reported as a count; index, the project
roster, every project with its solution membership and
type count alone and the observed edges, NuGet audit
advisories and workspace diagnostics each reported as a
count, which is the menu --projects globs pick from.
--projects <projects> Survey only the projects matching these name globs
(semicolon-separated, '*' allowed); references in both
directions are kept, so an edge can name a project
outside the scope. A filter matching no project refuses
the survey (exit 2) and lists the available names.
-?, -h, --help Show help and usage information
graph needs no spec, so it is the first command to run on a solution that has none. Besides the projects and their references, it lists each type name that two projects, or a project and a package, both declare. --json writes the survey arch_graph returns, and --grain coarsens it by the rungs under Grains.
Description:
Run the MCP stdio server bound to a solution and spec.
Usage:
sliderule mcp [<solution>] [options]
Arguments:
<solution> Solution file, a directory to search, or omitted to walk up from the working
directory.
Options:
--spec <spec> A built spec DLL, or a csproj that is a member of the target solution. Omit to
use the convention.
-?, -h, --help Show help and usage information
The Coding agents page covers the client config, how the server binds a solution, and its tools. A solution argument that does not resolve exits 2 before the handshake. Without an argument, the server starts even when it cannot bind a solution. Started at a terminal, with no client on its input, mcp prints how to configure one and exits 2.
The server keeps the solution loaded between calls, and never reads or writes the persisted cache. It exits after a stretch with no tool call, and when the process that launched it exits. The variables that change either are listed under Environment variables.
Description:
Run as a Claude Code hook: read the event's payload on stdin, check the working tree when an
agent's turn ends, and answer in Claude Code's exit codes. 0 lets the stop stand, with any
tripwire warnings on stdout as context for the agent; 2 refuses it, with the report on stderr; 1
is SlideRule's own error, reported on stderr without blocking.
Usage:
sliderule hook [<solution>] [options]
Arguments:
<solution> Solution file, or a directory to search, relative to the working tree the hook fires
for. Omit it to use the settings file, or the walk up from that tree.
Options:
--spec <spec> A built spec DLL, or a csproj that is a member of the target solution,
relative to the working tree the hook fires for. Omit it to use the
settings file, or the convention.
--diff-base <diff-base> The git ref the check's scope tripwires list changed files from. The
hook reads it on an edit, a hand run, or a stop with no snapshot of
the tree (no state, or no answer from git). Any other stop passes the
check the changed code files it listed itself. Warnings only, never
failures. [default: HEAD]
--max-rounds <max-rounds> How many consecutive continuations one prompt may get from a red rule
or a warning. Past it the hook reports the red rule without blocking,
and the turn ends. [default: 3]
-?, -h, --help Show help and usage information
The exit-code contract maps the hook's exit codes onto the ones under Exit codes. The Coding agents page shows where the hook fits, and hooks/ has the settings to paste.
A command finds its solution in this order:
- The argument, a solution file or a directory to search.
SLIDERULE_SOLUTION_PATH, which names a solution file, when the argument is left out.- A walk up from the working directory, which stops at the first directory with a
sliderule.jsonor exactly one solution file.
The walk climbs past a directory with several solution files, and counts a .slnf filter only where no .sln or .slnx is in the same directory. A walk that reaches the root without a match fails. It names the solution files of the first directory it climbed past, or else any solution one level below where it started. A command run from the repository root therefore finds no solution under src/ without the argument or a settings file there.
The spec comes from --spec, a built DLL or a csproj in the solution. Without it, the spec is the one the settings file names, and otherwise the one project in the solution that references SlideRule. A solution with no such project fails with No spec project found, and one with several fails with Multiple spec projects found and lists them.
A solution file named by the argument or by the environment variable wins over a settings file, and a settings file wins over the plain walk. A directory argument is searched the way the working directory is, settings file included. A solution file chosen any of these ways takes its spec and render settings from the nearest sliderule.json above it, and only when that file names it.
A sliderule.json at the root of a repository names the solution and the spec once. Every command run below it reads it, and so do the MCP server and the hook. A run inside a nested directory with exactly one solution file of its own stops there instead, and uses the settings file only if it names that solution. It is JSON with comments and trailing commas allowed, and its paths are relative to the file.
| Key | What it sets |
|---|---|
solution |
the solution file; required |
spec |
the spec csproj or built spec DLL; omit for the convention |
render.model |
true adds sliderule.model.json to every render |
render.diagram.path |
the file render draws into; required in render.diagram |
render.diagram.only |
project-name globs to draw |
render.diagram.exclude |
project-name globs to leave out |
$schema is read and ignored, for an editor's schema pointer. Any other key fails the command, naming the file and the key, so a misspelt key never passes for a setting. Getting started shows a first file.
A warning is something check noticed that does not affect the verdict. It never changes a rule's status or the exit code. In the text report, a rule that passed with a warning is headed warn. The JSON report lists each warning under its rule with a kind, and SARIF reports it as a warning-level result.
| Kind | Raised when |
|---|---|
inertTarget |
a forbidden target matched no types |
deadOperand |
a pattern in a rule's list matched no types |
deadExemplar |
a rule's exemplar matched no declared type |
orphanedBaseline |
a ratchet with no baseline fails, and a section has an old ID |
quarantinedScopeTouched |
a changed file declares a type in a quarantined scope |
cautionedScopeTouched |
a changed file declares a type in a cautioned scope |
An inertTarget rule can never fire, so either its target is wrong or what it forbids does not exist yet. A deadOperand rule was not measured as written, so status never suggests promoting it and baseline init skips it. A deadExemplar leaves the verdict and the counts as they were. An orphanedBaseline warning appears when a ratcheted rule fails with no baseline while a section is filed under a rule ID the spec does not declare. Its hint gives the baseline rename that would move the section. The two tripwire kinds need --diff-base. A quarantine warning asks whether the change had to edit inside the scope at all, and a caution warning asks that the scope's dragons be read first.
| Code | Meaning |
|---|---|
0 |
the run succeeded, and check found no red rule |
1 |
check found a red rule, or render --check a stale file |
2 |
SlideRule's own error: a refusal, a usage error, an incomplete model |
status exits 0 over red rules, because a burndown is its answer. A command line that does not parse exits 2 with the parse error on stderr. One that names no command also prints the root help, and one that names a group without its subcommand, such as sliderule baseline, prints that group's help. Both go to stderr, which keeps stdout empty for a caller that parses it. A run cancelled with Ctrl+C or a termination signal prints Cancelled. and exits 2 when it stops within System.CommandLine's two-second grace. A run that outlives the grace is ended by System.CommandLine, which exits 130 after Ctrl+C and 143 after a termination signal.
Every JSON document a command writes has a schemaVersion at its top, except the hook document, whose shape is Claude Code's.
| Document | Written by | schemaVersion |
|---|---|---|
| check report | check --json, arch_check |
3 |
| status burndown | status --json, arch_status |
2 |
| graph survey | graph --json, arch_graph |
1 |
| baseline file | baseline |
2 |
| model file | render --model |
2 |
| hook document | hook |
unversioned |
A version moves when a key is removed, renamed or given a new meaning, which a reader written for the old shape would misread. A key added for something new does not move it, except in the model file, whose reader rejects a key it does not know. A key appears only when it has something to report, so a document with no new facts is byte for byte what it was. The human-readable reports have no version and can gain lines in any release. A baseline reader still accepts the version before the current one, and any write upgrades the file.
The check report, the status burndown and the graph survey also list the NuGet audit advisories the load raised, under packageAudit. Each advisory is one entry, with NuGet's message and the projects that reported it. An advisory is about a package's published record, so it never marks the model incomplete.
The hook document is the hookSpecificOutput object Claude Code reads from a hook's stdout. hook writes it when a clean check warned, with the report as additionalContext, and names the event it answers:
| Event | When hook writes the document |
|---|---|
PostToolUse |
a checked edit came back clean with a warning |
Stop |
an agent's turn ended clean with a warning |
SubagentStop |
a worker's turn ended clean with a warning |
check --json and graph --json take --grain, and arch_check and arch_graph take grain. Each rung keeps less than the one before it, and every rung answers about the same rules and projects. --rules and --projects narrow the subject instead. A coarsened document has a grain key naming its rung, and a full one has none.
| Grain | check --json drops |
graph --json drops |
|---|---|---|
full |
none; the whole report stays, sites included | none; the whole survey stays, namespace inventories included |
overview |
each violation's sites, keeping their count | each project's namespace inventory |
skeleton |
each rule's violations, keeping their count | package references; external references and shared type names, as counts |
index |
rule prose; audit advisories and diagnostics, as counts | frameworks, packaging, project references; edges, audit advisories and diagnostics, as counts |
index lists every rule ID and every project name, which are what --rules and --projects take, so it is the menu to narrow from. Over MCP the server steps a document down these rungs until it fits, as the response budget explains.
check --sarif <path> writes the check as SARIF 2.1.0, the format GitHub code scanning reads. The file contains one run. Its driver lists every rule in the spec's order. Each has the generated sentence, the Because, the Fix followed by each exemplar type's file and line, and the Citation as the help link. A rule reports at error by default, and a scope's tripwire at warning.
Each violation site is one result, at its file and line relative to the solution directory:
| Result | level |
baselineState |
|---|---|---|
| a site of a red rule | error |
new, or updated for a grown pair |
| a grandfathered site | note |
unchanged |
| a check warning, such as a tripwire touch | warning |
new |
A grandfathered site also has an external suppression that quotes its baseline entry's reason, or names the baseline file when the entry has none. Its message repeats that attribution, since code scanning shows the message and ignores the suppression. A violation with no site, such as a rule whose subject matched no types, adds no result and still fails the run. Workspace diagnostics and an incomplete model are reported as notifications on the run's invocation.
Each result's partialFingerprints includes slideRuleViolationIdentity/v1, built from the violation's source, target and subject, the file, and the site's ordinal within that file. Code that moves around a site leaves the key alone, so one violation stays one alert across runs. The SARIF section of SlideRule on itself shows a grandfathered result from a real run.
check, explain, render, status, graph, baseline add and hook keep what they extract in a persisted cache, one directory per solution. baseline init and baseline accept-reductions always extract fresh. When no file has changed, or an edit changed only whitespace or comments, the next run builds the model from the cache without loading the workspace.
After an edit, a run loads only the projects it re-extracts and the projects they reference, through a temporary solution filter. An edit inside member bodies, non-constant initializers or top-level statements re-extracts only its own project. A project that references an edited one, directly or through another, is re-extracted only when the edit changed a declaration, even a private one.
The cache's record of the last whole load provides the spec's resolution and the load results of the projects the filter leaves out. The run loads the whole solution instead when the record lacks the spec's resolution, or a project to re-extract is not declared in the solution. It does the same when the load rejects the filter, or the filtered load finds a restore failure or workspace diagnostic the record lacks, or any failed project. A change to the solution file, a project file, a restore's project.assets.json, or a Directory.Build.props, Directory.Build.targets, Directory.Packages.props or global.json starts over. So does a cache another SlideRule version wrote.
| OS | Default cache root |
|---|---|
| Windows | %LOCALAPPDATA%\SlideRule\cache |
| Linux | $XDG_DATA_HOME/SlideRule/cache, else ~/.local/share/SlideRule/cache |
| macOS | ~/Library/Application Support/SlideRule/cache |
Each solution gets a directory under the root, named after the solution file with a short hash of its full path. SLIDERULE_CACHE_DIR moves the root. The cache is local derived data, so deleting it costs one cold run.
A --binlog capture is kept in the solution's cache directory. Later check, status, graph and hook runs replay the whole capture, even after an edit. A stored capture can go stale, become unreadable or come from another SlideRule version. A run that then needs the workspace prints a warning: line on stderr and runs a design-time build instead. For a stale capture the line is warning: build capture is stale ('<path>' no longer matches the capture); running a design-time build instead. Re-capture: rebuild with -bl and re-run with --binlog. A --binlog file that cannot be replayed fails the run with exit 2 and names the cause.
A run with --no-cache bypasses the cache and any stored capture, loads and extracts fresh, and leaves both as they were.
A project that fails to load makes the model wrong, because every rule would be judged without that project's code. check, render, graph, status and every baseline subcommand except rename exit 2 and name the projects that failed. --allow-workspace-diagnostics opts into the partial model. With or without it, the check and status documents say modelIncomplete: true and list failedProjects.
A project whose NuGet packages did not resolve is wrong in the same way, though it loads. Only the edges its package references would have produced are missing. Without the gate, a rule about a package would report itself inert and the run would pass. This covers a restore that failed and one that never ran. An SDK-style project writes obj/project.assets.json every time it restores, so a missing one is a fact about that project. A non-SDK-style .NET Framework project never writes one and is left alone. These projects take the same opt-out and are listed as restoreFailedProjects. Their refusal lists them in a block of their own and sends you to dotnet restore. A project that failed to load is sent to dotnet build instead.
The xUnit adapter answers both cases the same way: one named test fails with both causes, every rule case skips, and an AllowWorkspaceDiagnostics override opts in.
A solution filter makes the model smaller, and still right. check, status, graph and the arch_context tool answer, and the JSON documents list the declared projects the filtered run never checked as uncheckedProjects. explain --type and explain --path answer too, and list those projects above the answer, as check does above its text report. A green over a subset then cannot pass for a green over the solution. baseline init, baseline accept-reductions and render exit 2 instead, because the files they would write describe projects the run never measured. Run them against the solution the filter references.
The narrowing is measured from what loaded, so a filter whose references pull in the whole solution counts as the whole solution and lists no unchecked projects. Committed baselines, render targets, arch_context paths, diff resolution and the reported paths all resolve against the solution the filter references. A filter kept apart from its solution therefore answers with the solution's own paths. A rule whose whole selection lies in the unchecked projects reports as skipped and names the filter. An unfiltered run still fails a rule whose subject matches no types. The xUnit adapter keeps every rule verdict over a filter and skips Workspace_LoadedCompletely, naming what was not checked.
Two more stamps describe a model that is smaller and still right. unsupportedProjects names the declared projects SlideRule cannot read, such as F#, VB or SQL projects, each with its reason. No rule can be violated in one. A shared project is listed as well, because its code is read only inside the projects that import it. multiTargetedProjects names the projects compiled for several frameworks, each with the framework whose members and hierarchy their shared types follow; their references come from every framework.
Loading a non-SDK-style project, and replaying a binary log from .NET Framework MSBuild.exe, both run the .NET Framework build host that Roslyn ships. That host needs Windows and a Visual Studio or Build Tools install that includes MSBuild\Current\Bin\MSBuild.exe, which the tool finds with vswhere.
Where several are installed, it prefers Visual Studio 2019 or 2022. Where neither is installed, it takes the newest it found and names it on stderr, next to any load failure. Set SLIDERULE_VS_INSTALL_PATH to an install root, the parent of MSBuild\Current\Bin, to choose one yourself. A spec project that targets net48 needs none of this and builds anywhere.
SlideRule reads the variables below. You configure it through the SLIDERULE_* ones, and it reads the ones Claude Code or the operating system sets only to fit in with its host.
| Variable | Set by | What it does |
|---|---|---|
SLIDERULE_SOLUTION_PATH |
you | names the solution when no argument does |
SLIDERULE_VS_INSTALL_PATH |
you | chooses the Framework build host's install |
SLIDERULE_CACHE_DIR |
you | moves the cache root |
SLIDERULE_IDLE_TIMEOUT_MINUTES |
you | idle minutes before the MCP server exits; 30 by default, 0 never |
SLIDERULE_DISABLE_PARENT_WATCH |
you | true keeps the MCP server running after its launcher exits; Windows only |
SLIDERULE_DISABLE_WARM_WORKSPACE |
you | true makes the MCP server load the solution on every call |
SLIDERULE_LOG_LEVEL |
you | the MCP server's log level, Warning by default |
SLIDERULE_HOOK_STATE_DIR |
you | where hook keeps its per-session state |
CLAUDE_CODE_SESSION_ID |
Claude Code | tags the MCP server's log lines |
CLAUDE_PROJECT_DIR |
Claude Code | the project directory hook checks |
MAX_MCP_OUTPUT_TOKENS |
Claude Code | sizes the MCP reply budget |
CLAUDE_CONFIG_DIR |
Claude Code | locates your own CLAUDE.md, which render never counts |
USERPROFILE |
the operating system | your home directory on Windows |
HOME |
the operating system | your home directory elsewhere |
The MCP server writes a daily log to the logs directory next to the default cache root, such as %LOCALAPPDATA%\SlideRule\logs on Windows. The launcher that runs the server from a source checkout reads two variables of its own, which hooks/README.md documents.