skill-developer skill
$ npx snappy-skills install skill-developer
$ npx snappy-skills install --all
$ npx snappy-skills update
Ideas and concepts for future improvements to the skill system.
Current State: Requires Claude Code restart to pick up changes to skill-rules.json
Future Enhancement: Hot-reload configuration without restart
Implementation Ideas:
Benefits:
Current State: Skills are independent
Future Enhancement: Specify skill dependencies and load order
Configuration Idea:
json{
"my-advanced-skill": {
"dependsOn": ["prerequisite-skill", "base-skill"],
"type": "domain",
...
}
}
Use Cases:
Benefits:
Current State: Enforcement level is static
Future Enhancement: Enforce based on context or environment
Configuration Idea:
json{
"enforcement": {
"default": "suggest",
"when": {
"production": "block",
"development": "suggest",
"ci": "block"
}
}
}
Use Cases:
Benefits:
Current State: No usage tracking
Future Enhancement: Track skill usage patterns and effectiveness
Metrics to Collect:
Dashbord Ideas:
Benefits:
Current State: No version tracking
Future Enhancement: Version skills and track compatibility
Configuration Idea:
json{
"my-skill": {
"version": "2.1.0",
"minClaudeVersion": "1.5.0",
"changelog": "Added support for new workflow patterns",
...
}
}
Benefits:
Current State: English only
Future Enhancement: Support multiple languages for skill content
Implementation Ideas:
Use Cases:
Current State: Manual testing with npx tsx commands
Future Enhancement: Automated skill testing
Features:
Example Test:
typescriptdescribe('database-verification', () => {
it('triggers on Prisma imports', () => {
const result = testSkill({
prompt: "add user tracking",
file: "services/user.ts",
content: "import { PrismaService } from './prisma'"
});
expect(result.triggered).toBe(true);
expect(result.skill).toBe('database-verification');
});
});
Benefits:
# Advanced Topics & Future Enhancements
Ideas and concepts for future improvements to the skill system.
---
## Dynamic Rule Updates
**Current State:** Requires Claude Code restart to pick up changes to skill-rules.json
**Future Enhancement:** Hot-reload configuration without restart
**Implementation Ideas:**
- Watch skill-rules.json for changes
- Reload on file modification
- Invalidate cached compiled regexes
- Notify user of reload
**Benefits:**
- Faster iteration during skill development
- No need to restart Claude Code
- Better developer experience
---
## Skill Dependencies
**Current State:** Skills are independent
**Future Enhancement:** Specify skill dependencies and load order
**Configuration Idea:**
```json
{
"my-advanced-skill": {
"dependsOn": ["prerequisite-skill", "base-skill"],
"type": "domain",
...
}
}
```
**Use Cases:**
- Advanced skill builds on base skill knowledge
- Ensure foundational skills loaded first
- Chain skills for complex workflows
**Benefits:**
- Better skill composition
- Clearer skill relationships
- Progressive disclosure
---
## Conditional Enforcement
**Current State:** Enforcement level is static
**Future Enhancement:** Enforce based on context or environment
**Configuration Idea:**
```json
{
"enforcement": {
"default": "suggest",
"when": {
"production": "block",
"development": "suggest",
"ci": "block"
}
}
}
```
**Use Cases:**
- Stricter enforcement in production
- Relaxed rules during development
- CI/CD pipeline requirements
**Benefits:**
- Environment-appropriate enforcement
- Flexible rule application
- Context-aware guardrails
---
## Skill Analytics
**Current State:** No usage tracking
**Future Enhancement:** Track skill usage patterns and effectiveness
**Metrics to Collect:**
- Skill trigger frequency
- False positive rate
- False negative rate
- Time to skill usage after suggestion
- User override rate (skip markers, env vars)
- Performance metrics (execution time)
**Dashbord Ideas:**
- Most/least used skills
- Skills with highest false positive rate
- Performance bottlenecks
- Skill effectiveness scores
**Benefits:**
- Data-driven skill improvement
- Identify problems early
- Optimize patterns based on real usage
---
## Skill Versioning
**Current State:** No version tracking
**Future Enhancement:** Version skills and track compatibility
**Configuration Idea:**
```json
{
"my-skill": {
"version": "2.1.0",
"minClaudeVersion": "1.5.0",
"changelog": "Added support for new workflow patterns",
...
}
}
```
**Benefits:**
- Track skill evolution
- Ensure compatibility
- Document changes
- Support migration paths
---
## Multi-Language Support
**Current State:** English only
**Future Enhancement:** Support multiple languages for skill content
**Implementation Ideas:**
- Language-specific SKILL.md variants
- Automatic language detection
- Fallback to English
**Use Cases:**
- International teams
- Localized documentation
- Multi-language projects
---
## Skill Testing Framework
**Current State:** Manual testing with npx tsx commands
**Future Enhancement:** Automated skill testing
**Features:**
- Test cases for trigger patterns
- Assertion framework
- CI/CD integration
- Coverage reports
**Example Test:**
```typescript
describe('database-verification', () => {
it('triggers on Prisma imports', () => {
const result = testSkill({
prompt: "add user tracking",
file: "services/user.ts",
content: "import { PrismaService } from './prisma'"
});
expect(result.triggered).toBe(true);
expect(result.skill).toBe('database-verification');
});
});
```
**Benefits:**
- Prevent regressions
- Validate patterns before deployment
- Confidence in changes
---
## Related Files
- [SKILL.md](SKILL.md) - Main skill guide
- [TROUBLESHOOTING.md](TROUBLESHOOTING.md) - Current debugging guide
- [HOOK_MECHANISMS.md](HOOK_MECHANISMS.md) - How hooks work today
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
json{
"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
json{
"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 checks
Claude 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
json{
"skills_used": [
"database-verification",
"error-tracking"
],
"files_verified": []
}
The hook cannot detect when the skill is actually invoked - it just blocks once per session per skill. This means:
Reduce patterns:
File path patterns:
form/src/services/** better than form/**Content patterns:
Related Files:
# Hook Mechanisms - Deep Dive
Technical deep dive into how the UserPromptSubmit and PreToolUse hooks work.
## Table of Contents
- [UserPromptSubmit Hook Flow](#userpromptsubmit-hook-flow)
- [PreToolUse Hook Flow](#pretooluse-hook-flow)
- [Exit Code Behavior (CRITICAL)](#exit-code-behavior-critical)
- [Session State Management](#session-state-management)
- [Performance Considerations](#performance-considerations)
---
## UserPromptSubmit Hook Flow
### Execution Sequence
```
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
```
### Key Points
- **Exit code**: Always 0 (allow)
- **stdout**: → Claude's context (injected as system message)
- **Timing**: Runs BEFORE Claude processes prompt
- **Behavior**: Non-blocking, advisory only
- **Purpose**: Make Claude aware of relevant skills
### Input Format
```json
{
"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?"
}
```
### Output Format (to stdout)
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🎯 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.
---
## PreToolUse Hook Flow
### Execution Sequence
```
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
```
### Key Points
- **Exit code 2**: BLOCK (stderr → Claude)
- **Exit code 0**: ALLOW
- **Timing**: Runs BEFORE tool execution
- **Session tracking**: Prevents repeated blocks in same session
- **Fail open**: On errors, allows operation (don't break workflow)
- **Purpose**: Enforce critical guardrails
### Input Format
```json
{
"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": "..."
}
}
```
### Output Format (to stderr when blocked)
```
⚠️ 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 checks
```
Claude receives this message and understands it needs to use the skill before retrying the edit.
---
## Exit Code Behavior (CRITICAL)
### Exit Code Reference Table
| 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 |
### Why Exit Code 2 Matters
This is THE critical mechanism for enforcement:
1. **Only way** to send message to Claude from PreToolUse
2. stderr content is "fed back to Claude automatically"
3. Claude sees the block message and understands what to do
4. Tool execution is prevented
5. Critical for enforcement of guardrails
### Example Conversation Flow
```
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)]
```
---
## Session State Management
### Purpose
Prevent repeated nagging in the same session - once Claude uses a skill, don't block again.
### State File Location
`.claude/hooks/state/skills-used-{session_id}.json`
### State File Structure
```json
{
"skills_used": [
"database-verification",
"error-tracking"
],
"files_verified": []
}
```
### How It Works
1. **First edit** of file with Prisma:
- Hook blocks with exit code 2
- Updates session state: adds "database-verification" to skills_used
- Claude sees message, uses skill
2. **Second edit** (same session):
- Hook checks session state
- Finds "database-verification" in skills_used
- Exits with code 0 (allow)
- No message to Claude
3. **Different session**:
- New session ID = new state file
- Hook blocks again
### Limitation
The hook cannot detect when the skill is *actually* invoked - it just blocks once per session per skill. This means:
- If Claude doesn't use the skill but makes a different edit, it won't block again
- Trust that Claude follows the instruction
- Future enhancement: detect actual Skill tool usage
---
## Performance Considerations
### Target Metrics
- **UserPromptSubmit**: < 100ms
- **PreToolUse**: < 200ms
### Performance Bottlenecks
1. **Loading skill-rules.json** (every execution)
- Future: Cache in memory
- Future: Watch for changes, reload only when needed
2. **Reading file content** (PreToolUse)
- Only when contentPatterns configured
- Only if file exists
- Can be slow for large files
3. **Glob matching** (PreToolUse)
- Regex compilation for each pattern
- Future: Compile once, cache
4. **Regex matching** (Both hooks)
- Intent patterns (UserPromptSubmit)
- Content patterns (PreToolUse)
- Future: Lazy compile, cache compiled regexes
### Optimization Strategies
**Reduce patterns:**
- Use more specific patterns (fewer to check)
- Combine similar patterns where possible
**File path patterns:**
- More specific = fewer files to check
- Example: `form/src/services/**` better than `form/**`
**Content patterns:**
- Only add when truly necessary
- Simpler regex = faster matching
---
**Related Files:**
- [SKILL.md](SKILL.md) - Main skill guide
- [TROUBLESHOOTING.md](TROUBLESHOOTING.md) - Debug hook issues
- [SKILL_RULES_REFERENCE.md](SKILL_RULES_REFERENCE.md) - Configuration reference
The docs in this skill describe a hook-driven skill auto-activation system. The
working parts ship in resources/. This file wires them up.
| File | Goes to | Purpose |
|---|---|---|
skill-activation-prompt.sh |
.claude/hooks/ |
UserPromptSubmit shim; pipes stdin to the TS hook |
skill-activation-prompt.ts |
.claude/hooks/ |
Matches the prompt against the registry, prints the activation block |
skill-rules.example.json |
.claude/skills/skill-rules.json |
The registry — rename and fill in with your skills |
hooks-package.json |
.claude/hooks/package.json |
Pins tsx + typescript so npx tsx resolves locally |
hooks-tsconfig.json |
.claude/hooks/tsconfig.json |
Typecheck config for the hook |
bash# from your project root
mkdir -p .claude/hooks .claude/skills
cp .claude/skills/skill-developer/resources/skill-activation-prompt.sh .claude/hooks/
cp .claude/skills/skill-developer/resources/skill-activation-prompt.ts .claude/hooks/
cp .claude/skills/skill-developer/resources/hooks-package.json .claude/hooks/package.json
cp .claude/skills/skill-developer/resources/hooks-tsconfig.json .claude/hooks/tsconfig.json
cp .claude/skills/skill-developer/resources/skill-rules.example.json .claude/skills/skill-rules.json
chmod +x .claude/hooks/skill-activation-prompt.sh
cd .claude/hooks && npm install && cd -
Register the hook in .claude/settings.json:
json{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/skill-activation-prompt.sh"
}
]
}
]
}
}
bashecho '{"session_id":"t","transcript_path":"","cwd":"'"$PWD"'","permission_mode":"default","prompt":"create a new skill"}' \
| CLAUDE_PROJECT_DIR="$PWD" .claude/hooks/skill-activation-prompt.sh
You should see the SKILL ACTIVATION CHECK block listing skill-developer.
Silence means no trigger matched — check promptTriggers in your
skill-rules.json against the prompt you passed.
The hook reads $CLAUDE_PROJECT_DIR/.claude/skills/skill-rules.json. It is
project-scoped: each project carries its own registry. There is no
user-level (~/.claude) fallback in this implementation — add one if you want
global rules.
HOOK_MECHANISMS.md documents a second hook, skill-verification-guard.ts
(PreToolUse on Edit|Write, exit code 2 to block edits when a required skill
was not loaded), plus its session state at
.claude/hooks/state/skills-used-{session_id}.json. That hook was never
implemented in the source repository — the design is documented, the file does
not exist. Build it from HOOK_MECHANISMS.md if you want enforcement; the
UserPromptSubmit hook above is suggestion-only.
# Install the Activation System
The docs in this skill describe a hook-driven skill auto-activation system. The
working parts ship in `resources/`. This file wires them up.
## What's in resources/
| File | Goes to | Purpose |
|---|---|---|
| `skill-activation-prompt.sh` | `.claude/hooks/` | UserPromptSubmit shim; pipes stdin to the TS hook |
| `skill-activation-prompt.ts` | `.claude/hooks/` | Matches the prompt against the registry, prints the activation block |
| `skill-rules.example.json` | `.claude/skills/skill-rules.json` | The registry — rename and fill in with your skills |
| `hooks-package.json` | `.claude/hooks/package.json` | Pins `tsx` + `typescript` so `npx tsx` resolves locally |
| `hooks-tsconfig.json` | `.claude/hooks/tsconfig.json` | Typecheck config for the hook |
## Steps
```bash
# from your project root
mkdir -p .claude/hooks .claude/skills
cp .claude/skills/skill-developer/resources/skill-activation-prompt.sh .claude/hooks/
cp .claude/skills/skill-developer/resources/skill-activation-prompt.ts .claude/hooks/
cp .claude/skills/skill-developer/resources/hooks-package.json .claude/hooks/package.json
cp .claude/skills/skill-developer/resources/hooks-tsconfig.json .claude/hooks/tsconfig.json
cp .claude/skills/skill-developer/resources/skill-rules.example.json .claude/skills/skill-rules.json
chmod +x .claude/hooks/skill-activation-prompt.sh
cd .claude/hooks && npm install && cd -
```
Register the hook in `.claude/settings.json`:
```json
{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/skill-activation-prompt.sh"
}
]
}
]
}
}
```
## Verify
```bash
echo '{"session_id":"t","transcript_path":"","cwd":"'"$PWD"'","permission_mode":"default","prompt":"create a new skill"}' \
| CLAUDE_PROJECT_DIR="$PWD" .claude/hooks/skill-activation-prompt.sh
```
You should see the `SKILL ACTIVATION CHECK` block listing `skill-developer`.
Silence means no trigger matched — check `promptTriggers` in your
`skill-rules.json` against the prompt you passed.
## Scope
The hook reads `$CLAUDE_PROJECT_DIR/.claude/skills/skill-rules.json`. It is
**project-scoped**: each project carries its own registry. There is no
user-level (`~/.claude`) fallback in this implementation — add one if you want
global rules.
## Not included
`HOOK_MECHANISMS.md` documents a second hook, `skill-verification-guard.ts`
(PreToolUse on `Edit|Write`, exit code 2 to block edits when a required skill
was not loaded), plus its session state at
`.claude/hooks/state/skills-used-{session_id}.json`. That hook was never
implemented in the source repository — the design is documented, the file does
not exist. Build it from `HOOK_MECHANISMS.md` if you want enforcement; the
UserPromptSubmit hook above is suggestion-only.
Ready-to-use regex and glob patterns for skill triggers. Copy and customize for your skills.
regex(add|create|implement|build).*?(feature|endpoint|route|service|controller)
regex(create|add|make|build).*?(component|UI|page|modal|dialog|form)
regex(add|create|modify|update).*?(user|table|column|field|schema|migration)
(database|prisma).*?(change|update|query)
regex(fix|handle|catch|debug).*?(error|exception|bug)
(add|implement).*?(try|catch|error.*?handling)
regex(how does|how do|explain|what is|describe|tell me about).*?
regex(create|add|modify|update).*?(workflow|step|branch|condition)
(debug|troubleshoot|fix).*?workflow
regex(write|create|add).*?(test|spec|unit.*?test)
globfrontend/src/**/*.tsx # All React components
frontend/src/**/*.ts # All TypeScript files
frontend/src/components/** # Only components directory
globform/src/**/*.ts # Form service
email/src/**/*.ts # Email service
users/src/**/*.ts # Users service
projects/src/**/*.ts # Projects service
glob**/schema.prisma # Prisma schema (anywhere)
**/migrations/**/*.sql # Migration files
database/src/**/*.ts # Database scripts
globform/src/workflow/**/*.ts # Workflow engine
form/src/workflow-definitions/**/*.json # Workflow definitions
glob**/*.test.ts # TypeScript tests
**/*.test.tsx # React component tests
**/*.spec.ts # Spec files
regeximport.*[Pp]risma # Prisma imports
PrismaService # PrismaService usage
prisma\. # prisma.something
\.findMany\( # Prisma query methods
\.create\(
\.update\(
\.delete\(
regexexport class.*Controller # Controller classes
router\. # Express router
app\.(get|post|put|delete|patch) # Express app routes
regextry\s*\{ # Try blocks
catch\s*\( # Catch blocks
throw new # Throw statements
regexexport.*React\.FC # React functional components
export default function.* # Default function exports
useState|useEffect # React hooks
Usage Example:
json{
"my-skill": {
"promptTriggers": {
"intentPatterns": [
"(create|add|build).*?(component|UI|page)"
]
},
"fileTriggers": {
"pathPatterns": [
"frontend/src/**/*.tsx"
],
"contentPatterns": [
"export.*React\\.FC",
"useState|useEffect"
]
}
}
}
Related Files:
# Common Patterns Library
Ready-to-use regex and glob patterns for skill triggers. Copy and customize for your skills.
---
## Intent Patterns (Regex)
### Feature/Endpoint Creation
```regex
(add|create|implement|build).*?(feature|endpoint|route|service|controller)
```
### Component Creation
```regex
(create|add|make|build).*?(component|UI|page|modal|dialog|form)
```
### Database Work
```regex
(add|create|modify|update).*?(user|table|column|field|schema|migration)
(database|prisma).*?(change|update|query)
```
### Error Handling
```regex
(fix|handle|catch|debug).*?(error|exception|bug)
(add|implement).*?(try|catch|error.*?handling)
```
### Explanation Requests
```regex
(how does|how do|explain|what is|describe|tell me about).*?
```
### Workflow Operations
```regex
(create|add|modify|update).*?(workflow|step|branch|condition)
(debug|troubleshoot|fix).*?workflow
```
### Testing
```regex
(write|create|add).*?(test|spec|unit.*?test)
```
---
## File Path Patterns (Glob)
### Frontend
```glob
frontend/src/**/*.tsx # All React components
frontend/src/**/*.ts # All TypeScript files
frontend/src/components/** # Only components directory
```
### Backend Services
```glob
form/src/**/*.ts # Form service
email/src/**/*.ts # Email service
users/src/**/*.ts # Users service
projects/src/**/*.ts # Projects service
```
### Database
```glob
**/schema.prisma # Prisma schema (anywhere)
**/migrations/**/*.sql # Migration files
database/src/**/*.ts # Database scripts
```
### Workflows
```glob
form/src/workflow/**/*.ts # Workflow engine
form/src/workflow-definitions/**/*.json # Workflow definitions
```
### Test Exclusions
```glob
**/*.test.ts # TypeScript tests
**/*.test.tsx # React component tests
**/*.spec.ts # Spec files
```
---
## Content Patterns (Regex)
### Prisma/Database
```regex
import.*[Pp]risma # Prisma imports
PrismaService # PrismaService usage
prisma\. # prisma.something
\.findMany\( # Prisma query methods
\.create\(
\.update\(
\.delete\(
```
### Controllers/Routes
```regex
export class.*Controller # Controller classes
router\. # Express router
app\.(get|post|put|delete|patch) # Express app routes
```
### Error Handling
```regex
try\s*\{ # Try blocks
catch\s*\( # Catch blocks
throw new # Throw statements
```
### React/Components
```regex
export.*React\.FC # React functional components
export default function.* # Default function exports
useState|useEffect # React hooks
```
---
**Usage Example:**
```json
{
"my-skill": {
"promptTriggers": {
"intentPatterns": [
"(create|add|build).*?(component|UI|page)"
]
},
"fileTriggers": {
"pathPatterns": [
"frontend/src/**/*.tsx"
],
"contentPatterns": [
"export.*React\\.FC",
"useState|useEffect"
]
}
}
}
```
---
**Related Files:**
- [SKILL.md](SKILL.md) - Main skill guide
- [TRIGGER_TYPES.md](TRIGGER_TYPES.md) - Detailed trigger documentation
- [SKILL_RULES_REFERENCE.md](SKILL_RULES_REFERENCE.md) - Complete schema
Comprehensive guide for creating and managing skills in Claude Code with auto-activation system, following Anthropic's official best practices including the 500-line rule and progressive disclosure pattern.
Automatically activates when you mention:
1. UserPromptSubmit Hook (Proactive Suggestions)
.claude/hooks/skill-activation-prompt.ts2. Stop Hook - Error Handling Reminder (Gentle Reminders)
.claude/hooks/error-handling-reminder.tsPhilosophy Change (2025-10-27): We moved away from blocking PreToolUse for Sentry/error handling. Instead, use gentle post-response reminders that don't block workflow but maintain code quality awareness.
Location: .claude/skills/skill-rules.json
Defines:
Purpose: Enforce critical best practices that prevent errors
Characteristics:
"guardrail""block""critical" or "high"Examples:
database-verification - Verify table/column names before Prisma queriesfrontend-dev-guidelines - Enforce React/TypeScript patternsWhen to Use:
Purpose: Provide comprehensive guidance for specific areas
Characteristics:
"domain""suggest""high" or "medium"Examples:
backend-dev-guidelines - Node.js/Express/TypeScript patternsfrontend-dev-guidelines - React/TypeScript best practiceserror-tracking - Sentry integration guidanceWhen to Use:
Location: .claude/skills/{skill-name}/SKILL.md
Template:
markdown---
name: my-new-skill
description: Brief description including keywords that trigger this skill. Mention topics, file types, and use cases. Be explicit about trigger terms.
---
# My New Skill
## Purpose
What this skill helps with
## When to Use
Specific scenarios and conditions
## Key Information
The actual guidance, documentation, patterns, examples
Best Practices:
See SKILL_RULES_REFERENCE.md for complete schema.
Basic Template:
json{
"my-new-skill": {
"type": "domain",
"enforcement": "suggest",
"priority": "medium",
"promptTriggers": {
"keywords": ["keyword1", "keyword2"],
"intentPatterns": ["(create|add).*?something"]
}
}
}
Test UserPromptSubmit:
bashecho '{"session_id":"test","prompt":"your test prompt"}' | \
npx tsx .claude/hooks/skill-activation-prompt.ts
Test PreToolUse:
bashcat <<'EOF' | npx tsx .claude/hooks/skill-verification-guard.ts
{"session_id":"test","tool_name":"Edit","tool_input":{"file_path":"test.ts"}}
EOF
Based on testing:
✅ Keep SKILL.md under 500 lines
✅ Use progressive disclosure with reference files
✅ Add table of contents to reference files > 100 lines
✅ Write detailed description with trigger keywords
✅ Test with 3+ real scenarios before documenting
✅ Iterate based on actual usage
Example: Database column name verification
Example: Frontend development guidelines
Rarely used - most skills are either BLOCK or SUGGEST.
Purpose: Don't nag repeatedly in same session
How it works:
State File: .claude/hooks/state/skills-used-{session_id}.json
Purpose: Permanent skip for verified files
Marker: // @skip-validation
Usage:
typescript// @skip-validation
import { PrismaService } from './prisma';
// This file has been manually verified
NOTE: Use sparingly - defeats the purpose if overused
Purpose: Emergency disable, temporary override
Global disable:
bashexport SKIP_SKILL_GUARDRAILS=true # Disables ALL PreToolUse blocks
Skill-specific:
bashexport SKIP_DB_VERIFICATION=true
export SKIP_ERROR_REMINDER=true
When creating a new skill, verify:
.claude/skills/{name}/SKILL.mdskill-rules.jsonjq . skill-rules.jsonFor detailed information on specific topics, see:
Complete guide to all trigger types:
Complete skill-rules.json schema:
Deep dive into hook internals:
Comprehensive debugging guide:
Ready-to-use pattern collection:
Future enhancements and ideas:
.claude/skills/{name}/SKILL.md with frontmatter.claude/skills/skill-rules.jsonnpx tsx commandsSee TRIGGER_TYPES.md for complete details.
// @skip-validation (permanent skip)SKIP_SKILL_GUARDRAILS (emergency disable)✅ 500-line rule: Keep SKILL.md under 500 lines
✅ Progressive disclosure: Use reference files for details
✅ Table of contents: Add to reference files > 100 lines
✅ One level deep: Don't nest references deeply
✅ Rich descriptions: Include all trigger keywords (max 1024 chars)
✅ Test first: Build 3+ evaluations before extensive documentation
✅ Gerund naming: Prefer verb + -ing (e.g., "processing-pdfs")
Test hooks manually:
bash# UserPromptSubmit
echo '{"prompt":"test"}' | npx tsx .claude/hooks/skill-activation-prompt.ts
# PreToolUse
cat <<'EOF' | npx tsx .claude/hooks/skill-verification-guard.ts
{"tool_name":"Edit","tool_input":{"file_path":"test.ts"}}
EOF
See TROUBLESHOOTING.md for complete debugging guide.
Configuration:
.claude/skills/skill-rules.json - Master configuration.claude/hooks/state/ - Session tracking.claude/settings.json - Hook registrationHooks:
.claude/hooks/skill-activation-prompt.ts - UserPromptSubmit.claude/hooks/error-handling-reminder.ts - Stop event (gentle reminders)All Skills:
.claude/skills/*/SKILL.md - Skill content filesSkill Status: COMPLETE - Restructured following Anthropic best practices ✅
Line Count: < 500 (following 500-line rule) ✅
Progressive Disclosure: Reference files for detailed information ✅
Next: Create more skills, refine patterns based on usage
---
name: skill-developer
description: 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.
---
# Skill Developer Guide
## Purpose
Comprehensive guide for creating and managing skills in Claude Code with auto-activation system, following Anthropic's official best practices including the 500-line rule and progressive disclosure pattern.
## When to Use This Skill
Automatically activates when you mention:
- Creating or adding skills
- Modifying skill triggers or rules
- Understanding how skill activation works
- Debugging skill activation issues
- Working with skill-rules.json
- Hook system mechanics
- Claude Code best practices
- Progressive disclosure
- YAML frontmatter
- 500-line rule
---
## System Overview
### Two-Hook Architecture
**1. UserPromptSubmit Hook** (Proactive Suggestions)
- **File**: `.claude/hooks/skill-activation-prompt.ts`
- **Trigger**: BEFORE Claude sees user's prompt
- **Purpose**: Suggest relevant skills based on keywords + intent patterns
- **Method**: Injects formatted reminder as context (stdout → Claude's input)
- **Use Cases**: Topic-based skills, implicit work detection
**2. Stop Hook - Error Handling Reminder** (Gentle Reminders)
- **File**: `.claude/hooks/error-handling-reminder.ts`
- **Trigger**: AFTER Claude finishes responding
- **Purpose**: Gentle reminder to self-assess error handling in code written
- **Method**: Analyzes edited files for risky patterns, displays reminder if needed
- **Use Cases**: Error handling awareness without blocking friction
**Philosophy Change (2025-10-27):** We moved away from blocking PreToolUse for Sentry/error handling. Instead, use gentle post-response reminders that don't block workflow but maintain code quality awareness.
### Configuration File
**Location**: `.claude/skills/skill-rules.json`
Defines:
- All skills and their trigger conditions
- Enforcement levels (block, suggest, warn)
- File path patterns (glob)
- Content detection patterns (regex)
- Skip conditions (session tracking, file markers, env vars)
---
## Skill Types
### 1. Guardrail Skills
**Purpose:** Enforce critical best practices that prevent errors
**Characteristics:**
- Type: `"guardrail"`
- Enforcement: `"block"`
- Priority: `"critical"` or `"high"`
- Block file edits until skill used
- Prevent common mistakes (column names, critical errors)
- Session-aware (don't repeat nag in same session)
**Examples:**
- `database-verification` - Verify table/column names before Prisma queries
- `frontend-dev-guidelines` - Enforce React/TypeScript patterns
**When to Use:**
- Mistakes that cause runtime errors
- Data integrity concerns
- Critical compatibility issues
### 2. Domain Skills
**Purpose:** Provide comprehensive guidance for specific areas
**Characteristics:**
- Type: `"domain"`
- Enforcement: `"suggest"`
- Priority: `"high"` or `"medium"`
- Advisory, not mandatory
- Topic or domain-specific
- Comprehensive documentation
**Examples:**
- `backend-dev-guidelines` - Node.js/Express/TypeScript patterns
- `frontend-dev-guidelines` - React/TypeScript best practices
- `error-tracking` - Sentry integration guidance
**When to Use:**
- Complex systems requiring deep knowledge
- Best practices documentation
- Architectural patterns
- How-to guides
---
## Quick Start: Creating a New Skill
### Step 1: Create Skill File
**Location:** `.claude/skills/{skill-name}/SKILL.md`
**Template:**
```markdown
---
name: my-new-skill
description: Brief description including keywords that trigger this skill. Mention topics, file types, and use cases. Be explicit about trigger terms.
---
# My New Skill
## Purpose
What this skill helps with
## When to Use
Specific scenarios and conditions
## Key Information
The actual guidance, documentation, patterns, examples
```
**Best Practices:**
- ✅ **Name**: Lowercase, hyphens, gerund form (verb + -ing) preferred
- ✅ **Description**: Include ALL trigger keywords/phrases (max 1024 chars)
- ✅ **Content**: Under 500 lines - use reference files for details
- ✅ **Examples**: Real code examples
- ✅ **Structure**: Clear headings, lists, code blocks
### Step 2: Add to skill-rules.json
See [SKILL_RULES_REFERENCE.md](SKILL_RULES_REFERENCE.md) for complete schema.
**Basic Template:**
```json
{
"my-new-skill": {
"type": "domain",
"enforcement": "suggest",
"priority": "medium",
"promptTriggers": {
"keywords": ["keyword1", "keyword2"],
"intentPatterns": ["(create|add).*?something"]
}
}
}
```
### Step 3: Test Triggers
**Test UserPromptSubmit:**
```bash
echo '{"session_id":"test","prompt":"your test prompt"}' | \
npx tsx .claude/hooks/skill-activation-prompt.ts
```
**Test PreToolUse:**
```bash
cat <<'EOF' | npx tsx .claude/hooks/skill-verification-guard.ts
{"session_id":"test","tool_name":"Edit","tool_input":{"file_path":"test.ts"}}
EOF
```
### Step 4: Refine Patterns
Based on testing:
- Add missing keywords
- Refine intent patterns to reduce false positives
- Adjust file path patterns
- Test content patterns against actual files
### Step 5: Follow Anthropic Best Practices
✅ Keep SKILL.md under 500 lines
✅ Use progressive disclosure with reference files
✅ Add table of contents to reference files > 100 lines
✅ Write detailed description with trigger keywords
✅ Test with 3+ real scenarios before documenting
✅ Iterate based on actual usage
---
## Enforcement Levels
### BLOCK (Critical Guardrails)
- Physically prevents Edit/Write tool execution
- Exit code 2 from hook, stderr → Claude
- Claude sees message and must use skill to proceed
- **Use For**: Critical mistakes, data integrity, security issues
**Example:** Database column name verification
### SUGGEST (Recommended)
- Reminder injected before Claude sees prompt
- Claude is aware of relevant skills
- Not enforced, just advisory
- **Use For**: Domain guidance, best practices, how-to guides
**Example:** Frontend development guidelines
### WARN (Optional)
- Low priority suggestions
- Advisory only, minimal enforcement
- **Use For**: Nice-to-have suggestions, informational reminders
**Rarely used** - most skills are either BLOCK or SUGGEST.
---
## Skip Conditions & User Control
### 1. Session Tracking
**Purpose:** Don't nag repeatedly in same session
**How it works:**
- First edit → Hook blocks, updates session state
- Second edit (same session) → Hook allows
- Different session → Blocks again
**State File:** `.claude/hooks/state/skills-used-{session_id}.json`
### 2. File Markers
**Purpose:** Permanent skip for verified files
**Marker:** `// @skip-validation`
**Usage:**
```typescript
// @skip-validation
import { PrismaService } from './prisma';
// This file has been manually verified
```
**NOTE:** Use sparingly - defeats the purpose if overused
### 3. Environment Variables
**Purpose:** Emergency disable, temporary override
**Global disable:**
```bash
export SKIP_SKILL_GUARDRAILS=true # Disables ALL PreToolUse blocks
```
**Skill-specific:**
```bash
export SKIP_DB_VERIFICATION=true
export SKIP_ERROR_REMINDER=true
```
---
## Testing Checklist
When creating a new skill, verify:
- [ ] Skill file created in `.claude/skills/{name}/SKILL.md`
- [ ] Proper frontmatter with name and description
- [ ] Entry added to `skill-rules.json`
- [ ] Keywords tested with real prompts
- [ ] Intent patterns tested with variations
- [ ] File path patterns tested with actual files
- [ ] Content patterns tested against file contents
- [ ] Block message is clear and actionable (if guardrail)
- [ ] Skip conditions configured appropriately
- [ ] Priority level matches importance
- [ ] No false positives in testing
- [ ] No false negatives in testing
- [ ] Performance is acceptable (<100ms or <200ms)
- [ ] JSON syntax validated: `jq . skill-rules.json`
- [ ] **SKILL.md under 500 lines** ⭐
- [ ] Reference files created if needed
- [ ] Table of contents added to files > 100 lines
---
## Reference Files
For detailed information on specific topics, see:
### [TRIGGER_TYPES.md](TRIGGER_TYPES.md)
Complete guide to all trigger types:
- Keyword triggers (explicit topic matching)
- Intent patterns (implicit action detection)
- File path triggers (glob patterns)
- Content patterns (regex in files)
- Best practices and examples for each
- Common pitfalls and testing strategies
### [SKILL_RULES_REFERENCE.md](SKILL_RULES_REFERENCE.md)
Complete skill-rules.json schema:
- Full TypeScript interface definitions
- Field-by-field explanations
- Complete guardrail skill example
- Complete domain skill example
- Validation guide and common errors
### [HOOK_MECHANISMS.md](HOOK_MECHANISMS.md)
Deep dive into hook internals:
- UserPromptSubmit flow (detailed)
- PreToolUse flow (detailed)
- Exit code behavior table (CRITICAL)
- Session state management
- Performance considerations
### [TROUBLESHOOTING.md](TROUBLESHOOTING.md)
Comprehensive debugging guide:
- Skill not triggering (UserPromptSubmit)
- PreToolUse not blocking
- False positives (too many triggers)
- Hook not executing at all
- Performance issues
### [PATTERNS_LIBRARY.md](PATTERNS_LIBRARY.md)
Ready-to-use pattern collection:
- Intent pattern library (regex)
- File path pattern library (glob)
- Content pattern library (regex)
- Organized by use case
- Copy-paste ready
### [ADVANCED.md](ADVANCED.md)
Future enhancements and ideas:
- Dynamic rule updates
- Skill dependencies
- Conditional enforcement
- Skill analytics
- Skill versioning
---
## Quick Reference Summary
### Create New Skill (5 Steps)
1. Create `.claude/skills/{name}/SKILL.md` with frontmatter
2. Add entry to `.claude/skills/skill-rules.json`
3. Test with `npx tsx` commands
4. Refine patterns based on testing
5. Keep SKILL.md under 500 lines
### Trigger Types
- **Keywords**: Explicit topic mentions
- **Intent**: Implicit action detection
- **File Paths**: Location-based activation
- **Content**: Technology-specific detection
See [TRIGGER_TYPES.md](TRIGGER_TYPES.md) for complete details.
### Enforcement
- **BLOCK**: Exit code 2, critical only
- **SUGGEST**: Inject context, most common
- **WARN**: Advisory, rarely used
### Skip Conditions
- **Session tracking**: Automatic (prevents repeated nags)
- **File markers**: `// @skip-validation` (permanent skip)
- **Env vars**: `SKIP_SKILL_GUARDRAILS` (emergency disable)
### Anthropic Best Practices
✅ **500-line rule**: Keep SKILL.md under 500 lines
✅ **Progressive disclosure**: Use reference files for details
✅ **Table of contents**: Add to reference files > 100 lines
✅ **One level deep**: Don't nest references deeply
✅ **Rich descriptions**: Include all trigger keywords (max 1024 chars)
✅ **Test first**: Build 3+ evaluations before extensive documentation
✅ **Gerund naming**: Prefer verb + -ing (e.g., "processing-pdfs")
### Troubleshoot
Test hooks manually:
```bash
# UserPromptSubmit
echo '{"prompt":"test"}' | npx tsx .claude/hooks/skill-activation-prompt.ts
# PreToolUse
cat <<'EOF' | npx tsx .claude/hooks/skill-verification-guard.ts
{"tool_name":"Edit","tool_input":{"file_path":"test.ts"}}
EOF
```
See [TROUBLESHOOTING.md](TROUBLESHOOTING.md) for complete debugging guide.
---
## Related Files
**Configuration:**
- `.claude/skills/skill-rules.json` - Master configuration
- `.claude/hooks/state/` - Session tracking
- `.claude/settings.json` - Hook registration
**Hooks:**
- `.claude/hooks/skill-activation-prompt.ts` - UserPromptSubmit
- `.claude/hooks/error-handling-reminder.ts` - Stop event (gentle reminders)
**All Skills:**
- `.claude/skills/*/SKILL.md` - Skill content files
---
**Skill Status**: COMPLETE - Restructured following Anthropic best practices ✅
**Line Count**: < 500 (following 500-line rule) ✅
**Progressive Disclosure**: Reference files for detailed information ✅
**Next**: Create more skills, refine patterns based on usage
Complete schema and configuration reference for .claude/skills/skill-rules.json.
Path: .claude/skills/skill-rules.json
This JSON file defines all skills and their trigger conditions for the auto-activation system.
typescriptinterface SkillRules {
version: string;
skills: Record<string, SkillRule>;
}
interface SkillRule {
type: 'guardrail' | 'domain';
enforcement: 'block' | 'suggest' | 'warn';
priority: 'critical' | 'high' | 'medium' | 'low';
promptTriggers?: {
keywords?: string[];
intentPatterns?: string[]; // Regex strings
};
fileTriggers?: {
pathPatterns: string[]; // Glob patterns
pathExclusions?: string[]; // Glob patterns
contentPatterns?: string[]; // Regex strings
createOnly?: boolean; // Only trigger on file creation
};
blockMessage?: string; // For guardrails, {file_path} placeholder
skipConditions?: {
sessionSkillUsed?: boolean; // Skip if used in session
fileMarkers?: string[]; // e.g., ["@skip-validation"]
envOverride?: string; // e.g., "SKIP_DB_VERIFICATION"
};
}
| Field | Type | Required | Description |
|---|---|---|---|
version |
string | Yes | Schema version (currently "1.0") |
skills |
object | Yes | Map of skill name → SkillRule |
| Field | Type | Required | Description |
|---|---|---|---|
type |
string | Yes | "guardrail" (enforced) or "domain" (advisory) |
enforcement |
string | Yes | "block" (PreToolUse), "suggest" (UserPromptSubmit), or "warn" |
priority |
string | Yes | "critical", "high", "medium", or "low" |
promptTriggers |
object | Optional | Triggers for UserPromptSubmit hook |
fileTriggers |
object | Optional | Triggers for PreToolUse hook |
blockMessage |
string | Optional* | Required if enforcement="block". Use {file_path} placeholder |
skipConditions |
object | Optional | Escape hatches and session tracking |
*Required for guardrails
| Field | Type | Required | Description |
|---|---|---|---|
keywords |
string[] | Optional | Exact substring matches (case-insensitive) |
intentPatterns |
string[] | Optional | Regex patterns for intent detection |
| Field | Type | Required | Description |
|---|---|---|---|
pathPatterns |
string[] | Yes* | Glob patterns for file paths |
pathExclusions |
string[] | Optional | Glob patterns to exclude (e.g., test files) |
contentPatterns |
string[] | Optional | Regex patterns to match file content |
createOnly |
boolean | Optional | Only trigger when creating new files |
*Required if fileTriggers is present
| Field | Type | Required | Description |
|---|---|---|---|
sessionSkillUsed |
boolean | Optional | Skip if skill already used this session |
fileMarkers |
string[] | Optional | Skip if file contains comment marker |
envOverride |
string | Optional | Environment variable name to disable skill |
Complete example of a blocking guardrail skill with all features:
json{
"database-verification": {
"type": "guardrail",
"enforcement": "block",
"priority": "critical",
"promptTriggers": {
"keywords": [
"prisma",
"database",
"table",
"column",
"schema",
"query",
"migration"
],
"intentPatterns": [
"(add|create|implement).*?(user|login|auth|tracking|feature)",
"(modify|update|change).*?(table|column|schema|field)",
"database.*?(change|update|modify|migration)"
]
},
"fileTriggers": {
"pathPatterns": [
"**/schema.prisma",
"**/migrations/**/*.sql",
"database/src/**/*.ts",
"form/src/**/*.ts",
"email/src/**/*.ts",
"users/src/**/*.ts",
"projects/src/**/*.ts",
"utilities/src/**/*.ts"
],
"pathExclusions": [
"**/*.test.ts",
"**/*.spec.ts"
],
"contentPatterns": [
"import.*[Pp]risma",
"PrismaService",
"prisma\\.",
"\\.findMany\\(",
"\\.findUnique\\(",
"\\.findFirst\\(",
"\\.create\\(",
"\\.createMany\\(",
"\\.update\\(",
"\\.updateMany\\(",
"\\.upsert\\(",
"\\.delete\\(",
"\\.deleteMany\\("
]
},
"blockMessage": "⚠️ BLOCKED - Database Operation Detected\n\n📋 REQUIRED ACTION:\n1. Use Skill tool: 'database-verification'\n2. Verify ALL table and column names against schema\n3. Check database structure with DESCRIBE commands\n4. Then retry this edit\n\nReason: Prevent column name errors in Prisma queries\nFile: {file_path}\n\n💡 TIP: Add '// @skip-validation' comment to skip future checks",
"skipConditions": {
"sessionSkillUsed": true,
"fileMarkers": [
"@skip-validation"
],
"envOverride": "SKIP_DB_VERIFICATION"
}
}
}
Complete example of a suggestion-based domain skill:
json{
"project-catalog-developer": {
"type": "domain",
"enforcement": "suggest",
"priority": "high",
"promptTriggers": {
"keywords": [
"layout",
"layout system",
"grid",
"grid layout",
"toolbar",
"column",
"cell editor",
"cell renderer",
"submission",
"submissions",
"blog dashboard",
"datagrid",
"data grid",
"CustomToolbar",
"GridLayoutDialog",
"useGridLayout",
"auto-save",
"column order",
"column width",
"filter",
"sort"
],
"intentPatterns": [
"(how does|how do|explain|what is|describe).*?(layout|grid|toolbar|column|submission|catalog)",
"(add|create|modify|change).*?(toolbar|column|cell|editor|renderer)",
"blog dashboard.*?"
]
},
"fileTriggers": {
"pathPatterns": [
"frontend/src/features/submissions/**/*.tsx",
"frontend/src/features/submissions/**/*.ts"
],
"pathExclusions": [
"**/*.test.tsx",
"**/*.test.ts"
]
}
}
}
bashcat .claude/skills/skill-rules.json | jq .
If valid, jq will pretty-print the JSON. If invalid, it will show the error.
Trailing comma:
json{
"keywords": ["one", "two",] // ❌ Trailing comma
}
Missing quotes:
json{
type: "guardrail" // ❌ Missing quotes on key
}
Single quotes (invalid JSON):
json{
'type': 'guardrail' // ❌ Must use double quotes
}
jq)blockMessage{file_path} placeholderRelated Files:
# skill-rules.json - Complete Reference
Complete schema and configuration reference for `.claude/skills/skill-rules.json`.
## Table of Contents
- [File Location](#file-location)
- [Complete TypeScript Schema](#complete-typescript-schema)
- [Field Guide](#field-guide)
- [Example: Guardrail Skill](#example-guardrail-skill)
- [Example: Domain Skill](#example-domain-skill)
- [Validation](#validation)
---
## File Location
**Path:** `.claude/skills/skill-rules.json`
This JSON file defines all skills and their trigger conditions for the auto-activation system.
---
## Complete TypeScript Schema
```typescript
interface SkillRules {
version: string;
skills: Record<string, SkillRule>;
}
interface SkillRule {
type: 'guardrail' | 'domain';
enforcement: 'block' | 'suggest' | 'warn';
priority: 'critical' | 'high' | 'medium' | 'low';
promptTriggers?: {
keywords?: string[];
intentPatterns?: string[]; // Regex strings
};
fileTriggers?: {
pathPatterns: string[]; // Glob patterns
pathExclusions?: string[]; // Glob patterns
contentPatterns?: string[]; // Regex strings
createOnly?: boolean; // Only trigger on file creation
};
blockMessage?: string; // For guardrails, {file_path} placeholder
skipConditions?: {
sessionSkillUsed?: boolean; // Skip if used in session
fileMarkers?: string[]; // e.g., ["@skip-validation"]
envOverride?: string; // e.g., "SKIP_DB_VERIFICATION"
};
}
```
---
## Field Guide
### Top Level
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `version` | string | Yes | Schema version (currently "1.0") |
| `skills` | object | Yes | Map of skill name → SkillRule |
### SkillRule Fields
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `type` | string | Yes | "guardrail" (enforced) or "domain" (advisory) |
| `enforcement` | string | Yes | "block" (PreToolUse), "suggest" (UserPromptSubmit), or "warn" |
| `priority` | string | Yes | "critical", "high", "medium", or "low" |
| `promptTriggers` | object | Optional | Triggers for UserPromptSubmit hook |
| `fileTriggers` | object | Optional | Triggers for PreToolUse hook |
| `blockMessage` | string | Optional* | Required if enforcement="block". Use `{file_path}` placeholder |
| `skipConditions` | object | Optional | Escape hatches and session tracking |
*Required for guardrails
### promptTriggers Fields
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `keywords` | string[] | Optional | Exact substring matches (case-insensitive) |
| `intentPatterns` | string[] | Optional | Regex patterns for intent detection |
### fileTriggers Fields
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `pathPatterns` | string[] | Yes* | Glob patterns for file paths |
| `pathExclusions` | string[] | Optional | Glob patterns to exclude (e.g., test files) |
| `contentPatterns` | string[] | Optional | Regex patterns to match file content |
| `createOnly` | boolean | Optional | Only trigger when creating new files |
*Required if fileTriggers is present
### skipConditions Fields
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `sessionSkillUsed` | boolean | Optional | Skip if skill already used this session |
| `fileMarkers` | string[] | Optional | Skip if file contains comment marker |
| `envOverride` | string | Optional | Environment variable name to disable skill |
---
## Example: Guardrail Skill
Complete example of a blocking guardrail skill with all features:
```json
{
"database-verification": {
"type": "guardrail",
"enforcement": "block",
"priority": "critical",
"promptTriggers": {
"keywords": [
"prisma",
"database",
"table",
"column",
"schema",
"query",
"migration"
],
"intentPatterns": [
"(add|create|implement).*?(user|login|auth|tracking|feature)",
"(modify|update|change).*?(table|column|schema|field)",
"database.*?(change|update|modify|migration)"
]
},
"fileTriggers": {
"pathPatterns": [
"**/schema.prisma",
"**/migrations/**/*.sql",
"database/src/**/*.ts",
"form/src/**/*.ts",
"email/src/**/*.ts",
"users/src/**/*.ts",
"projects/src/**/*.ts",
"utilities/src/**/*.ts"
],
"pathExclusions": [
"**/*.test.ts",
"**/*.spec.ts"
],
"contentPatterns": [
"import.*[Pp]risma",
"PrismaService",
"prisma\\.",
"\\.findMany\\(",
"\\.findUnique\\(",
"\\.findFirst\\(",
"\\.create\\(",
"\\.createMany\\(",
"\\.update\\(",
"\\.updateMany\\(",
"\\.upsert\\(",
"\\.delete\\(",
"\\.deleteMany\\("
]
},
"blockMessage": "⚠️ BLOCKED - Database Operation Detected\n\n📋 REQUIRED ACTION:\n1. Use Skill tool: 'database-verification'\n2. Verify ALL table and column names against schema\n3. Check database structure with DESCRIBE commands\n4. Then retry this edit\n\nReason: Prevent column name errors in Prisma queries\nFile: {file_path}\n\n💡 TIP: Add '// @skip-validation' comment to skip future checks",
"skipConditions": {
"sessionSkillUsed": true,
"fileMarkers": [
"@skip-validation"
],
"envOverride": "SKIP_DB_VERIFICATION"
}
}
}
```
### Key Points for Guardrails
1. **type**: Must be "guardrail"
2. **enforcement**: Must be "block"
3. **priority**: Usually "critical" or "high"
4. **blockMessage**: Required, clear actionable steps
5. **skipConditions**: Session tracking prevents repeated nagging
6. **fileTriggers**: Usually has both path and content patterns
7. **contentPatterns**: Catch actual usage of technology
---
## Example: Domain Skill
Complete example of a suggestion-based domain skill:
```json
{
"project-catalog-developer": {
"type": "domain",
"enforcement": "suggest",
"priority": "high",
"promptTriggers": {
"keywords": [
"layout",
"layout system",
"grid",
"grid layout",
"toolbar",
"column",
"cell editor",
"cell renderer",
"submission",
"submissions",
"blog dashboard",
"datagrid",
"data grid",
"CustomToolbar",
"GridLayoutDialog",
"useGridLayout",
"auto-save",
"column order",
"column width",
"filter",
"sort"
],
"intentPatterns": [
"(how does|how do|explain|what is|describe).*?(layout|grid|toolbar|column|submission|catalog)",
"(add|create|modify|change).*?(toolbar|column|cell|editor|renderer)",
"blog dashboard.*?"
]
},
"fileTriggers": {
"pathPatterns": [
"frontend/src/features/submissions/**/*.tsx",
"frontend/src/features/submissions/**/*.ts"
],
"pathExclusions": [
"**/*.test.tsx",
"**/*.test.ts"
]
}
}
}
```
### Key Points for Domain Skills
1. **type**: Must be "domain"
2. **enforcement**: Usually "suggest"
3. **priority**: "high" or "medium"
4. **blockMessage**: Not needed (doesn't block)
5. **skipConditions**: Optional (less critical)
6. **promptTriggers**: Usually has extensive keywords
7. **fileTriggers**: May have only path patterns (content less important)
---
## Validation
### Check JSON Syntax
```bash
cat .claude/skills/skill-rules.json | jq .
```
If valid, jq will pretty-print the JSON. If invalid, it will show the error.
### Common JSON Errors
**Trailing comma:**
```json
{
"keywords": ["one", "two",] // ❌ Trailing comma
}
```
**Missing quotes:**
```json
{
type: "guardrail" // ❌ Missing quotes on key
}
```
**Single quotes (invalid JSON):**
```json
{
'type': 'guardrail' // ❌ Must use double quotes
}
```
### Validation Checklist
- [ ] JSON syntax valid (use `jq`)
- [ ] All skill names match SKILL.md filenames
- [ ] Guardrails have `blockMessage`
- [ ] Block messages use `{file_path}` placeholder
- [ ] Intent patterns are valid regex (test on regex101.com)
- [ ] File path patterns use correct glob syntax
- [ ] Content patterns escape special characters
- [ ] Priority matches enforcement level
- [ ] No duplicate skill names
---
**Related Files:**
- [SKILL.md](SKILL.md) - Main skill guide
- [TRIGGER_TYPES.md](TRIGGER_TYPES.md) - Complete trigger documentation
- [TROUBLESHOOTING.md](TROUBLESHOOTING.md) - Debugging configuration issues
Complete reference for configuring skill triggers in Claude Code's skill auto-activation system.
Case-insensitive substring matching in user's prompt.
Topic-based activation where user explicitly mentions the subject.
json"promptTriggers": {
"keywords": ["layout", "grid", "toolbar", "submission"]
}
project-catalog-developerRegex pattern matching to detect user's intent even when they don't mention the topic explicitly.
Action-based activation where user describes what they want to do rather than the specific topic.
json"promptTriggers": {
"intentPatterns": [
"(create|add|implement).*?(feature|endpoint)",
"(how does|explain).*?(layout|workflow)"
]
}
Database Work:
(add).*?(feature)database-verification, error-trackingComponent Creation:
(create).*?(component) (if component in pattern)frontend-dev-guidelines(create|add|modify|build|implement)(feature|endpoint|component|workflow).*? instead of .*regex# Database Work
(add|create|implement).*?(user|login|auth|feature)
# Explanations
(how does|explain|what is|describe).*?
# Frontend Work
(create|add|make|build).*?(component|UI|page|modal|dialog)
# Error Handling
(fix|handle|catch|debug).*?(error|exception|bug)
# Workflow Operations
(create|add|modify).*?(workflow|step|branch|condition)
Glob pattern matching against the file path being edited.
Domain/area-specific activation based on file location in the project.
json"fileTriggers": {
"pathPatterns": [
"frontend/src/**/*.tsx",
"form/src/**/*.ts"
],
"pathExclusions": [
"**/*.test.ts",
"**/*.spec.ts"
]
}
** = Any number of directories (including zero)* = Any characters within a directory namefrontend/src/**/*.tsx = All .tsx files in frontend/src and subdirs**/schema.prisma = schema.prisma anywhere in projectform/src/**/*.ts = All .ts files in form/src subdirsfrontend/src/components/Dashboard.tsxfrontend/src/**/*.tsxfrontend-dev-guidelines**/*.test.tsform/src/services/** not form/**glob# Frontend
frontend/src/**/*.tsx # All React components
frontend/src/**/*.ts # All TypeScript files
frontend/src/components/** # Only components directory
# Backend Services
form/src/**/*.ts # Form service
email/src/**/*.ts # Email service
users/src/**/*.ts # Users service
# Database
**/schema.prisma # Prisma schema (anywhere)
**/migrations/**/*.sql # Migration files
database/src/**/*.ts # Database scripts
# Workflows
form/src/workflow/**/*.ts # Workflow engine
form/src/workflow-definitions/**/*.json # Workflow definitions
# Test Exclusions
**/*.test.ts # TypeScript tests
**/*.test.tsx # React component tests
**/*.spec.ts # Spec files
Regex pattern matching against the file's actual content (what's inside the file).
Technology-specific activation based on what the code imports or uses (Prisma, controllers, specific libraries).
json"fileTriggers": {
"contentPatterns": [
"import.*[Pp]risma",
"PrismaService",
"\\.findMany\\(",
"\\.create\\("
]
}
Prisma Detection:
import { PrismaService } from '@project/database'import.*[Pp]rismadatabase-verificationController Detection:
export class UserController {export class.*Controllererror-trackingimport.*[Pp]risma (case-insensitive with [Pp])\.findMany\( not .findMany(regex# Prisma/Database
import.*[Pp]risma # Prisma imports
PrismaService # PrismaService usage
prisma\. # prisma.something
\.findMany\( # Prisma query methods
\.create\(
\.update\(
\.delete\(
# Controllers/Routes
export class.*Controller # Controller classes
router\. # Express router
app\.(get|post|put|delete|patch) # Express app routes
# Error Handling
try\s*\{ # Try blocks
catch\s*\( # Catch blocks
throw new # Throw statements
# React/Components
export.*React\.FC # React functional components
export default function.* # Default function exports
useState|useEffect # React hooks
✅ Use specific, unambiguous keywords
✅ Test all patterns with real examples
✅ Include common variations
✅ Use non-greedy regex: .*?
✅ Escape special characters in content patterns
✅ Add exclusions for test files
✅ Make file path patterns narrow and specific
❌ Use overly generic keywords ("system", "work")
❌ Make intent patterns too broad (false positives)
❌ Make patterns too specific (false negatives)
❌ Forget to test with regex tester (https://regex101.com/)
❌ Use greedy regex: .* instead of .*?
❌ Match too broadly in file paths
Test keyword/intent triggers:
bashecho '{"session_id":"test","prompt":"your test prompt"}' | \
npx tsx .claude/hooks/skill-activation-prompt.ts
Test file path/content triggers:
bashcat <<'EOF' | npx tsx .claude/hooks/skill-verification-guard.ts
{
"session_id": "test",
"tool_name": "Edit",
"tool_input": {"file_path": "/path/to/test/file.ts"}
}
EOF
Related Files:
# Trigger Types - Complete Guide
Complete reference for configuring skill triggers in Claude Code's skill auto-activation system.
## Table of Contents
- [Keyword Triggers (Explicit)](#keyword-triggers-explicit)
- [Intent Pattern Triggers (Implicit)](#intent-pattern-triggers-implicit)
- [File Path Triggers](#file-path-triggers)
- [Content Pattern Triggers](#content-pattern-triggers)
- [Best Practices Summary](#best-practices-summary)
---
## Keyword Triggers (Explicit)
### How It Works
Case-insensitive substring matching in user's prompt.
### Use For
Topic-based activation where user explicitly mentions the subject.
### Configuration
```json
"promptTriggers": {
"keywords": ["layout", "grid", "toolbar", "submission"]
}
```
### Example
- User prompt: "how does the **layout** system work?"
- Matches: "layout" keyword
- Activates: `project-catalog-developer`
### Best Practices
- Use specific, unambiguous terms
- Include common variations ("layout", "layout system", "grid layout")
- Avoid overly generic words ("system", "work", "create")
- Test with real prompts
---
## Intent Pattern Triggers (Implicit)
### How It Works
Regex pattern matching to detect user's intent even when they don't mention the topic explicitly.
### Use For
Action-based activation where user describes what they want to do rather than the specific topic.
### Configuration
```json
"promptTriggers": {
"intentPatterns": [
"(create|add|implement).*?(feature|endpoint)",
"(how does|explain).*?(layout|workflow)"
]
}
```
### Examples
**Database Work:**
- User prompt: "add user tracking feature"
- Matches: `(add).*?(feature)`
- Activates: `database-verification`, `error-tracking`
**Component Creation:**
- User prompt: "create a dashboard widget"
- Matches: `(create).*?(component)` (if component in pattern)
- Activates: `frontend-dev-guidelines`
### Best Practices
- Capture common action verbs: `(create|add|modify|build|implement)`
- Include domain-specific nouns: `(feature|endpoint|component|workflow)`
- Use non-greedy matching: `.*?` instead of `.*`
- Test patterns thoroughly with regex tester (https://regex101.com/)
- Don't make patterns too broad (causes false positives)
- Don't make patterns too specific (causes false negatives)
### Common Pattern Examples
```regex
# Database Work
(add|create|implement).*?(user|login|auth|feature)
# Explanations
(how does|explain|what is|describe).*?
# Frontend Work
(create|add|make|build).*?(component|UI|page|modal|dialog)
# Error Handling
(fix|handle|catch|debug).*?(error|exception|bug)
# Workflow Operations
(create|add|modify).*?(workflow|step|branch|condition)
```
---
## File Path Triggers
### How It Works
Glob pattern matching against the file path being edited.
### Use For
Domain/area-specific activation based on file location in the project.
### Configuration
```json
"fileTriggers": {
"pathPatterns": [
"frontend/src/**/*.tsx",
"form/src/**/*.ts"
],
"pathExclusions": [
"**/*.test.ts",
"**/*.spec.ts"
]
}
```
### Glob Pattern Syntax
- `**` = Any number of directories (including zero)
- `*` = Any characters within a directory name
- Examples:
- `frontend/src/**/*.tsx` = All .tsx files in frontend/src and subdirs
- `**/schema.prisma` = schema.prisma anywhere in project
- `form/src/**/*.ts` = All .ts files in form/src subdirs
### Example
- File being edited: `frontend/src/components/Dashboard.tsx`
- Matches: `frontend/src/**/*.tsx`
- Activates: `frontend-dev-guidelines`
### Best Practices
- Be specific to avoid false positives
- Use exclusions for test files: `**/*.test.ts`
- Consider subdirectory structure
- Test patterns with actual file paths
- Use narrower patterns when possible: `form/src/services/**` not `form/**`
### Common Path Patterns
```glob
# Frontend
frontend/src/**/*.tsx # All React components
frontend/src/**/*.ts # All TypeScript files
frontend/src/components/** # Only components directory
# Backend Services
form/src/**/*.ts # Form service
email/src/**/*.ts # Email service
users/src/**/*.ts # Users service
# Database
**/schema.prisma # Prisma schema (anywhere)
**/migrations/**/*.sql # Migration files
database/src/**/*.ts # Database scripts
# Workflows
form/src/workflow/**/*.ts # Workflow engine
form/src/workflow-definitions/**/*.json # Workflow definitions
# Test Exclusions
**/*.test.ts # TypeScript tests
**/*.test.tsx # React component tests
**/*.spec.ts # Spec files
```
---
## Content Pattern Triggers
### How It Works
Regex pattern matching against the file's actual content (what's inside the file).
### Use For
Technology-specific activation based on what the code imports or uses (Prisma, controllers, specific libraries).
### Configuration
```json
"fileTriggers": {
"contentPatterns": [
"import.*[Pp]risma",
"PrismaService",
"\\.findMany\\(",
"\\.create\\("
]
}
```
### Examples
**Prisma Detection:**
- File contains: `import { PrismaService } from '@project/database'`
- Matches: `import.*[Pp]risma`
- Activates: `database-verification`
**Controller Detection:**
- File contains: `export class UserController {`
- Matches: `export class.*Controller`
- Activates: `error-tracking`
### Best Practices
- Match imports: `import.*[Pp]risma` (case-insensitive with [Pp])
- Escape special regex chars: `\\.findMany\\(` not `.findMany(`
- Patterns use case-insensitive flag
- Test against real file content
- Make patterns specific enough to avoid false matches
### Common Content Patterns
```regex
# Prisma/Database
import.*[Pp]risma # Prisma imports
PrismaService # PrismaService usage
prisma\. # prisma.something
\.findMany\( # Prisma query methods
\.create\(
\.update\(
\.delete\(
# Controllers/Routes
export class.*Controller # Controller classes
router\. # Express router
app\.(get|post|put|delete|patch) # Express app routes
# Error Handling
try\s*\{ # Try blocks
catch\s*\( # Catch blocks
throw new # Throw statements
# React/Components
export.*React\.FC # React functional components
export default function.* # Default function exports
useState|useEffect # React hooks
```
---
## Best Practices Summary
### DO:
✅ Use specific, unambiguous keywords
✅ Test all patterns with real examples
✅ Include common variations
✅ Use non-greedy regex: `.*?`
✅ Escape special characters in content patterns
✅ Add exclusions for test files
✅ Make file path patterns narrow and specific
### DON'T:
❌ Use overly generic keywords ("system", "work")
❌ Make intent patterns too broad (false positives)
❌ Make patterns too specific (false negatives)
❌ Forget to test with regex tester (https://regex101.com/)
❌ Use greedy regex: `.*` instead of `.*?`
❌ Match too broadly in file paths
### Testing Your Triggers
**Test keyword/intent triggers:**
```bash
echo '{"session_id":"test","prompt":"your test prompt"}' | \
npx tsx .claude/hooks/skill-activation-prompt.ts
```
**Test file path/content triggers:**
```bash
cat <<'EOF' | npx tsx .claude/hooks/skill-verification-guard.ts
{
"session_id": "test",
"tool_name": "Edit",
"tool_input": {"file_path": "/path/to/test/file.ts"}
}
EOF
```
---
**Related Files:**
- [SKILL.md](SKILL.md) - Main skill guide
- [SKILL_RULES_REFERENCE.md](SKILL_RULES_REFERENCE.md) - Complete skill-rules.json schema
- [PATTERNS_LIBRARY.md](PATTERNS_LIBRARY.md) - Ready-to-use pattern library
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:
json"keywords": ["layout", "grid"]
Fix: Add more keyword variations to skill-rules.json
Check:
promptTriggers.intentPatternsExample:
json"intentPatterns": [
"(create|add).*?(database.*?table)" // Too specific
]
Fix: Broaden the pattern:
json"intentPatterns": [
"(create|add).*?(table|database)" // Better
]
Check:
Example:
yaml# SKILL.md
name: project-catalog-developer
json// skill-rules.json
"project-catalogue-developer": { // ❌ Typo: catalogue vs catalog
...
}
Fix: Make names match exactly
Check:
bashcat .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:
bashecho '{"session_id":"debug","prompt":"your test prompt here"}' | \
npx tsx .claude/hooks/skill-activation-prompt.ts
Expected: 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:
json"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:
json"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:
json"contentPatterns": [
"import.*[Pp]risma"
]
import { PrismaService } from './prisma' → ✅ Matchesimport { Database } from './db' → ❌ Doesn't matchDebug:
bash# Check if pattern exists in file
grep -i "prisma" path/to/file.ts
Fix: Adjust content patterns or add missing imports
Check session state:
bashls .claude/hooks/state/
cat .claude/hooks/state/skills-used-{session-id}.json
Example:
json{
"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:
bashrm .claude/hooks/state/skills-used-{session-id}.json
Check file for skip marker:
bashgrep "@skip-validation" path/to/file.ts
If found, the file is permanently skipped.
Fix: Remove the marker if verification is needed again
Check:
bashecho $SKIP_DB_VERIFICATION
echo $SKIP_SKILL_GUARDRAILS
If set, the skill is disabled.
Fix: Unset the environment variable:
bashunset SKIP_DB_VERIFICATION
Test the hook manually:
bashcat <<'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:
json"keywords": ["user", "system", "create"] // Too broad
Solution: Make keywords more specific
json"keywords": [
"user authentication",
"user tracking",
"create feature"
]
Problem:
json"intentPatterns": [
"(create)" // Matches everything with "create"
]
Solution: Add context to patterns
json"intentPatterns": [
"(create|add).*?(database|table|feature)" // More specific
]
Advanced: Use negative lookaheads to exclude
regex(create)(?!.*test).*?(feature) // Don't match if "test" appears
Problem:
json"pathPatterns": [
"form/**" // Matches everything in form/
]
Solution: Use narrower patterns
json"pathPatterns": [
"form/src/services/**/*.ts", // Only service files
"form/src/controllers/**/*.ts"
]
Problem:
json"contentPatterns": [
"Prisma" // Matches in comments, strings, etc.
]
// Don't use Prisma hereconst note = "Prisma is cool"Solution: Make patterns more specific
json"contentPatterns": [
"import.*[Pp]risma", // Only imports
"PrismaService\\.", // Only actual usage
"prisma\\.(findMany|create)" // Specific methods
]
Last resort: If false positives are frequent:
json{
"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:
bashcat .claude/settings.json | jq '.hooks.UserPromptSubmit'
cat .claude/settings.json | jq '.hooks.PreToolUse'
Expected: Hook entries present
Fix: Add missing hook registration:
json{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/skill-activation-prompt.sh"
}
]
}
]
}
}
Check:
bashls -l .claude/hooks/*.sh
Expected: -rwxr-xr-x (executable)
Fix:
bashchmod +x .claude/hooks/*.sh
Check:
bashhead -1 .claude/hooks/skill-activation-prompt.sh
Expected: #!/bin/bash
Fix: Add correct shebang to first line
Check:
bashnpx tsx --version
Expected: Version number
Fix: Install dependencies:
bashcd .claude/hooks
npm install
Check:
bashcd .claude/hooks
npx tsc --noEmit skill-activation-prompt.ts
Expected: 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:
regex(create|add|modify|update|implement|build).*?(feature|endpoint|route|service|controller|component|UI|page)
Solution: Simplify
regex(create|add).*?(feature|endpoint) // Fewer alternatives
Problem:
json"pathPatterns": [
"**/*.ts" // Checks ALL TypeScript files
]
Solution: Be more specific
json"pathPatterns": [
"form/src/services/**/*.ts", // Only specific directory
"form/src/controllers/**/*.ts"
]
Content pattern matching reads entire file - slow for large files.
Solution:
bash# 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:
Related Files:
# Troubleshooting - Skill Activation Issues
Complete debugging guide for skill activation problems.
## Table of Contents
- [Skill Not Triggering](#skill-not-triggering)
- [UserPromptSubmit Not Suggesting](#userpromptsubmit-not-suggesting)
- [PreToolUse Not Blocking](#pretooluse-not-blocking)
- [False Positives](#false-positives)
- [Hook Not Executing](#hook-not-executing)
- [Performance Issues](#performance-issues)
---
## 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.keywords` in skill-rules.json
- Are the keywords actually in your prompt?
- Remember: case-insensitive substring matching
**Example:**
```json
"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:**
```json
"intentPatterns": [
"(create|add).*?(database.*?table)" // Too specific
]
```
- "create a database table" → ✅ Matches
- "add new table" → ❌ Doesn't match (missing "database")
**Fix:** Broaden the pattern:
```json
"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:**
```yaml
# SKILL.md
name: project-catalog-developer
```
```json
// skill-rules.json
"project-catalogue-developer": { // ❌ Typo: catalogue vs catalog
...
}
```
**Fix:** Make names match exactly
#### 4. JSON Syntax Error
**Check:**
```bash
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:
```bash
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.pathPatterns` in skill-rules.json
- Glob pattern syntax
**Example:**
```json
"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:**
```json
"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:**
```json
"contentPatterns": [
"import.*[Pp]risma"
]
```
- File has: `import { PrismaService } from './prisma'` → ✅ Matches
- File has: `import { Database } from './db'` → ❌ Doesn't match
**Debug:**
```bash
# 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:**
```bash
ls .claude/hooks/state/
cat .claude/hooks/state/skills-used-{session-id}.json
```
**Example:**
```json
{
"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:
```bash
rm .claude/hooks/state/skills-used-{session-id}.json
```
#### 5. File Marker Present
**Check file for skip marker:**
```bash
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:**
```bash
echo $SKIP_DB_VERIFICATION
echo $SKIP_SKILL_GUARDRAILS
```
If set, the skill is disabled.
**Fix:** Unset the environment variable:
```bash
unset SKIP_DB_VERIFICATION
```
#### Debug Command
Test the hook manually:
```bash
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:**
```json
"keywords": ["user", "system", "create"] // Too broad
```
- Triggers on: "user manual", "file system", "create directory"
**Solution:** Make keywords more specific
```json
"keywords": [
"user authentication",
"user tracking",
"create feature"
]
```
### 2. Intent Patterns Too Broad
**Problem:**
```json
"intentPatterns": [
"(create)" // Matches everything with "create"
]
```
- Triggers on: "create file", "create folder", "create account"
**Solution:** Add context to patterns
```json
"intentPatterns": [
"(create|add).*?(database|table|feature)" // More specific
]
```
**Advanced:** Use negative lookaheads to exclude
```regex
(create)(?!.*test).*?(feature) // Don't match if "test" appears
```
### 3. File Paths Too Generic
**Problem:**
```json
"pathPatterns": [
"form/**" // Matches everything in form/
]
```
- Triggers on: test files, config files, everything
**Solution:** Use narrower patterns
```json
"pathPatterns": [
"form/src/services/**/*.ts", // Only service files
"form/src/controllers/**/*.ts"
]
```
### 4. Content Patterns Catching Unrelated Code
**Problem:**
```json
"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
```json
"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:
```json
{
"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`:**
```bash
cat .claude/settings.json | jq '.hooks.UserPromptSubmit'
cat .claude/settings.json | jq '.hooks.PreToolUse'
```
Expected: Hook entries present
**Fix:** Add missing hook registration:
```json
{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/skill-activation-prompt.sh"
}
]
}
]
}
}
```
### 2. Bash Wrapper Not Executable
**Check:**
```bash
ls -l .claude/hooks/*.sh
```
Expected: `-rwxr-xr-x` (executable)
**Fix:**
```bash
chmod +x .claude/hooks/*.sh
```
### 3. Incorrect Shebang
**Check:**
```bash
head -1 .claude/hooks/skill-activation-prompt.sh
```
Expected: `#!/bin/bash`
**Fix:** Add correct shebang to first line
### 4. npx/tsx Not Available
**Check:**
```bash
npx tsx --version
```
Expected: Version number
**Fix:** Install dependencies:
```bash
cd .claude/hooks
npm install
```
### 5. TypeScript Compilation Error
**Check:**
```bash
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:**
```regex
(create|add|modify|update|implement|build).*?(feature|endpoint|route|service|controller|component|UI|page)
```
- Long alternations = slow
**Solution:** Simplify
```regex
(create|add).*?(feature|endpoint) // Fewer alternatives
```
### 3. Too Many Files Checked
**Problem:**
```json
"pathPatterns": [
"**/*.ts" // Checks ALL TypeScript files
]
```
**Solution:** Be more specific
```json
"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
```bash
# 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](SKILL.md) - Main skill guide
- [HOOK_MECHANISMS.md](HOOK_MECHANISMS.md) - How hooks work
- [SKILL_RULES_REFERENCE.md](SKILL_RULES_REFERENCE.md) - Configuration reference
{
"name": "claude-hooks",
"version": "1.0.0",
"description": "TypeScript hooks for Claude Code skill auto-activation",
"private": true,
"type": "module",
"scripts": {
"check": "tsc --noEmit",
"test": "tsx skill-activation-prompt.ts < test-input.json"
},
"dependencies": {
"@types/node": "^20.11.0",
"tsx": "^4.7.0",
"typescript": "^5.3.3"
}
}
{
"name": "claude-hooks",
"version": "1.0.0",
"description": "TypeScript hooks for Claude Code skill auto-activation",
"private": true,
"type": "module",
"scripts": {
"check": "tsc --noEmit",
"test": "tsx skill-activation-prompt.ts < test-input.json"
},
"dependencies": {
"@types/node": "^20.11.0",
"tsx": "^4.7.0",
"typescript": "^5.3.3"
}
}
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"lib": ["ES2022"],
"outDir": "./dist",
"rootDir": ".",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"types": ["node"]
},
"include": ["*.ts"],
"exclude": ["node_modules", "dist"]
}
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"lib": ["ES2022"],
"outDir": "./dist",
"rootDir": ".",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"types": ["node"]
},
"include": ["*.ts"],
"exclude": ["node_modules", "dist"]
}
#!/bin/bash
set -e
cd "$CLAUDE_PROJECT_DIR/.claude/hooks"
cat | npx tsx skill-activation-prompt.ts
#!/bin/bash set -e cd "$CLAUDE_PROJECT_DIR/.claude/hooks" cat | npx tsx skill-activation-prompt.ts
#!/usr/bin/env node
import { readFileSync } from 'fs';
import { join } from 'path';
interface HookInput {
session_id: string;
transcript_path: string;
cwd: string;
permission_mode: string;
prompt: string;
}
interface PromptTriggers {
keywords?: string[];
intentPatterns?: string[];
}
interface SkillRule {
type: 'guardrail' | 'domain';
enforcement: 'block' | 'suggest' | 'warn';
priority: 'critical' | 'high' | 'medium' | 'low';
promptTriggers?: PromptTriggers;
}
interface SkillRules {
version: string;
skills: Record<string, SkillRule>;
}
interface MatchedSkill {
name: string;
matchType: 'keyword' | 'intent';
config: SkillRule;
}
async function main() {
try {
// Read input from stdin
const input = readFileSync(0, 'utf-8');
const data: HookInput = JSON.parse(input);
const prompt = data.prompt.toLowerCase();
// Load skill rules
const projectDir = process.env.CLAUDE_PROJECT_DIR || '$HOME/project';
const rulesPath = join(projectDir, '.claude', 'skills', 'skill-rules.json');
const rules: SkillRules = JSON.parse(readFileSync(rulesPath, 'utf-8'));
const matchedSkills: MatchedSkill[] = [];
// Check each skill for matches
for (const [skillName, config] of Object.entries(rules.skills)) {
const triggers = config.promptTriggers;
if (!triggers) {
continue;
}
// Keyword matching
if (triggers.keywords) {
const keywordMatch = triggers.keywords.some(kw =>
prompt.includes(kw.toLowerCase())
);
if (keywordMatch) {
matchedSkills.push({ name: skillName, matchType: 'keyword', config });
continue;
}
}
// Intent pattern matching
if (triggers.intentPatterns) {
const intentMatch = triggers.intentPatterns.some(pattern => {
const regex = new RegExp(pattern, 'i');
return regex.test(prompt);
});
if (intentMatch) {
matchedSkills.push({ name: skillName, matchType: 'intent', config });
}
}
}
// Generate output if matches found
if (matchedSkills.length > 0) {
let output = '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';
output += '🎯 SKILL ACTIVATION CHECK\n';
output += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n';
// Group by priority
const critical = matchedSkills.filter(s => s.config.priority === 'critical');
const high = matchedSkills.filter(s => s.config.priority === 'high');
const medium = matchedSkills.filter(s => s.config.priority === 'medium');
const low = matchedSkills.filter(s => s.config.priority === 'low');
if (critical.length > 0) {
output += '⚠️ CRITICAL SKILLS (REQUIRED):\n';
critical.forEach(s => output += ` → ${s.name}\n`);
output += '\n';
}
if (high.length > 0) {
output += '📚 RECOMMENDED SKILLS:\n';
high.forEach(s => output += ` → ${s.name}\n`);
output += '\n';
}
if (medium.length > 0) {
output += '💡 SUGGESTED SKILLS:\n';
medium.forEach(s => output += ` → ${s.name}\n`);
output += '\n';
}
if (low.length > 0) {
output += '📌 OPTIONAL SKILLS:\n';
low.forEach(s => output += ` → ${s.name}\n`);
output += '\n';
}
output += 'ACTION: Use Skill tool BEFORE responding\n';
output += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';
console.log(output);
}
process.exit(0);
} catch (err) {
console.error('Error in skill-activation-prompt hook:', err);
process.exit(1);
}
}
main().catch(err => {
console.error('Uncaught error:', err);
process.exit(1);
});
#!/usr/bin/env node
import { readFileSync } from 'fs';
import { join } from 'path';
interface HookInput {
session_id: string;
transcript_path: string;
cwd: string;
permission_mode: string;
prompt: string;
}
interface PromptTriggers {
keywords?: string[];
intentPatterns?: string[];
}
interface SkillRule {
type: 'guardrail' | 'domain';
enforcement: 'block' | 'suggest' | 'warn';
priority: 'critical' | 'high' | 'medium' | 'low';
promptTriggers?: PromptTriggers;
}
interface SkillRules {
version: string;
skills: Record<string, SkillRule>;
}
interface MatchedSkill {
name: string;
matchType: 'keyword' | 'intent';
config: SkillRule;
}
async function main() {
try {
// Read input from stdin
const input = readFileSync(0, 'utf-8');
const data: HookInput = JSON.parse(input);
const prompt = data.prompt.toLowerCase();
// Load skill rules
const projectDir = process.env.CLAUDE_PROJECT_DIR || '$HOME/project';
const rulesPath = join(projectDir, '.claude', 'skills', 'skill-rules.json');
const rules: SkillRules = JSON.parse(readFileSync(rulesPath, 'utf-8'));
const matchedSkills: MatchedSkill[] = [];
// Check each skill for matches
for (const [skillName, config] of Object.entries(rules.skills)) {
const triggers = config.promptTriggers;
if (!triggers) {
continue;
}
// Keyword matching
if (triggers.keywords) {
const keywordMatch = triggers.keywords.some(kw =>
prompt.includes(kw.toLowerCase())
);
if (keywordMatch) {
matchedSkills.push({ name: skillName, matchType: 'keyword', config });
continue;
}
}
// Intent pattern matching
if (triggers.intentPatterns) {
const intentMatch = triggers.intentPatterns.some(pattern => {
const regex = new RegExp(pattern, 'i');
return regex.test(prompt);
});
if (intentMatch) {
matchedSkills.push({ name: skillName, matchType: 'intent', config });
}
}
}
// Generate output if matches found
if (matchedSkills.length > 0) {
let output = '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';
output += '🎯 SKILL ACTIVATION CHECK\n';
output += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n';
// Group by priority
const critical = matchedSkills.filter(s => s.config.priority === 'critical');
const high = matchedSkills.filter(s => s.config.priority === 'high');
const medium = matchedSkills.filter(s => s.config.priority === 'medium');
const low = matchedSkills.filter(s => s.config.priority === 'low');
if (critical.length > 0) {
output += '⚠️ CRITICAL SKILLS (REQUIRED):\n';
critical.forEach(s => output += ` → ${s.name}\n`);
output += '\n';
}
if (high.length > 0) {
output += '📚 RECOMMENDED SKILLS:\n';
high.forEach(s => output += ` → ${s.name}\n`);
output += '\n';
}
if (medium.length > 0) {
output += '💡 SUGGESTED SKILLS:\n';
medium.forEach(s => output += ` → ${s.name}\n`);
output += '\n';
}
if (low.length > 0) {
output += '📌 OPTIONAL SKILLS:\n';
low.forEach(s => output += ` → ${s.name}\n`);
output += '\n';
}
output += 'ACTION: Use Skill tool BEFORE responding\n';
output += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';
console.log(output);
}
process.exit(0);
} catch (err) {
console.error('Error in skill-activation-prompt hook:', err);
process.exit(1);
}
}
main().catch(err => {
console.error('Uncaught error:', err);
process.exit(1);
});
{
"version": "1.0",
"description": "Skill activation triggers for Claude Code. Controls when skills automatically suggest or block actions.",
"skills": {
"skill-developer": {
"type": "domain",
"enforcement": "suggest",
"priority": "high",
"description": "Meta-skill for creating and managing Claude Code skills",
"promptTriggers": {
"keywords": [
"skill system",
"create skill",
"add skill",
"skill triggers",
"skill rules",
"hook system",
"skill development",
"skill-rules.json"
],
"intentPatterns": [
"(how do|how does|explain).*?skill",
"(create|add|modify|build).*?skill",
"skill.*?(work|trigger|activate|system)"
]
}
},
"backend-dev-guidelines": {
"type": "domain",
"enforcement": "suggest",
"priority": "high",
"description": "Backend development patterns for Node.js/Express/TypeScript",
"promptTriggers": {
"keywords": [
"backend",
"backend development",
"microservice",
"controller",
"service",
"repository",
"route",
"routing",
"express",
"API",
"endpoint",
"middleware",
"validation",
"Zod",
"Prisma",
"database access",
"BaseController",
"dependency injection",
"unifiedConfig",
"configuration"
],
"intentPatterns": [
"(create|add|implement|build).*?(route|endpoint|API|controller|service|repository)",
"(fix|handle|debug).*?(error|exception|backend)",
"(add|implement).*?(middleware|validation|error.*?handling)",
"(organize|structure|refactor).*?(backend|service|API)",
"(how to|best practice).*?(backend|route|controller|service)"
]
},
"fileTriggers": {
"pathPatterns": [
"blog-api/src/**/*.ts",
"auth-service/src/**/*.ts",
"notifications-service/src/**/*.ts",
"backend/**/*.ts",
"api/**/*.ts",
"server/**/*.ts",
"services/**/*.ts"
],
"pathExclusions": [
"**/*.test.ts",
"**/*.spec.ts"
],
"contentPatterns": [
"router\\.",
"app\\.(get|post|put|delete|patch)",
"export.*Controller",
"export.*Service",
"prisma\\."
]
}
},
"frontend-dev-guidelines": {
"type": "guardrail",
"enforcement": "block",
"priority": "high",
"description": "React/TypeScript best practices including MUI v7 compatibility",
"promptTriggers": {
"keywords": [
"component",
"react component",
"UI",
"interface",
"page",
"modal",
"dialog",
"form",
"MUI",
"Material-UI",
"Grid",
"styling",
"frontend",
"React"
],
"intentPatterns": [
"(create|add|make|build|update|modify|edit).*?(component|UI|page|modal|dialog|form)",
"(how to|best practice).*?(component|react|MUI)",
"(style|design|layout).*?(component|UI)"
]
},
"fileTriggers": {
"pathPatterns": [
"frontend/src/**/*.tsx",
"frontend/src/**/*.ts",
"client/src/**/*.tsx",
"client/src/**/*.ts",
"src/**/*.tsx"
],
"pathExclusions": [
"**/*.test.tsx",
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.spec.ts",
"**/*.styles.ts",
"**/vite.config.ts",
"**/tsconfig.json"
],
"contentPatterns": [
"from '@mui/material';",
"import.*Grid.*from.*@mui",
"<Grid ",
"Grid2",
"Unstable_Grid",
"makeStyles",
"@material-ui/core"
]
},
"blockMessage": "⚠️ BLOCKED - Frontend Best Practices Required\n\n📋 REQUIRED ACTION:\n1. Use Skill tool: 'frontend-dev-guidelines'\n2. Review MUI v7 patterns (Grid uses size={{}} prop, NOT xs/sm props)\n3. Check React/TypeScript best practices\n4. Use proper styling patterns\n5. Then retry this edit\n\nReason: Enforce MUI v7 compatibility and React best practices\nFile: {file_path}\n\n💡 TIP: Add '// @skip-validation' comment to skip future checks",
"skipConditions": {
"sessionSkillUsed": true,
"fileMarkers": [
"@skip-validation"
],
"envOverride": "SKIP_FRONTEND_GUIDELINES"
}
},
"route-tester": {
"type": "domain",
"enforcement": "suggest",
"priority": "high",
"description": "Testing authenticated API routes with JWT cookie-based auth",
"promptTriggers": {
"keywords": [
"test route",
"test endpoint",
"test API",
"route testing",
"API testing",
"authenticated route",
"JWT testing",
"cookie auth",
"test with auth"
],
"intentPatterns": [
"(test|debug|verify).*?(route|endpoint|API)",
"(how to|how do I).*?test.*?(route|endpoint|API)",
"test.*?(authenticated|auth|JWT|cookie)"
]
},
"fileTriggers": {
"pathPatterns": [
"**/routes/**/*.ts",
"**/test-*.js",
"**/test-*.ts"
],
"contentPatterns": [
"router\\.(get|post|put|delete|patch)",
"app\\.(get|post|put|delete|patch)"
]
}
},
"error-tracking": {
"type": "domain",
"enforcement": "suggest",
"priority": "high",
"description": "Sentry error tracking and performance monitoring patterns",
"promptTriggers": {
"keywords": [
"error handling",
"exception",
"sentry",
"error tracking",
"captureException",
"monitoring",
"performance tracking"
],
"intentPatterns": [
"(add|create|implement|setup).*?(error handling|sentry|error tracking)",
"(fix|handle|catch).*?(error|exception)",
"(how to|best practice).*?(error|sentry|monitoring)"
]
},
"fileTriggers": {
"pathPatterns": [
"**/instrument.ts",
"**/sentry*.ts",
"**/*Controller.ts",
"**/*Service.ts"
],
"contentPatterns": [
"@sentry",
"Sentry\\.",
"captureException",
"captureMessage"
]
}
}
},
"notes": {
"enforcement_types": {
"suggest": "Skill suggestion appears but doesn't block execution",
"block": "Requires skill to be used before proceeding (guardrail)",
"warn": "Shows warning but allows proceeding"
},
"priority_levels": {
"critical": "Highest - Always trigger when matched",
"high": "Important - Trigger for most matches",
"medium": "Moderate - Trigger for clear matches",
"low": "Optional - Trigger only for explicit matches"
},
"customization": {
"pathPatterns": "Adjust to match your project structure (blog-api, auth-service, etc.)",
"keywords": "Add domain-specific terms relevant to your project",
"intentPatterns": "Use regex for flexible user intent matching"
}
}
}
{
"version": "1.0",
"description": "Skill activation triggers for Claude Code. Controls when skills automatically suggest or block actions.",
"skills": {
"skill-developer": {
"type": "domain",
"enforcement": "suggest",
"priority": "high",
"description": "Meta-skill for creating and managing Claude Code skills",
"promptTriggers": {
"keywords": [
"skill system",
"create skill",
"add skill",
"skill triggers",
"skill rules",
"hook system",
"skill development",
"skill-rules.json"
],
"intentPatterns": [
"(how do|how does|explain).*?skill",
"(create|add|modify|build).*?skill",
"skill.*?(work|trigger|activate|system)"
]
}
},
"backend-dev-guidelines": {
"type": "domain",
"enforcement": "suggest",
"priority": "high",
"description": "Backend development patterns for Node.js/Express/TypeScript",
"promptTriggers": {
"keywords": [
"backend",
"backend development",
"microservice",
"controller",
"service",
"repository",
"route",
"routing",
"express",
"API",
"endpoint",
"middleware",
"validation",
"Zod",
"Prisma",
"database access",
"BaseController",
"dependency injection",
"unifiedConfig",
"configuration"
],
"intentPatterns": [
"(create|add|implement|build).*?(route|endpoint|API|controller|service|repository)",
"(fix|handle|debug).*?(error|exception|backend)",
"(add|implement).*?(middleware|validation|error.*?handling)",
"(organize|structure|refactor).*?(backend|service|API)",
"(how to|best practice).*?(backend|route|controller|service)"
]
},
"fileTriggers": {
"pathPatterns": [
"blog-api/src/**/*.ts",
"auth-service/src/**/*.ts",
"notifications-service/src/**/*.ts",
"backend/**/*.ts",
"api/**/*.ts",
"server/**/*.ts",
"services/**/*.ts"
],
"pathExclusions": [
"**/*.test.ts",
"**/*.spec.ts"
],
"contentPatterns": [
"router\\.",
"app\\.(get|post|put|delete|patch)",
"export.*Controller",
"export.*Service",
"prisma\\."
]
}
},
"frontend-dev-guidelines": {
"type": "guardrail",
"enforcement": "block",
"priority": "high",
"description": "React/TypeScript best practices including MUI v7 compatibility",
"promptTriggers": {
"keywords": [
"component",
"react component",
"UI",
"interface",
"page",
"modal",
"dialog",
"form",
"MUI",
"Material-UI",
"Grid",
"styling",
"frontend",
"React"
],
"intentPatterns": [
"(create|add|make|build|update|modify|edit).*?(component|UI|page|modal|dialog|form)",
"(how to|best practice).*?(component|react|MUI)",
"(style|design|layout).*?(component|UI)"
]
},
"fileTriggers": {
"pathPatterns": [
"frontend/src/**/*.tsx",
"frontend/src/**/*.ts",
"client/src/**/*.tsx",
"client/src/**/*.ts",
"src/**/*.tsx"
],
"pathExclusions": [
"**/*.test.tsx",
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.spec.ts",
"**/*.styles.ts",
"**/vite.config.ts",
"**/tsconfig.json"
],
"contentPatterns": [
"from '@mui/material';",
"import.*Grid.*from.*@mui",
"<Grid ",
"Grid2",
"Unstable_Grid",
"makeStyles",
"@material-ui/core"
]
},
"blockMessage": "⚠️ BLOCKED - Frontend Best Practices Required\n\n📋 REQUIRED ACTION:\n1. Use Skill tool: 'frontend-dev-guidelines'\n2. Review MUI v7 patterns (Grid uses size={{}} prop, NOT xs/sm props)\n3. Check React/TypeScript best practices\n4. Use proper styling patterns\n5. Then retry this edit\n\nReason: Enforce MUI v7 compatibility and React best practices\nFile: {file_path}\n\n💡 TIP: Add '// @skip-validation' comment to skip future checks",
"skipConditions": {
"sessionSkillUsed": true,
"fileMarkers": [
"@skip-validation"
],
"envOverride": "SKIP_FRONTEND_GUIDELINES"
}
},
"route-tester": {
"type": "domain",
"enforcement": "suggest",
"priority": "high",
"description": "Testing authenticated API routes with JWT cookie-based auth",
"promptTriggers": {
"keywords": [
"test route",
"test endpoint",
"test API",
"route testing",
"API testing",
"authenticated route",
"JWT testing",
"cookie auth",
"test with auth"
],
"intentPatterns": [
"(test|debug|verify).*?(route|endpoint|API)",
"(how to|how do I).*?test.*?(route|endpoint|API)",
"test.*?(authenticated|auth|JWT|cookie)"
]
},
"fileTriggers": {
"pathPatterns": [
"**/routes/**/*.ts",
"**/test-*.js",
"**/test-*.ts"
],
"contentPatterns": [
"router\\.(get|post|put|delete|patch)",
"app\\.(get|post|put|delete|patch)"
]
}
},
"error-tracking": {
"type": "domain",
"enforcement": "suggest",
"priority": "high",
"description": "Sentry error tracking and performance monitoring patterns",
"promptTriggers": {
"keywords": [
"error handling",
"exception",
"sentry",
"error tracking",
"captureException",
"monitoring",
"performance tracking"
],
"intentPatterns": [
"(add|create|implement|setup).*?(error handling|sentry|error tracking)",
"(fix|handle|catch).*?(error|exception)",
"(how to|best practice).*?(error|sentry|monitoring)"
]
},
"fileTriggers": {
"pathPatterns": [
"**/instrument.ts",
"**/sentry*.ts",
"**/*Controller.ts",
"**/*Service.ts"
],
"contentPatterns": [
"@sentry",
"Sentry\\.",
"captureException",
"captureMessage"
]
}
}
},
"notes": {
"enforcement_types": {
"suggest": "Skill suggestion appears but doesn't block execution",
"block": "Requires skill to be used before proceeding (guardrail)",
"warn": "Shows warning but allows proceeding"
},
"priority_levels": {
"critical": "Highest - Always trigger when matched",
"high": "Important - Trigger for most matches",
"medium": "Moderate - Trigger for clear matches",
"low": "Optional - Trigger only for explicit matches"
},
"customization": {
"pathPatterns": "Adjust to match your project structure (blog-api, auth-service, etc.)",
"keywords": "Add domain-specific terms relevant to your project",
"intentPatterns": "Use regex for flexible user intent matching"
}
}
}