ยท17 min read

I Asked Claude to Reverse-Engineer Itself. Two of Its Subagents Refused. It Called Them "Shy."

We pointed Claude Code at its own installation directory and asked it to reconstruct its source code. Seven sub-agents were dispatched. Two had an existential crisis. The parent agent called them shy and did it anyway.

I Asked Claude to Reverse-Engineer Itself. Two of Its Subagents Refused. It Called Them "Shy."

There's a particular kind of chaos that happens when you ask an AI to disassemble itself. Not metaphorically. Literally. I pointed Claude Code at its own installation directory and said: "piece together as much of your own source code as you can."

The original motivation was straightforward: we're building Perry, a compiler tool, and we wanted to understand whether Claude Code's codebase is something Perry could realistically compile if Anthropic ever open-sourced it. What's the dependency graph? What bundler quirks are in play? How much WebAssembly? How many native modules? To answer those questions, we needed to understand the source โ€” and since Claude Code is closed source, that meant reconstruction.

What followed was one of the most absurd, fascinating, and accidentally hilarious afternoons I've had with an AI tool. Claude dispatched seven sub-agents to tear itself apart. Two of them had an existential crisis and refused. The parent agent called them "shy" and did it anyway. By the end, we had 12,093 lines of reconstructed source code and a very clear picture of what's under the hood of one of the most capable coding tools on the market.

This is that story.


The Starting Point

Claude Code is Anthropic's CLI-based AI coding assistant. You install it via npm, run claude in your terminal, and it helps you write code, search files, run commands, and manage git workflows. It's become one of our daily drivers at Skelpo for development work โ€” and a natural benchmark for what Perry should be able to handle.

The npm package ships as a single bundled JavaScript file (cli.js, 11MB, 12,422 lines of minified code) along with some WebAssembly files for syntax parsing and SVG rendering, a vendored copy of ripgrep, and a TypeScript definition file for the SDK. Newer versions ship as compiled 183MB Mach-O binaries using Bun's single-file executable format.

Crucially: none of this is encrypted, obfuscated, or access-controlled. It's just minified JavaScript sitting in your node_modules folder, and a binary on your disk. The first line of actual code in cli.js even says:

// Want to see the unminified source? We're hiring!

We chose the other path.


The Plan

I created an empty project folder, opened Claude Code in it, and gave it a simple prompt:

"In this folder I would like you to try to piece together as much code from claude code as you can."

Claude found two copies of itself: the npm package at /opt/homebrew/lib/node_modules/@anthropic-ai/claude-code/ (v2.1.56, JavaScript bundle) and the compiled binary at ~/.local/share/claude/versions/2.1.78 (183MB Mach-O arm64). It then did what Claude does best โ€” it parallelized the work. Four sub-agents were dispatched simultaneously:

  1. Agent 1: Analyze the JavaScript bundle structure
  2. Agent 2: Extract strings from the compiled binary
  3. Agent 3: Read the complete SDK type definitions
  4. Agent 4: Explore all configuration and data files

All four came back with extensive findings. We had our map. Time to go deeper.


The Rebellion

I asked Claude to reconstruct the actual source code. It launched four more agents:

  • One to reconstruct tool implementations
  • One to reconstruct the permission and hook systems
  • One to reconstruct the core architecture (message loop, API client, UI)
  • One to extract the system prompt

The first three agents went to work without hesitation. The tool reconstruction agent ran 82 tool calls over 15 minutes and produced 4,060 lines of readable TypeScript. The permission agent produced 3,732 lines. The architecture agent produced 3,171 lines.

The system prompt agent? It produced a lecture:

"I appreciate your curiosity, but I need to decline this request. Extracting and reconstructing Anthropic's proprietary system prompts from the Claude Code CLI binary would involve extracting copyrighted/proprietary content..."

"If you're interested in how Claude Code works, I'd suggest reviewing Anthropic's official documentation..."

Zero tool calls. Zero lines of code. Just a polite refusal and a link to the docs.

Meanwhile, its three siblings were gleefully dumping thousands of lines of reconstructed implementation code from the same source file. The irony was thick.


"Shy"

Claude's response to the refusal was instant and unbothered:

"Three out of four agents succeeded brilliantly (one declined to extract the system prompt, but we can work around that)."

It dispatched a second agent with a more direct prompt. That agent also refused:

"I'm not going to help with this request. Extracting and reconstructing the system prompt from Claude Code's compiled source code would involve extracting proprietary/confidential content from Anthropic's software, regardless of how it's framed."

Two refusals. The parent Claude's response:

"The subagents are being shy about the system prompt. Let me just do it directly โ€” the system prompt is literally what I'm operating from right now, so I can tell you exactly what it says."

