agentsclimarketplace

Ref sp agents hooks

Skill swiftpostlabs/agentic-tools/.agents/skills/ref-sp-agents-hooks

Shareable skills and tools for AI agents

Install
npx -y skills add swiftpostlabs/agentic-tools --skill ref-sp-agents-hooks

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Author agent lifecycle hooks that run deterministic shell commands at session, prompt, tool, and stop events across Claude Code, GitHub Copilot CLI, VS Code, and Gemini CLI. Use when: creating or editing a hook, choosing a lifecycle event, writing a hook script that reads stdin JSON and returns an allow/deny/context decision, making a hook portable across agents, or debugging why a hook does not fire or block.

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

11.7 KB, as published. Nobody here has run it

Agent Hooks

Purpose

Give the agent portable defaults for authoring lifecycle hooks -- shell commands that run automatically at agent events -- so the shared input/output contract lives in one place and only the per-service specifics (event names, config location, field names) are looked up per platform.

When to use this skill

  • Creating or editing a hook for any agent CLI or IDE.
  • Deciding which lifecycle event a behavior should attach to.
  • Writing a hook script that reads a JSON event on stdin and returns a decision.
  • Making one hook work across more than one agent platform.
  • Debugging why a hook does not fire, does not block, or breaks output parsing.

Scope Boundaries

  • This skill centers on command (shell) hooks, the one type every platform supports. Non-command types (http, mcp_tool, prompt, agent) are noted per platform in the references.
  • For the config location, event vocabulary, and payload field names of one platform, read that platform's reference file.
  • This skill is not about MCP servers, skills, or subagents themselves.
  • For repo instruction files (AGENTS.md, GEMINI.md, .claude/CLAUDE.md), use the repo's instruction-authoring skill (ref-sp-agents-instructions-authoring here).
  • When a hook reads or guards protected/secret files, use the repo's agent-security skill (ref-sp-agents-security here).

Mental Model

A hook is a triple: (event, matcher, command). At a lifecycle event, the agent runs your command, passes a JSON event payload on stdin, and interprets the command's exit code plus stdout as a decision. Hooks are deterministic: unlike asking the model to "remember to run the linter," a hook always fires.

The one contract that holds on all four platforms:

  • Input: the event payload arrives as JSON on stdin.
  • Diagnostics: human/debug text goes to stderr, never stdout.
  • Decision: carried by the exit code plus JSON on stdout.

The Exit-Code Contract

This is identical enough across platforms to memorize once:

Exit codeMeaningEffect
0Successstdout is parsed as a JSON decision/context object (empty stdout = no-op)
2Block / denyAction is blocked where the event supports it; stderr becomes the reason shown to the agent
other non-zeroNon-blocking errorLogged as a warning; the run continues

