Gemini CLI
Integrate sus with Gemini CLI hooks to automatically scan packages installed by AI agents
Gemini CLI's hooks system lets you intercept and customize agent behavior at specific points in the agentic loop. By using the BeforeTool 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
lodashsinstead oflodash - 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
- sus CLI installed
- Gemini CLI
Setup
1. Create the hooks configuration
Create .gemini/settings.json in your project root:
{
"hooks": {
"BeforeTool": [
{
"matcher": "shell|bash|run_shell_command",
"hooks": [
{
"name": "sus-gateway",
"type": "command",
"command": "$GEMINI_PROJECT_DIR/.gemini/hooks/sus-gateway.sh",
"timeout": 5000
}
]
}
]
}
}The matcher is a regex that matches shell-related tool names, ensuring the hook only runs for shell commands.
2. Create the hook script
Create .gemini/hooks/sus-gateway.sh:
#!/bin/bash
input=$(cat)
cmd=$(echo "$input" | jq -r '.input.command // .input.args.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"}'
fi3. Make the script executable
chmod +x .gemini/hooks/sus-gateway.shImportant: JSON Output Rules
Gemini CLI has strict requirements for hook output:
- Only JSON to stdout - Your script must output only valid JSON. No
echoorprintstatements before the JSON. - Use stderr for debugging - Write debug output to stderr:
echo "debug" >&2 - Exit code 0 - Return exit code 0 with
decision: "block"to deny an action - Exit code 2 - For critical system blocks (script failures, security stops)
If stdout contains any non-JSON text, parsing fails and the hook is treated as allowing the action.
How It Works
When Gemini CLI tries to run a package install command:
- Gemini CLI attempts
npm install express - Hook intercepts via
BeforeToolevent - Hook outputs
{"decision":"block", "reason":"..."} - Gemini CLI follows the instruction and runs
sus add express - sus scans the package for vulnerabilities
- If safe, sus installs using your detected package manager
Command Mapping
The hook intercepts these commands and routes them through sus:
| Original Command | sus Equivalent |
|---|---|
npm install pkg | sus add pkg |
yarn add pkg | sus add pkg |
pnpm add pkg | sus add pkg |
bun add pkg | sus add pkg |
pip install pkg | sus add pkg |
cargo add pkg | sus add pkg |
Commands without specific packages (like npm install to install from package.json) are allowed through.
Testing the Integration
Ask Gemini CLI to install a package:
Install the express packageYou should see the hook block the command and instruct Gemini to use sus instead:
🔍 checking express@4.21.0...
✅ not sus
├─ publisher: expressjs (verified)
├─ downloads: 32M/week
├─ cves: 0
└─ install scripts: none
📦 installed
📝 updated AGENTS.md docs indexGlobal Configuration
To apply sus hooks to all your projects, add the configuration to your user settings at ~/.gemini/settings.json.
For the hook script, either:
- Place it at a fixed global path and reference it absolutely
- Or use
$GEMINI_PROJECT_DIRfor project-relative paths
Managing Hooks
Gemini CLI provides commands to manage hooks without editing JSON:
# View all hooks
/hooks panel
# Enable/disable all hooks
/hooks enable-all
/hooks disable-all
# Toggle individual hooks
/hooks enable sus-gateway
/hooks disable sus-gatewayTroubleshooting
Hook not triggering
- Verify the settings file exists at
.gemini/settings.json - Check that the script is executable:
chmod +x .gemini/hooks/sus-gateway.sh - Verify the matcher regex matches your shell tool name
- Check
/hooks panelto see if the hook is enabled
JSON parsing errors
If the hook isn't blocking commands, check that your script outputs only JSON:
# Test the script
echo '{"input":{"command":"npm install express"}}' | .gemini/hooks/sus-gateway.shExpected output (no extra text):
{"decision":"block","reason":"Use `sus add express` instead for security scanning."}Debugging
Write debug output to stderr (not stdout):
#!/bin/bash
input=$(cat)
echo "Received: $input" >&2 # Debug to stderr
cmd=$(echo "$input" | jq -r '.input.command // empty')
echo "Command: $cmd" >&2 # Debug to stderr
# ... rest of scriptjq not found
The script requires jq for JSON parsing. Install it:
# macOS
brew install jq
# Ubuntu/Debian
sudo apt-get install jq
# Windows (with chocolatey)
choco install jqNext Steps
- Learn about threat detection
- Learn about AGENTS.md
- See other integration guides
On this page