Linting (ign lint)
ign lint PATH... [--strict] [-- <extra ignition-lint args>] delegates
to ignition-lint —
the external linter for Ignition project resources (Perspective view
structure, naming conventions, embedded scripts). The verb is LOCAL:
no gateway, no profile (the envelope carries profile: null), and the
tool is discovered on PATH (first executable ignition-lint wins).
The doctor posture (default). The command exits 0 whenever the tool RAN — findings are DATA, never a crash:
{"ok":true,"profile":null,"data":{"ran":true,"tool":"/path/ignition-lint",
"child_exit_code":1,"issues_found":2,
"report":{"issues":[...],"summary":{"errors":1,"warnings":1}},
"stdout":"<the tool's raw stdout>","stderr_preview":"<first 4000 chars>"}}
All keys always ride (report is null when stdout was not the
tool's JSON; stdout stays verbatim either way). The child's exit
code travels as child_exit_code so agents can branch without
parsing.
--strict for CI. With --strict the CLI exits with the
linter's own code LITERALLY (exit 1 = findings at/above the tool's
--fail-on threshold, default error) — the envelope still prints
first, then the exit mirrors the child (masked to the 0–127 shell
range; a signal-killed tool exits 1). This is the one sanctioned
success-path exit exception.
No tool installed? Exit 6 lint_tool_absent with the install
hint: uv tool install ignition-lint-toolkit (or
pip install ignition-lint-toolkit).
Argument mapping. Every PATH rides as --target <path> on the
tool's arg vector alongside --report-format json (the data
contract); anything after -- passes through verbatim for the
tool's own flags (--profile perspective, --checks naming,
--fail-on warning, …). Spawning is an arg VECTOR — never a shell
string. Pair it with project export --decode-scripts: lint the
decoded .py sidecars, then re-import with --encode-scripts.