skills-expert
Provide expert guidance on skills architecture, YAML frontmatter, tool permissions, and debugging. Use when creating, troubleshooting, or validating skills. Trigger with "skill not loading", "frontmatter", or "allowed-tools".
SKILL.md
| Name | skills-expert |
| Description | Provide expert guidance on skills architecture, YAML frontmatter, tool permissions, and debugging. Use when creating, troubleshooting, or validating skills. Trigger with "skill not loading", "frontmatter", or "allowed-tools". |
name: skills-expert description: "Provide expert guidance on skills architecture, YAML frontmatter, tool permissions, and debugging. Use when creating, troubleshooting, or validating skills. Trigger with "skill not loading", "frontmatter", or "allowed-tools"." allowed-tools: Read,Write,Glob,Grep,Edit version: 1.0.0 author: Jeremy Longshore jeremy@intentsolutions.io license: MIT
Skills Expert
Provide expert guidance on Claude Code skills development, validation, and troubleshooting.
Overview
This skill transforms Claude into a Claude Skills architecture expert. Use when:
- Creating new skills
- Debugging skill discovery/invocation issues
- Validating YAML frontmatter
- Understanding tool permissions
- Optimizing skill descriptions for selection
Prerequisites
- Access to skill files in
.claude/skills/orskills-pack/.claude/skills/ - Understanding of target skill's purpose
Claude Skills Architecture
YAML Frontmatter Fields
Required Fields
| Field | Max Length | Purpose |
|---|---|---|
name | 64 chars | Identifier used as command in Skill tool invocation |
description | 1024 chars | Primary signal Claude uses to decide when to invoke skill |
Optional Fields
| Field | Type | Purpose |
|---|---|---|
allowed-tools | CSV string | Pre-approved tools during skill execution |
model | string | Override model ("inherit" or model ID) |
version | string | Semantic versioning (e.g., "1.0.0") |
license | string | License metadata |
mode | boolean | true = appears in Mode Commands section |
disable-model-invocation | boolean | true = requires manual /skill-name |
Undocumented but Functional
| Field | Behavior |
|---|---|
when_to_use | Appends to description with hyphen separator |
Critical Rule: Skill MUST have description OR when_to_use or it's filtered out.
Directory Structure
skill-name/
├── SKILL.md # Core prompt + frontmatter (required)
├── scripts/ # Python/Bash executables
├── references/ # Documentation loaded via Read tool
└── assets/ # Templates, static files (referenced by path)
{baseDir} Variable
Template variable resolving to skill installation directory:
## Resources
- Skill standard: `{baseDir}/references/skill-standard.md`
Never hardcode absolute paths.
Tool Permission Scoping
Permissions in allowed-tools are scoped to skill execution only:
# Granular scoping examples
allowed-tools: "Bash(git:*),Read,Grep" # Only git commands
allowed-tools: "Bash(npm:*),Read,Write" # Only npm commands
allowed-tools: "Read,Glob,Grep" # Read-only audit
Skill Selection Mechanism
Claude decides skill invocation through pure language understanding:
- Claude receives Skill tool with
<available_skills>section - Each skill formatted as:
"skill-name": description - Claude's transformer matches user intent to descriptions
- Claude invokes Skill tool with matching
command
No embeddings, regex, or classifiers - pure LLM reasoning.
Execution Flow
- User request matches skill description
- Claude invokes
Skilltool withcommand: "skill-name" - Two messages injected:
- Visible:
<command-message>The "skill-name" skill is loading</command-message> - Hidden: Full SKILL.md content (isMeta: true)
- Visible:
- Tool permissions scoped to
allowed-tools - Skill prompt expands into conversation context
Token Budget
- Default skill description budget: 15,000 characters
- Typical skill prompt: 500-5,000 words
Discovery Priority
Skills loaded in order (later overrides earlier):
- User settings (
~/.config/claude/skills/) - Project settings (
.claude/skills/) - Plugin-provided skills
- Built-in skills
Critical Gotchas
- Skills are NOT concurrency-safe - Multiple simultaneous skill invocations cause context conflicts
- Skills don't live in system prompts - They're in the
toolsarray as part of Skill meta-tool when_to_useis undocumented/experimental - Safer to rely on detaileddescription- Hardcoded paths break portability - Always use
{baseDir}
Three-Stage Execution Pipeline
1. VALIDATION
- Syntax checking
- Skill existence verification
- Frontmatter parsing
2. PERMISSION EVALUATION
- Deny rules checked first (blocking patterns)
- Allow rules checked second (pre-approved)
- Default: prompt user for approval
3. LOADING & INJECTION
- SKILL.md content loaded
- Two messages injected (visible + hidden)
- Context modifier applied
- Tool permissions scoped
Where Skills Actually Live
Skills are NOT in system prompts. They're bundled in the tools array:
tools: [
{ name: "Read", ... },
{ name: "Write", ... },
{
name: "Skill", // Meta-tool
inputSchema: { command: string },
prompt: "<available_skills>..." // Dynamic, contains all skill descriptions
}
]
This enables dynamic loading without system prompt manipulation.
Instructions
When Creating Skills
- Write action-oriented descriptions that explicitly state use cases
- Keep descriptions under 1024 chars - be concise
- Use minimal tool permissions - principle of least privilege
- Use {baseDir} for all path references
- Include all four directories (scripts/, references/, assets/) even if empty
- Test discovery by asking Claude "what skills do you have?"
When Debugging Skills
- Check YAML frontmatter syntax (no tabs, proper quoting)
- Verify
descriptionorwhen_to_useexists - Check skill directory is in correct location
- Verify SKILL.md filename (case-insensitive)
- Check for
disable-model-invocation: trueblocking auto-discovery
When Validating Compliance
# Nixtla Standard Checklist
- [ ] name: lowercase + hyphens, matches folder name
- [ ] description: action-oriented, <1024 chars
- [ ] version: semver format
- [ ] allowed-tools: minimal necessary
- [ ] NO deprecated fields (author, priority, audience)
- [ ] mode: true ONLY for mode skills
- [ ] disable-model-invocation: true ONLY for infra/dangerous skills
Output
- Validated SKILL.md frontmatter
- Corrected skill configurations
- Debugging recommendations
- Skill architecture explanations
Error Handling
| Issue | Solution |
|---|---|
| Skill not discovered | Check description/when_to_use exists |
| Tools not working | Verify allowed-tools syntax |
| Wrong skill invoked | Improve description specificity |
| Skill filtered out | Add required frontmatter fields |
Examples
- Diagnose why a skill does not auto-trigger, then propose an updated
descriptionthat includes both “Use when …” and “Trigger with …”. - Audit a skill for minimal
allowed-toolsand scopedBash(...)usage.
Resources
- Project validator:
004-scripts/validate_skills_v2.py - Project skills:
003-skills/.claude/skills/
Examples
Example 1: Minimal Skill
---
name: my-skill
description: Generate reports from CSV data. Use when user has CSV files and needs analysis.
allowed-tools: "Read,Write,Glob"
version: "1.0.0"
---
Example 2: Mode Skill
---
name: expert-mode
description: Transform Claude into domain expert for extended session.
mode: true
allowed-tools: "Read,Write,Glob,Grep,Edit,Bash"
version: "1.0.0"
---
Example 3: Infrastructure Skill
---
name: deploy-skill
description: Deploy application to production. Dangerous - requires explicit invocation.
disable-model-invocation: true
allowed-tools: "Bash(deploy:*),Read,Glob"
version: "1.0.0"
---
Resources
- Skill standard:
{baseDir}/references/skill-standard.md - Deep dive source: https://leehanchung.github.io/blogs/2025/10/26/claude-skills-deep-dive/