Create and manage Claude Code skills following Anthropic best practices. Use when creating new skills, modifying skill-rules.json, understanding trigger patterns, working with hooks, debugging skill activation, or implementing progressive disclosure. Covers skill structure, YAML frontmatter, trigger types (keywords, intent patterns, file paths, content patterns), enforcement levels (block, suggest, warn), hook mechanisms (UserPromptSubmit, PreToolUse), session tracking, and the 500-line rule.
77
77%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Passed
No known issues
Technical deep dive into how the UserPromptSubmit and PreToolUse hooks work.
User submits prompt
↓
.claude/settings.json registers hook
↓
skill-activation-prompt.sh executes
↓
npx tsx skill-activation-prompt.ts
↓
Hook reads stdin (JSON with prompt)
↓
Loads skill-rules.json
↓
Matches keywords + intent patterns
↓
Groups matches by priority (critical → high → medium → low)
↓
Outputs formatted message to stdout
↓
stdout becomes context for Claude (injected before prompt)
↓
Claude sees: [skill suggestion] + user's prompt{
"session_id": "abc-123",
"transcript_path": "/path/to/transcript.json",
"cwd": "/root/git/your-project",
"permission_mode": "normal",
"hook_event_name": "UserPromptSubmit",
"prompt": "how does the layout system work?"
}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🎯 SKILL ACTIVATION CHECK
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📚 RECOMMENDED SKILLS:
→ project-catalog-developer
ACTION: Use Skill tool BEFORE responding
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━Claude sees this output as additional context before processing the user's prompt.
Claude calls Edit/Write tool
↓
.claude/settings.json registers hook (matcher: Edit|Write)
↓
skill-verification-guard.sh executes
↓
npx tsx skill-verification-guard.ts
↓
Hook reads stdin (JSON with tool_name, tool_input)
↓
Loads skill-rules.json
↓
Checks file path patterns (glob matching)
↓
Reads file for content patterns (if file exists)
↓
Checks session state (was skill already used?)
↓
Checks skip conditions (file markers, env vars)
↓
IF MATCHED AND NOT SKIPPED:
Update session state (mark skill as enforced)
Output block message to stderr
Exit with code 2 (BLOCK)
ELSE:
Exit with code 0 (ALLOW)
↓
IF BLOCKED:
stderr → Claude sees message
Edit/Write tool does NOT execute
Claude must use skill and retry
IF ALLOWED:
Tool executes normally{
"session_id": "abc-123",
"transcript_path": "/path/to/transcript.json",
"cwd": "/root/git/your-project",
"permission_mode": "normal",
"hook_event_name": "PreToolUse",
"tool_name": "Edit",
"tool_input": {
"file_path": "/root/git/your-project/form/src/services/user.ts",
"old_string": "...",
"new_string": "..."
}
}⚠️ BLOCKED - Database Operation Detected
📋 REQUIRED ACTION:
1. Use Skill tool: 'database-verification'
2. Verify ALL table and column names against schema
3. Check database structure with DESCRIBE commands
4. Then retry this edit
Reason: Prevent column name errors in Prisma queries
File: form/src/services/user.ts
💡 TIP: Add '// @skip-validation' comment to skip future checksClaude receives this message and understands it needs to use the skill before retrying the edit.
| Exit Code | stdout | stderr | Tool Execution | Claude Sees |
|---|---|---|---|---|
| 0 (UserPromptSubmit) | → Context | → User only | N/A | stdout content |
| 0 (PreToolUse) | → User only | → User only | Proceeds | Nothing |
| 2 (PreToolUse) | → User only | → CLAUDE | BLOCKED | stderr content |
| Other | → User only | → User only | Blocked | Nothing |
This is THE critical mechanism for enforcement:
User: "Add a new user service with Prisma"
Claude: "I'll create the user service..."
[Attempts to Edit form/src/services/user.ts]
PreToolUse Hook: [Exit code 2]
stderr: "⚠️ BLOCKED - Use database-verification"
Claude sees error, responds:
"I need to verify the database schema first."
[Uses Skill tool: database-verification]
[Verifies column names]
[Retries Edit - now allowed (session tracking)]Prevent repeated nagging in the same session - once Claude uses a skill, don't block again.
.claude/hooks/state/skills-used-{session_id}.json
{
"skills_used": [
"database-verification",
"error-tracking"
],
"files_verified": []
}First edit of file with Prisma:
Second edit (same session):
Different session:
The hook cannot detect when the skill is actually invoked - it just blocks once per session per skill. This means:
Loading skill-rules.json (every execution)
Reading file content (PreToolUse)
Glob matching (PreToolUse)
Regex matching (Both hooks)
Reduce patterns:
File path patterns:
form/src/services/** better than form/**Content patterns:
Related Files: