Command checks
A command check runs your own command on the files you select. gspot reads its output as findings, so they appear in the same report as every other check.
Example: find unfinished notes
Section titled “Example: find unfinished notes”This check reports FIXME lines in the files under notes/. It needs Node.js on your PATH.
Save this checker under the example filename:
import { readFile } from 'node:fs/promises';
for (const path of process.argv.slice(2)) { const lines = (await readFile(path, 'utf8')).split('\n'); for (const [index, line] of lines.entries()) { if (!line.includes('FIXME')) continue; console.log(`${path}:${index + 1}: ${line}`); process.exitCode = 1; }}Add the check to gspot.toml as a [[command_check]] record:
[[command_check]]name = "notes"command = ["node", "scripts/check-notes.mjs", "{files}"]paths = ["notes/**"]stage = "commit"summary = "Finds unfinished FIXME notes."help = "Replace each FIXME note with the finished instruction."output = { format = "regex", pattern = '^(?<file>[^:]+):(?<line>\d+): (?<message>.*)$' }Save this note under the example filename:
FIXME: document the deployment command.Apply the settings and run the check:
gspot applygspot check --only notesThe check exits with 1 and reports a finding on the first line of the note. Replace that line with
the finished instruction:
Run the deployment command documented in the release guide.Run the same check again. It exits with 0 and reports no findings.
How the command runs
Section titled “How the command runs”command lists arguments; gspot runs them without a shell. {files} expands to the
selected files, one argument each. File names with spaces need no extra quoting. To run the
command once for each file, use {file} instead. Then a regular expression match without a file group
uses the file of that run.
By default, any nonzero exit fails the check. When your tool uses one exit code for findings,
set exit_codes = [1]. Any other nonzero exit then counts as a failed run, exit code
2, even when the tool printed findings first. An empty list makes every nonzero exit a failed
run.
Read the output
Section titled “Read the output”output.format selects the parser:
| Format | What it reads |
|---|---|
regex |
Lines matched by pattern, with named file, line, column, rule, and message groups. |
grouped |
A file heading matched by file_pattern, then findings matched by pattern. |
sarif |
SARIF results, rule metadata, source locations, and fixes. |
knip |
Knip JSON issue categories and source positions. |
semgrep |
Semgrep JSON results, locations, lint rule IDs, messages, and fixes. |
trufflehog |
TruffleHog JSON findings, with raw secret output withheld. |
typos |
typos JSON, with byte offsets converted to character columns. |
markdownlint |
markdownlint result objects and their lint rule and source locations. |
json |
JSON findings selected by items, children, and fields. |
lines |
Each nonempty output line as a finding without a source location. |
none |
Exit status only, without output findings. |
The regex groups have these meanings:
| Group | Meaning |
|---|---|
file |
Source path, resolved from the command’s working folder. |
line |
Source line number. |
column |
Source column number. |
rule |
Lint rule name. |
message |
Finding text. |
For JSON, map the report’s field names:
output = { format = "json", fields = { message = "message" } }Malformed output makes the run incomplete with exit code 2.
Add a fix command
Section titled “Add a fix command”For gspot check --fix, set fix to a list of arguments.
--fix runs every fixer, then runs them again on the files that changed, so a formatter
reads what another fixer wrote. Then it runs the checks again. The fix commands change your working tree, not the staging area.
If the fix command exits with one of the exit_codes, gspot reports remaining findings.
Other nonzero exits count as a failed run.
Command check settings lists the accepted inputs.