Skip to main content

hook-creator

Create new Claude Code lifecycle hook (PreToolUse/PostToolUse/Stop/SessionStart) with bash + hooks.json. Triggers: create hook, lifecycle hook, PreToolUse, PostToolUse, hook event.

Informations de source

Dépôt
softspark/ai-toolkit
Dernière activité de la source
23 septembre 2026 à 08:05
Langue détectée de SKILL.md
anglais
Étoiles
177
Forks
21

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
hook-creator
description
Create new Claude Code lifecycle hook (PreToolUse/PostToolUse/Stop/SessionStart) with bash + hooks.json. Triggers: create hook, lifecycle hook, PreToolUse, PostToolUse, hook event.
effort
high
disable-model-invocation
true
argument-hint
[hook event or description]
allowed-tools
Read, Write, Edit, Bash, Grep, Glob
# Hook Creator $ARGUMENTS Create a new Claude Code hook following ai-toolkit conventions. ## Supported Hook Events ### Core lifecycle | Event | Fires When | Matcher | Typical Use | |-------|-----------|---------|-------------| | `SessionStart` | Session begins, resumes, or clears | `startup\|resume\|clear` | Context injection, rules reminder | | `SessionEnd` | Session is closing | any | Flush logs, save transcripts | | `UserPromptSubmit` | User submits a prompt | any | Prompt governance, usage tracking | | `Notification` | Claude sends a notification | any | OS alerts, Slack pings | | `MessageDisplay` | Assistant message text streams in completed-line batches | none | Return `displayContent` to replace the rendered batch without changing the transcript | ### Tool lifecycle | Event | Fires When | Matcher | Typical Use | |-------|-----------|---------|-------------| | `PreToolUse` | Before a tool executes | tool name (e.g. `Bash`) or `if:` rule | Safety guards, validation, `"defer"` for headless | | `PostToolUse` | After a tool executes | tool name | Feedback loops, logging, format-on-save | | `PostToolUseFailure` | After a tool fails | tool name | Failure telemetry, recovery hints | | `PostToolBatch` | After a batch of tool calls completes | any | Batch summaries, aggregate validation | ### Turn lifecycle | Event | Fires When | Matcher | Typical Use | |-------|-----------|---------|-------------| | `Stop` | Claude finishes responding | any | Quality checks, session save | | `StopFailure` | Turn ends due to an API error (rate limit, auth) | any | Alerting, fallback behavior | | `UserPromptExpansion` | Claude expands or rewrites a submitted prompt | any | Prompt policy and context shaping | ### Subagent lifecycle | Event | Fires When | Matcher | Typical Use | |-------|-----------|---------|-------------| | `SubagentStart` | Subagent launches | any | Observability | | `SubagentStop` | Subagent completes | any | Result validation | ### Compaction | Event | Fires When | Matcher | Typical Use | |-------|-----------|---------|-------------| | `PreCompact` | Before context compaction; can block with exit 2 or `{"decision":"block"}` | any | Context preservation | | `PostCompact` | After compaction completes | any | Re-inject state that was summarized away | ### Model changes | Event | Fires When | Matcher | Typical Use | |-------|-----------|---------|-------------| | `PreModelSwitch` | Before a user/client model switch; exit 2 or `decision: "block"` cancels it | canonical target model | Model policy; requires Claude Code 2.1.251+ | | `PostModelSwitch` | After the session model changes; cannot block | canonical target model | Model-specific context; requires Claude Code 2.1.251+ | ### Permissions & elicitation | Event | Fires When | Matcher | Typical Use | |-------|-----------|---------|-------------| | `PermissionRequest` | Tool awaiting permission; can return `updatedInput` | any | Headless approval flows | | `PermissionDenied` | Auto-mode classifier denied a tool call; return `{retry: true}` to allow retry | any | Coach the model, log denials | | `Elicitation` | MCP `elicitation/create` request arrives | any | Intercept / override MCP UI prompts | | `ElicitationResult` | Elicitation response ready to be sent back | any | Validate / transform elicitation replies | ### Agent Teams | Event | Fires When | Matcher | Typical Use | |-------|-----------|---------|-------------| | `TaskCreated` | New task registered via `TaskCreate` | any | Audit, assignment routing | | `TaskCompleted` | Agent Teams task finished | any | Lint, type check, notify | | `TeammateIdle` | Agent Teams member idle | any | Completeness reminder | ### Worktrees & environment | Event | Fires When | Matcher | Typical Use | |-------|-----------|---------|-------------| | `WorktreeCreate` | Worktree is being created; `type: "http"` can return `hookSpecificOutput.worktreePath` | any | Provision worktree dirs | | `WorktreeRemove` | Worktree is being removed | any | Cleanup | | `CwdChanged` | Working directory changes during a session | any | Reactive env management (e.g., direnv) | | `DirectoryAdded` | A working directory was added with `/add-dir` or SDK `register_repo_root`; runs asynchronously after the add and cannot block it | `slash_command\|register_repo_root` | Prepare a newly added repository | | `FileChanged` | Tracked file is modified on disk | any | Re-lint, reload config | | `ConfigChange` | Settings / config file changed | any | Re-validate, warn on drift | ### Setup / bootstrap | Event | Fires When | Matcher | Typical Use | |-------|-----------|---------|-------------| | `Setup` | First-run / initialization | any | Project bootstrap | | `InstructionsLoaded` | CLAUDE.md or `.claude/rules/*.md` loaded into context | load reason | Verify presence of mandatory rules | ## Hook Handler Types Claude Code supports five handler `type` values in `hooks.json`: | Type | Purpose | Required fields | |------|---------|-----------------| | `command` | Run a shell script / binary | `command` (path + args) | | `http` | Call a local or remote HTTP endpoint | `url` | | `prompt` | Inject a prompt to the fast inline model and use its verdict | `prompt` | | `agent` | Spawn an experimental tool-using subagent to evaluate the event | `prompt` | | `mcp_tool` | Invoke an already-connected MCP tool | `server`, `tool`; optional `input` object | `command` remains the default and ai-toolkit's hook entries all use it. The other types are documented here so you can author them by hand when needed. `PermissionRequest` accepts `prompt` hooks but skips `agent` hooks. Both model-switch events accept `command`, `http`, and `mcp_tool` only. MCP tool hooks use `input` for arguments; `arguments` is not a supported handler field. MCP hooks on `SessionStart` cannot run at launch before servers connect, and `Setup` always skips them. Use command hooks for required initialization. Source: https://code.claude.com/docs/en/hooks (reviewed 2026-09-23). ## Workflow 1. **Capture intent** -- ask: what should the hook do? Which lifecycle event? 2. **Select event** -- pick from the Supported Hook Events table above 3. **Define matcher** -- tool name for PreToolUse/PostToolUse, empty for global 4. **Write script** -- create `app/hooks/{event-name-kebab}.sh` 5. **Register in hooks.json** -- add entry to `app/hooks.json` 6. **Validate** -- run `scripts/validate.py` ## Hook Script Conventions - Location: `app/hooks/{event-name-kebab}.sh` - Shebang: `#!/bin/bash` - Header comment: script name, purpose, event, matcher - Respect `TOOLKIT_HOOK_PROFILE` env var (`minimal` = skip non-essential hooks) - Exit 0 on success; use exit 2 for a blocking verdict on supported events. Other non-zero codes generally report an error without blocking. - Output goes to Claude's context as plain text - No external dependencies -- bash builtins and coreutils only - Keep output concise -- hooks fire frequently ## hooks.json Entry Format ```json { "_source": "ai-toolkit", "matcher": "", "hooks": [ { "type": "command", "command": "\"$HOME/.softspark/ai-toolkit/hooks/{script-name}.sh\"" } ] } ``` Required fields: - `_source`: always `"ai-toolkit"` (used by merge/strip logic) - `matcher`: tool name or regex for Pre/PostToolUse, empty string for global events - `hooks[].type`: `"command"`, `"http"`, `"prompt"`, `"agent"`, or `"mcp_tool"` (ai-toolkit uses `"command"`) - `hooks[].command`: path to script using `$HOME/.softspark/ai-toolkit/hooks/` prefix (for `type: command`) Optional fields (read from Claude Code docs, not emitted by ai-toolkit by default): Common to every handler type: - `hooks[].if`: one permission-rule filter (e.g. `"Bash(git push*)"`); evaluated only for tool events - `hooks[].timeout`: seconds to wait before canceling the handler (type and event defaults apply if omitted) - `hooks[].statusMessage`: short message surfaced in the UI while the hook runs - `hooks[].once`: run once per session; only honored in skill frontmatter and ignored in settings files or agent frontmatter Command-handler fields: - `hooks[].args`: argument vector for exec form. Prefer exec form when a command uses `${CLAUDE_PROJECT_DIR}`, `${CLAUDE_PLUGIN_ROOT}`, or `${CLAUDE_PLUGIN_DATA}` path placeholders - `hooks[].async`: run in the background without blocking; background hooks cannot return decisions - `hooks[].asyncRewake`: run in the background and wake Claude on exit code 2; implies `async` - `hooks[].shell`: choose `bash` or `powershell` for shell form; ignored when `args` selects exec form Prompt and agent handlers both require `hooks[].prompt`; `type: agent` does not accept an agent name field. Agent handlers are experimental, so prefer `command` for production enforcement. `MessageDisplay` has no matcher, runs once per rendered batch in interactive sessions, and defaults to a 10-second timeout. Its `displayContent` output changes only the screen text; Claude and the transcript retain the original response. `DirectoryAdded` is always asynchronous and non-blocking regardless of the handler configuration. ## Script Template ```bash #!/bin/bash # {script-name}.sh — {One-line purpose}. # # Fires on: {EventName} # Matcher: {matcher or "all"} # Skipped when TOOLKIT_HOOK_PROFILE=minimal. PROFILE="${TOOLKIT_HOOK_PROFILE:-standard}" [ "$PROFILE" = "minimal" ] && exit 0 # --- Hook logic here --- exit 0 ``` ## Rules - **MUST** use one script per hook entry — no inline multi-line commands inside `hooks.json` - **MUST** keep `Pre*` hooks fast and deterministic — they gate every matching tool call, slow hooks throttle the whole agent - **NEVER** write secrets, tokens, or credentials to stdout — hook output is injected into LLM context and can be extracted - **NEVER** exit non-zero from a `Post*` or `Stop` hook unless you intend to block further processing; exit 0 is the safe default - **CRITICAL**: respect the `TOOLKIT_HOOK_PROFILE` env var. Profile `minimal` must be a no-op for non-essential hooks. - **MANDATORY**: test the script standalone (`bash app/hooks/{name}.sh`) before adding it to `hooks.json` ## Gotchas - `PreToolUse` hooks that exit non-zero **block** the tool call. A slow or flaky hook (network call, lock contention) becomes a DoS against Claude's own workflow. Keep Pre hooks to pure-bash checks of local state. - Hook output (stdout) is injected verbatim into the model's context. A hook that runs `git log --all` prints hundreds of lines the model then has to wade through — be surgical, print only what matters. - The path in `hooks.json` is resolved relative to the user's machine, not the ai-toolkit repo. Use `$HOME/.softspark/ai-toolkit/hooks/<name>.sh` as the canonical location (installer symlinks there). - `SessionStart` with matcher `startup|compact` fires on both fresh starts AND after context compaction. Hooks that assume "new session" will mis-fire after compaction — check for explicit context markers if the distinction matters. - Bash hooks on Windows (without WSL) will not run. If the hook must work cross-platform, wrap it in a Node or Python script and call from the bash stub — or flag the hook as `posix-only` in the description. ## Validation Checklist After creating the hook: - [ ] Script exists in `app/hooks/` and is executable (`chmod +x`) - [ ] Entry added to `app/hooks.json` with `_source: "ai-toolkit"` - [ ] Event name matches a supported lifecycle event - [ ] `scripts/validate.py` passes - [ ] Script runs without errors: `bash app/hooks/{name}.sh` - [ ] Hook count in README.md and docs updated if needed ## When NOT to Use - For a **skill** (slash command) — use `/skill-creator` - For an **agent** definition — use `/agent-creator` - For a git pre-commit hook (not a Claude Code hook) — use `/git-mastery` or `scripts/install_git_hooks.py` - For one-off automation that is not tied to a Claude Code event — use a plain shell script outside the toolkit - To modify an existing toolkit hook — edit the file directly; this skill is create-only
Voir sur GitHub