Skip to content

Repository files navigation

claude-skill-kit

A linter and sync tool for maintaining a library of Claude Code Agent Skills.

If you've written more than a handful of SKILL.md files, you've probably hit the same problems: a skill's name: frontmatter drifts from its folder name, a skill balloons past the point where the model reliably uses the whole thing, someone hardcodes C:\Users\yourname\... into a skill body and it breaks the moment anyone else clones the repo, or you've got two copies of a skill (one you edit, one that's actually loaded) that have quietly diverged.

claude-skill-kit is two small, dependency-free PowerShell scripts that catch all of that:

  • lint-skills.ps1 — checks every skill for frontmatter correctness, name/folder match, a line-count cap, and hardcoded absolute paths.
  • sync-skills.ps1 — keeps a single "master" copy of your skills in sync with the deployed copy (or copies) that Claude Code / Cowork actually load, via robocopy.

Both scripts are standalone: they resolve everything from their own location ($PSScriptRoot), so you can drop this repo anywhere and point it at your own skills.

The problem: one edit surface

Claude Code loads skills from a project's .claude/skills/ folder. If you maintain skills across multiple projects, or want a single browsable catalog of everything you've built, you end up copy-pasting skills around — and copies drift. The fix is the same one you'd use for any config-drift problem: one canonical place you edit, one tool that deploys it out.

your-repo/
├── skills/
│   └── core/                  ← the master holder — edit skills here
│       ├── git-advanced/
│       │   └── SKILL.md
│       └── security-hardening/
│           ├── SKILL.md
│           └── reference.md
├── .claude/
│   └── skills/                ← the deployed copy — Claude Code loads from here
│       ├── git-advanced/
│       └── security-hardening/
├── manifest.json              ← maps master subfolders -> deploy targets
├── lint-skills.ps1
└── sync-skills.ps1

Edit under skills/<set>/, run sync-skills.ps1 -Mode Push, and the deployed copy catches up. If an agent self-edits a deployed skill live, -Mode Pull absorbs that change back into the master so it stays the single source of truth.

What the linter checks

For every SKILL.md under each configured skillset, lint-skills.ps1 checks:

Check What it catches
YAML frontmatter present A skill with no --- block — Claude Code can't read its metadata at all
name field present Missing name means the skill can't be identified
name matches the folder name Copy-paste drift — you renamed the folder but not the frontmatter (or vice versa)
description field present The description is how the model decides to invoke the skill — no description means it never triggers
Body ≤ 200 lines Long skills are less reliably followed in full; the cap pushes you toward the extract-to-reference pattern (move worked examples to a sibling reference.md, keep the rules in SKILL.md)
No hardcoded absolute paths C:\Users\..., /mnt/..., ~/.claude/... — anything that only works on the machine that wrote it

Skills that legitimately need to exceed the 200-line cap (multi-stage orchestrator skills, for example) can be listed in lint-exempt.txt — the linter reports them as accepted complexity instead of flagging them.

Quickstart

# Lint every skillset defined in manifest.json
pwsh ./lint-skills.ps1

# Lint just one skillset
pwsh ./lint-skills.ps1 -Only core

# Check for drift between the master and the deployed copy (non-destructive, default mode)
pwsh ./sync-skills.ps1

# Deploy the master out to .claude/skills (additive — never deletes a deployed-only file)
pwsh ./sync-skills.ps1 -Mode Push

# Absorb changes an agent made directly to the deployed copy, back into the master
pwsh ./sync-skills.ps1 -Mode Pull

# Regenerate REGISTRY.md (a catalog of every skill + its description) from frontmatter
pwsh ./sync-skills.ps1 -Mode Registry

Example: linting a skill

Given a skill with a folder/name mismatch:

skills/core/git-advanced/SKILL.md
---
name: git-advanced-workflows   <- doesn't match the folder name
description: Advanced git workflows...
---
> pwsh ./lint-skills.ps1

Linted 5 skills across 1 skillset(s).

1 issue(s):
  [core/git-advanced] name 'git-advanced-workflows' != folder 'git-advanced'

Fix the name (or the folder), re-run, and you're clean:

Linted 5 skills across 1 skillset(s).
All clean.

Bundled example skills

skills/core/ ships five real, generic engineering skills so you can see the pattern and lint something on first run without writing your own skill first:

  • git-advanced — worktrees, bisect, interactive rebase, hooks, recovery techniques
  • tdd-mastery — Red-Green-Refactor cycle, test structure, and patterns across Jest/pytest/Go
  • testing-strategies — contract testing, snapshot testing, property-based testing, test doubles
  • security-hardening — input validation, CSRF, CSP, secrets management, dependency auditing
  • python-best-practices — modern type hints, dataclasses vs. Pydantic, async patterns, packaging

security-hardening, testing-strategies, and python-best-practices each ship a sibling reference.md demonstrating the extract-to-reference pattern: the SKILL.md carries the rules and checklist, the reference file carries the full worked code examples, keeping the skill body under the 200-line cap without losing the detail.

manifest.json

Maps each master subfolder to where it deploys:

{
  "skillsets": [
    { "name": "core", "master": "skills\\core", "target": ".claude\\skills" }
  ]
}

Add more entries to manage multiple skillsets (e.g. a core set everyone gets, plus a project-specific set) or to fan the same master out to more than one deployed location.

Configuration files

  • manifest.json — the skillset map (see above).
  • lint-exempt.txt — one skill-folder name per line; skills listed here are exempt from the 200-line cap. Ships as an empty template — add your own exemptions as your skills grow.
  • REGISTRY.md — auto-generated catalog of every skill and its description. Regenerate with sync-skills.ps1 -Mode Registry after adding or editing a skill; don't hand-edit it.

Requirements

  • Windows PowerShell 5.1+ or PowerShell 7+ (pwsh)
  • robocopy (ships with Windows; used by sync-skills.ps1 for the Push/Pull copy)
  • Pester 5.x, only if you want to run the test suite (tests/)

Tests

Install-Module Pester -Scope CurrentUser -MinimumVersion 5.0 -Force  # if not already installed
Invoke-Pester ./tests/lint-skills.Tests.ps1 -Output Detailed

The suite builds small fixture skill trees under Pester's TestDrive to exercise each check in isolation (missing file, missing name, name/folder mismatch, missing description, over-cap body, exempted over-cap body, hardcoded path) and finishes with a smoke test that lints this repo's own bundled skills and asserts a clean report.

CI (.github/workflows/ci.yml) runs the linter and the Pester suite on windows-latest on every push and pull request.

License

MIT — see LICENSE.

About

Lint, sync, and catalog your Claude Code skill library — a frontmatter/name-match/200-line-cap/hardcoded-path linter, a master↔deploy sync tool, and an auto-generated registry. PowerShell.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages