Security
Hook
Hooks
What rugproof runs automatically, and when. A hook is a command Claude Code fires at a fixed moment, without you asking for it.
Install
> /plugin marketplace add omermaksutii/RugProof > /plugin install rugproof@rugproof
Ships with rugproof. Installing the plugin gets these hooks.
Where it lives
- hooks/post-test-coverage.shGitHub
Read the script
#!/usr/bin/env bash # Rugproof post-test hook — analyzes coverage after `forge test` and reports gaps. # Hooks into Bash PostToolUse via plugin.json, fires when forge/hardhat test commands finish. set -euo pipefail PAYLOAD="$(cat)" COMMAND="$(echo "${PAYLOAD}" | python3 -c 'import json,sys; print(json.load(sys.stdin).get("tool_input",{}).get("command",""))' 2>/dev/null || echo "")" # Only act on test commands if ! echo "${COMMAND}" | grep -qE '(forge test|hardhat test|npm test|yarn test)'; then exit 0 fi REPO_ROOT="$(pwd)" CONFIG="${REPO_ROOT}/.rugproof.yml" if [[ ! -f "${CONFIG}" ]]; then exit 0 fi ENABLED="$(grep -A2 '^hooks:' "${CONFIG}" 2>/dev/null | grep -A1 'post_test:' | grep 'enabled:' | awk '{print $2}' || echo 'true')" if [[ "${ENABLED}" != "true" ]]; then exit 0 fi # Run coverage analysis (best-effort; non-blocking) if command -v forge >/dev/null 2>&1; then COV_OUT="$(forge coverage --report summary 2>/dev/null | tail -n 30 || echo "")" if [[ -n "${COV_OUT}" ]]; then UNDER_80="$(echo "${COV_OUT}" | awk -F'|' '$3 ~ /[0-9]/ {gsub(/%/, "", $3); if ($3+0 < 80) print " ⚠ " $2 " — " $3 "% line coverage"}' || true)" if [[ -n "${UNDER_80}" ]]; then cat >&2 <<EOF rugproof: coverage gaps detected (line < 80%): ${UNDER_80} tip: /coverage (in Claude Code) auto-generates tests for the gaps EOF fi fi fi exit 0 - hooks/pre-commit-quickscan.shGitHub
Read the script
#!/usr/bin/env bash # Rugproof pre-commit hook — runs /quick-scan on staged Solidity files. # Blocks the commit if findings at or above the configured threshold are found. # # Install: copy to .git/hooks/pre-commit, or symlink: # ln -sf "$(pwd)/hooks/pre-commit-quickscan.sh" .git/hooks/pre-commit # # Disable per-commit with: git commit --no-verify (not recommended) set -euo pipefail REPO_ROOT="$(git rev-parse --show-toplevel)" CONFIG="${REPO_ROOT}/.rugproof.yml" if [[ ! -f "${CONFIG}" ]]; then echo "rugproof: no .rugproof.yml found, skipping pre-commit scan." echo " (run /rugproof-init in Claude Code to set up.)" exit 0 fi # Read enabled flag from config (defaults to true) ENABLED="$(grep -A2 '^hooks:' "${CONFIG}" 2>/dev/null | grep -A1 'pre_commit:' | grep 'enabled:' | awk '{print $2}' || echo 'true')" if [[ "${ENABLED}" != "true" ]]; then exit 0 fi # Get staged Solidity files STAGED="$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(sol|vy)$' || true)" if [[ -z "${STAGED}" ]]; then exit 0 fi echo "rugproof: scanning $(echo "${STAGED}" | wc -l | tr -d ' ') staged file(s)…" # Invoke Claude Code with /quick-scan on the staged files. # This requires the `claude` CLI (Claude Code) to be on PATH. if ! command -v claude >/dev/null 2>&1; then echo "rugproof: 'claude' CLI not found on PATH; skipping scan." echo " install: https://claude.ai/code" exit 0 fi OUTPUT="$(echo "${STAGED}" | xargs -I {} claude code -p "/quick-scan {}" --output-format=json 2>/dev/null || echo '{"findings":[]}')" # Count findings at/above threshold THRESHOLD="$(grep '^severity_threshold:' "${CONFIG}" 2>/dev/null | awk '{print $2}' || echo 'high')" declare -A LEVEL=( [info]=0 [low]=1 [medium]=2 [high]=3 [critical]=4 ) THRESHOLD_LVL="${LEVEL[${THRESHOLD}]:-3}" # Parse JSON output for severity counts (best-effort; falls back gracefully) N_BLOCKING="$(echo "${OUTPUT}" | python3 -c ' import json, sys try: d = json.load(sys.stdin) sev_lvl = {"info":0,"low":1,"medium":2,"high":3,"critical":4} th = '"${THRESHOLD_LVL}"' print(sum(1 for f in d.get("findings",[]) if sev_lvl.get(f.get("severity","").lower(),0) >= th)) except Exception: print(0) ' 2>/dev/null || echo 0)" if [[ "${N_BLOCKING}" -gt 0 ]]; then echo echo "❌ rugproof: ${N_BLOCKING} finding(s) at or above '${THRESHOLD}' severity" echo " review: /audit (in Claude Code) for details" echo " bypass: git commit --no-verify (use only with reason)" exit 1 fi echo "✓ rugproof: no blocking findings" exit 0 - hooks/pre-deploy-check.shGitHub
Read the script
#!/usr/bin/env bash # Rugproof pre-deploy hook — runs /audit on build artifacts before deployment. # Blocks `forge create`, `hardhat run scripts/deploy.*`, etc. on Critical / High findings. # # Wired via plugin.json's PreToolUse hook on Bash. Receives JSON on stdin from Claude Code: # { "tool_name": "Bash", "tool_input": { "command": "..." } } # Should exit 0 to allow, exit 2 with stderr message to deny (Claude Code convention). set -euo pipefail # Read the hook payload PAYLOAD="$(cat)" COMMAND="$(echo "${PAYLOAD}" | python3 -c 'import json,sys; print(json.load(sys.stdin).get("tool_input",{}).get("command",""))' 2>/dev/null || echo "")" # Fast-path: only intercept commands that look like deploys if ! echo "${COMMAND}" | grep -qE '(forge create|forge script.*--broadcast|hardhat .*deploy|hardhat run.*deploy)'; then exit 0 fi REPO_ROOT="$(pwd)" CONFIG="${REPO_ROOT}/.rugproof.yml" if [[ ! -f "${CONFIG}" ]]; then exit 0 fi ENABLED="$(grep -A2 '^hooks:' "${CONFIG}" 2>/dev/null | grep -A1 'pre_deploy:' | grep 'enabled:' | awk '{print $2}' || echo 'true')" if [[ "${ENABLED}" != "true" ]]; then exit 0 fi echo "rugproof: pre-deploy check — auditing build artifacts before broadcasting…" >&2 if ! command -v claude >/dev/null 2>&1; then echo "rugproof: 'claude' CLI not found, skipping pre-deploy audit." >&2 exit 0 fi OUTPUT="$(claude code -p "/audit" --output-format=json 2>/dev/null || echo '{"findings":[]}')" THRESHOLD="$(grep -A2 '^hooks:' "${CONFIG}" 2>/dev/null | grep -A1 'pre_deploy:' | grep 'fail_on:' | awk '{print $2}' || echo 'medium')" declare -A LEVEL=( [info]=0 [low]=1 [medium]=2 [high]=3 [critical]=4 ) TH="${LEVEL[${THRESHOLD}]:-2}" N="$(echo "${OUTPUT}" | python3 -c ' import json, sys try: d = json.load(sys.stdin) sev_lvl = {"info":0,"low":1,"medium":2,"high":3,"critical":4} th = '"${TH}"' print(sum(1 for f in d.get("findings",[]) if sev_lvl.get(f.get("severity","").lower(),0) >= th)) except Exception: print(0) ' 2>/dev/null || echo 0)" if [[ "${N}" -gt 0 ]]; then cat >&2 <<EOF ❌ rugproof: pre-deploy check failed — ${N} finding(s) at/above '${THRESHOLD}' severity review: /audit (full report) override: set RUGPROOF_BYPASS_DEPLOY=1 (logged to .rugproof-bypass-log) EOF if [[ "${RUGPROOF_BYPASS_DEPLOY:-0}" == "1" ]]; then echo "$(date -u +%FT%TZ) BYPASS user=$(whoami) cmd=${COMMAND}" >> "${REPO_ROOT}/.rugproof-bypass-log" echo "rugproof: BYPASS active — proceeding with deploy" >&2 exit 0 fi exit 2 fi echo "✓ rugproof: pre-deploy audit clean" >&2 exit 0 - hooks/pre-push-audit.shGitHub
Read the script
#!/usr/bin/env bash # Rugproof pre-push hook — runs full /audit on changed files vs the upstream branch. # Blocks the push if Critical or High findings exist. # # Install: ln -sf "$(pwd)/hooks/pre-push-audit.sh" .git/hooks/pre-push set -euo pipefail REPO_ROOT="$(git rev-parse --show-toplevel)" CONFIG="${REPO_ROOT}/.rugproof.yml" if [[ ! -f "${CONFIG}" ]]; then exit 0 fi ENABLED="$(grep -A2 '^hooks:' "${CONFIG}" 2>/dev/null | grep -A1 'pre_push:' | grep 'enabled:' | awk '{print $2}' || echo 'true')" if [[ "${ENABLED}" != "true" ]]; then exit 0 fi # Determine base branch (default: main) BASE="${RUGPROOF_BASE:-main}" if ! git rev-parse --verify "${BASE}" >/dev/null 2>&1; then BASE="origin/main" fi CHANGED="$(git diff --name-only "${BASE}...HEAD" -- '*.sol' '*.vy' 2>/dev/null || true)" if [[ -z "${CHANGED}" ]]; then echo "rugproof: no Solidity/Vyper changes vs ${BASE}, skipping pre-push audit." exit 0 fi echo "rugproof: auditing $(echo "${CHANGED}" | wc -l | tr -d ' ') changed file(s) vs ${BASE}…" if ! command -v claude >/dev/null 2>&1; then echo "rugproof: 'claude' CLI not found, skipping pre-push audit." exit 0 fi OUTPUT="$(claude code -p "/audit-changes ${BASE}" --output-format=json 2>/dev/null || echo '{"findings":[]}')" THRESHOLD="$(grep -A2 '^hooks:' "${CONFIG}" 2>/dev/null | grep -A1 'pre_push:' | grep 'fail_on:' | awk '{print $2}' || echo 'high')" declare -A LEVEL=( [info]=0 [low]=1 [medium]=2 [high]=3 [critical]=4 ) TH="${LEVEL[${THRESHOLD}]:-3}" N="$(echo "${OUTPUT}" | python3 -c ' import json, sys try: d = json.load(sys.stdin) sev_lvl = {"info":0,"low":1,"medium":2,"high":3,"critical":4} th = '"${TH}"' findings = [f for f in d.get("findings",[]) if sev_lvl.get(f.get("severity","").lower(),0) >= th] print(len(findings)) for f in findings[:5]: print(f" ❌ [{f.get(\"severity\",\"?\").upper()}] {f.get(\"id\",\"?\")} {f.get(\"title\",\"\")} ({f.get(\"path\",\"?\")}:{f.get(\"line\",\"?\")})", file=sys.stderr) except Exception: print(0) ' 2>/dev/null || echo 0)" # Read first line as count, rest is already on stderr COUNT="$(echo "${N}" | head -n1)" if [[ "${COUNT}" -gt 0 ]]; then echo echo "❌ rugproof: ${COUNT} finding(s) at/above '${THRESHOLD}' severity in changed files" echo " bypass: git push --no-verify (use sparingly, document why)" exit 1 fi echo "✓ rugproof: pre-push audit clean" exit 0
Read the script before you install anything that runs on your machine. This is the one part of a plugin that acts without being asked.
Ships withrugproof
Rugproof your code before someone else does. 🌐 Live site: omermaksutii.github.io/RugProof 📦 Latest: v1.0.0 — 45 commands · 23 agents · 45 skills · 13 MCP servers · tested, offline-first, with rule packs, a benchmark, non-EVM coverage, and post-deploy
Get the whole plugin
Stats
9
Stars
0
Forks
Maintained
Maintenance
JavaScript
Language
MIT
License
1mo ago
Last commit
4mo ago
Created
Repo: omermaksutii/RugProof

