plugins/build/skills/check-makefile/SKILL.md
Audits a top-level Makefile against 29 deterministic checks (strict-shell pin, `.SHELLFLAGS`, `MAKEFLAGS` warnings, `.PHONY` coverage, tab-indent, header comment, help-target patterns, variable-assignment discipline, top-level shell, destructive-op guards including `rm -rf`/`sudo`/global-install/curl-pipe, recipe hygiene, secrets, file/line size, optional `checkmake` wrap) plus seven judgment dimensions and a Tier-3 cross-Makefile collision check. Use when the user wants to "audit a makefile", "lint a makefile", or "review this makefile". Not for POSIX-`make`, compilation trees, or recursive multi-module builds — different rubric.
npx skillsauth add bcbeidel/wos check-makefileInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Audit a top-level Makefile for structural soundness, safety, help/.PHONY coverage, recipe hygiene, and adherence to the workflow-orchestration rubric. The rubric — what makes a Makefile load-bearing, the anatomy template, the patterns that work — lives in makefile-best-practices.md.
This skill follows the check-skill pattern. Tier-1 detection is in 11 scripts emitting JSON envelopes via _common.py (29 rule_ids total). Tier-2 has 7 judgment dimensions read inline by the primary agent. Tier-3 is collision (cross-Makefile drift in multi-Makefile scope).
Also fires when the user phrases the request as:
Read $ARGUMENTS:
Makefile (or *.mk file) — audit that file.Makefile, GNUmakefile, *.mk. Do not recurse — recursive multi-module builds are out of scope.Confirm scope aloud.
Invoke 11 detection scripts:
SCRIPTS="${SKILL_DIR}/scripts"
TARGETS="$ARGUMENTS"
python3 "$SCRIPTS/check_secrets.py" $TARGETS # 1 rule: secret (FAIL)
python3 "$SCRIPTS/check_structure.py" $TARGETS # 7 rules: shell-pin, shellflags (FAIL); warn-undefined, no-builtin-rules, delete-on-error, default-goal, header-comment (WARN)
python3 "$SCRIPTS/check_phony.py" $TARGETS # 1 rule: phony-coverage (WARN)
python3 "$SCRIPTS/check_help.py" $TARGETS # 3 rules: help-target, help-auto, help-desc (WARN)
python3 "$SCRIPTS/check_indent.py" $TARGETS # 1 rule: tab-indent (FAIL)
python3 "$SCRIPTS/check_naming.py" $TARGETS # 2 rules: target-name, helper-prefix (WARN)
python3 "$SCRIPTS/check_variables.py" $TARGETS # 2 rules: assignment-op, top-level-shell (WARN)
python3 "$SCRIPTS/check_safety.py" $TARGETS # 5 rules: unguarded-rm, sudo, global-install, curl-pipe (FAIL); destructive-guard (WARN)
python3 "$SCRIPTS/check_recipes.py" $TARGETS # 4 rules: literal-make, at-discipline, or-true-guard, recipe-length (WARN)
bash "$SCRIPTS/check_checkmake.sh" $TARGETS # 1 rule: checkmake (WARN); inapplicable when absent
bash "$SCRIPTS/check_size.sh" $TARGETS # 2 rules: size, line-length (WARN)
Each script emits a JSON array of envelopes. recommended_changes is canonical — copy through verbatim.
Script-to-rules map (29 Tier-1 rule_ids):
| Script | rule_ids | Severity |
|---|---|---|
| check_secrets.py | secret | fail |
| check_structure.py | shell-pin, shellflags | fail |
| check_structure.py | warn-undefined, no-builtin-rules, delete-on-error, default-goal, header-comment | warn |
| check_phony.py | phony-coverage | warn |
| check_help.py | help-target, help-auto, help-desc | warn |
| check_indent.py | tab-indent | fail |
| check_naming.py | target-name, helper-prefix | warn |
| check_variables.py | assignment-op, top-level-shell | warn |
| check_safety.py | unguarded-rm, sudo, global-install, curl-pipe | fail |
| check_safety.py | destructive-guard | warn |
| check_recipes.py | literal-make, at-discipline, or-true-guard, recipe-length | warn |
| check_checkmake.sh | checkmake | warn |
| check_size.sh | size, line-length | warn |
The previously-INFO helper-prefix rule is remapped to warn (the pattern has no INFO).
Tier-2 exclusion list. Any FAIL in secret, shell-pin, shellflags, tab-indent, unguarded-rm, sudo, global-install, or curl-pipe excludes the Makefile from Tier-2.
Missing-tool degradation. check_checkmake.sh emits an envelope with overall_status: inapplicable and exits 0 when checkmake is absent. Other scripts continue.
For each Makefile that passed the Tier-2 exclusion gate, evaluate against the 7 judgment rules at references/check-*.md:
| File | Dimension | Severity |
|---|---|---|
| check-target-contract-integrity.md | D1 — public target surface fulfills the workflow-orchestration contract | warn |
| check-destructive-op-safety.md | D2 — destructive ops are guarded, scoped, or reversible | warn |
| check-recipe-hygiene.md | D3 — recipes use $(MAKE), @-discipline, judicious \|\| true | warn |
| check-variable-and-override-discipline.md | D4 — assignment ops reflect intent; no top-level shell | warn |
| check-incremental-correctness.md | D5 — file targets list real prerequisites; .PHONY annotated | warn |
| check-naming-and-structure.md | D6 — target names verb-ish; helpers prefixed; sections grouped | warn |
| check-documentation-intent.md | D7 — header comment + per-target ## help; comments explain why | warn |
Evaluator policy: see check-skill-pattern.md §Evaluator policy. Read all 7 rule files first, then evaluate the Makefile in one LLM call.
Evaluate against check-collision.md. For multi-Makefile scope (Makefile + sibling *.mk files), surface duplicate .PHONY lists, divergent SHELL pins, or competing help definitions as warn. Single-Makefile scope returns inapplicable.
Merge findings from all 3 tiers into a unified table:
| Tier | rule_id | Location | Status | Reasoning |
|------|---------|----------|--------|-----------|
Sort: fail before warn before inapplicable; Tier-1 before Tier-2 before Tier-3 within severity. Each Recommendation: line copies through recommended_changes verbatim.
Ask once: "Apply fixes? Enter y (all), n (skip), or comma-separated numbers."
For each selected finding:
SHELL pin, .SHELLFLAGS, missing .PHONY entry, tab-indent fix, help-target awk parser. Show diff; write on confirmation./build:build-makefile.After each fix, re-run the relevant Tier-1 script.
.PHONY membership, tab-indent — handle deterministically in Tier-1.pass envelope.checkmake is absent, the corresponding envelope emits inapplicable — surface it.recommended_changes. Copy through; do not paraphrase.*.mk only; recursive multi-module builds are out of scope.check_checkmake.sh wrapper gracefully degrades to inapplicable when checkmake is absent.Chainable to: /build:build-makefile (rebuild non-compliant Makefile from scratch).
tools
Use when the user wants to "audit a help skill", "review my plugin index", or "verify my help-skill is up to date". Audits a plugins/<plugin>/skills/help/SKILL.md against the help-skill rubric — coverage, freshness, frontmatter fidelity, plus five judgment dimensions and a trigger-collision check.
tools
Use when the user wants to "scaffold a help skill", "add a /<plugin>:help command", or "build a plugin index skill", or wants to give a plugin an orientation surface that lists its skills and common workflows. Produces a SKILL.md at plugins/<plugin>/skills/help/SKILL.md.
tools
Audits pair-level integrity of a primitive-pair (the artifact `/build:build-skill-pair` produces) by walking the four required artifact slots — principles doc, `build-<primitive>/SKILL.md`, `check-<primitive>/SKILL.md`, and the `primitive-routing.md` registration — and reports cross-artifact issues a per-SKILL.md checker cannot see: missing principles doc, divergent principles paths between halves, absent routing registration, missing build→check handoff. Per-half structural compliance with the unified pattern (`check-skill-pattern.md`) is delegated to `plugins/build/_shared/scripts/check_skill_pattern.py`. Use when the user wants to "audit a skill pair", "review a primitive pair", or "validate the skill pair for X". Not for auditing a single SKILL.md — route to `/build:check-skill`. Not for re-distilling a stale principles doc — route to `/build:build-skill-pair`.
testing
Audit a root-level resolver — verify AGENTS.md pointer, managed-region integrity, filing-table coverage against disk, context-table actionability, and trigger-eval pass rate. Use when the user wants to "audit a resolver", "validate routing table", or "find dark capabilities".