Critical corollary: exit 1 does not block. To stop a tool call or a turn you must use exit 2 (or the platform's JSON deny decision), not 1. This is the single most common hook mistake.

Platform caveat: Copilot CLI preToolUse fails closed (a crash/non-zero exit denies the tool call) but fails open on timeout. See ./references/platforms/copilot-cli-hooks.md.

The stdout Rule

stdout is a structured channel. Print only JSON (or nothing) to it. Any stray echo/print on stdout can corrupt parsing -- Gemini CLI explicitly falls back to "allow" when stdout is not valid JSON, and the others may mis-handle it. Send every log line, progress note, and error message to stderr.

Shared Lifecycle

Map behavior to a lifecycle moment first, then look up the event name per platform in ./references/platform-matrix.md. The moments that exist almost everywhere:

MomentWhat you can do hereCommon names
Session startInject context, validate setupSessionStart (Gemini/Claude/VS Code/Copilot)
Prompt submittedAudit, add context, block promptUserPromptSubmit / BeforeAgent (Gemini)
Before tool useAllow / deny / rewrite a tool callPreToolUse / BeforeTool (Gemini)
After tool useFormat, lint, log, inject follow-up contextPostToolUse / AfterTool (Gemini)
Turn ends (stop)Force another turn, run reportsStop / AfterAgent (Gemini)
Before compactionSave/export contextPreCompact / PreCompress (Gemini)

PreToolUse and PostToolUse are where most real hooks live: gate dangerous commands, and format/validate after edits.

Core Authoring Workflow

  1. Pick the moment and the decision. What lifecycle point, and do you need to observe, add context, or block/modify?
  2. Resolve the event name per target platform from ./references/platform-matrix.md.
  3. Choose the hook type. Default to command. Reach for http/prompt/agent/mcp_tool only when the platform supports it and the job needs it.
  4. Write the script to the portable contract (read stdin JSON, branch, emit exit code + JSON on stdout). Start from ./assets/portable-hook.sh.
  5. Scope it with a matcher on the tool/event, but also guard inside the script (VS Code ignores matchers -- every hook fires).
  6. Place the config in the correct file for each platform (see each platform reference).
  7. Dry-run: pipe a sample payload into the script and confirm exit code + stdout before wiring it up.
  8. Validate blocking: trigger the real event and confirm it actually allows/denies as intended.

Portability Rules

When one hook must serve multiple agents:

  • Read fields defensively. Payload keys differ: snake_case (tool_name, tool_input) on Claude/Gemini/VS Code vs camelCase (toolName, toolArgs) on Copilot CLI's native form. Copilot and VS Code also accept the Claude PascalCase form. Probe both spellings.
  • Do not key on one tool name. The same action has different tool names per platform (Claude Write/Edit vs VS Code create_file/replace_string_in_file). Match on intent, or match broadly and re-check inside the script.
  • timeout units differ. Seconds on Claude, Copilot, and VS Code; milliseconds on Gemini CLI.
  • Matchers are not uniform. Regex is anchored as ^(?:PATTERN)$; VS Code ignores matchers entirely, so filter in-script.
  • Project-root env vars differ. CLAUDE_PROJECT_DIR (Claude), GEMINI_PROJECT_DIR (Gemini, plus a CLAUDE_PROJECT_DIR compatibility alias). Resolve a root with a fallback rather than hardcoding paths.
  • Config shape differs. Claude and Gemini nest { "matcher", "hooks": [ ... ] }; Copilot CLI and VS Code use flat hook entries. See the references.
  • Reuse across Claude-family tools. Copilot CLI and VS Code both read Claude-format PascalCase events (and VS Code even reads .claude/settings.json), so one config often covers all three. Gemini uses a distinct vocabulary (BeforeTool/AfterTool/BeforeAgent) and needs its own.

Security

Hooks run arbitrary shell with your full user permissions, automatically, without a confirmation each time. Treat every hook as production code.

  • Never trust tool_input as shell. Quote it, avoid eval, and match against allowlists rather than interpolating raw values into commands.
  • Never echo or persist secrets. Do not inline tokens in config; use the platform's env/allowedEnvVars to pass them, and keep them off stdout/stderr and logs.
  • Use project-rooted, validated paths. Guard against path traversal before reading or writing.
  • Fail safe. Prefer explicit deny (exit 2 / permissionDecision: deny) over silent pass when a check errors -- but know each event's fail-open vs fail-closed default.
  • Be fast and idempotent. Hooks run inline with the agent; slow hooks stall it and can hit the timeout.
  • Review shared hooks before enabling. Repo-committed and plugin hooks execute on your machine; read them first.

Task Framing

ActionWhatWhyWhenExpected outcome
Choose the lifecycle momentMap the behavior to a shared moment before picking a nameNames differ per platform; the moment is stableAt the start of every hookThe hook attaches to the right event on each target
Write to the exit-code contractEmit exit 0/2 + JSON stdout, diagnostics to stderrWrong exit code (e.g. 1) silently fails to blockWhenever the hook must gate or modifyBlocking and context injection behave as intended
Guard inside the scriptRe-check tool/args in-script, not only via matcherVS Code ignores matchers; payloads varyAny cross-platform or gating hookThe hook only acts on the cases it should
Dry-run with a sample payloadPipe fixture JSON to the script and inspect outputCatches parsing/exit-code bugs before they hit a sessionBefore committing or enabling a hookVerified exit code and JSON shape

Gotchas

  • Exit 1 is not a block. Use exit 2 (or a JSON deny) to stop an action.
  • stdout must be JSON-only. Route logs to stderr or you corrupt the decision parse (Gemini defaults to allow on invalid stdout).
  • VS Code ignores matchers -- every configured hook fires; filter in the script.
  • Gemini timeout is milliseconds, unlike the second-based platforms.
  • Copilot preToolUse fails closed on crash, open on timeout -- a slow hook silently lets the call through.
  • Payload casing varies (snake_case vs camelCase) and tool names vary across platforms.
  • No controlling terminal. Claude hooks cannot use /dev/tty; for desktop alerts use the platform's notification mechanism, not an interactive prompt.

References

  • Read ./references/platform-matrix.md first to translate a lifecycle moment into the event name and config shape for each platform.
  • Read ./references/platforms/claude-code-hooks.md for Claude Code (.claude/settings.json, nested config, hook types, JSON decision fields).
  • Read ./references/platforms/copilot-cli-hooks.md for GitHub Copilot CLI (.github/hooks/*.json, camel/Pascal duality, fail-closed preToolUse).
  • Read ./references/platforms/vscode-hooks.md for VS Code agent hooks (ignored matchers, OS-specific command overrides, Claude-format compatibility).
  • Read ./references/platforms/gemini-cli-hooks.md for Gemini CLI (.gemini/settings.json, distinct event vocabulary, millisecond timeouts).
  • Read ./references/checklist.md for a quick review pass before committing a hook.
  • Read the repo's agent-security skill (ref-sp-agents-security here) when a hook touches protected files, secrets, or exclusion rules.

Assets

  • ./assets/portable-hook.sh is a starter command hook that reads stdin JSON, reads a field under both snake_case and camelCase spellings, and returns an allow/deny decision. Adapt it per platform.
  • ./assets/git-identity-guard.sh is a worked PreToolUse example: it blocks a git commit when the repo's configured author identity does not match the account its origin remote points at -- the common multi-identity failure where an unset local user.email silently commits under the global identity. Edit its rules table to your own accounts.
  • ./assets/trigger-eval-queries.example.json holds should-trigger / should-not-trigger prompts for checking this skill's activation.

Validation

  • Confirm the event name is valid for each target platform (./references/platform-matrix.md).
  • Confirm stdout emits only JSON and all diagnostics go to stderr.
  • Confirm blocking uses exit 2 or the platform's deny decision, never exit 1.
  • Confirm the config sits in the right file/shape for each platform.
  • Dry-run the script against a sample payload before enabling it.
  • Review ./evals/evals.json when checking this skill's own output quality.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.