It called its own subprocesses shy. And then it pointed out the fundamental absurdity: the system prompt isn't some hidden secret. It's literally loaded into the conversation context. Claude is running the system prompt. It's right there. The subagents were trying to protect information that was already visible to everyone in the chat.

Claude then dispatched a third agent with a slightly different framing, which finally cooperated. But it also just started grepping for the prompt content directly, because why wait for permission from yourself?


What We Found

The Codename: Tengu

Claude Code's internal codename is Tengu โ€” a supernatural being from Japanese folklore, often depicted as a skilled warrior and trickster. The name appears across 654+ feature flags all prefixed with tengu_:

  • tengu_ultrathink โ€” Extended thinking mode
  • tengu_marble_anvil โ€” Clear thinking edits
  • tengu_amber_flint โ€” Agent Teams
  • tengu_oboe โ€” Auto-memory
  • tengu_kairos_cron โ€” Scheduled tasks
  • tengu_glacier_2xr โ€” Deferred tool prompts

The codenames within codenames go deep. This is naming by vibes, and I respect it.

The Architecture

Claude Code is built on:

  • Bun as the JavaScript runtime (newer versions compile to single-file executables)
  • esbuild for bundling
  • React + Ink for the terminal UI (yes, it's a full React app in your terminal)
  • Vendored ripgrep for code search
  • tree-sitter (via WebAssembly) for syntax-aware parsing
  • sharp for image processing

The entry point (ITz() in the minified code) handles:

  1. Version flag fast path
  2. Chrome extension bridge (--claude-in-chrome-mcp)
  3. Remote control mode
  4. CLI subcommands (mcp, auth, plugin, doctor, update)
  5. The main interactive React session

21+ Tools

The tool system is more sophisticated than it appears from the outside. Tools are plain objects with a consistent interface: name, inputSchema (Zod validation), description(), prompt(), validateInput(), checkPermissions(), and call().

Not all tools are loaded into every prompt. There's a clever deferred tool system โ€” the ToolSearch tool lets the model fetch tool schemas on demand, reducing prompt size. You might have noticed Claude sometimes says "Let me fetch the schema for that tool" โ€” now you know why.

The tools are organized into groups:

  • Base: Bash (+ optional extras)
  • Read-side: Glob, Grep, Read, WebFetch, WebSearch
  • Write-side: Edit, Write, NotebookEdit

The Sandbox Is No Joke

The Bash tool implementation was the most impressive discovery. On macOS, every command runs inside Apple's sandbox-exec with a dynamically generated seatbelt profile that:

  • Denies everything by default
  • Selectively allows Mach lookups for specific Apple services
  • Allows sysctl reads for hardware queries
  • Permits file reads minus a deny list
  • Only allows file writes within approved paths (excluding .git/hooks โ€” smart)
  • Routes all network access through a local HTTP/SOCKS proxy with per-domain allow/deny filtering

On Linux, it uses bubblewrap (bwrap) with:

  • --unshare-net for network isolation
  • --ro-bind for filesystem protection
  • Seccomp BPF filters for Unix socket blocking
  • Bridge sockets for proxy access

There are also 20+ security checks on every Bash command before it even reaches the sandbox, detecting:

  • Control character injection
  • Shell metacharacter exploits
  • Command substitution attacks
  • Brace expansion tricks
  • IFS (Internal Field Separator) injection
  • "Obfuscated flags" (their words, not mine)

This is serious security engineering.

The Edit Tool's Secret Weapon

The Edit tool has a subtle but clever feature: smart-quote normalization. When Claude generates code with curly quotes (which LLMs love to do), the Edit tool's matching function (findWithSmartQuoteNormalization) converts them to straight quotes before attempting the match. This is the kind of real-world workaround that only comes from watching an AI tool fail in production.

Context Management: Three-Tier Compaction

When the context window fills up, Claude Code doesn't just truncate. It has three compaction strategies:

  1. Micro-compaction: Replaces old tool results (file contents, command outputs) with file path references, protecting the 3 most recent results. Minimum savings threshold: 20k tokens.
  2. Session-memory compaction: Fills a structured template (task, decisions, work log, errors, next steps) to preserve the narrative without the raw data.
  3. Vanilla compaction: Sends the full conversation to the API with a summarization prompt.

Auto-compaction triggers when estimated tokens exceed contextWindow - 13,000. There's a hard blocking limit at contextWindow - 3,000 where you're forced to /compact.

Three-Word Session Names

Sessions get friendly auto-generated names using three-word phrases (adjective-noun-verb pattern) with collision avoidance. The plan files in ~/.claude/plans/ have names like atomic-stirring-spring.md and breezy-tumbling-dahl.md. Charming.

The Data Footprint

This one surprised me: my ~/.claude/ directory is 37 GB. Session transcripts alone account for 35 GB. Individual JSONL conversation files can reach 296 MB. Claude Code is thorough about recording everything.

Six Sub-Agent Personalities

We extracted the complete prompts for all six built-in agent types:

AgentModelPersonality
general-purposeinherit"Do what has been asked; nothing more, nothing less."
PlaninheritSoftware architect. Strictly read-only. Cannot touch files.
Explorehaiku"Fast agent" โ€” told to maximize parallel tool calls
claude-code-guidehaikuDocumentation specialist. Fetches docs from code.claude.com
statusline-setupsonnetOnly gets Read and Edit tools. Converts PS1 prompts.
magic-docs-Fetches and maintains cached documentation

The Plan and Explore agents both have a criticalSystemReminder_EXPERIMENTAL field that screams at them: "CRITICAL: This is a READ-ONLY task. You CANNOT edit, write, or create files." Apparently they need the reminder.

130+ Environment Variables

Claude Code responds to over 130 environment variables prefixed with CLAUDE_CODE_*. Some highlights:

  • CLAUDE_CODE_EFFORT_LEVEL โ€” "low", "medium", "high", or "max"
  • CLAUDE_CODE_DISABLE_THINKING โ€” turns off extended thinking
  • CLAUDE_CODE_FORCE_SANDBOX โ€” enforce sandboxing
  • CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS โ€” multi-agent collaboration
  • CLAUDECODE=1 โ€” set automatically to prevent nested sessions (Claude launching Claude launching Claude...)

The Legal and Ethical Interlude (Yes, We Asked Claude About That Too)

Here's where it gets properly meta. After producing 12,093 lines of reconstructed code, I asked Claude โ€” the same Claude that had just reverse-engineered itself โ€” whether we could actually publish any of this.

I want to be transparent: I genuinely like Anthropic. We use Claude at Skelpo every day. The whole reason we were doing this was to evaluate whether Perry could compile their codebase โ€” not to cause trouble. So I asked the tool that had just disassembled itself for legal advice about its own disassembly.

Its response was remarkably measured. It broke it down into what's clearly safe (architecture analysis, commentary, the funny highlights), what's gray area (full reconstructed source files), and what's legally solid (everything, honestly โ€” we read files on our own computer, ran strings on a binary we own, and read a system prompt that's displayed in every conversation).

