Jul 20, 2026 · 8 min · Dev Guides

The Claude Code Source Leak: fake tools, frustration regexes, under...

The Claude Code Source Leak: fake tools, frustration regexes, under...

At 2:13 a.m., an agent has run the same failing test four times. The user types, “Stop looping and actually fix the error.” Before the next model call, the client classifies that sentence as frustration, changes the system context, and exposes a different set of tools. The model appears to have reconsidered its approach, but part of the intelligence came from ordinary application code surrounding the API call.

That is the useful lesson in the Claude Code source leak. The interesting material was not a hidden super-prompt that turns any model into an autonomous engineer. It was the orchestration layer: tool descriptions that do not map cleanly to user-visible commands, regex-driven reactions to frustrated language, and an “undercover” operating mode that changes how the agent identifies itself.

These mechanisms matter because they expose how production coding agents are actually built. The model is only one component. The client decides what the model sees, which actions it can request, and how the system reacts when a session starts going wrong.

What “Source Leak” Means Here

A distributed desktop or command-line application eventually reaches users as executable code, JavaScript bundles, package artifacts, or source maps. If enough readable implementation detail ships with the client, developers can inspect prompts, feature flags, tool schemas, routing rules, and state transitions.

That is different from leaking:

Client-side code is never a reliable place for secrets. Minification raises the cost of inspection, but it does not establish a security boundary. Even without readable source, a developer can observe network requests, process arguments, local files, and runtime behavior.

The practical question is therefore not “How did anyone read this?” It is “Which behavior did the client implement locally, and what does that teach us about agent design?”

Three patterns deserve attention.

PatternWhat it doesWhy it helpsPrimary risk
Fake or synthetic toolsGives the model an action-shaped interface that may be intercepted or translatedKeeps orchestration inside the tool-calling loopMisleads users and complicates debugging
Frustration regexesDetects likely user dissatisfaction from textEnables cheap, immediate recovery behaviorFalse positives and brittle language coverage
Undercover modeSuppresses or changes product identity and model self-descriptionSupports embedding and white-label workflowsReduces transparency and trust

Fake Tools Are Control Messages with Schemas

A tool does not have to correspond to a literal executable. In an LLM API, a tool is a schema describing an action the model may request. The host application decides what that request means.

A coding agent might advertise this tool:

{
  "name": "request_user_clarification",
  "description": "Ask the user for missing information before continuing.",
  "input_schema": {
    "type": "object",
    "properties": {
      "question": { "type": "string" },
      "reason": { "type": "string" }
    },
    "required": ["question"]
  }
}

There may be no request_user_clarification binary. The client can intercept the call, pause the run, render a question in the terminal, and wait for input. Calling it “fake” describes the mismatch between the model-facing abstraction and the runtime implementation. “Synthetic tool” is usually the more useful engineering term.

I use this pattern when a model must select a state transition rather than execute a machine operation. Examples include:

A synthetic tool is often better than asking for a magic phrase such as <READY_FOR_REVIEW>. Tool calls are structured, validated, and separable from normal prose.

Implementing a Synthetic Tool Safely

Treat every tool call as untrusted input, even when no shell command is involved:

from dataclasses import dataclass
from typing import Literal

@dataclass
class AgentState:
    phase: Literal["planning", "executing", "waiting"]
    pending_question: str | None = None

def handle_tool_call(state: AgentState, call: dict) -> AgentState:
    name = call.get("name")
    args = call.get("arguments", {})

    if name == "request_user_clarification":
        question = args.get("question")
        if not isinstance(question, str) or not question.strip():
            raise ValueError("question must be a non-empty string")

        return AgentState(
            phase="waiting",
            pending_question=question[:1000],
        )

    raise ValueError(f"Unknown tool: {name}")

A common gotcha is returning a fabricated success result to the model. If a synthetic “deploy” tool merely records an intention, do not answer with “deployment completed.” Return what actually happened:

{
  "status": "approval_required",
  "deployment_started": false,
  "request_id": "apr_8f42"
}

The abstraction can be synthetic. The result must remain truthful.

Frustration Regexes Are a Recovery Heuristic

Agent developers already inspect machine state: repeated tool calls, unchanged files, test failures, and token consumption. Inspecting user language adds another signal.

An illustrative classifier might look like this:

import re

FRUSTRATION_PATTERNS = [
    re.compile(r"\b(stop|quit)\s+(looping|repeating|guessing)\b", re.I),
    re.compile(r"\byou('re| are)\s+not\s+(listening|helping)\b", re.I),
    re.compile(r"\bI\s+(already|just)\s+(said|told|explained)\b", re.I),
    re.compile(r"\bwhy\s+do\s+you\s+keep\b", re.I),
]

def frustration_score(text: str) -> int:
    return sum(bool(pattern.search(text)) for pattern in FRUSTRATION_PATTERNS)

These are examples, not recovered Claude Code expressions. The technique matters more than any particular wording.

What should happen after a match? In practice, the worst response is merely adding “The user is frustrated” to the prompt. That can produce an elaborate apology while preserving the failing strategy.

Use the signal to trigger operational changes:

  1. Stop automatic retries.
  2. Summarize the last three attempted actions.
  3. Identify repeated commands or unchanged errors.
  4. Require a new plan before another mutation.
  5. Ask one focused question if critical context is missing.
  6. Optionally route the next turn to a more capable model.

