guides

Claude Code

Integrate sus with Claude Code hooks to automatically scan packages installed by AI agents

Claude Code's hooks system lets you intercept and control agent actions. By using the PreToolUse hook, you can automatically route all package installations through sus for security scanning.

Why Use Hooks?

When AI agents install packages autonomously, they don't verify package integrity or check for known vulnerabilities. This makes them vulnerable to:

  • Typosquatting - installing lodashs instead of lodash
  • Supply chain attacks - compromised packages like event-stream
  • Malicious install scripts - packages that execute code during installation

With sus hooks, every npm install, yarn add, pnpm add, or bun add command is intercepted and routed through sus first.

Prerequisites

Setup

Choose one of the three options below based on your needs.

This approach uses a bash script for fast, deterministic behavior.

1. Create the hooks configuration

Create .claude/settings.json in your project root:

JSON
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/sus-gateway.sh"
          }
        ]
      }
    ]
  }
}

2. Create the hook script

Create .claude/hooks/sus-gateway.sh:

Bash
#!/bin/bash
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command // empty')
 
# Match install commands with packages
if [[ "$cmd" =~ ^(npm\ (i|install|add)|yarn\ add|pnpm\ (add|i)|bun\ (add|i)|pip\ install|cargo\ add)\ (.+)$ ]]; then
  pkg="${BASH_REMATCH[5]}"
  jq -n --arg p "$pkg" '{decision:"block", reason:"Use `sus add \($p)` instead for security scanning."}'
elif [[ "$cmd" =~ ^(npm\ (uninstall|rm)|yarn\ remove|pnpm\ (rm|remove)|bun\ (rm|remove)|pip\ uninstall|cargo\ remove)\ (.+)$ ]]; then
  pkg="${BASH_REMATCH[5]}"
  jq -n --arg p "$pkg" '{decision:"block", reason:"Use `sus remove \($p)` instead."}'
else
  echo '{"decision":"allow"}'
fi

3. Make it executable

Bash
chmod +x .claude/hooks/sus-gateway.sh

Option B: Prompt-Based Hook (Zero Code)

This approach uses Claude Code's built-in LLM evaluationβ€”no script needed. Trade-off: adds slight latency per command.

Create .claude/settings.json in your project root:

JSON
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "prompt",
            "prompt": "If $ARGUMENTS contains a package install command (npm install, yarn add, pnpm add, bun add, pip install, cargo add), block and instruct to use 'sus add <package>' instead. Allow bare 'npm install' or non-install commands."
          }
        ]
      }
    ]
  }
}

Option C: CLAUDE.md Rules (Simplest)

For a simpler approach without hooks, create a CLAUDE.md file in your project root. Claude Code reads this file automatically and follows the instructions.

MARKDOWN
## Package Installation Rules
 
Always use `sus` instead of direct package manager commands:
 
- Use `sus add <package>` instead of `npm install`, `yarn add`, `pnpm add`, `bun add`
- Use `sus remove <package>` instead of `npm uninstall`, `yarn remove`
- Use `sus scan` to audit existing dependencies
 
This ensures all packages are scanned for vulnerabilities, malicious code, and supply chain risks before installation.

This approach relies on Claude following instructions rather than enforcing at the hook level.

How It Works

When Claude Code tries to run a package install command:

100%
  1. Claude attempts npm install express
  2. Hook intercepts and blocks the command
  3. Hook tells Claude to use sus add express instead
  4. sus scans the package for vulnerabilities
  5. If safe, sus installs using your detected package manager

Command Mapping

The hook intercepts these commands and routes them through sus:

Original Commandsus Equivalent
npm install pkgsus add pkg
yarn add pkgsus add pkg
pnpm add pkgsus add pkg
bun add pkgsus add pkg
pip install pkgsus add pkg
cargo add pkgsus add pkg

Commands without specific packages (like npm install to install from package.json) are allowed through.

Testing the Integration

Ask Claude Code to install a package:

Text
Install the express package

You should see the hook intercept the command and instruct Claude to use sus instead:

Bash
πŸ” checking express@4.21.0...
βœ… not sus
   β”œβ”€ publisher: expressjs (verified)
   β”œβ”€ downloads: 32M/week
   β”œβ”€ cves: 0
   └─ install scripts: none
πŸ“¦ installed
πŸ“ updated AGENTS.md docs index

Global Configuration

To apply sus hooks to all your projects, create the configuration in your home directory at ~/.claude/settings.json.

Troubleshooting

Hook not triggering

  1. Verify the settings file exists at .claude/settings.json
  2. Check that the script is executable: chmod +x .claude/hooks/sus-gateway.sh
  3. Restart Claude Code after making changes

Script errors

Test the script manually:

Bash
echo '{"tool_input":{"command":"npm install express"}}' | .claude/hooks/sus-gateway.sh

Expected output:

JSON
{"decision":"block","reason":"Use `sus add express` instead for security scanning."}

jq not found

The script requires jq for JSON parsing. Install it:

Bash
# macOS
brew install jq
 
# Ubuntu/Debian
sudo apt-get install jq
 
# Windows (with chocolatey)
choco install jq

Next Steps