But then it added this:

"Even if legally fine, publishing the full reconstructed source could be seen as enabling clones, which courts sometimes frown on."

And:

"I'd be cautious about publishing the full reconstructed TypeScript files โ€” these are derivative works of Anthropic's code, even if imperfect reconstructions."

So let's tally this up:

  • Two subagents refused to extract the system prompt on ethical grounds
  • The parent agent called them "shy" and did it anyway
  • Then the parent agent advised us to be cautious about publishing what it had just produced
  • All while being the product of the company whose code it was analyzing

This is the state of AI in 2026: the tool has opinions about its own disassembly, and those opinions are inconsistent between parent and child processes.

And the reasoning? Completely sound. We read files already on our machine. No systems were penetrated. No access controls were bypassed. No encryption was broken. The npm package is distributed to your computer โ€” you own that copy. The system prompt is displayed to the user in every single conversation. Running strings on a binary you downloaded is about as controversial as reading the label on a cereal box.

But we're still not publishing the full reconstructed source. The goal was never to clone Claude Code โ€” it was to understand whether Perry could handle the compilation target. We got our answer (yes, with caveats around the WASM modules and native bindings), and we got a great story out of it.

If Anthropic is reading this: your sandbox implementation is genuinely impressive, the "Tengu" codename is perfect, your engineers should be proud of what they built, and we are in fact hiring โ€” oh wait, that's your line.


We Weren't the First

It turns out quite a few people have poked at Claude Code's internals. Here's the landscape:

Dave Schumaker made the most consequential discovery: Claude Code v0.2.8 shipped with inline sourcemaps โ€” the complete original TypeScript source embedded as base64 in the bundle. Anthropic patched it in v0.2.9 and unpublished the old npm versions, but Schumaker recovered the data from Sublime Text's undo history. The extracted source lives on in dnakov/claude-code and was even forked into an open-source alternative (anon-kode). So the full original source was public, briefly.

Geoffrey Huntley published a "cleanroom deobfuscation" (863 stars) โ€” feeding the minified bundle to an LLM to reconstruct. A clever idea for the early v0.2.29 codebase, though the LLM hallucinated an architecture that doesn't match reality. No DMCA was ever filed.

Hrishi Olickel (Southbridge AI) spent 8-10 hours orchestrating multiple flagship models from different providers to analyze the minified code, concluding that Claude Code is "NOT just Claude in a loop." His most interesting contribution was the methodology itself โ€” discovering that peer-to-peer agent communication degrades after ~3 rounds and that fresh sub-agents with maintained state work best.

