Complete debugging guide for skill activation problems.
Symptoms: Ask a question, but no skill suggestion appears in output.
Common Causes:
Check:
- Look at
promptTriggers.keywordsin skill-rules.json - Are the keywords actually in your prompt?
- Remember: case-insensitive substring matching
Example:
"keywords": ["layout", "grid"]- "how does the layout work?" → ✅ Matches "layout"
- "how does the grid system work?" → ✅ Matches "grid"
- "how do layouts work?" → ✅ Matches "layout"
- "how does it work?" → ❌ No match
Fix: Add more keyword variations to skill-rules.json
Check:
- Look at
promptTriggers.intentPatterns - Test regex at https://regex101.com/
- May need broader patterns
Example:
"intentPatterns": [
"(create|add).*?(database.*?table)" // Too specific
]- "create a database table" → ✅ Matches
- "add new table" → ❌ Doesn't match (missing "database")
Fix: Broaden the pattern:
"intentPatterns": [
"(create|add).*?(table|database)" // Better
]Check:
- Skill name in SKILL.md frontmatter
- Skill name in skill-rules.json
- Must match exactly
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:
- Trailing commas
- Missing quotes
- Single quotes instead of double
- Unescaped characters in strings
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:
- File path being edited
fileTriggers.pathPatternsin skill-rules.json- Glob pattern syntax
Example:
"pathPatterns": [
"frontend/src/**/*.tsx"
]- Editing:
frontend/src/components/Dashboard.tsx→ ✅ Matches - Editing:
frontend/tests/Dashboard.test.tsx→ ✅ Matches (add exclusion!) - Editing:
backend/src/app.ts→ ❌ Doesn't match
Fix: Adjust glob patterns or add the missing path
Check:
- Are you editing a test file?
- Look at
fileTriggers.pathExclusions
Example:
"pathExclusions": [
"**/*.test.ts",
"**/*.spec.ts"
]- Editing:
services/user.test.ts→ ❌ Excluded - Editing:
services/user.ts→ ✅ Not excluded
Fix: If test exclusion too broad, narrow it or remove
Check:
- Does the file actually contain the pattern?
- Look at
fileTriggers.contentPatterns - Is the regex correct?
Example:
"contentPatterns": [
"import.*[Pp]risma"
]- File has:
import { PrismaService } from './prisma'→ ✅ Matches - File has:
import { Database } from './db'→ ❌ Doesn't match
Debug:
# 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:
- Exit code 2 + stderr message if should block
- Exit code 0 + no output if should allow
Symptoms: Skill triggers when it shouldn't.
Common Causes & Solutions:
Problem:
"keywords": ["user", "system", "create"] // Too broad- Triggers on: "user manual", "file system", "create directory"
Solution: Make keywords more specific
"keywords": [
"user authentication",
"user tracking",
"create feature"
]Problem:
"intentPatterns": [
"(create)" // Matches everything with "create"
]- Triggers on: "create file", "create folder", "create account"
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/
]- Triggers on: test files, config files, everything
Solution: Use narrower patterns
"pathPatterns": [
"form/src/services/**/*.ts", // Only service files
"form/src/controllers/**/*.ts"
]Problem:
"contentPatterns": [
"Prisma" // Matches in comments, strings, etc.
]- Triggers on:
// Don't use Prisma here - Triggers on:
const 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:
- Count patterns in skill-rules.json
- Each pattern = regex compilation + matching
Solution: Reduce patterns
- Combine similar patterns
- Remove redundant patterns
- Use more specific patterns (faster matching)
Problem:
(create|add|modify|update|implement|build).*?(feature|endpoint|route|service|controller|component|UI|page)- Long alternations = slow
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:
- Only use content patterns when necessary
- Consider file size limits (future enhancement)
# 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:
- UserPromptSubmit: < 100ms
- PreToolUse: < 200ms
Related Files:
- SKILL.md - Main skill guide
- HOOK_MECHANISMS.md - How hooks work
- SKILL_RULES_REFERENCE.md - Configuration reference