The Problem We Kept Running Into Ourselves
We were building Pretense, a tool to protect proprietary code from LLM APIs, using Claude Code. The irony was clear to us.
Every time we asked Claude to help refactor a mutation algorithm or write tests for the proxy interceptor, we were sending our own proprietary code to Anthropic's API. The scanner logic we had spent months developing. The mutation map format we designed to be compact and reversible. The heuristics we built for identifying code blocks in mixed prompts.
We were the target user. We had the exact problem we were trying to solve. And we were still exposed ourselves because the tool was still unfinished.
That is how most good tools start. You build the thing you need. You make it work for yourself. Then you figure out whether other people have the same problem.
They do. A lot of them.
What We Built
Pretense is a local-first AI firewall. It sits between your development tools and the LLM API.
The core capability is mutation, which is a different thing from redaction. That distinction matters.
Redaction removes information from your prompt before it reaches the model. If redaction removes getUserToken, the model sees [REDACTED]. A model asked about a function it has lost the name of produces weak output. Redaction breaks the tool to protect it.
Mutation replaces the identifier with a deterministic synthetic. getUserToken becomes _fn4a2b. The function still exists in the prompt. The call graph is intact. The model can reason about the code, suggest improvements, and write tests. When the response comes back, Pretense swaps every identifier synthetic back to the real identifier, byte-exact. You get working code with your real function names. Detected secrets stay as stand-ins in the answer by design.
Your proprietary identifiers stay on your machine. The mutation map lives in .pretense/mutation-map.json, off Pretense's servers. Anthropic's servers see only stand-in names.
The Technical Insight
Here is the thing about LLMs that makes mutation work: they reason well whatever the identifiers are called.
When Claude refactors a function, it is reasoning about the structure of the code. The control flow, the data dependencies, the patterns that suggest potential improvements. The actual name getUserToken is noise to the model. The model would produce the same quality output if the function were named _fn4a2b.
This is the key insight Pretense is built on. The semantic content that makes AI output useful is structural. The semantic content that makes your code proprietary is the identifiers. Those are separable.
Redaction tools confused these two things. They removed the identifiers to protect confidentiality and destroyed the structural context the LLM needed to be useful. Pretense separates the concerns: preserve structure, transform identifiers.
The result is LLM output quality within 3% of unprotected prompts, with byte-exact round-trip fidelity for identifier reversal.
What We're Launching Today
CLI v0.2.0. The command-line interface now supports all major AI providers: Anthropic, OpenAI, Google (Gemini). One proxy, all providers. We added streaming support so large responses stream back in real-time, straight through to your tool.
MCP server. Pretense ships a Model Context Protocol server that registers with Claude Code. When active, Claude Code calls pretense_scan before processing any tool result containing code.
VS Code extension. A status bar indicator shows mutation activity in real-time. The command palette includes Pretense: Scan Current File and Pretense: View Mutation Map.
GitHub Action. The pretense-scan Action runs in CI and blocks merges on unprotected API calls in CI pipelines.
Dashboard. A Next.js dashboard that shows mutation activity across your team, session history, secret detection events, and compliance metrics.
What's Next
Team features are the next focus. Right now, Pretense is an individual developer tool. The next version extends this to teams: a shared mutation policy, centralized audit log, and team-level reporting.
Enterprise SSO is coming. BoxyHQ SAML integration for organizations that require SSO for all tools.
Custom mutation rules. Today, Pretense mutates all identifiers uniformly. The next version allows per-file and per-pattern rules.
The longer-term roadmap is on-prem deployment. Some organizations keep all AI traffic inside their own infrastructure.
How to Try It in 30 Seconds
curl -fsSL https://pretense.ai/install.sh | sh
cd your-project
pretense init
pretense start
export ANTHROPIC_BASE_URL=http://localhost:9339
claude "help me refactor this module"
We are launching on Product Hunt today because we want to hear from the developer community. If you have questions, we are in the comments all day.
Upvote on Product Hunt: https://www.producthunt.com/posts/pretense
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.