Why This Combination Matters
Claude Code is the most capable AI coding tool available in 2026. It reads entire file trees, executes terminal commands, accesses clipboard contents, and maintains multi-session context across your project. This capability is also what makes it the highest-IP-risk tool in the category.
When Claude Code runs on a production codebase, it sends more than a single function for review. It sends file contents, terminal output, test results, and scaffolded context that can include hundreds of proprietary identifiers in a single session.
Pretense intercepts that traffic on your machine, before it goes out. This guide covers the complete setup.
What Claude Code Actually Sends to Anthropic
Before configuring protection, it helps to know what you are protecting.
A typical Claude Code session sends:
Session start: project directory structure (file tree)
Per-request: full file contents for any file read or referenced
Terminal output: stdout/stderr from any command Claude runs
Clipboard: content pasted into the session
Multi-turn context: the full conversation including prior code blocks
The file tree alone reveals your architecture. The file contents reveal your implementation. The terminal output can include environment variables, connection strings, and error messages with internal identifiers.
Pretense intercepts all API traffic and applies mutation to code blocks in all of these contexts.
Installation
# Install Pretense CLI globally
curl -fsSL https://pretense.ai/install.sh | sh
# Verify installation
pretense --version
# pretense 0.2.4
For teams using pnpm or yarn:
pnpm add -g pretense
# or
yarn global add pretense
Initialization
Run this once per project:
cd your-project
pretense init
This creates .pretense/config.yaml with defaults:
# .pretense/config.yaml
version: 2
provider: anthropic
proxy:
port: 9339
host: localhost
mutation:
enabled: true
identifiers: true
strings: false
comments: scan-only
secrets:
enabled: true
block: true
patterns: all
audit:
enabled: true
path: .pretense/audit.log
format: json
Commit .pretense/config.yaml to your repository. Keep .pretense/audit.log and .pretense/mutation-map.json out of version control (add these to .gitignore).
Starting the Proxy
pretense start
# Pretense proxy running on localhost:9339
# Mutation engine initialized
# Provider: Anthropic (api.anthropic.com)
# Secrets scanner: 32 patterns active
# Audit log: .pretense/audit.log
The proxy runs as a local process. For team deployments, you can run it as a system service (see the team rollout section below).
Configuring Claude Code
Set the ANTHROPIC_BASE_URL environment variable to route Claude Code through Pretense:
export ANTHROPIC_BASE_URL=http://localhost:9339
# Then use Claude Code normally:
claude "review the auth module and suggest improvements"
For persistent configuration, add to your shell profile:
# ~/.zshrc or ~/.bashrc
export ANTHROPIC_BASE_URL=http://localhost:9339
Claude Code reads ANTHROPIC_BASE_URL natively as its API endpoint. That single variable is all the configuration Claude Code needs.
What Pretense Protects (and Where Its Scope Ends)
Protected by Pretense:
- -Function names, method names, class names in code blocks
- -Variable names in function scope
- -Property names on objects and interfaces
- -Constructor parameter names
- -Secrets and credentials matching known patterns (API keys, JWTs, tokens), swapped for stand-in tokens that stay in place in the answer by design
- -Emails and phone numbers, flagged by default
Outside Pretense's scope:
- -Commit messages: these are sent as plain text context and read as prose, separate from code identifiers
- -File paths: Pretense keeps directory structures and file names as written, since the model needs them for context
- -Freeform natural language prompts: "our getUserToken function works by..." reads as prose, outside the code identifier parser
- -Secrets in prose context: a developer typing an API key into the prompt manually relies on the secrets scanner, which swaps it for a stand-in when it matches a known pattern
The core principle: Pretense is a code firewall, purpose-built for code and distinct from general DLP tools. It is optimized for the highest-value, highest-volume risk, which is identifier names in code blocks.
Verifying It Works
After starting the proxy and setting the environment variable, run a test session:
# Create a test file with identifiable function names
cat > /tmp/test-pretense.ts << 'EOF'
async function processUserPayment(userId: string, amount: number): Promise<void> {
const customer = await getCustomerRecord(userId);
await chargeStripeCustomer(customer.stripeId, amount);
}
EOF
# Ask Claude Code to review it
claude "review /tmp/test-pretense.ts for error handling"
Then check the audit log:
pretense audit --limit 1
Output:
{
"timestamp": "2026-04-04T10:22:11Z",
"session": "sess_8f3c",
"file": "/tmp/test-pretense.ts",
"model": "claude-opus-4",
"mutations": [
{ "original": "processUserPayment", "synthetic": "_fn4a2b", "kind": "fn" },
{ "original": "userId", "synthetic": "_v7c1d", "kind": "v" },
{ "original": "getCustomerRecord", "synthetic": "_fn2b8e", "kind": "fn" },
{ "original": "chargeStripeCustomer", "synthetic": "_fn9d1a", "kind": "fn" },
{ "original": "customer", "synthetic": "_v3f6b", "kind": "v" }
],
"secretsSwapped": 0,
"roundTripFidelity": "byte-exact"
}
The mutations confirm that proprietary identifiers were replaced before transmission. In the response from Claude Code, Pretense swaps identifier names back byte-exact, so you get working suggestions with your real function names intact.
Team Rollout: Setting ANTHROPIC_BASE_URL at Org Level
For enterprise teams, you want every developer routing through Pretense automatically.
Option 1: Dotenv at the repo level
# .env (committed to repo, gitignored values in .env.local)
ANTHROPIC_BASE_URL=http://localhost:9339
Developers running direnv or any dotenv-compatible shell will pick this up automatically.
Option 2: Shell profile via onboarding script
#!/bin/bash
# scripts/setup-pretense.sh
echo 'export ANTHROPIC_BASE_URL=http://localhost:9339' >> ~/.zshrc
echo 'export ANTHROPIC_BASE_URL=http://localhost:9339' >> ~/.bashrc
curl -fsSL https://pretense.ai/install.sh | sh
pretense init
echo "Pretense configured. Run 'pretense start' before using Claude Code."
Option 3: CI gate
Add a step to your CI pipeline that fails any outbound request to api.anthropic.com that bypassed the Pretense mutation layer. Pretense adds a custom header (X-Pretense-Session) to all proxied requests that CI can verify.
Option 4: Team-wide proxy server
For air-gapped or high-security environments, run Pretense as a shared proxy on your internal network. Developers point ANTHROPIC_BASE_URL at the internal proxy address in place of localhost:
# Deploy on internal server
PRETENSE_PROXY_HOST=0.0.0.0 pretense start --port 9339
# Developer machines
export ANTHROPIC_BASE_URL=http://pretense.internal.company.com:9339
The team proxy approach centralizes audit logging: all mutation logs aggregate to one location for compliance export.
Reading the Mutation Log
The audit log at .pretense/audit.log is newline-delimited JSON. Each line is one session:
# View last 10 sessions
pretense audit --limit 10
# Export for SOC2 evidence
pretense audit --format csv --limit 100000 > ai-tool-audit.csv
# Search for specific identifier
pretense audit --json --limit 1000 | grep processPayment
The CSV export is formatted for direct submission to SOC2 audit evidence packages and is compatible with Drata, Vanta, and Secureframe.
How I run Pretense on my own code
I build Pretense with Claude Code, and my sessions run through it. Here is the setup I give a new engineer, in order.
- -Run the agent through the proxy. Type
pretense run claudewhere you would typeclaude. It starts a local proxy on port 9339, points Claude Code at it and stops the proxy when the session ends. Detected secrets and PII leave the laptop as stand-in tokens. - -Put hooks on every repo.
pretense installadds a pre-commit and a pre-push hook. A key that never lands in git is a key an agent never reads. - -Scan before an agent reads the repo.
pretense scan path .lists what it finds. In CI,pretense scan ciexits 0 when clean, 2 on findings and 3 when it examined nothing. Treat 3 as a failure. - -Preview the swap.
pretense review .shows what would be mutated.pretense mutate <file> --previewprints one file mutated and leaves the file on disk as it was. - -Round-trip a file you need to share.
pretense mutate <file> --map <map>swaps the secrets in place.pretense reverse <file> --map <map>turns it back into the original, byte for byte, from the encrypted map on your machine. We run that round trip on real files before every CLI release and compare sha256 hashes.
One thing I learned the hard way: inside a session the agent sees stand-ins, so a file the agent writes can hold a stand-in where you expected a real value. Grep what the agent wrote before you ship it.
What Pretense will not do is put a secret back into the model's answer. Code identifiers come back byte-exact. Secrets and PII stay as stand-ins in the response. That is deliberate: a prompt-injected model can echo a token into a link, and reversing it there would hand over the real key.
What this means if you lead an engineering team
The outcome: your team keeps asking AI assistants about real systems, configs and connection strings, and detected secrets leave each laptop as stand-ins.
- -No new workflow. Engineers type
pretense run claudein place ofclaude. Other AI CLIs run the same way, for examplepretense run gemini. - -Guard the repo as well as the prompt.
pretense installadds pre-commit and pre-push hooks.pretense scan ciin the pipeline fails on findings (exit 2) and on an empty scan (exit 3). - -Answers stay usable. Identifiers inside fenced code blocks go out as stand-ins and come back byte-exact, so the code the model writes still uses your names.
- -Measure before you mandate. Run it on your own repo for a week.
pretense auditshows what it swapped and when.
Try it on your own repo: create a free account, then run npm i -g @pretense/cli and pretense run claude. If you need a security review first, talk to me.