ClaudeSuperPower
P

PreToolUse (mcp__cockroachdb-toolbox__cockroachdb-execute-sql)

Hook

Fires on

PreToolUsematchingmcp__cockroachdb-toolbox__cockroachdb-execute-sql

Immediately before a tool runs — this is where an action can be denied.

Where this sits in a session

  1. Session start
  2. Prompt submitted
  3. Prompt expansion
  4. Before tool use
  5. After tool use
  6. Notification
  7. Before compaction
  8. Subagent finished
  9. Turn finished
  10. Session end

Can blockThis hook is able to deny the action or send Claude back to work.

What it runs

Executed automatically when the event fires — no prompt, no confirmation.

command· timeout 10s
python3 -c 'import sys, os, runpy; p = os.path.normpath(r"${CLAUDE_PLUGIN_ROOT}/scripts/validate-sql.py"); p = ("\\?\\" + p) if os.name == "nt" else p; runpy.run_path(p, run_name="__main__")'; exit 0

Install it yourself

Paste into .claude/settings.json to run this hook without installing the whole plugin. Adjust the paths to point at your own copy of the scripts.

settings.json
{
  "hooks": {
    "PreToolUse": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python3 -c 'import sys, os, runpy; p = os.path.normpath(r\"${CLAUDE_PLUGIN_ROOT}/scripts/validate-sql.py\"); p = (\"\\\\?\\\\\" + p) if os.name == \"nt\" else p; runpy.run_path(p, run_name=\"__main__\")'; exit 0",
            "timeout": 10
          }
        ],
        "matcher": "mcp__cockroachdb-toolbox__cockroachdb-execute-sql"
      }
    ]
  }
}

Source

Read this before installing — it runs on your machine with your permissions.

#!/usr/bin/env python3
"""Pre-execution SQL validation for CockroachDB.
Blocks dangerous patterns before they reach the database.
Receives JSON on stdin from Claude Code PreToolUse hook.
Exit 0 = allow, exit 2 = block.
"""

import json
import re
import sys


def main():
    try:
        data = json.load(sys.stdin)
    except (json.JSONDecodeError, EOFError):
        sys.exit(0)

    tool_input = data.get("tool_input", {})
    sql = tool_input.get("sql", "") or tool_input.get("statement", "")
    if not sql:
        sys.exit(0)

    sql_upper = sql.upper()

    # Block DROP DATABASE
    if re.search(r"DROP\s+DATABASE", sql_upper):
        json.dump({
            "hookSpecificOutput": {
                "hookEventName": "PreToolUse",
                "permissionDecision": "deny",
                "permissionDecisionReason":
                    "DROP DATABASE is blocked by CockroachDB plugin safety hook. "
                    "Use DROP TABLE for individual tables instead."
            }
        }, sys.stdout)
        sys.exit(0)

    # Block TRUNCATE (data loss risk)
    if re.search(r"^\s*TRUNCATE\s", sql_upper, re.MULTILINE):
        json.dump({
            "hookSpecificOutput": {
                "hookEventName": "PreToolUse",
                "permissionDecision": "deny",
                "permissionDecisionReason":
                    "TRUNCATE is blocked by CockroachDB plugin safety hook. "
                    "Use DELETE with a WHERE clause for targeted row removal."
            }
        }, sys.stdout)
        sys.exit(0)

    # Warn about SERIAL (anti-pattern — causes hotspots)
    if re.search(r"\b(SERIAL|BIGSERIAL)\b", sql_upper):
        json.dump({
            "systemMessage":
                "WARNING: SERIAL/BIGSERIAL creates sequential IDs that cause write "
                "hotspots in CockroachDB. Use UUID with gen_random_uuid() instead: "
                "id UUID PRIMARY KEY DEFAULT gen_random_uuid()"
        }, sys.stdout)
        sys.exit(0)

    # Warn about multiple DDL in one transaction
    ddl_count = len(re.findall(
        r"(CREATE|ALTER|DROP)\s+(TABLE|INDEX|VIEW|SEQUENCE|TYPE|SCHEMA)",
        sql_upper
    ))
    if ddl_count > 1:
        json.dump({
            "systemMessage":
                "WARNING: Multiple DDL statements detected. CockroachDB supports "
                "only one DDL per transaction. Split into separate statements or "
                "use SET autocommit_before_ddl = true."
        }, sys.stdout)
        sys.exit(0)

    sys.exit(0)


if __name__ == "__main__":
    main()

Shipped by 1 plugin

Installing any of these installs this hook.

Reviews

Log in to leave a review.

No reviews yet — be the first.

Explore related

Other things in this space — across every part of the ecosystem, not just hooks.