Skip to main content

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.