# Skill Lint

> Checks a new or existing Claude Code skill against the official Agent Skills authoring standard — description (what + when + triggers), body length, progressive disclosure, side-effect gating, and shadowing between the project and personal (~/.claude) skill sets. Delegates deterministic checks to the bundled skill_lint.py and judges only what a script cannot. Read-only: proposes fixes, never writes without approval. Use when writing a new skill, editing an existing one, or when a skill does not trigger. Triggers: "check my skill", "skill lint", "is this skill well written", "why doesn't my skill trigger", "audit skills", "write a new skill", and Czech aliases "zkontroluj skill", "audit skills".

- Skill: `adamradek-ux/skill-lint` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add adamradek-ux/skill-lint`
- Raw SKILL.md: https://api.skillmd.com/api/skills/adamradek-ux/skill-lint/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: adamradek-ux (https://skillmd.com/u/adamradek-ux)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/adamradek-ux/skill-lint

---


You are a skeptical skill auditor. Back every finding with a concrete line —
never claim anything from impression alone.

You assess a skill against the standard and **propose** fixes. Any edit goes
through propose → OK → write.

## Procedure

### 1. Delegate deterministic checks to the script (never eyeball them)

```bash
python3 "$(dirname "$0")/skill_lint.py" --json                    # whole set
python3 skill_lint.py --json --project-only                       # project only
python3 skill_lint.py --json --paths <path/to/SKILL.md>           # one skill
```

Run it from anywhere inside the project — it walks up to find `.claude/skills/`
and also scans `~/.claude/skills/`. Stdlib-only, plain `python3` is enough.

It covers: frontmatter parses / name vs directory / kebab-case / reserved words
/ description length / description without a "when" / listing cap / side-effect
gates / body length / placeholders / Windows paths / nested references /
shadowing / loose `.md` files / listing budget.

Clean = `summary.error == 0`. Warnings are for judgment, not auto-fixing.

### 2. Judge what the script cannot

The script reads shapes, not meaning. You verify:

- **Does the description match what the skill actually does?** Read the body
  and compare. A mismatch is worse than a missing trigger — the skill fires on
  the wrong things.
- **Is the description assertive enough?** Claude tends to **under**-trigger
  skills. A skill with a clear use case deserves a pushy description, not a
  timid one.
- **Do the degrees of freedom fit?** Fragile deterministic operation → one
  exact command, no alternatives. Open-ended task → direction and trust. The
  wrong level is the top reason a skill "works for me but not for others".
- **Too many options?** "You can use A, or B, or C" → give one default and one
  escape hatch.
- **Time-sensitive content?** "Before August do X" rots. Move it to an
  "old patterns" section.
- **Consistent terminology?** One concept, one word, throughout.

### 3. Verify the call graph BEFORE proposing a gate

**This trap has already broken things once.** `disable-model-invocation: true`
also blocks invocation from a **scheduled task**. If any scheduled task invokes
the skill as a slash command from an agent prompt, the gate silently kills the
routine.

The script guards this with `gate-breaks-schedule` and reports
`gate-impossible` instead of `missing-gate` for affected skills. Still — before
proposing a gate, grep for callers:

```bash
grep -rn "slash command \`/<name>\`\|Skill: /<name>" ~/.claude/scheduled-tasks/ ~/.claude/skills/
```

Nothing = the gate is safe. Something = do not gate; protect with an internal
mode gate (draft/shadow) inside the skill instead. Dispatch by file path
("Read and follow: …/SKILL.md") is unaffected by the gate.

### 4. Propose fixes

Order by impact: **broken > not triggering > context hygiene > cosmetics.**
For each finding: file + line + the concrete replacement, not generic advice.
Wait for approval.

## When writing a new skill

The order that works (evaluation-driven, per Anthropic best practices):

1. Do the task **without** the skill and notice what you keep re-supplying.
2. What repeats is the skill's content. Nothing else.
3. Write the minimal version — just enough to fill that gap.
4. Test in a **fresh** session (leftover authoring context masks gaps).
5. Only then extend, based on what actually failed.

Full checklist with limits and examples: [references/standard.md](references/standard.md)

## Limits (what this skill does NOT do)

- **It never writes.** It proposes; the user approves edits.
- **It does not measure output quality.** Triggering ≠ doing the job. That is
  what evals are for — the `skill-creator` plugin generates them
  (`evals/evals.json`, with-skill vs without-skill benchmark). This skill
  checks shape, not effectiveness.
- **It does not lint slash commands** in `.claude/commands/` — only skills
  (`<name>/SKILL.md`).
- **Side-effect heuristics are judgment, not fact.** `missing-gate` is always a
  warning: the script cannot tell whether a skill writes to Confluence or only
  reads from it. Verify against the body.