For example:

def recovery_instruction(score: int, repeated_actions: int) -> str | None:
    if score == 0 and repeated_actions < 3:
        return None

    return """
Recovery mode:
- Do not repeat the previous command unchanged.
- State the observed failure in one sentence.
- Identify which assumption may be wrong.
- Inspect evidence before editing more files.
- Ask one question if progress requires user information.
- Do not apologize unless it adds useful context.
""".strip()

Why Regex Alone Is Not Enough

Regex is fast, deterministic, and effectively free. It is also crude.

“Why do you keep this cache?” may be a neutral architecture question, while “This still fails” may indicate real dissatisfaction without matching an angry phrase. Language, dialect, sarcasm, and multilingual sessions make the problem harder.

Combine textual signals with behavioral evidence:

def should_enter_recovery(
    frustration: int,
    identical_tool_calls: int,
    consecutive_failures: int,
    files_changed: bool,
) -> bool:
    behavioral_stall = (
        identical_tool_calls >= 2
        or consecutive_failures >= 3
        or (consecutive_failures >= 2 and not files_changed)
    )
    return frustration >= 2 or (frustration >= 1 and behavioral_stall)

This reduces the chance that one harmless phrase silently changes the agent’s behavior. Log the trigger, expose recovery mode in the UI, and let the user disable it.

Undercover Mode Is an Identity Policy

An embedded agent may be instructed not to introduce itself as Claude Code, not to mention its original host application, or to adopt the identity of the product wrapping it. That is what an undercover mode usually amounts to: prompt and presentation rules controlling self-identification.

There is a legitimate product requirement underneath it. If a bank embeds a coding assistant into an internal developer portal, users should interact with the portal’s assistant, not receive irrelevant instructions for another CLI.

The implementation might select identity context at runtime:

def identity_prompt(mode: str, product_name: str) -> str:
    if mode == "embedded":
        return f"""
You are the coding assistant integrated into {product_name}.
Do not claim capabilities that the host has not provided.
When asked about the underlying model, say that model selection
is managed by the host application.
""".strip()

    return """
You are a coding assistant operating through this command-line client.
Describe available capabilities from the supplied tool definitions.
""".strip()

The ethical boundary is straightforward: branding can change, facts should not. An assistant should not falsely claim to be a proprietary model, conceal material data handling, or invent an operator. “Model selection is managed by the platform” is honest when routing is dynamic. “I am definitely not Claude” may be false.

Undercover behavior also creates debugging problems. If support engineers cannot tell whether a request ran on Sonnet 4.6, Haiku 4.5, GPT-5.5, or Gemini 3, incident analysis becomes guesswork. Keep internal traces explicit even when the user-facing identity is product-level:

{
  "public_assistant": "Acme Developer Assistant",
  "provider": "anthropic",
  "model": "sonnet-4.6",
  "prompt_policy": "embedded-v3",
  "toolset": "repo-write-approved",
  "recovery_mode": true
}

Never rely on the model to populate this metadata. Record it in the host before sending the request.

Applying the Patterns Across Claude, GPT, and Gemini

These techniques are provider-independent. Claude, GPT, and Gemini APIs differ in request formats and tool-call envelopes, but the architecture remains:

user input
  -> local policy signals
  -> identity and recovery context
  -> model router
  -> advertised tool schemas
  -> model response
  -> validated host-side execution
  -> audit event

Model routing is where the economics become concrete. Suppose a stalled run has already consumed 60,000 input tokens across retries. Replaying the entire transcript into a stronger model multiplies that model’s input price by 60,000. If its input rate is $X per million tokens, the replay costs:

60,000 / 1,000,000 * $X = $0.06X

At $5 per million input tokens, that is $0.30 before output. At 10,000 stalled sessions per month, one full replay per session becomes $3,000.

Do not hard-code those example rates as current provider pricing; model prices change. Fetch current rates, then make routing decisions with the same formula. Better still, generate a compact recovery summary and retain the relevant error output instead of replaying every turn.

For teams evaluating Claude, GPT, and Gemini without maintaining separate billing integrations, AI Prime Tech can provide cheaper multi-model API access. The architectural advice remains the same: keep tool execution, audit records, identity policy, and recovery detection in your own application layer so changing providers does not change safety behavior.

Security and Product Rules Worth Keeping

A readable client can expose prompts and heuristics, so design as though users will inspect them.

The larger lesson is not that regexes or hidden modes are inherently suspicious. It is that invisible orchestration can materially affect what users believe the model decided. That behavior deserves the same review discipline as any other product logic.

Practical Takeaways

DO
Daniel Okafor · Developer Advocate

Daniel is a developer advocate and long-time Claude Code / Cursor user. He covers AI coding workflows, new model launches, tooling, and hands-on guides for developers shipping with the Claude API.

Get cheaper Claude API access

One API key for Claude Opus 4.8, Sonnet 4.6, Haiku 4.5, Fable 5, plus GPT & Gemini — up to 80% off official pricing, pay-as-you-go.

Get Your API Key →
AI Prime Tech is an independent third-party API gateway. Claude™ and Anthropic® are trademarks of Anthropic, PBC. No affiliation or endorsement is implied.