Discover all skills in the project, score them across 6 criteria, and infer the appropriate effort level based on content analysis.
effort fields for the first timeAll SKILL.md files and flat .md files found in:
.claude/skills/**
~/.claude/skills/** (if requested).claude/commands/** (legacy flat files, still valid)/eval-skills ./my-skills-dir
Claude Code skills follow the agentskills.io open standard, extended with Claude Code-specific fields. Flag any field not in this table as unsupported.
| Field | Required | Notes |
|---|---|---|
name |
No | Display label shown in skill lists. The command name always comes from the directory name, not this field. |
description |
Recommended | Combined with when_to_use, truncated at 1,536 chars in context. First paragraph used if omitted. |
when_to_use |
No | Additional trigger phrases and example requests. Appended to description in context; counts toward the 1,536-char cap. |
allowed-tools |
No | Tools usable without per-use approval while the skill is active. Space-separated string or YAML list (both valid). |
license |
No | License identifier (agentskills.io spec) |
compatibility |
No | Compatibility constraints (agentskills.io spec) |
metadata |
No | Arbitrary metadata object (agentskills.io spec) |
| Field | Required | Notes |
|---|---|---|
argument-hint |
No | Hint shown during autocomplete. Example: [issue-number] or [filename] [format] |
arguments |
No | Named positional args for $name substitution. Space-separated string or YAML list. Names map to positions in order. |
disable-model-invocation |
No | true = user-only invocation. Removes skill from Claude's context and prevents preloading in subagents. |
user-invocable |
No | false = hides skill from / menu but Claude can still auto-invoke it. |
disallowed-tools |
No | Tools blocked while this skill is active. Cleared after the current message. |
model |
No | Override model for this skill's turn only. Reverts to session model on next prompt. |
effort |
No | Thinking effort: low, medium, high, xhigh, max. Overrides session effort for the turn. |
context |
No | fork = runs skill in an isolated subagent context. The skill body becomes the subagent's prompt. |
agent |
No | Which subagent type to use when context: fork is set. Options: Explore, Plan, general-purpose, or any custom agent in .claude/agents/. |
hooks |
No | Skill-scoped lifecycle hooks. Same format as session hooks. |
paths |
No | Glob patterns that limit when Claude auto-loads this skill. Same format as path-specific rules. |
shell |
No | Shell for !backtick injection: bash (default) or powershell. |
tags, category, keywords, usage, args are ignored by the runtime. Remove them to avoid confusion.
If a skill references substitution placeholders, verify they use the correct syntax:
| Placeholder | Meaning |
|---|---|
$ARGUMENTS |
Full argument string as typed |
$ARGUMENTS[N] or $N |
Argument at position N (0-based) |
$name |
Named argument declared in arguments: frontmatter |
${CLAUDE_SESSION_ID} |
Current session ID |
${CLAUDE_EFFORT} |
Active effort level (low / medium / high / xhigh / max) |
${CLAUDE_SKILL_DIR} |
Absolute path to the skill's directory; use it for referencing bundled scripts |
Incorrect placeholders ($1 when no arguments: field is declared, ${ARGS}, %ARGUMENTS%) are passed as literal text and silently break the skill.
| # | Criterion | Max | What is checked |
|---|---|---|---|
| 1 | name field | 1 | name field present and lowercase with hyphens only |
| 2 | description | 3 | Present (1), has "Use when" / trigger phrasing (1), when_to_use field present for skills that need broad matching (1) |
| 3 | allowed-tools | 2 | Present (1), scoped appropriately (1): not Bash without path scoping when read-only tools suffice |
| 4 | effort | 3 | Present (1), appropriate for content per inference engine below (2) |
| 5 | content structure | 5 | Has Purpose or When section (1), has concrete examples or usage (1), has clear workflow or steps (1), no placeholder text (1), no unsupported frontmatter fields (1) |
| 6 | bonus | +2 | argument-hint present when skill takes args (1), ${CLAUDE_SKILL_DIR} used for bundled scripts instead of hardcoded paths (1) |
Thresholds:
allowed-tools format noteBoth formats are valid and parse correctly:
Read Bash Grep
[Read, Bash, Grep]
Flag skills that use Bash globally (without path scoping like Bash(git *)) when they only need read operations (this grants unnecessary write access).
The combined description + when_to_use text is truncated at 1,536 chars per skill in Claude's context. Flag skills where the combined text exceeds this limit; the tail (often the trigger examples) gets silently cut.
For each skill, analyze description + content and classify using these signals:
low: Mechanical execution, no design decisionsSignals:
allowed-tools: Bash only, or Read onlyExamples: /commit, /release-notes, /scaffold, /sync, /format
medium: Analysis with bounded scope, categorizationSignals:
allowed-tools: Read + Grep + Bash combinationExamples: /code-review (single PR), /issue-triage, /dependency-audit, /test-coverage
high: Design decisions, adversarial reasoning, cross-system analysisSignals:
allowed-tools: broad access (Read + Write + Bash + external tools)Examples: /security-audit, /architecture-review, /eval-agents
xhigh / max: Exhaustive, multi-agent, long-runningSignals:
ultrathink or ultracode in skill bodyWorkflow tool or fan-out orchestration patternsExamples: /deep-research, /full-security-audit, /codebase-migration
If a skill has effort: already set but the inferred level differs, flag it:
⚠️ Effort mismatch: declared
low, inferredhigh. Skill spawns 4 sub-agents and performs security analysis.
# Find all SKILL.md files
find .claude/skills -name "SKILL.md" 2>/dev/null
# Find legacy flat command files
find .claude/commands -maxdepth 1 -name "*.md" ! -name "README*" 2>/dev/null
# If argument provided, use that path instead
For each skill file found:
--- and second ---)Apply the scoring criteria to each skill:
allowed-tools scope: is Bash used without path scoping when read-only tools suffice?context: fork skills for completeness; they must have an actionable task body and an agent field (or a reasonable default applies)Produce a structured report:
# Skills Audit: [project name or path]
Date: [today] | Scanned: N skills
## Summary
| Status | Count |
|--------|-------|
| ✅ Good (>=80%) | N |
| ⚠️ Needs work (60-79%) | N |
| ❌ Fix (<60%) | N |
**Effort coverage**: N/N skills have effort field set
---
## Per-Skill Results
### [skill-name] ([score]/16) [✅/⚠️/❌]
| Criterion | Score | Notes |
|-----------|-------|-------|
| name | ✅ 1/1 | ok |
| description | ⚠️ 2/3 | Missing when_to_use field |
| allowed-tools | ✅ 2/2 | Well-scoped |
| effort | ❌ 0/3 | Missing. Recommended: high |
| content structure | ⚠️ 3/5 | No examples section, unsupported field "tags" found |
**Effort inference**: `high`. Skill performs security analysis with adversarial reasoning.
Signals: "threat", "attack surface", "vulnerability scoring" in content; spawns 4 agents
**Priority fixes** (ordered by impact):
1. Add `effort: high` to frontmatter
2. Add `when_to_use` with trigger phrases
3. Remove unsupported field `tags`
4. Add a concrete usage example section
---
After all skills: print a Fix Summary.
At the end, print a ready-to-use patch block for all missing/mismatched effort fields:
## Recommended effort fields (copy-paste ready)
skill-name-1: effort: low # mechanical scaffold
skill-name-2: effort: high # security analysis, spawns agents
skill-name-3: effort: medium # code review, bounded scope
And a 1-line count: N skills need effort field · N mismatches · N missing allowed-tools · N unsupported fields to remove