Safa API · aisafa.xyz

Claude Code Hooks: A Practical Setup Guide for Automating Your Workflow (2026)

发布于 2026-08-25 · Safa API

Claude Code hooks are shell commands defined in your settings.json that fire automatically at specific points in Claude Code's lifecycle, such as before a tool runs, after it finishes, or when a session starts. They give you deterministic control over the agent instead of hoping the model remembers to run a linter or send a notification.

Why hooks matter

Without hooks, you rely on the model to "remember" to format code, block a dangerous command, or ping you when it's stuck waiting for input. That works most of the time, but not always, and "most of the time" is not good enough when a hook could just enforce the rule every single time. Hooks move that responsibility out of the LLM and into your own scripts, which run outside the model's control and can't be talked out of executing.

Common use cases developers are shipping in 2026:

The hook lifecycle events

Claude Code exposes hook events at different stages. The ones you'll use most often:

EventFires whenTypical use
SessionStartA new Claude Code session beginsLoad project context, check API key validity
PreToolUseBefore a tool (edit, bash, etc.) executesBlock dangerous commands, require confirmation
PostToolUseAfter a tool finishesAuto-format, run linter, log token usage
NotificationClaude sends a notification (e.g. waiting for input)Push alert to phone/desktop
StopClaude finishes respondingTrigger a build, send a summary

Basic configuration

Hooks live in your user-level ~/.claude/settings.json or project-level .claude/settings.json. Each hook entry has a matcher (which tool names it applies to) and a list of hooks with the command to run:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "npx prettier --write \"$CLAUDE_TOOL_FILE_PATH\""
          }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/block-dangerous.sh"
          }
        ]
      }
    ]
  }
}

Claude Code pipes a JSON payload describing the event to your command's stdin (tool name, file path, arguments). Your script reads that JSON, decides what to do, and returns an exit code: 0 to allow the action, non-zero to block it and surface a message back to Claude.

A real example: blocking risky bash commands

A minimal block-dangerous.sh that rejects rm -rf and force pushes:

#!/bin/bash
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command // ""')
if [[ "$cmd" == *"rm -rf"* || "$cmd" == *"push --force"* ]]; then
  echo '{"decision":"block","reason":"Destructive command blocked by hook"}'
  exit 1
fi
exit 0

This runs on every single bash call, with zero chance of the model "forgetting" to check. That's the whole point of hooks: rules that used to live in a prompt now live in code that always executes.

Hooks + a cheaper API endpoint

If you're running Claude Code with a lot of hooks and automated loops (tests, formatters, notifications), your token usage goes up fast, especially with PostToolUse hooks that re-read file contents for linting context. Two things help keep costs sane:

This is where Safa API fits in if you're pointing Claude Code at a custom base URL. It's a one-endpoint relay for Claude, GPT, and Gemini models, priced below the official Anthropic/OpenAI rates, with prompt caching supported so hook-heavy workflows (lots of small repeated calls) don't rack up a huge bill. Setup is the same two environment variables Claude Code already expects:

export ANTHROPIC_BASE_URL="https://aisafa.xyz/v1"
export ANTHROPIC_API_KEY="your-safa-api-key"

No credit card is required to sign up, and Alipay is accepted for top-ups, which is a real hassle-saver if you're outside the US and Anthropic's billing has ever rejected your card. Since it's a single key across Claude, GPT, and Gemini, you can also point a PostToolUse hook's own LLM call (say, a commit-message generator) at a different model without juggling three separate API keys.

Frequently Asked Questions

Do hooks slow down Claude Code?

Slightly, since each hook is a subprocess call, but well-written hooks (a formatter, a grep check) typically add well under a second. The tradeoff is worth it for guarantees like "never write to .env" that a prompt instruction alone can't provide.

Can hooks call external APIs, like sending a Slack message?

Yes. A hook is just a shell command, so it can curl any webhook, including Slack, Telegram, or a custom endpoint, when the Notification or Stop event fires.

Do hooks work with a custom API base URL?

Yes, hooks are independent of which model provider you're using. Whether Claude Code is pointed at Anthropic directly or at a relay like Safa API via ANTHROPIC_BASE_URL, hooks fire the same way since they operate on the tool lifecycle, not the model connection.

立即开始使用 Safa API API 中转

官方直连 · 一个接口接入 Claude / GPT / Gemini · 7×24 稳定

免费注册试用 →