Documentation

Everything you need to know about installing and authoring Claude Code hooks.

Getting Started

What is cc-hooks-install?

A CLI tool that installs Claude Code hooks from any GitHub repository with one command. Hooks are guardrails that run before or after Claude executes a tool — they can block destructive commands, auto-format code, log actions, and more.

How do I install hooks?

Run the CLI with the GitHub repo path:

$ npx cc-hooks-install add owner/repo

For hook collections hosted in subdirectories:

$ npx cc-hooks-install add owner/repo/path/to/hooks

An interactive prompt lets you select which hooks to install. Selected hooks are merged into your ~/.claude/settings.json. Existing hooks are preserved — nothing gets overwritten.

What gets installed?

Hook entries are added to your Claude Code settings.json under the appropriate event (e.g., PreToolUse, PostToolUse, Stop). Each hook is a shell command that Claude Code runs at that event. No binaries, no daemons — just JSON config.

Does it work with other AI agents?

Hooks are a Claude Code feature. Other agents (Cursor, Copilot, Windsurf) don't currently support the same hook system. If they adopt a similar format in the future, this tool could be extended to support them.

How Hooks Work

What is a PreToolUse hook?

A command that runs before Claude executes a tool (like Bash, Write, or Edit). The hook receives the tool input as JSON on stdin. If the hook outputs a JSON object with "decision": "block", Claude is prevented from running the command.

What is a PostToolUse hook?

A command that runs after a tool succeeds. Common use: auto-formatting files after Claude writes them. The hook receives both the tool input and response on stdin.

How does blocking work?

A typical safety hook extracts the command, checks it against a pattern, and returns a block decision if it matches:

jq -r '.tool_input.command' | {
  read -r cmd
  if echo "$cmd" | grep -qE 'rm -rf'; then
    echo '{"decision":"block","reason":"BLOCKED: rm -rf detected"}'
  fi
}

Can hooks slow down Claude?

Hooks run simple shell commands (jq + grep) that complete in milliseconds. You won't notice them. If a hook hangs, Claude Code enforces a timeout.

Authoring Hooks

How do I create my own hook package?

Add a claude-hooks.json to your GitHub repo root (or any subdirectory):

{
  "name": "my-tool",
  "description": "Safety hooks for my CLI tool",
  "author": "your-username",
  "version": "1.0.0",
  "hooks": [
    {
      "name": "Block write operations",
      "description": "Prevents write commands without approval",
      "default": true,
      "event": "PreToolUse",
      "matcher": "Bash",
      "hook": {
        "type": "command",
        "command": "your hook command here"
      }
    }
  ]
}

What fields are required?

Field Required Description
name Yes Package name
description Yes What these hooks do
author Yes GitHub username
version Yes Semver version
hooks[] Yes Array of hook definitions
hooks[].name Yes Human-readable hook name
hooks[].event Yes PreToolUse, PostToolUse, Stop, etc.
hooks[].matcher Yes Tool name (Bash, Write|Edit, etc.)
hooks[].hook Yes The hook object (type + command)
hooks[].default No Pre-selected in prompt (default: true)

How do users find my hooks?

When someone installs hooks from your repo, it's automatically registered in the directory. No submission process needed — just add a claude-hooks.json and share the install command.

Can I put hooks in a subdirectory?

Yes. The CLI supports subpaths:

$ npx cc-hooks-install add owner/repo/path/to/hooks

The CLI looks for claude-hooks.json at that path. This lets you host multiple hook collections in one repo.

FAQ

Will this overwrite my existing hooks?

No. Hooks are appended to your existing configuration. If a hook with the same command already exists, it's skipped. Your settings.json is never replaced — only merged.

How do I remove a hook?

Open ~/.claude/settings.json and remove the hook entry from the hooks object. Or use /hooks in Claude Code to view and manage your hooks.

Does the CLI collect data?

After a successful install, the CLI sends the repo name to the directory API so it appears on this site. No personal data, device info, or hook content is sent — just the repo path (e.g., sieteunoseis/spok-api). This is fire-and-forget and never blocks the install.

To opt out, use either:

$ npx cc-hooks-install add owner/repo --no-telemetry $ CC_HOOKS_NO_TELEMETRY=1 npx cc-hooks-install add owner/repo

Does it require authentication?

No. The CLI fetches from public GitHub repos using raw.githubusercontent.com. No GitHub token needed. Private repos are not supported in v1.

Where do I report issues?

Open an issue on GitHub.