A Claude Code skill that scaffolds and lints other Claude Code skills against
Anthropic's published SKILL.md authoring rules, so your skill actually gets
discovered and loaded instead of sitting on disk doing nothing.
Most skills that fail to trigger are not broken in the body. They fail in the frontmatter, quietly: a description written in first person, a name with uppercase or a reserved word, a field over the length limit, or a body that grew past the point where it should have been split into reference files. None of those throw an error you'd notice. The skill just never loads, and you assume the model ignored it.
Skill Forge checks for exactly those problems and tells you the precise fix.
skill-forge/
├── SKILL.md # the skill itself, for Claude Code
├── scripts/
│ ├── lint-skill.js # the linter (also a CLI)
│ └── scaffold-skill.js # generates a compliant skeleton
├── references/
│ ├── authoring-rules.md # every rule, with source quotes
│ ├── description-examples.md # good vs. bad descriptions
│ └── progressive-disclosure.md # how SKILL.md + references/ load
├── examples/
│ ├── good-skill/SKILL.md # passes the linter
│ └── bad-skill/SKILL.md # fails the linter (the test fixture)
└── test/
└── lint-skill.test.js # node --test
Skill Forge is a Claude Code skill. Pick one of two ways to install it.
As a personal skill — copy the directory into your skills folder:
git clone https://github.com/VelkinaStudio/skill-forge
cp -r skill-forge ~/.claude/skills/skill-forgeProject-scoped instead of personal: copy into .claude/skills/skill-forge inside
the repo you're working in.
As a plugin — if you distribute it through a plugin marketplace, place the same
directory under the plugin's skills/ folder. The SKILL.md is the only file
Claude needs to discover it; the scripts and references load on demand.
Once installed, Claude loads it automatically when you ask to create, review, or
fix a skill, or you can invoke it directly with /skill-forge.
You can also run the two scripts standalone with no install — they only need Node 18+ and have no dependencies.
node scripts/lint-skill.js path/to/SKILL.md
# or point at the directory and it finds SKILL.md inside
node scripts/lint-skill.js path/to/skill-directoryIt prints one line per violation — the rule, what's wrong, and the exact fix — and exits non-zero if any error is found. Warnings don't change the exit code, so you can wire the error gate into CI.
Example, run against the bad fixture:
[ERROR] name-bad-chars: name "Claude_PDF_Helper" contains disallowed characters:
["C","_","P","D","F","H"]. Only lowercase letters, numbers, and hyphens
are allowed.
fix: Rename to "claude-pdf-helper".
[ERROR] name-reserved-word: name "Claude_PDF_Helper" contains the reserved word
"claude".
fix: Remove "claude" from the name. Reserved words are: anthropic, claude.
[ERROR] description-not-third-person: description appears to use first/second
person. The docs require third person because it is injected into the
system prompt.
fix: Rewrite in third person: "Processes X and generates Y. Use when ..."
node scripts/scaffold-skill.js "review terraform plans for drift" --out=.claude/skillsThis writes a SKILL.md, a references/guide.md, and a scripts/helper.js under a
folder named from your intent. The generated SKILL.md is checked against the
linter before it's written, so the skeleton always passes. Then you fill in the real
description triggers and the real procedure — the parts the generator can't know.
Preview without writing files:
node scripts/scaffold-skill.js "review terraform plans for drift" --printnode --testThe suite asserts the good example passes the linter and the bad example fails it, plus the field-limit and scaffold checks.
All verified against Anthropic's docs (checked 2026-06-03):
name: max 64 chars, lowercase letters/numbers/hyphens only, no XML tags, no reserved words (anthropic,claude).description: non-empty, max 1024 chars, no XML tags, third person, states both what it does and when to use it.- body: under 500 lines, with deep material split into
references/.
Sources and exact quotes are in
references/authoring-rules.md. If a limit ever
changes, it lives in one place — the RULES object in scripts/lint-skill.js.
MIT. See LICENSE.
Built by Velkina — https://velkina.com