9.8 KiB
Troubleshooting - Skill Activation Issues
Complete debugging guide for skill activation problems.
Table of Contents
Skill Not Triggering
UserPromptSubmit Not Suggesting
Symptoms: Ask a question, but no skill suggestion appears in output.
Common Causes:
1. Keywords Don't Match
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
2. Intent Patterns Too Specific
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
]
3. Typo in Skill Name
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
4. JSON Syntax Error
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
Debug Command
Test the hook manually:
echo '{"session_id":"debug","prompt":"your test prompt here"}' | \
npx tsx .claude/hooks/skill-activation-prompt.ts
Expected: Your skill should appear in the output.
PreToolUse Not Blocking
Symptoms: Edit a file that should trigger a guardrail, but no block occurs.
Common Causes:
1. File Path Doesn't Match Patterns
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
2. Excluded by pathExclusions
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
3. Content Pattern Not Found
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.ts
Fix: Adjust content patterns or add missing imports
4. Session Already Used Skill
Check session state:
ls .claude/hooks/state/
cat .claude/hooks/state/skills-used-{session-id}.json
Example:
{
"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}.json
5. File Marker Present
Check file for skip marker:
grep "@skip-validation" path/to/file.ts
If found, the file is permanently skipped.
Fix: Remove the marker if verification is needed again
6. Environment Variable Override
Check:
echo $SKIP_DB_VERIFICATION
echo $SKIP_SKILL_GUARDRAILS
If set, the skill is disabled.
Fix: Unset the environment variable:
unset SKIP_DB_VERIFICATION
Debug Command
Test 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
False Positives
Symptoms: Skill triggers when it shouldn't.
Common Causes & Solutions:
1. Keywords Too Generic
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"
]
2. Intent Patterns Too Broad
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" appears
3. File Paths Too Generic
Problem:
"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"
]
4. Content Patterns Catching Unrelated Code
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
]
5. Adjust Enforcement Level
Last resort: If false positives are frequent:
{
"enforcement": "block" // Change to "suggest"
}
This makes it advisory instead of blocking.
Hook Not Executing
Symptoms: Hook doesn't run at all - no suggestion, no block.
Common Causes:
1. Hook Not Registered
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"
}
]
}
]
}
}
2. Bash Wrapper Not Executable
Check:
ls -l .claude/hooks/*.sh
Expected: -rwxr-xr-x (executable)
Fix:
chmod +x .claude/hooks/*.sh
3. Incorrect Shebang
Check:
head -1 .claude/hooks/skill-activation-prompt.sh
Expected: #!/bin/bash
Fix: Add correct shebang to first line
4. npx/tsx Not Available
Check:
npx tsx --version
Expected: Version number
Fix: Install dependencies:
cd .claude/hooks
npm install
5. TypeScript Compilation Error
Check:
cd .claude/hooks
npx tsc --noEmit skill-activation-prompt.ts
Expected: No output (no errors)
Fix: Correct TypeScript syntax errors
Performance Issues
Symptoms: Hooks are slow, noticeable delay before prompt/edit.
Common Causes:
1. Too Many Patterns
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)
2. Complex Regex
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 alternatives
3. Too Many Files Checked
Problem:
"pathPatterns": [
"**/*.ts" // Checks ALL TypeScript files
]
Solution: Be more specific
"pathPatterns": [
"form/src/services/**/*.ts", // Only specific directory
"form/src/controllers/**/*.ts"
]
4. Large Files
Content pattern matching reads entire file - slow for large files.
Solution:
- Only use content patterns when necessary
- Consider file size limits (future enhancement)
Measure Performance
# 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"}}
EOF
Target metrics:
- UserPromptSubmit: < 100ms
- PreToolUse: < 200ms
Related Files:
- SKILL.md - Main skill guide
- HOOK_MECHANISMS.md - How hooks work
- SKILL_RULES_REFERENCE.md - Configuration reference