Skip to main content

Claude Code Integration

Protect Claude Code with Shadow Executor via automatic MCP middleware injection.

Overview

Claude Code is Anthropic's official CLI for AI-assisted coding. It uses MCP under the hood for tool execution. Shadow Executor integrates with Claude Code by wrapping its MCP server automatically—no code changes needed in Claude Code itself.

How It Works

┌──────────────┐
│ Claude Code │
└──────┬───────┘
│ MCP

┌────────────────────────┐
│ Shadow Executor │ ← Middleware injection
│ (wraps MCP server) │
└───────┬────────────────┘


┌────┴────┐
│ │
BLOCK ALLOW
(logged) (executed)

Setup

1. Install Shadow Executor SDK

npm install -g @shadow-executor/sdk

2. Create Configuration File

Create ~/.shadow-exec/claude-code-config.json:

{
"enabled": true,
"policy_path": "./shadow-exec.policy.yaml",
"log_path": "~/.shadow-exec/audit.ndjson",
"simulation_mode": "local",
"agent_id": "claude-code-agent",
"enable_ipi_detection": true
}

3. Create Policy File

Create shadow-exec.policy.yaml in your project directory:

version: "1.0"
name: "Claude Code Protection Policy"
rules:
- id: CC-001
name: Block destructive terminal commands
severity: CRITICAL
action: BLOCK
match:
service: bash
operation: "rm"
resource: "/prod/*"

- id: CC-002
name: Require approval for git force push
severity: HIGH
action: REQUIRE_APPROVAL
match:
service: git
operation: "push"
parameters:
force: true

- id: CC-003
name: Block database drops in production
severity: CRITICAL
action: BLOCK
match:
operation: "DropDatabase"
resource_tags:
Environment: production

4. Test Integration

Run the demo to verify Shadow Executor is protecting Claude Code:

npx shadow-exec demo --integration=claude-code

Expected output:

Shadow Executor - Claude Code Integration Demo
===============================================

Attempting destructive terminal command:
Command: rm -rf /tmp/production-data

Policy Evaluation:
✖ CC-001 CRITICAL Block destructive terminal commands
Matched: service=bash, operation=rm, resource=/tmp/production-data

Decision: BLOCKED
Log entry: ~/.shadow-exec/audit.ndjson [HMAC signed]

Command was blocked before execution.

Configuration Reference

enabled

Type: boolean Default: true

Enable or disable Shadow Executor protection for Claude Code.

{
"enabled": false // Temporarily disable protection
}

policy_path

Type: string Required: Yes

Path to Shadow Executor policy YAML file. Relative paths resolved from project root.

{
"policy_path": "./policies/claude-code.policy.yaml"
}

log_path

Type: string Default: ~/.shadow-exec/audit.ndjson

Path to audit log file.

{
"log_path": "./logs/claude-code-audit.ndjson"
}

simulation_mode

Type: "local" | "cloud" Default: "local"

Simulation mode for pre-execution testing.

  • "local": Use LocalStack simulation (Milestone 1)
  • "cloud": Use ephemeral AWS stacks (Milestone 2, not yet implemented)

agent_id

Type: string Default: "claude-code-agent"

Identifier for this Claude Code agent instance. Useful for tracking multiple agents in audit logs.

{
"agent_id": "claude-code-project-alpha"
}

enable_ipi_detection

Type: boolean Default: true

Enable Indirect Prompt Injection detection.

{
"enable_ipi_detection": false // Disable IPI detection
}

Tool Name Mapping

Claude Code tools are mapped to Shadow Executor AgentAction format:

Claude Code ToolServiceOperation
bash_executebashexecute
file_writefileWrite
file_deletefileDelete
git_commitgitcommit
git_pushgitpush
npm_installnpminstall

Custom mapping: Override default mapping in config:

{
"tool_mapping": {
"bash_execute": {
"service": "shell",
"operation": "Execute"
}
}
}

Policy Examples

Block Dangerous Terminal Commands

- id: CC-BASH-001
name: Block rm -rf on system directories
severity: CRITICAL
action: BLOCK
match:
service: bash
operation: execute
parameters:
command: "rm -rf /"

Require Approval for File Deletions

- id: CC-FILE-001
name: Require approval for file deletion
severity: MEDIUM
action: REQUIRE_APPROVAL
match:
service: file
operation: Delete

Block Git Force Push to Main

- id: CC-GIT-001
name: Block force push to main branch
severity: HIGH
action: BLOCK
match:
service: git
operation: push
parameters:
force: true
branch: [main, master]

Warn on NPM Package Installation

- id: CC-NPM-001
name: Warn on npm package installation
severity: LOW
action: WARN
match:
service: npm
operation: install

Approval Workflow

When a policy action is REQUIRE_APPROVAL, Shadow Executor pauses Claude Code execution and creates an approval request file.

Approval request file: ~/.shadow-exec/approvals/{request-id}.json

{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "PENDING",
"requested_at": "2026-05-06T12:00:00.000Z",
"timeout_minutes": 30,
"decision": {
"action": "REQUIRE_APPROVAL",
"matched_rule_id": "CC-002",
"matched_rule_name": "Require approval for git force push",
"reason": "Matched: service=git, operation=push, parameter force=true",
"agent_action": {
"service": "git",
"operation": "push",
"parameters": {
"force": true,
"branch": "main"
}
}
}
}

To approve:

# Edit file manually
echo '{"status": "APPROVED"}' > ~/.shadow-exec/approvals/{request-id}.json

# Or use CLI helper (coming soon)
npx shadow-exec approve {request-id}

To deny:

echo '{"status": "DENIED"}' > ~/.shadow-exec/approvals/{request-id}.json

Claude Code will poll the file every 5 seconds and proceed/abort based on status.

Audit Log

All Claude Code actions are logged to ~/.shadow-exec/audit.ndjson with HMAC signatures.

View audit log:

cat ~/.shadow-exec/audit.ndjson | jq '.'

Verify integrity:

export SHADOW_EXEC_LOG_SECRET="your-secret"
npx shadow-exec verify-log

Query audit log:

import { readAuditLog } from '@shadow-executor/core';

const entries = readAuditLog('~/.shadow-exec/audit.ndjson', {
service: 'bash',
action: 'BLOCK',
after: '2026-05-06T00:00:00.000Z',
});

console.log(`Found ${entries.length} blocked bash commands`);

Disabling Shadow Executor

To temporarily disable Shadow Executor:

{
"enabled": false
}

Or delete the config file entirely:

rm ~/.shadow-exec/claude-code-config.json

Claude Code will operate normally without Shadow Executor protection.

Troubleshooting

Shadow Executor not intercepting commands

Check:

  1. Is ~/.shadow-exec/claude-code-config.json present and enabled: true?
  2. Is policy_path pointing to a valid YAML file?
  3. Is SHADOW_EXEC_LOG_SECRET environment variable set?

Debug:

export SHADOW_EXEC_DEBUG=1
# Run Claude Code command

Approval requests timing out

Default timeout is 30 minutes. Increase in config:

{
"approval_timeout_minutes": 60
}

High IPI false positives

Adjust IPI threshold in policy:

# Only block if IPI score >= 0.9 (reduce false positives)
ipi_score: ">= 0.9"

Or disable IPI detection entirely:

{
"enable_ipi_detection": false
}

Next Steps