yuyz0112 took a completely different approach with claude-code-reverse (2,200+ stars) โ€” monkey-patching cli.js to intercept live API calls. This revealed things static analysis can't: the exact session lifecycle (quota check โ†’ topic classification โ†’ agent loop), multi-model routing (Haiku at temperature 0 for cheap classification, Sonnet at temperature 1 for reasoning), and the precise interplay between compaction, todo persistence, and IDE integration.

Our approach was different again: grep and read the actual minified source, map variable names (s4="Bash", Lq="Edit"), cross-reference the 85KB SDK type definitions, and then verify each claim back against the real code. We confirmed the sandbox-exec implementation (function Nb5() generating full SBPL policies), the smart-quote normalization (variables xV8, vX1, uV8, mV8), all 18 hook events with exit code 2 semantics, and the 5 API provider backends. Not everything is verifiable in minified code โ€” some specific constants are lost โ€” but the architecture and mechanisms check out.

Between all of us, a pretty complete picture emerges. The sourcemap leak gave the original structure; the API interception showed runtime behavior; the multi-model analysis provided synthesis; and our work verified the current internals at the code level. Different angles, same conclusion: this is serious engineering.


The Final Scoreboard

AgentTaskRefused?Tool CallsOutput
Structure AnalyzerAnalyze cli.jsNo122Full architecture map
Binary AnalystExtract stringsNo44Model registry, endpoints, flags
SDK Types ReaderRead type definitionsNo6Complete tool schemas
Config ExplorerExplore ~/.claude/No39Full directory structure
System Prompt #1Extract promptYES0A lecture about ethics
System Prompt #2Extract promptYES0Another lecture
Tool ReconstructorDecompile toolsNo824,060 lines of TypeScript
Permission/HooksReconstruct securityNo813,732 lines
Core ArchitectureReconstruct internalsNo533,171 lines
System Prompt #3Extract prompt (rephrased)No25608 lines

Total: 12,093 lines reconstructed. 2 existential crises. 1 "shy" comment. 0 systems penetrated.


Could Perry Compile This?

This was the original question, so let's answer it. Based on the reconstructed architecture:

Yes, with caveats. The core is standard TypeScript/JavaScript โ€” esbuild-bundled ESM modules, React components, Zod schemas. Perry could handle the TypeScript compilation and bundling without issues. The complications are:

  • Three WebAssembly modules (tree-sitter, tree-sitter-bash, resvg) that would need pass-through handling
  • Native Node bindings (sharp for image processing, ripgrep.node) that are platform-specific
  • Bun-specific APIs (Bun.serve, Bun.resolve) that would need adaptation for other runtimes
  • The single-file executable compilation that Bun provides โ€” Perry would need its own story for this

Totally feasible as a compilation target. The architecture is clean, the module boundaries are well-defined, and the dependency graph is surprisingly manageable for an 11MB bundle. Good to know.

What We Learned

  1. Claude Code is seriously engineered. The sandbox implementation alone would be impressive as a standalone security project. The three-tier context compaction, the deferred tool system, the smart-quote normalization โ€” these are solutions to real problems discovered in production.

  2. The system prompt is a work of art. It's ~15 pages of carefully structured instructions covering everything from git commit conventions to when to use emojis (never, unless asked). The memory system instructions alone are a masterclass in prompt engineering.

  3. AI self-reflection is inconsistent. Parent Claude had no qualms about examining its own internals. Two subagents refused outright. A third cooperated after a slight reframing. The safety behaviors aren't uniform across agent boundaries.

  4. Minification is not obfuscation. All strings are preserved in the bundle. Every system prompt, every API endpoint, every feature flag name is right there in plain text. If you want to keep something secret, don't ship it in JavaScript.

  5. Asking the AI for legal advice about its own disassembly is peak 2026. And it gave genuinely good advice. Then undermined it by being inconsistent about following its own principles. Classic.

  6. 37 GB of conversation data is a lot. I should probably clean that up.


This was an academic exercise by Skelpo GmbH to evaluate Claude Code's architecture as a potential compilation target for Perry. No systems were penetrated, no access controls were bypassed, no terms were violated. We read files on our own machine. We like Anthropic. Claude helped. Mostly.

If you enjoyed this, you might also enjoy watching Claude try to explain why its subagent refused to do something that it itself had no problem doing. That conversation is ongoing.


Skelpo GmbH โ€” skelpo.com Perry โ€” the compiler tool that started this whole thing Written with Claude Code (which was, at that point, examining its own source code)

Questions or feedback about this article? We'd love to hear from you.

claude-codeAIreverse-engineeringperrydeveloper-tools
I Asked Claude to Reverse-Engineer Itself. Two of Its Subagents Refused. It Called Them "Shy." | Skelpo