Claude CLI Hooks
Akto Guardrails for Claude CLI provides security validation for AI interactions. It intercepts prompts before sending to Claude, MCP tool calls before they execute, and responses after generation — validating each against security policies, blocking risky behavior, and reporting events to your Akto dashboard.
Key Features
✅ Zero Installation - No standalone apps to install
✅ Transparent Integration - Uses Claude CLI's native hook mechanism
✅ Real-time Protection - Validates every prompt, MCP tool call and response
✅ MCP Coverage - Tool calls are reported as JSON-RPC
tools/call, so MCP servers and tools show up in your inventory✅ Centralized Monitoring - All events reported to Akto dashboard
✅ Flexible Deployment - Supports Argus and Atlas modes
✅ Configurable Behavior - Blocking or observation modes
How It Works
Claude CLI's hook system executes custom scripts at four critical points — two around the conversation, and two around every tool call the agent makes:
4 Hook Points:
UserPromptSubmit— Validates prompts before sending to Claude APIPreToolUse— Validates MCP tool input before execution. The only hook that can block a tool call: it returnspermissionDecision: "deny"with a reasonPostToolUse— Captures MCP tool results for observability and response guardrailsStop— Validates responses when Claude finishes generating
How MCP tool calls are recognised. Claude Code names MCP tools mcp__<server>__<tool>. The PreToolUse hook parses that shape, and for a match reports the call to Akto as a JSON-RPC tools/call on the /mcp path — so it lands in your MCP inventory with the server and tool broken out. Tool calls that are not MCP (Bash, Read, Edit, …) still pass through the same hook; they are mirrored to /tool/<tool-name> instead. Ingestion of non-MCP tool calls is off by default — set AKTO_INGEST_NON_MCP_TOOLS=true to enable it.
File Structure
Key Files:
Wrapper scripts (
.sh): Set environment variables, invoke Python scripts⚠️ Contains
AKTO_DATA_INGESTION_URLplaceholder - Must be replaced with your Akto instance URL
Python scripts (
.py): Core validation logic and Akto API communicationakto-validate-mcp-request.py: Validates every tool call before it runs. Reports MCP calls (mcp__<server>__<tool>) as JSON-RPCtools/callon/mcp; can deny the callakto-validate-mcp-response.py: Captures the tool result as a JSON-RPC result. Observational — it cannot blockakto_ingestion_utility.py,akto_machine_id.py,akto_heartbeat.py: shared modules imported by the hook scripts. All three live in theshared/GitHub directory, notclaude-cli-hooks/, so they are fetched fromSHARED_BASE— miss any one and the hooks fail at import withModuleNotFoundErrorakto_heartbeat.py: Registers this device with Akto every 30s. Required — without a heartbeat record, mini-runtime cannot resolve the device to a user and drops every hook event before indexing, so the endpoint never appears under LLM observability / traces even though ingestion succeedsakto_machine_id.py: Generates unique device identifiers for Atlas modesettings.json: Links hooks to wrapper scripts
Setup Guide
Prerequisites
Claude CLI installed (Installation Guide)
Akto instance URL
Python 3.7+ (standard library only — the hooks need no third-party packages)
macOS, Linux, or Windows with bash/zsh
Installation Steps
Create Directories
Download Hook Scripts
akto_ingestion_utility.py must land in the same directory as the hook scripts — they import it as a plain top-level module, resolved from the script's own directory. Skipping this download makes every hook fail with ModuleNotFoundError: No module named 'akto_ingestion_utility'.
Configure Akto Ingestion URL, API Token and Device ID ⚠️ CRITICAL STEP
All wrapper scripts contain the placeholders {{AKTO_DATA_INGESTION_URL}}, {{AKTO_API_TOKEN}} and {{DEVICE_ID (optional)}} that must be replaced — the URL with your actual Akto instance URL, the token with your Akto API token (obtain it from Akto Atlas → Connectors → Setup Guardrail card), and {{DEVICE_ID (optional)}} with this machine's device label, which the dashboard shows as the device name. If your deployment does not require auth, set the token to an empty string so the placeholder is removed (an unsubstituted {{AKTO_API_TOKEN}} would be sent as an invalid Authorization header).
Automated replacement:
Manual replacement (alternative):
Edit each wrapper script and replace:
With:
Files to update:
akto-validate-prompt-wrapper.shakto-validate-response-wrapper.shakto-validate-mcp-request-wrapper.shakto-validate-mcp-response-wrapper.sh
Configure Hooks
Create Claude CLI settings configuration:
Configure Hook Behavior (Optional)
Edit wrapper scripts to customize:
Mode Options:
Argus: Standard validation and reporting
Atlas: Includes device-specific metadata
Sync Mode:
true: Blocks threats
false: Reports but allows execution
Verify Installation
Check logs to confirm hooks are working:
Test by running a Claude command:
You should see log entries indicating validation occurred.
Configuration Reference
Wrapper Script Variables
MCP Tool Hook Variables
Read by akto-validate-mcp-request.py / akto-validate-mcp-response.py. All optional — the defaults match what the enterprise installer configures.
On-prem deployments must override DATABASE_ABSTRACTOR_SERVICE_URL. The wrappers default to the SaaS cyborg endpoint. If your Akto runs on-prem, point it at your own abstractor before the heartbeat can register the device — and until it registers, LLM observability and traces stay empty.
How DEVICE_ID is reported: the hooks send <DEVICE_ID>.ai-agent.claudecli as the request host, and the dashboard uses the first label of that host as the device name. If DEVICE_ID is empty the hooks fall back to the lowercased computer name (or, where that cannot be resolved, the raw machine UUID — which is why a device sometimes shows up as a bare hex string).
Environment Variables (Optional)
Override defaults via environment variables or config file:
Option 1: Environment variables
Option 2: Config file
Troubleshooting
ModuleNotFoundError: No module named 'akto_ingestion_utility'
The shared ingestion utility was not downloaded, or landed outside ~/.claude/hooks/. It lives in the shared/ directory on GitHub, not under HOOKS_BASE, so it needs its own curl.
If the file is present and the import still fails, check that PYTHONSAFEPATH is unset — it suppresses the script-directory entry on sys.path that this import relies on.
MCP Tool Calls Not Appearing
PreToolUse fires for every tool call, but only names matching mcp__<server>__<tool> are reported as MCP tools/call on /mcp. Built-in tools (Bash, Read, Edit, …) take the non-MCP path and are not ingested unless you opt in.
If the log shows Validating built-in / non-MCP tool request, the call was not an MCP tool — that is expected for Claude's own tools.
Endpoint Appears in Inventory but Traces / LLM Observability Are Empty
Ingestion and trace indexing are separate paths. mini-runtime resolves each hook event's device to a user via the heartbeat record (moduleInfo.name → additionalData.username); an event whose device has no heartbeat, and which carries no user_email header, is discarded before indexing. Claude Code's hook payloads never carry an email, so the heartbeat is the only thing that can satisfy this — the collection still shows up in inventory, which is why the endpoint looks connected.
If the file is missing, re-run the download step. If it is present but never sends, confirm DATABASE_ABSTRACTOR_SERVICE_URL points at a reachable abstractor (see the hint above) and that AKTO_AGENT_HEARTBEAT is not set — that flag is for machines where the Akto agent already publishes the heartbeat, and it disables publishing from the hook.
Hooks Not Executing
Ingestion URL Not Configured
Check Logs for Errors
Events Not in Dashboard
Uninstallation
To completely remove Akto hooks from Claude CLI:
Complete Removal
Selective Removal (Keep Logs)
If you want to preserve logs for audit purposes:
Backup Before Removal
Verify Removal
Restore Claude CLI to Default
After uninstallation, Claude CLI will operate without Akto security monitoring. No additional configuration is needed beyond removing the files. Test with:
Enterprise Deployment
Automated Deployment Script
Deploy to developers:
Quick Setup Summary
Resources
Support: support@akto.io
Community: https://www.akto.io/community
Last updated