plugins/build/skills/build-pre-commit-config/SKILL.md
Scaffolds a reproducible pre-commit configuration — a `.pre-commit-config.yaml` at the repo root (optionally with local shell scripts under `scripts/hooks/`) that runs formatters, linters, and validators against staged changes via the `pre-commit` framework. Pins every `rev:`, declares scope per hook, serializes file-mutators, and documents the bootstrap. Use when the user wants to "set up pre-commit", "scaffold pre-commit hooks", or "configure .pre-commit-config.yaml". Not for hand-rolled `.git/hooks/` scripts, not for `pre-push` / `commit-msg` / server-side hooks, not for CI pipelines — route to the appropriate primitive.
npx skillsauth add bcbeidel/wos build-pre-commit-configInstall 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.
Scaffold a .pre-commit-config.yaml plus any accompanying local hook
scripts. The authoring rubric — anatomy template, patterns that work,
anti-patterns, safety posture — lives in
pre-commit-config-best-practices.md.
This skill is the workflow; the principles doc is the rubric.
This skill is pre-commit framework only by scope. Hand-rolled
.git/hooks/pre-commit scripts, commit-msg / pre-push /
server-side hooks, and CI pipeline configuration are out of scope and
refused at the Scope Gate.
Workflow sequence: 1. Route → 2. Scope Gate → 3. Elicit → 4. Draft → 5. Safety Check → 6. Review Gate → 7. Save → 8. Test
Also fires when the user phrases the request as:
Confirm a pre-commit config is the right primitive:
/build:build-hook. Claude Code hooks
and git pre-commit hooks share a name but nothing else.pre-push, commit-msg, or server-side git hook → out of
scope. The pre-commit framework supports pre-push via stages:,
but this skill scaffolds pre-commit stage only.pre-commit run --all-files is the
right mirror of this config, not a replacement./build:build-bash-script or
/build:build-python-script. This skill produces a config that
orchestrates hooks; a standalone script is a different unit.Right primitive → proceed to Scope Gate.
Refuse — and name the alternative — when any of these fire:
.pre-commit-config.yaml already exists at the project root.
Offer to /build:check-pre-commit-config on the existing file
and iterate from findings instead of scaffolding over it.pre-commit framework is Python-based; without it, scaffold a
different quality gate (CI-only, language-native runner, etc.)..git/hooks/pre-commit. Refuse; the
principles doc this skill enforces is framework-only.If any signal fires, state the signal, name the alternative, and stop.
If $ARGUMENTS is non-empty, parse it as free-form project context
and pre-fill inferable fields. Otherwise ask, one question at a time:
1. Repo root — where will .pre-commit-config.yaml land? Usually
the project root (default); monorepo sub-trees may land elsewhere.
2. Languages present — which languages/file types exist in the repo? (Python, JavaScript/TypeScript, Go, Rust, Shell, YAML, JSON, Markdown, Terraform, Dockerfile, etc.) Drives the hook selection.
3. Existing tooling preferences — is the team already using specific formatters/linters? (Black vs Ruff-format, ESLint vs Biome, gofmt vs goimports, rustfmt, shfmt, etc.) Prefer opinionated formatters with minimal config.
4. Baseline hygiene hooks — include the pre-commit-hooks
baseline (trailing-whitespace, end-of-file-fixer,
check-merge-conflict, check-added-large-files, check-yaml,
check-json)? Default yes; skip only if the user explicitly opts out.
5. Custom local hooks — does the repo need any in-repo validation
(schema validation, config consistency, license headers, secret
scanning beyond detect-secrets)? If yes, scaffold one or more
scripts/hooks/*.sh|py stubs and wire them as repo: local hooks.
6. CI mirror — is CI configured to run
pre-commit run --all-files? If not, offer to emit a CI-snippet
alongside the config (GitHub Actions .github/workflows/pre-commit.yml
template) — the mirror is explicitly out-of-scope to write, but
called out in the Test handoff.
7. Minimum pre-commit version — default to the version the user tests in CI; if unknown, default to the current stable minor.
Produce three artifacts.
Artifact 1: .pre-commit-config.yaml.
One conditionalized template. Omit sections the intake rules out.
minimum_pre_commit_version: "<from intake #7>"
default_language_version:
python: python3.11 # (if Python in intake #2)
node: "20.17.0" # (if JS/TS in intake #2)
exclude: | # vendored + generated
(?x)^(
node_modules/|
dist/|
build/|
target/|
\.venv/|
vendor/|
third_party/
)
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0 # verify current tag before save
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-merge-conflict
- id: check-added-large-files
- id: check-yaml # (if YAML in intake #2)
- id: check-json # (if JSON in intake #2)
# One block per language, driven by intake #2 + #3. Example (Python):
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.6.9
hooks:
- id: ruff
name: ruff (fix + lint)
args: [--fix]
require_serial: true
types_or: [python, pyi]
- id: ruff-format
name: ruff format
require_serial: true
types_or: [python, pyi]
# Local hooks (if intake #5 named any):
- repo: local
hooks:
- id: <custom-id>
name: <human-readable name>
entry: scripts/hooks/<custom>.sh
language: script
files: <regex>
pass_filenames: true
Every rev: is a placeholder — the draft states explicitly that
the user (or the Review Gate) verifies the current stable tag before
save. Never commit rev: main or HEAD.
Artifact 2: local hook scripts (one per intake #5 entry).
Each script uses the toolkit's bash-script convention: shebang,
set -euo pipefail, safe IFS, header comment, operates on argv
(pre-commit passes staged filenames). Actual hook logic is a stub
the user fills in — scaffolding the shape is this skill's job.
#!/usr/bin/env bash
#
# <id>.sh — <one-line purpose>.
# Invoked by pre-commit; staged filenames passed as positional args.
set -euo pipefail
IFS=$'\n\t'
for file in "$@"; do
: # TODO(<owner>): implement <id> check for "$file"
done
Artifact 3: bootstrap snippet — README lines documenting
pre-commit install and the one-time pre-commit install --install-hooks
warm-up, ready to paste.
Present all artifacts to the user before the Safety Check.
Review the draft against the rubric before presenting. Group:
Reproducibility. minimum_pre_commit_version set. Every rev:
is an immutable tag (vX.Y.Z) or 40-char SHA — no main / master /
HEAD / latest / stable. default_language_version pins
interpreters for language-specific hooks.
Scope. Every hook has files:, types:, or types_or: (or
inherits one from the upstream repo). Repo-wide exclude covers
generated / vendored directories. pass_filenames: false appears
only with a justifying comment.
Safety. No network I/O in entry: or referenced scripts (no
curl, wget, pip install, npm install, apt-get, brew,
gem install, go get). No sudo / elevated privileges. No
destructive commands (rm -rf, docker system prune,
terraform destroy, git reset --hard, git clean -fdx,
git push, git tag, git rebase, git update-ref).
Error handling. No || true / --exit-zero / toggled set +e
in scripts. Shell scripts start with #!/usr/bin/env bash +
set -euo pipefail + safe IFS.
File-mutator discipline. Any hook that modifies files
(Black/Ruff-format/Prettier/gofmt/rustfmt/shfmt/clang-format/
terraform fmt, or any --fix / --write variant) declares
require_serial: true.
Hygiene. Every hook has an explicit id and a human-readable
name. No duplication of built-in pre-commit-hooks
(trailing-whitespace, end-of-file-fixer,
check-merge-conflict, check-added-large-files) across multiple
repos.
Performance. No full test suites (pytest, go test,
cargo test, npm test) or whole-repo type checkers
(mypy ., pyright, tsc) in the commit-time stage.
If any check fails, revise before presenting. The Review Gate is for user approval, not correctness recovery.
Present all artifacts and wait for explicit user approval before writing any file. If the user requests changes, revise and re-present. Continue until explicit approval or cancellation.
Write the approved files to their paths:
<repo-root>/.pre-commit-config.yaml<repo-root>/scripts/hooks/<id>.sh (or .py) for each local hookFor shell scripts, chmod +x them — pre-commit respects the
executable bit.
Show the bootstrap snippet for the user to paste into the README.
Offer the audit:
"Run
/build:check-pre-commit-config <repo-root>to audit the scaffolded config against YAML shape,rev:pinning, scope declarations, safety rules, and the judgment dimensions?"
Also offer the CI mirror (explicitly not scaffolded above):
"Add a GitHub Actions workflow that runs
pre-commit run --all-fileson every PR? I can produce a.github/workflows/pre-commit.ymlstub."
rev: main / HEAD / any floating ref. Every rev:
in the draft is a verified immutable tag or a clear placeholder
the user must resolve before save.entry: — any hook needing &&,
||, |, ;, $(...) gets a scripts/hooks/*.sh file instead.pytest, go test, tsc, mypy . belong in CI / pre-push,
not here. Refuse if the user asks for them in the commit stage..pre-commit-config.yaml — Scope
Gate signal #1 applies. Offer the audit instead.rev: in the draft is either a verified current tag or a
placeholder flagged for the user to resolve at Review Gate.require_serial: true is mandatory on any hook that modifies
files. Do not omit it to "keep the config short."id and a human-readable name.IFS + header comment) —
dogfooded via /build:build-bash-script when the hook logic is
non-trivial.rm <repo-root>/.pre-commit-config.yaml plus rm -rf <repo-root>/scripts/hooks/ if scaffolded. The artifacts are
self-contained — no settings.json entry, no installer state
until the user runs pre-commit install.Chainable to: /build:check-pre-commit-config (audit the
scaffolded config), /build:build-bash-script or
/build:build-python-script (when a local hook's logic is
non-trivial and deserves the bash / Python script conventions).
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".