ci: add lint and configuration validation workflow - #16
Merged
Conversation
Nothing verified this repository until now: every PR merged without an automated check. Beyond ruff, the workflow checks the failure modes that break the template silently for whoever copies it — a hook whose script was renamed stops firing, a broken CLAUDE.md @-import drops that rule from context, and a skill missing frontmatter becomes undiscoverable. None of those surface an error at runtime. shellcheck covers the hooks because quoting and boundary bugs in them have shipped twice before. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
setup-uv publishes no floating major tag past v7, so @v10 does not resolve. Caught by the workflow's own first run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
shellcheck SC2034, surfaced by the new CI on its first run. The hook inspects the filesystem, not the payload, so the assignment was dead weight that implied otherwise. stdin is still drained. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Aug 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds
.github/workflows/ci.ymlandscripts/validate_config.py. Until now this repository had no automated verification at all — the previous four PRs each merged with zero checks.What it checks
ruff check/ruff format --checkscripts/validate_config.pyshellcheck --severity=warningThe validator targets the failure modes specific to a config template — the ones that fail silently for whoever copies
.claude/:settings.jsonthat don't exist. A renamed or deleted script doesn't error; the guardrail simply stops firing.protect-main.shblocks force-pushes andrm -rf /, so losing it quietly is the bad case.CLAUDE.md@-imports that don't resolve. A broken path drops that rule from Claude's context with no warning — the standards silently stop applying.SKILL.mdlost itsname/descriptionfrontmatter. Claude discovers skills through those fields, so a malformed one becomes invisible to automatic invocation. With 22 skills, 10 of them re-synced from upstream in chore(skills): re-sync vendored skills with anthropics/skills #13, this is worth a guard.settings.jsonor MCP config. The only one that's loud, and the cheapest to check.shellcheckis there because hook bugs have shipped twice: #10 (aPreToolUseifcondition that silently disabled both hooks) and #11 (a\bword-boundary that letrm -rf /through). Severity is capped atwarningso style nitpicks don't gate merges.What the first runs actually caught
CI is now green, after two red runs that were worth having:
astral-sh/setup-uv@v10didn't resolve. I readv10.0.0from the releases API, but setup-uv stopped publishing floating major tags after v7 — only full semver tags exist for v8 onward. Pinned to@v10.0.0. (actions/checkout@v7does maintain a floating tag and was fine.)SC2034insession-start.sh:input=$(cat)assigned the payload to a variable nothing read. Not a bug — that hook inspects the filesystem, not the payload — but the dead assignment implied the payload mattered. Nowcat >/dev/nullwith a comment saying stdin is drained so Claude Code's write to the pipe completes. Smoke-tested by piping a payload in and confirming valid JSON out.Verification
The validator was tested by injecting each fault — pointing a hook at
verify-typo.shand an import attesting-typo.md— and confirming it reported both and exited non-zero. A check that can't fail isn't a check.Also in this PR
pyproject.toml's ruffincludewas["pyproject.toml", "src/**/*.py"], which covered nothing this repository actually ships — there is nosrc/. Extended toscripts/**/*.pyand.claude/statusline.py; both already pass, so this is scope, not fixes. Vendored.claude/skills/scripts stay excluded.No test job: this repo ships configuration, not application code. The pytest config in
pyproject.tomlis for projects built from the template.🤖 Generated with Claude Code