.claude/skills/hook-creator/SKILL.md
Creates and registers hooks for the Claude Code framework. Handles pre/post tool execution, validation, memory, and session hooks. Use when new validation, safety, or automation hooks are needed.
npx skillsauth add oimiragieo/agent-studio hook-creatorInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Creates, validates, and registers hooks for the multi-agent orchestration framework.
After creating ANY hook, you MUST update documentation:
1. Add to .claude/hooks/README.md under appropriate category
2. Register in config.yaml or settings.json if required
3. Update learnings.md with hook summary
Verification:
grep "<hook-name>" .claude/hooks/README.md || echo "ERROR: hooks/README.md NOT UPDATED!"
WHY: Hooks not documented are invisible and unmaintainable.
This skill creates hooks for the Claude Code framework:
| Type | Location | Purpose | When Triggered |
| ------- | ------------------------ | --------------------------------------- | ---------------------- |
| Safety | .claude/hooks/safety/ | Validate commands, block dangerous ops | Before Bash/Write/Edit |
| Memory | .claude/hooks/memory/ | Auto-update learnings, extract insights | After task completion |
| Routing | .claude/hooks/routing/ | Enforce router-first protocol | On UserPromptSubmit |
| Session | .claude/hooks/session/ | Initialize/cleanup sessions | Session start/end |
When creating hooks, determine which agent archetypes will be governed by the new hook. See .claude/docs/@HOOK_AGENT_MAP.md for:
After creating a hook, you MUST add it to both the matrix AND update affected agents' ## Enforcement Hooks sections.
| Hook Event | When Triggered | Use Case |
| ------------------ | ------------------------- | --------------------------------------- |
| PreToolUse | Before tool executes | Validation, blocking, permission checks |
| PostToolUse | After tool completes | Logging, cleanup, notifications |
| UserPromptSubmit | Before model sees message | Routing, intent analysis, filtering |
BEFORE creating any hook file, check if it already exists:
Check if hook already exists:
test -f .claude/hooks/<category>/<hook-name>.cjs && echo "EXISTS" || echo "NEW"
If hook EXISTS:
DO NOT proceed with creation
Invoke artifact-updater workflow instead:
Skill({
skill: 'artifact-updater',
args: '--type hook --path .claude/hooks/<category>/<hook-name>.cjs --changes "<description of requested changes>"',
});
Return updater result and STOP
If hook is NEW:
Before proceeding with creation, run the 3-layer duplicate check:
const { checkDuplicate } = require('.claude/lib/creation/duplicate-detector.cjs');
const result = checkDuplicate({
artifactType: 'hook',
name: proposedName,
description: proposedDescription,
keywords: proposedKeywords || [],
});
Handle results:
EXACT_MATCH: Stop creation. Route to hook-updater skill instead: Skill({ skill: 'hook-updater' })REGISTRY_MATCH: Warn user — artifact is registered but file may be missing. Investigate before creating. Ask user to confirm.SIMILAR_FOUND: Display candidates with scores. Ask user: "Similar artifact(s) exist. Continue with new creation or update existing?"NO_MATCH: Proceed to Step 0.5 (companion check).Override: If user explicitly passes --force, skip this check entirely.
Before proceeding with creation, run the ecosystem companion check:
companion-check.cjs from .claude/lib/creators/companion-check.cjscheckCompanions("hook", "{hook-name}") to identify companion artifactsThis step is informational (does not block creation) but ensures the full artifact ecosystem is considered.
Use .claude/lib/routing/routing-table.cjs as the canonical routing reference.
Before finalizing any hook, compare against routing-table structure:
Before creating a hook, gather:
// Example requirements gathering
{
purpose: "Validate git push commands to prevent force push",
trigger: "pre-tool (Bash)",
target_tools: ["Bash"],
behavior: "block if force push detected",
exit_codes: { 0: "allow", 1: "block" }
}
| If hook does... | Type | Location |
| -------------------- | ------- | ------------------------ |
| Validates commands | Safety | .claude/hooks/safety/ |
| Modifies routing | Routing | .claude/hooks/routing/ |
| Updates memory | Memory | .claude/hooks/memory/ |
| Session init/cleanup | Session | .claude/hooks/session/ |
Naming Convention: <action>-<target>.cjs
Examples:
validate-git-force-push.cjsenforce-tdd-workflow.cjsextract-workflow-learnings.cjsmemory-reminder.cjsAll hooks use CommonJS format and follow this template:
'use strict';
/**
* {Hook Name}
*
* Type: {pre|post}-{tool} | session-{start|end} | user-prompt
* Purpose: {One line description}
* Trigger: {When this hook runs}
*
* Exit codes:
* - 0: Allow operation (with optional warning)
* - 1: Block operation (when in blocking mode)
*
* Environment:
* {HOOK_NAME}_MODE=block|warn|off (default: warn unless explicitly required)
*/
const fs = require('fs');
const path = require('path');
// Find project root by looking for .claude directory
function findProjectRoot() {
let dir = __dirname;
while (dir !== path.parse(dir).root) {
if (fs.existsSync(path.join(dir, '.claude'))) {
return dir;
}
dir = path.dirname(dir);
}
return process.cwd();
}
const PROJECT_ROOT = findProjectRoot();
const ENFORCEMENT_MODE = process.env.HOOK_NAME_MODE || 'warn';
/**
* Parse hook input from Claude Code
* Claude Code passes JSON via process.argv[2] for hooks
* @returns {Object|null} Parsed hook input or null
*/
function parseHookInput() {
try {
if (process.argv[2]) {
return JSON.parse(process.argv[2]);
}
} catch (e) {
// Fallback for testing or invalid input
}
return null;
}
/**
* Validate hook - called by Claude Code or programmatically
* @param {Object} context - Hook context with tool info
* @param {string} context.tool - Tool name (Bash, Write, Edit, Read)
* @param {Object} context.parameters - Tool parameters
* @returns {Object} Validation result with valid (boolean), error (string), and optional warning (string)
*/
function validate(context) {
const { tool, parameters } = context;
// YOUR VALIDATION LOGIC HERE
// Return validation result
return { valid: true, error: '' };
}
/**
* Main execution for CLI hook usage
*/
function main() {
// Skip if enforcement is off
if (ENFORCEMENT_MODE === 'off') {
process.exit(0);
}
const hookInput = parseHookInput();
if (!hookInput) {
process.exit(0);
}
// Get tool name and input
const toolName = hookInput.tool_name || hookInput.tool;
const toolInput = hookInput.tool_input || hookInput.input || {};
// Run validation
const result = validate({ tool: toolName, parameters: toolInput });
if (!result.valid) {
if (ENFORCEMENT_MODE === 'block') {
console.error(`BLOCKED: ${result.error}`);
process.exit(1);
} else {
console.warn(`WARNING: ${result.error}`);
process.exit(0);
}
}
if (result.warning) {
console.warn(`WARNING: ${result.warning}`);
}
process.exit(0);
}
// Run main if executed directly
if (require.main === module) {
main();
}
// Export for programmatic use and testing
module.exports = {
validate,
findProjectRoot,
PROJECT_ROOT,
};
Every hook MUST have a corresponding test file:
'use strict';
const { validate } = require('./hook-name.cjs');
describe('Hook Name', () => {
test('allows valid operations', () => {
const result = validate({
tool: 'Bash',
parameters: { command: 'git status' },
});
expect(result.valid).toBe(true);
expect(result.error).toBe('');
});
test('blocks dangerous operations', () => {
const result = validate({
tool: 'Bash',
parameters: { command: 'git push --force' },
});
expect(result.valid).toBe(false);
expect(result.error).toContain('force push');
});
test('handles missing parameters gracefully', () => {
const result = validate({
tool: 'Bash',
parameters: {},
});
expect(result.valid).toBe(true);
});
});
Some hooks require registration in config files:
For pre/post-tool hooks (settings.json):
{
"hooks": {
"pre-tool": [".claude/hooks/safety/hook-name.cjs"],
"post-tool": [".claude/hooks/memory/hook-name.cjs"]
}
}
For event hooks (config.yaml):
hooks:
UserPromptSubmit:
- path: .claude/hooks/routing/hook-name.cjs
type: command
SessionStart:
- path: .claude/hooks/session/hook-name.cjs
type: command
After creating a hook, update .claude/hooks/README.md:
#### {Hook Name} (`hook-name.cjs`)
{Description of what the hook does}
**When it runs:** {Trigger condition}
**What it checks/does:** {Detailed behavior}
Verify with:
grep "hook-name" .claude/hooks/README.md || echo "ERROR: Not documented!"
This analysis is MANDATORY. Hook creation is INCOMPLETE without it.
After creating a hook:
Settings Registration (BLOCKING)
grep "hook-name" .claude/settings.jsonTest Coverage (BLOCKING)
node .claude/hooks/<category>/<name>.test.cjsDocumentation
Related Hooks
Full Checklist:
[HOOK-CREATOR] System Impact Analysis for: <hook-name>
1. HOOK FILE CREATED
[ ] Created at .claude/hooks/<type>/<hook-name>.cjs
[ ] Follows CJS format with validate() export
[ ] Has main() function for CLI execution
[ ] Handles graceful degradation (warn by default)
2. TEST FILE CREATED (minimum 10 test cases)
[ ] Created at .claude/hooks/<type>/<hook-name>.test.cjs
[ ] Tests valid operations (3+ cases)
[ ] Tests blocked operations (3+ cases)
[ ] Tests edge cases (3+ cases)
[ ] Tests error handling (1+ cases)
3. DOCUMENTATION UPDATED
[ ] Added to .claude/hooks/README.md
[ ] Documented trigger conditions
[ ] Documented exit codes
4. REGISTRATION (BLOCKING)
[ ] Added to settings.json (pre/post-tool hooks)
[ ] Added to config.yaml (event hooks)
[ ] Verified: grep "<hook-name>" .claude/settings.json
5. MEMORY UPDATED
[ ] Added to learnings.md with hook summary
6. HOOK-AGENT MAP UPDATED (MANDATORY)
[ ] Added new hook to @HOOK_AGENT_MAP.md Section 1 matrix
[ ] Determined which agent archetypes are affected (based on hook trigger/tool target)
[ ] Updated affected agents' `## Enforcement Hooks` sections
[ ] Verified: `grep "<hook-name>" .claude/docs/@HOOK_AGENT_MAP.md || echo "ERROR: Hook not in agent map!"`
BLOCKING: If ANY item above is missing, hook creation is INCOMPLETE.
This step is CRITICAL. After creating the hook artifact, you MUST register it in the hook discovery system.
Phase 1 Context: Phase 1 is responsible for tool and hook validation/discovery. Hooks created without registration are invisible to the system and will not be loaded at startup.
After hook file is written and tested:
Create/Update Hook Registry Entry in appropriate location:
If registry doesn't exist, create .claude/context/artifacts/hook-registry.json:
{
"hooks": [
{
"name": "{hook-name}",
"id": "{hook-name}",
"description": "{Brief description from hook}",
"category": "{safety|routing|memory|session|validation|audit}",
"type": "{pre-tool|post-tool|user-prompt|session-start|session-end}",
"version": "1.0.0",
"targetTools": ["{Tool1}", "{Tool2}"],
"enforcementMode": "{block|warn|off}",
"defaultEnabled": true,
"filePath": ".claude/hooks/{category}/{hook-name}.cjs",
"testFilePath": ".claude/hooks/{category}/{hook-name}.test.cjs",
"environmentVariable": "{HOOK_NAME}_MODE"
}
]
}
Validate Hook Against Schema:
Ensure hook validates against .claude/schemas/hook-schema.json (if exists):
# Validate hook structure
node -e "
const hook = require('./.claude/hooks/{category}/{hook-name}.cjs');
if (hook.validate) console.log('✓ Has validate() export');
if (hook.PROJECT_ROOT) console.log('✓ Has PROJECT_ROOT');
if (hook.findProjectRoot) console.log('✓ Has findProjectRoot()');
"
Register Hook in Loader:
Update .claude/lib/hooks/hook-loader.cjs (if exists) to include new hook:
const HOOKS_MANIFEST = {
'{hook-name}': {
path: './.claude/hooks/{category}/{hook-name}.cjs',
type: '{pre-tool|post-tool}',
matcher: '{Bash|Write|Edit|Read}', // Optional
enabled: true,
enforcementMode: process.env.{HOOK_NAME}_MODE || 'warn'
}
};
Register Hook in Configuration:
For pre/post-tool hooks - Update .claude/settings.json:
{
"hooks": {
"pre-tool": ["./.claude/hooks/safety/{hook-name}.cjs"],
"post-tool": ["./.claude/hooks/memory/{hook-name}.cjs"]
}
}
For event hooks - Update .claude/config.yaml:
hooks:
UserPromptSubmit:
- path: ./.claude/hooks/routing/{hook-name}.cjs
type: command
SessionStart:
- path: ./.claude/hooks/session/{hook-name}.cjs
type: command
Document in .claude/hooks/README.md:
Add entry under appropriate category:
#### {Hook Name} (`{hook-name}.cjs`)
{Detailed description of what the hook does.}
**When it runs:** {Trigger condition - e.g., "Before every Bash command", "After task completion"}
**What it checks/does:**
- {Check/action 1}
- {Check/action 2}
- {Check/action 3}
**Enforcement mode:** `process.env.{HOOK_NAME}_MODE` (default: `warn`)
**Test file:** `.claude/hooks/{category}/{hook-name}.test.cjs`
**Related hooks:** {List any hooks that interact with this one}
Update Memory:
Append to .claude/context/memory/learnings.md:
## Hook: {hook-name}
- **Type:** {pre-tool|post-tool|event}
- **Category:** {safety|routing|memory|session|validation}
- **Purpose:** {Detailed purpose}
- **Trigger:** {When it runs}
- **Enforcement:** {Block/warn/off by default}
- **Integration Notes:** {Any special considerations}
Why this matters: Without hook registration:
Phase 1 Integration: Hook registry is the discovery mechanism for Phase 1, enabling the system to validate hooks against schema, load them at startup, and enforce safety rules consistently.
This step verifies the artifact is properly integrated into the ecosystem.
Before calling TaskUpdate({ status: "completed" }), you MUST run the Post-Creation Validation workflow:
Run the 10-item integration checklist:
node .claude/tools/cli/validate-integration.cjs .claude/hooks/<category>/<hook-name>.cjs
Verify exit code is 0 (all checks passed)
If exit code is 1 (one or more checks failed):
Only proceed when validation passes
This step is BLOCKING. Do NOT mark task complete until validation passes.
Why this matters: The Party Mode incident showed that fully-implemented artifacts can be invisible to the Router if integration steps are missed. This validation ensures no "invisible artifact" pattern.
Reference: .claude/workflows/core/post-creation-validation.md
# Create hook using CLI tool
node .claude/tools/hook-creator/create-hook.mjs \
--name "hook-name" \
--type "PreToolUse|PostToolUse|UserPromptSubmit" \
--purpose "Description of what the hook does" \
--category "safety|routing|memory|audit|security|validation|custom" \
--matcher "Edit|Write|Bash" # Optional: tool matcher regex
# List all hooks
node .claude/tools/hook-creator/create-hook.mjs --list
# Validate hook structure
node .claude/tools/hook-creator/create-hook.mjs --validate "<path>"
# Assign to agents
node .claude/tools/hook-creator/create-hook.mjs --assign "name" --agents "agent1,agent2"
# Unregister hook
node .claude/tools/hook-creator/create-hook.mjs --unregister "<path>"
# Test with sample input
echo '{"tool_name":"Edit","tool_input":{"file_path":"test.js"} }' | node .claude/hooks/<category>/<hook-name>.cjs
For validating commands before execution:
'use strict';
/**
* Validate Git Force Push
* Prevents accidental force pushes to protected branches
*/
const PROTECTED_BRANCHES = ['main', 'master', 'production'];
function validate(context) {
const { tool, parameters } = context;
if (tool !== 'Bash') {
return { valid: true, error: '' };
}
const command = parameters?.command || '';
// Check for force push
if (command.includes('git push') && (command.includes('--force') || command.includes('-f'))) {
// Check if pushing to protected branch
for (const branch of PROTECTED_BRANCHES) {
if (command.includes(branch)) {
return {
valid: false,
error: `Force push to ${branch} blocked. Use --force-with-lease instead.`,
};
}
}
return {
valid: true,
error: '',
warning: 'Force push detected. Ensure you know what you are doing.',
};
}
return { valid: true, error: '' };
}
module.exports = { validate };
For extracting learnings after task completion:
'use strict';
/**
* Extract Workflow Learnings
* Automatically captures patterns from completed workflows
*/
const fs = require('fs');
const path = require('path');
function findProjectRoot() {
let dir = __dirname;
while (dir !== path.parse(dir).root) {
if (fs.existsSync(path.join(dir, '.claude'))) return dir;
dir = path.dirname(dir);
}
return process.cwd();
}
const LEARNINGS_PATH = path.join(findProjectRoot(), '.claude/context/memory/learnings.md');
function extractLearnings(context) {
const { tool, parameters, result } = context;
// Only process completed tasks
if (!result || result.status !== 'completed') {
return { extracted: false };
}
// Extract patterns from result
const learnings = [];
if (result.patterns) {
learnings.push(...result.patterns);
}
if (result.decisions) {
learnings.push(...result.decisions);
}
if (learnings.length === 0) {
return { extracted: false };
}
// Append to learnings file
const entry = `\n## [${new Date().toISOString().split('T')[0]}] ${context.taskName || 'Task'}\n\n`;
const content = learnings.map(l => `- ${l}`).join('\n');
fs.appendFileSync(LEARNINGS_PATH, entry + content + '\n');
return { extracted: true, count: learnings.length };
}
module.exports = { extractLearnings };
For enforcing routing protocols:
'use strict';
/**
* Router First Enforcer
* Ensures all requests go through the Router agent
*/
function validate(context) {
const { prompt, currentAgent } = context;
// Skip if already routed
if (currentAgent === 'router') {
return { valid: true, error: '' };
}
// Skip slash commands (handled by skill system)
if (prompt && prompt.trim().startsWith('/')) {
return { valid: true, error: '' };
}
// Suggest routing
return {
valid: true,
error: '',
warning: 'Consider using Router to spawn appropriate agent via Task tool.',
};
}
module.exports = { validate };
For session lifecycle management:
'use strict';
/**
* Session Memory Initializer
* Reminds agents to read memory files at session start
*/
const fs = require('fs');
const path = require('path');
function findProjectRoot() {
let dir = __dirname;
while (dir !== path.parse(dir).root) {
if (fs.existsSync(path.join(dir, '.claude'))) return dir;
dir = path.dirname(dir);
}
return process.cwd();
}
const MEMORY_FILES = [
'.claude/context/memory/learnings.md',
'.claude/context/memory/issues.md',
'.claude/context/memory/decisions.md',
];
function initialize() {
const root = findProjectRoot();
console.log('\n' + '='.repeat(50));
console.log(' SESSION MEMORY REMINDER');
console.log('='.repeat(50));
console.log('\n Before starting work, read these memory files:');
for (const file of MEMORY_FILES) {
const fullPath = path.join(root, file);
if (fs.existsSync(fullPath)) {
const stats = fs.statSync(fullPath);
const modified = stats.mtime.toISOString().split('T')[0];
console.log(` - ${file} (updated: ${modified})`);
}
}
console.log('\n' + '='.repeat(50) + '\n');
return { initialized: true };
}
// Run on direct execution
if (require.main === module) {
initialize();
}
module.exports = { initialize };
node .claude/tools/hook-creator/create-hook.mjs \
--name "secret-detector" \
--type "PreToolUse" \
--purpose "Blocks commits containing secrets or credentials" \
--category "security" \
--matcher "Bash"
node .claude/tools/hook-creator/create-hook.mjs \
--name "operation-logger" \
--type "PostToolUse" \
--purpose "Logs all file modifications to audit trail" \
--category "audit"
node .claude/tools/hook-creator/create-hook.mjs \
--name "intent-classifier" \
--type "UserPromptSubmit" \
--purpose "Classifies user intent for intelligent routing" \
--category "routing"
This skill is part of the unified artifact lifecycle. For complete multi-agent orchestration:
Router Decision: .claude/workflows/core/router-decision.md
Artifact Lifecycle: .claude/workflows/core/skill-lifecycle.md
External Integration: .claude/workflows/core/external-integration.md
This skill is part of the Creator Ecosystem. After creating a hook, consider if companion artifacts are needed:
| Gap Discovered | Required Artifact | Creator to Invoke | When |
| ---------------------------------------- | ----------------- | -------------------------------------- | --------------------------------- |
| Domain knowledge needs a reusable skill | skill | Skill({ skill: 'skill-creator' }) | Gap is a full skill domain |
| Existing skill has incomplete coverage | skill update | Skill({ skill: 'skill-updater' }) | Close skill exists but incomplete |
| Capability needs a dedicated agent | agent | Skill({ skill: 'agent-creator' }) | Agent to own the capability |
| Existing agent needs capability update | agent update | Skill({ skill: 'agent-updater' }) | Close agent exists but incomplete |
| Domain needs code/project scaffolding | template | Skill({ skill: 'template-creator' }) | Reusable code patterns needed |
| Behavior needs pre/post execution guards | hook | Skill({ skill: 'hook-creator' }) | Enforcement behavior required |
| Process needs multi-phase orchestration | workflow | Skill({ skill: 'workflow-creator' }) | Multi-step coordination needed |
| Artifact needs structured I/O validation | schema | Skill({ skill: 'schema-creator' }) | JSON schema for artifact I/O |
| User interaction needs a slash command | command | Skill({ skill: 'command-creator' }) | User-facing shortcut needed |
| Repeated logic needs a reusable CLI tool | tool | Skill({ skill: 'tool-creator' }) | CLI utility needed |
| Narrow/single-artifact capability only | inline | Document within this artifact only | Too specific to generalize |
After creating a hook that needs additional capabilities:
// 1. Hook created but needs dedicated skill
Skill({ skill: 'skill-creator' });
// Create skill that encapsulates hook logic
// 2. Hook needs to be assigned to agent
// Update agent's workflow to include hook awareness
// 3. Hook needs workflow for testing
// Create workflow in .claude/workflows/<hook-name>-test-workflow.md
After hook is fully created and validated:
[ ] Does hook need a skill wrapper? -> Use skill-creator
[ ] Does hook need dedicated agent? -> Use agent-creator
[ ] Does hook need testing workflow? -> Create workflow
[ ] Should hook be enabled by default? -> Update config.yaml
[ ] Does hook interact with other hooks? -> Document in README.md
[ ] Run post-creation validation -> node .claude/tools/cli/validate-integration.cjs .claude/hooks/<category>/<hook-name>.cjs
These rules are INVIOLABLE. Breaking them causes silent failures.
1. NO HOOK WITHOUT validate() EXPORT
- Every hook MUST export validate() function
- Hooks without validate() cannot be called programmatically
2. NO HOOK WITHOUT main() FOR CLI
- Every hook MUST have main() for CLI execution
- Run only when require.main === module
3. NO HOOK WITHOUT ENFORCEMENT CONTROLS
- Support 'block|warn|off' via environment variable
- Default to 'warn' unless explicitly required to block
- Never crash on malformed input
4. NO HOOK WITHOUT ERROR HANDLING
- Wrap JSON.parse in try/catch
- Handle missing parameters gracefully
- Return valid: true when unsure (fail open, not closed)
5. NO HOOK WITHOUT TEST FILE
- Every hook needs <hook-name>.test.cjs
- Test valid, invalid, and edge cases
6. NO HOOK WITHOUT DOCUMENTATION
- Add to .claude/hooks/README.md
- Document trigger, behavior, exit codes
7. CROSS-PLATFORM PATHS
- Use path.join() not string concatenation
- Handle both / and \ path separators
- Use path.normalize() for comparison
8. NO CREATION WITHOUT SYSTEM IMPACT ANALYSIS
- Check if hook requires settings.json registration
- Check if hook requires config.yaml registration
- Update @HOOK_AGENT_MAP.md with new hook row (MANDATORY)
- Update affected agents' Enforcement Hooks sections (MANDATORY)
- Check if related hooks need updating
- Document all system changes made
9. IRON LAW I: PRE-TOOL HOOKS MUST VALIDATE AGAINST JSON SCHEMA
- PreToolUse hooks MUST compile and validate input against the companion
schemas/input.schema.json using AJV or equivalent before allowing execution
- Pattern: compile(schema) → validate(input) → exit 2 on schema failure
- Never block (exit 2) on schema-load errors — fail open, not closed
- Search: site:github.com "preToolUse" "ajv" "validate" filetype:cjs
10. IRON LAW III: POST-TOOL HOOKS MUST EMIT OBSERVABILITY EVENTS
- PostToolUse hooks MUST append a structured JSON line to
.claude/context/runtime/tool-events.jsonl via the centralized emitter:
const { sendEvent } = require('.claude/tools/observability/send-event.cjs')
- Required fields: tool_name, agent_id, session_id, outcome, timestamp
- Never crash on emit failure (try/catch, fail open)
- Inspect events: node .claude/tools/observability/send-event.cjs --tail 20
.claude/hooks/{category}/ (safety, routing, memory, session, validation, audit).claude/hooks/{category}/{name}.test.cjs (co-located with hooks)tests/ (integration tests for hooks).claude/docs/.claude/hooks/README.md.claude/docs/@*.mdThis skill outputs to: .claude/hooks/<category>/
Categories:
safety/ - Safety validators (command validation, security checks, shell security)routing/ - Router enforcement hooksmemory/ - Memory management hookssession/ - Session lifecycle hooksvalidation/ - Input/output validation hooks.claude/docs/FILE_PLACEMENT_RULES.md.claude/docs/DEVELOPER_WORKFLOW.md.claude/docs/ARTIFACT_NAMING.mdFile placement is enforced by file-placement-guard.cjs hook.
Invalid placements will be blocked in production mode.
Before creating a hook:
cat .claude/context/memory/learnings.md
Check for:
After completing:
.claude/context/memory/learnings.md.claude/context/memory/issues.md.claude/context/memory/decisions.mdASSUME INTERRUPTION: Your context may reset. If it's not in memory, it didn't happen.
This creator skill is part of a coordinated creator ecosystem. Any artifact created here must align with and validate against related creators:
agent-creator for ownership and execution pathsskill-creator for capability packaging and assignmenttool-creator for executable automation surfaceshook-creator for enforcement and guardrailsrule-creator and semgrep-rule-creator for policy and static checkstemplate-creator for standardized scaffoldsworkflow-creator for orchestration and phase gatingcommand-creator for user/operator command UXBefore completion, verify all relevant handshakes:
.claude/CLAUDE.md and related routing docs.validate-integration.cjs passes for the created artifact.For new patterns, templates, or workflows, research is mandatory:
mcp__Exa__web_search_exa({ query: '<topic> 2025 best practices' })mcp__Exa__get_code_context_exa({ query: '<topic> implementation examples' })mcp__Exa__web_search_exa({ query: 'site:arxiv.org <topic> 2024 2025' })WebFetch({ url: 'https://arxiv.org/search/?query=<topic>&searchtype=all&start=0' })arXiv is mandatory (not fallback) when topic involves: AI agents, LLM evaluation, orchestration, memory/RAG, security, static analysis, or any emerging methodology.
Run the shared evaluation framework to verify hook quality:
node .claude/skills/skill-creator/scripts/eval-runner.cjs --skill hook-creator
Grader assertions for hook artifacts:
0 (allow) or 2 (block) only; exit 1 is never used (treated as error, not block per SE-03)process.exit(2) on errors); advisory and PostToolUse hooks are fail-open (process.exit(0) on errors)try/catch; unexpected errors exit 0 (non-critical) or 2 (security-critical) — never crash without an exit code.claude/settings.json and documented in @ENFORCEMENT_HOOKS.mdSee .claude/skills/skill-creator/EVAL_WORKFLOW.md for full evaluation protocol and grader/analyzer agent usage.
tools
Comprehensive biosignal processing toolkit for analyzing physiological data including ECG, EEG, EDA, RSP, PPG, EMG, and EOG signals. Use this skill when processing cardiovascular signals, brain activity, electrodermal responses, respiratory patterns, muscle activity, or eye movements. Applicable for heart rate variability analysis, event-related potentials, complexity measures, autonomic nervous system assessment, psychophysiology research, and multi-modal physiological signal integration.
tools
Comprehensive toolkit for creating, analyzing, and visualizing complex networks and graphs in Python. Use when working with network/graph data structures, analyzing relationships between entities, computing graph algorithms (shortest paths, centrality, clustering), detecting communities, generating synthetic networks, or visualizing network topologies. Applicable to social networks, biological networks, transportation systems, citation networks, and any domain involving pairwise relationships.
data-ai
Molecular featurization for ML (100+ featurizers). ECFP, MACCS, descriptors, pretrained models (ChemBERTa), convert SMILES to features, for QSAR and molecular ML.
development
Run Python code in the cloud with serverless containers, GPUs, and autoscaling. Use when deploying ML models, running batch processing jobs, scheduling compute-intensive tasks, or serving APIs that require GPU acceleration or dynamic scaling.