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
Complete debugging guide for skill activation problems.
Symptoms: Ask a question, but no skill suggestion appears in output.
Common Causes:
Check:
promptTriggers.keywords in skill-rules.jsonExample:
"keywords": ["layout", "grid"]Fix: Add more keyword variations to skill-rules.json
Check:
promptTriggers.intentPatternsExample:
"intentPatterns": [
"(create|add).*?(database.*?table)" // Too specific
]Fix: Broaden the pattern:
"intentPatterns": [
"(create|add).*?(table|database)" // Better
]Check:
Example:
# SKILL.md
name: project-catalog-developer// skill-rules.json
"project-catalogue-developer": { // ❌ Typo: catalogue vs catalog
...
}Fix: Make names match exactly
Check:
cat .claude/skills/skill-rules.json | jq .If invalid JSON, jq will show the error.
Common errors:
Fix: Correct JSON syntax, validate with jq
Test the hook manually:
echo '{"session_id":"debug","prompt":"your test prompt here"}' | \
npx tsx .claude/hooks/skill-activation-prompt.tsExpected: Your skill should appear in the output.
Symptoms: Edit a file that should trigger a guardrail, but no block occurs.
Common Causes:
Check:
fileTriggers.pathPatterns in skill-rules.jsonExample:
"pathPatterns": [
"frontend/src/**/*.tsx"
]frontend/src/components/Dashboard.tsx → ✅ Matchesfrontend/tests/Dashboard.test.tsx → ✅ Matches (add exclusion!)backend/src/app.ts → ❌ Doesn't matchFix: Adjust glob patterns or add the missing path
Check:
fileTriggers.pathExclusionsExample:
"pathExclusions": [
"**/*.test.ts",
"**/*.spec.ts"
]services/user.test.ts → ❌ Excludedservices/user.ts → ✅ Not excludedFix: If test exclusion too broad, narrow it or remove
Check:
fileTriggers.contentPatternsExample:
"contentPatterns": [
"import.*[Pp]risma"
]import { PrismaService } from './prisma' → ✅ Matchesimport { Database } from './db' → ❌ Doesn't matchDebug:
# Check if pattern exists in file
grep -i "prisma" path/to/file.tsFix: Adjust content patterns or add missing imports
Check session state:
ls .claude/hooks/state/
cat .claude/hooks/state/skills-used-{session-id}.jsonExample:
{
"skills_used": ["database-verification"],
"files_verified": []
}If the skill is in skills_used, it won't block again in this session.
Fix: Delete the state file to reset:
rm .claude/hooks/state/skills-used-{session-id}.jsonCheck file for skip marker:
grep "@skip-validation" path/to/file.tsIf found, the file is permanently skipped.
Fix: Remove the marker if verification is needed again
Check:
echo $SKIP_DB_VERIFICATION
echo $SKIP_SKILL_GUARDRAILSIf set, the skill is disabled.
Fix: Unset the environment variable:
unset SKIP_DB_VERIFICATIONTest the hook manually:
cat <<'EOF' | npx tsx .claude/hooks/skill-verification-guard.ts 2>&1
{
"session_id": "debug",
"tool_name": "Edit",
"tool_input": {"file_path": "/root/git/your-project/form/src/services/user.ts"}
}
EOF
echo "Exit code: $?"Expected:
Symptoms: Skill triggers when it shouldn't.
Common Causes & Solutions:
Problem:
"keywords": ["user", "system", "create"] // Too broadSolution: Make keywords more specific
"keywords": [
"user authentication",
"user tracking",
"create feature"
]Problem:
"intentPatterns": [
"(create)" // Matches everything with "create"
]Solution: Add context to patterns
"intentPatterns": [
"(create|add).*?(database|table|feature)" // More specific
]Advanced: Use negative lookaheads to exclude
(create)(?!.*test).*?(feature) // Don't match if "test" appearsProblem:
"pathPatterns": [
"form/**" // Matches everything in form/
]Solution: Use narrower patterns
"pathPatterns": [
"form/src/services/**/*.ts", // Only service files
"form/src/controllers/**/*.ts"
]Problem:
"contentPatterns": [
"Prisma" // Matches in comments, strings, etc.
]// Don't use Prisma hereconst note = "Prisma is cool"Solution: Make patterns more specific
"contentPatterns": [
"import.*[Pp]risma", // Only imports
"PrismaService\\.", // Only actual usage
"prisma\\.(findMany|create)" // Specific methods
]Last resort: If false positives are frequent:
{
"enforcement": "block" // Change to "suggest"
}This makes it advisory instead of blocking.
Symptoms: Hook doesn't run at all - no suggestion, no block.
Common Causes:
Check .claude/settings.json:
cat .claude/settings.json | jq '.hooks.UserPromptSubmit'
cat .claude/settings.json | jq '.hooks.PreToolUse'Expected: Hook entries present
Fix: Add missing hook registration:
{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/skill-activation-prompt.sh"
}
]
}
]
}
}Check:
ls -l .claude/hooks/*.shExpected: -rwxr-xr-x (executable)
Fix:
chmod +x .claude/hooks/*.shCheck:
head -1 .claude/hooks/skill-activation-prompt.shExpected: #!/bin/bash
Fix: Add correct shebang to first line
Check:
npx tsx --versionExpected: Version number
Fix: Install dependencies:
cd .claude/hooks
npm installCheck:
cd .claude/hooks
npx tsc --noEmit skill-activation-prompt.tsExpected: No output (no errors)
Fix: Correct TypeScript syntax errors
Symptoms: Hooks are slow, noticeable delay before prompt/edit.
Common Causes:
Check:
Solution: Reduce patterns
Problem:
(create|add|modify|update|implement|build).*?(feature|endpoint|route|service|controller|component|UI|page)Solution: Simplify
(create|add).*?(feature|endpoint) // Fewer alternativesProblem:
"pathPatterns": [
"**/*.ts" // Checks ALL TypeScript files
]Solution: Be more specific
"pathPatterns": [
"form/src/services/**/*.ts", // Only specific directory
"form/src/controllers/**/*.ts"
]Content pattern matching reads entire file - slow for large files.
Solution:
# UserPromptSubmit
time echo '{"prompt":"test"}' | npx tsx .claude/hooks/skill-activation-prompt.ts
# PreToolUse
time cat <<'EOF' | npx tsx .claude/hooks/skill-verification-guard.ts
{"tool_name":"Edit","tool_input":{"file_path":"test.ts"}}
EOFTarget metrics:
Related Files: