Check your changes
groundrule check runs your rules’ checks against your code and tells you what to fix. By default it looks only at what you changed, so existing problems don’t block your work. This page explains what it checks, which findings fail it, how to read the output, and every option.
npx @groundrule/cli checkOnly standards with a check (a regular expression, a file rule, a dependency rule, and so on) can produce findings. Standards that are guidance only reach your agents through sync, and check counts them as guidance.
What it checks
Section titled “What it checks”| Command | What is checked |
|---|---|
check |
Your uncommitted work: staged and unstaged changes compared with your last commit, plus new files git doesn’t ignore. |
check --base <ref> |
Everything since your branch left <ref> (git’s merge base), plus your uncommitted work. Use it in CI and before opening a pull request: --base origin/main. |
check --all |
Every file in the repository, changed or not. The header says “(full audit)”. |
When checking changes, checks look only at the changed files. Change-set checks (such as “entity changes need a migration”) also see which files the change deleted.
enforcement.scope in .groundrule/config.yaml sets the default:
scope |
Without --all, a finding is “new” when… |
|---|---|
changed-lines (default) |
it’s on a line you added or changed. |
changed-files |
it’s anywhere in a file you changed. |
all |
always: check audits every file, as with --all. |
Other findings in the files you touched are legacy findings: they were there before your change. Findings that aren’t tied to a line, such as a missing lockfile, also count as legacy when checking changes. --all treats every finding as new.
Outside a git repository there’s no change to compare, so check warns “Not a git repository, so there is no change to compare. Checking every file instead.” and audits everything.
Groundrule never checks its own files: .groundrule/, the managed blocks in your agent files, and the Cursor and Copilot files it owns.
Which findings fail the check
Section titled “Which findings fail the check”A finding fails the check when all of these hold:
- It’s a violation, not a “possible” finding (see How to read a finding).
- No active exception covers it.
- It’s new, or
enforcement.legacyisenforce. - Its severity is at or above
enforcement.failOn.
failOn: the lowest severity that fails
Section titled “failOn: the lowest severity that fails”failOn |
Fails on |
|---|---|
blocker (default) |
blockers |
warning |
blockers and warnings |
none |
nothing. The report still lists every finding. |
Advisory and info findings never fail a check. Override the config for one run with --fail-on blocker|warning|none.
legacy: findings that were already there
Section titled “legacy: findings that were already there”legacy |
What happens to legacy findings |
|---|---|
report (default) |
Counted, hidden from the terminal report, and never fail. --verbose shows them. |
ignore |
Dropped from the report. |
enforce |
Treated like new findings: they can fail the check. |
How rollout stages change the result
Section titled “How rollout stages change the result”In a repository connected to the platform, each rule’s stage decides what check does with it:
| Stage | In check |
|---|---|
| Observe | Not run. Results are recorded only by scans. |
| Teach | Not run. The rule reaches your agents through sync. |
| Advise | Run. A blocker is reported as a warning, so with the default failOn: blocker it never fails the check. |
| Enforce | Run at the rule’s own severity. With the default failOn: blocker, its blockers fail the check. |
That’s why check may count fewer standards than sync writes: for example 43 checked, 79 in the agent files.
If you set failOn: warning, warnings from Advise rules fail the check too.
In an offline repository there are no stages. Every standard is checked at its own severity.
How to read a finding
Section titled “How to read a finding” groundrule check · 43 standards · 14 files (full audit)
✕ GHA-003 Do not interpolate untrusted event data into scripts BLOCKER · deterministic (regex) .github/workflows/ci.yml:8 Untrusted event data interpolated into a script 8: - run: echo "${{ github.event.pull_request.title }}" → Move the expression into the step's env: block (e.g. TITLE: ${{ github.event.issue.title }}) and use "$TITLE" in the script, always double-quoted. → groundrule explain GHA-003
⚠ TS-002 No deprecated HTTP and UUID packages warning · deterministic (dependencies) package.json:2 Forbidden dependency "request" package.json declares request (npm), which matches "request" → Use fetch or crypto.randomUUID() instead. → groundrule explain TS-002
Failed ✓ 31 passed ✕ 1 failed ⚠ 5 warnings 6 not applicable · 0.0sThe first line counts the standards checked and what was checked: “N files changed”, “N files changed vs origin/main”, or “N files (full audit)”.
Blocking findings come first, then the rest by severity. Each standard with findings gets one block:
| Part | Example | Meaning |
|---|---|---|
| Icon | ✕ ⚠ ? |
✕ fails the check. ⚠ is reported but doesn’t fail. ? is a possible finding the check isn’t confident about; it never fails. |
| ID and title | GHA-003 Do not interpolate… |
The standard. |
| Severity | BLOCKER, warning |
In capitals when the finding fails the check. |
| Source | deterministic (regex) |
How it was found, and by which check. See below. |
| Location | .github/workflows/ci.yml:8 |
File and line. May be followed by possible, legacy, or excepted by EX-1. |
| Message and evidence | 8: - run: echo … |
What was found, with up to two lines of evidence, such as the offending line. |
| Fix | → Move the expression… |
How to fix it. |
| Explain | → groundrule explain GHA-003 |
The command that shows the full rule. |
The source label says how the finding was produced:
| Label | Checks | Meaning |
|---|---|---|
deterministic |
regex, files, dependencies, change-set |
The same code always gives the same result. No AI. |
static analysis |
semgrep |
A Semgrep rule. Needs Semgrep installed; without it, the rule is “not evaluated”. |
AI |
llm |
Not yet available. Rules with an AI check are reported as not evaluated. |
At most five locations are shown per standard. The rest are summed up as “… N more in M files (show all with –verbose)”.
After the findings, you may see:
○ 3 legacy findings not introduced by this change · 1 finding covered by exceptions (show with --verbose);– <ID> not evaluated: <reason>, when a check couldn’t run, for example because Semgrep isn’t installed.
The last line gives the verdict, Passed or Failed, then counts: passed, failed, warnings, not evaluated, guidance (◇), and not applicable (rules whose languages or frameworks aren’t in this repository).
Options
Section titled “Options”| Option | What it does |
|---|---|
--base <ref> |
Compare against a branch or commit, such as origin/main. The ref must exist locally: fetch it first. |
--all |
Check every file, not only changes. |
-f, --format <format> |
terminal (default), json, sarif, or markdown. |
-o, --output <file> |
Write a json, sarif or markdown report to a file instead of printing it. The CLI prints “Wrote sarif report to groundrule.sarif (failed).” |
--summary <file> |
Also append a Markdown summary to a file, such as $GITHUB_STEP_SUMMARY. Works with any format. |
--fail-on <severity> |
blocker, warning, or none. Overrides enforcement.failOn for this run. |
--only <ids> |
Check only these standards, comma-separated, such as --only GHA-003,TS-001. Case doesn’t matter. |
--verbose |
Also show legacy findings, findings covered by exceptions, and every location. |
Examples:
# What a pull request adds, compared with maingit fetch origin mainnpx @groundrule/cli check --base origin/main
# One rule, everywherenpx @groundrule/cli check --all --only SEC-001
# A SARIF file for code scanning, and a summary for the job pagenpx @groundrule/cli check --base origin/main -f sarif -o groundrule.sarif --summary "$GITHUB_STEP_SUMMARY"Output formats
Section titled “Output formats”-
terminal: the report above. Colors turn off when the output isn’t a terminal orNO_COLORis set. -
json: the full result, including legacy and excepted findings, for scripts. -
sarif: SARIF 2.1.0, for GitHub code scanning and other tools. Findings covered by exceptions are marked as suppressed. -
markdown: a table for pull-request comments and job summaries. Real output:### Groundrule · ⚠ Passed with 1 warning| | Standard | Finding | Where | Source ||---|---|---|---|---|| ⚠ | **REACT-006** Give every img an alt attribute | <img> without an alt attribute<br>**Fix:** Add alt="what the image shows" for meaningful images, or alt="" if it is decorative. | `src/components/Hero.tsx:1` | deterministic |✓ 17 passed · ◇ 14 guidance<sub>Groundrule 0.1.0 · run `groundrule explain <ID>` for details</sub>
Each format is described field by field in Output formats.
Exit codes
Section titled “Exit codes”| Code | Meaning |
|---|---|
0 |
Passed: no finding fails the check. Warnings may still be listed. |
1 |
Failed: at least one finding fails the check. |
2 |
The check couldn’t run: a configuration error, a ref that can’t be compared (Cannot compare against "origin/main". Fetch it first (e.g. git fetch origin main).), a sign-in problem, or a wrong option. |
Exceptions
Section titled “Exceptions”When a rule shouldn’t apply to some code, record a time-boxed exception in .groundrule/exceptions.yaml instead of turning the rule off:
apiVersion: groundrule.dev/v1alpha1kind: ExceptionListspec: exceptions: - id: EX-1 standard: DOCKER-001 paths: ["tools/ci-image/Dockerfile"] reason: Build-only image; never runs as a service. requestedBy: maya@acme.example approvedBy: team:platform expires: 2026-12-31 remediation: Move the build to the shared runner image.| Field | Required | Meaning |
|---|---|---|
id |
Yes | EX- and a number, such as EX-1042. |
standard |
Yes | The standard’s ID. |
paths |
No | Globs for the files it covers. The default ** means the whole repository. |
reason |
Yes | Why the rule doesn’t apply here. |
expires |
Yes | A date (YYYY-MM-DD). The exception works through the end of that day (UTC). |
requestedBy, approvedBy, remediation |
No | Who asked, who approved, and the plan to remove the exception. |
Findings it covers are shown as excepted by EX-1 with --verbose, and never fail the check. When an exception expires, every command warns “EX-1 for DOCKER-001 expired on 2026-12-31 and no longer applies.”, and the findings count again. groundrule explain <ID> lists a rule’s exceptions. Commit the file, so the exception is reviewed like any other change.
More: Overrides and exceptions.
Run it before you push
Section titled “Run it before you push”Add a git hook, so you see findings before CI does. For example, in .git/hooks/pre-push:
#!/bin/shnpx @groundrule/cli check --base origin/mainMake it executable with chmod +x .git/hooks/pre-push. Coding agents run npx @groundrule/cli check themselves: the agent files tell them to.