Skip to content

ci: lint SKILL.md frontmatter on every push#172

Open
MukundaKatta wants to merge 1 commit intoJuliusBrussee:mainfrom
MukundaKatta:ci/lint-skill-files
Open

ci: lint SKILL.md frontmatter on every push#172
MukundaKatta wants to merge 1 commit intoJuliusBrussee:mainfrom
MukundaKatta:ci/lint-skill-files

Conversation

@MukundaKatta
Copy link
Copy Markdown
Contributor

Why

Caveman ships 10 SKILL.md files (across skills/, plugins/caveman/skills/, caveman-compress/, compress/, caveman/) and grew from 0 β†’ 30k stars in 11 days. That growth means each new contributor PR that touches a skill file is high-leverage β€” and also a good place for a small mistake to land silently. Malformed frontmatter, a missing description, or (worst) a committed API key in env would ship to every install.

This PR adds CI that catches those at PR time.

What

A single workflow: .github/workflows/lint-skills.yml β€” path-filtered to only run when a SKILL.md (or the workflow itself) changes. Uses MukundaKatta/claude-skill-linter (MIT, pinned to @v1) to validate:

  • YAML frontmatter parses
  • Required fields (name, description) present and well-formed
  • name is kebab-case
  • description has enough substance (and trigger language) for Claude to route to the skill
  • Hardcoded secrets (sk-, ghp_, AIza, xoxb-) are absent
  • Relative-path references resolve
  • Unknown frontmatter fields flagged (typo detection)

Current state

All 10 existing SKILL.md files pass β€” in strict mode, zero warnings, zero errors. The workflow starts green.

Ran locally against the repo:

βœ“ skills/compress/SKILL.md
βœ“ skills/caveman-review/SKILL.md
βœ“ skills/caveman-help/SKILL.md
βœ“ skills/caveman-commit/SKILL.md
βœ“ skills/caveman/SKILL.md
βœ“ plugins/caveman/skills/compress/SKILL.md
βœ“ plugins/caveman/skills/caveman/SKILL.md
βœ“ compress/SKILL.md
βœ“ caveman-compress/SKILL.md
βœ“ caveman/SKILL.md

Checked 10 file(s): 0 error(s), 0 warning(s)

(.cursor/skills/ and .windsurf/skills/ also pass; just not globbed by default since they're in dotfile dirs.)

Why strict mode

For a repo this visible, strict: 'true' is worth the signal β€” warnings (like missing trigger language in a description) become CI errors. If the noise turns out to be counterproductive on community PRs, flipping it to 'false' is a one-line change. I'd rather start strict and relax if needed than start lax and miss something.

Disclosure

I maintain claude-skill-linter. Happy to unpin @v1 β†’ pin to a specific SHA if you prefer immutability. The Action has no network calls at runtime β€” all validation is static on the repo's own file contents.

Test plan

  • Lints all 10 existing SKILL.md files β€” green
  • Linter source audited: no network, no telemetry, no writes to the workspace
  • Workflow path-filtered β€” won't run on unrelated commits
  • Pinned to @v1 (rolling major-version tag)

Adds a GitHub Actions workflow that validates every SKILL.md file in
the repo using claude-skill-linter. Catches at CI time:

- Malformed or unparseable YAML frontmatter
- Missing required fields (name, description)
- name not in kebab-case
- description too short to help Claude route to the skill
- Hardcoded API keys (sk-, ghp_, AIza, xoxb-)
- Broken relative-path references
- Unknown/typo'd frontmatter fields

All 10 current SKILL.md files pass in strict mode on main, so the
workflow starts green. strict: 'true' keeps warnings as errors β€” worth
the signal for a repo this visible; easy to relax if it becomes noise.

Path-filtered so the job only runs when a SKILL.md (or the workflow
itself) changes β€” no CI wait on unrelated commits.

Action: https://github.com/MukundaKatta/claude-skill-linter
(MIT, pinned to v1 for rolling compatibility.)

Signed-off-by: Mukunda Katta <mukunda.vjcs6@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant