Claude Code Is Not a CLI Tool, But a 'Living' System

Table of Contents
- Three-Tier Architecture: Claude Code’s Skeleton
- “On Distribution”: Growing Capabilities After Distribution
- Startup Optimization: The Secret of Parallel Prefetching
- Feature Flag: Two Parallel Control Mechanisms
- Four Strategies for Tool Registration
- Fail-Closed Default Philosophy
- What This Means for Developers
- Wrapping Up
Have you ever wondered why Claude Code feels completely different from traditional commands like ls, grep, or git, even though they’re all command-line tools?
When you use ls to list a directory, you get exactly what you asked for—百分之百 certain. But Claude Code? Ask it to “take a look at this file” and sometimes it uses FileReadTool, sometimes it uses BashTool’s cat, and sometimes it even runs a grep search first to decide which part to read.
The diagram: Traditional CLI is like a vending machine—insert coin, get product. Claude Code is like a chef who decides how to cook based on the situation
This difference isn’t about feature count—it’s fundamental. Traditional CLI tools are “dead”—all their behavior is hardcoded during development, fixed once distributed. Claude Code is “alive”—it can still decide how to act even while you’re using it, and can even write its own tools to solve problems.
Today we’re going to dissect the internals of this “living system” and see how it actually works.
Three-Tier Architecture: Claude Code’s Skeleton
If we compare Claude Code to a person, it has three layers:
Application Layer (TypeScript) is the brain and nervous system, responsible for thinking, decision-making, and coordination. This layer has 1884 TypeScript files where the Agent Loop runs, tools are registered, and system prompts are assembled.
Runtime Layer (Bun/JSC) is the circulatory system and muscles, providing power and execution capability. Bun handles fast startup, JavaScriptCore (Safari’s JS engine) executes code, and bun:bundle optimizes at build time.
External Dependencies Layer is the senses and external interfaces—Anthropic API provides the brain (model), MCP Servers provide extensible tools, and GrowthBook provides dynamic configuration.
The diagram: Claude Code’s three-tier architecture with information flowing between layers
The information flow between these three layers is bidirectional. The application layer sends requests downward, and the external dependencies layer returns results upward. The key insight: results from the model (Anthropic API) directly influence the application layer’s behavior—the model decides which tools to call, how to call them, and whether to continue. This is why it’s called a “living” system: its behavior isn’t entirely preset by code, but shaped by code + model + prompts together.
“On Distribution”: Growing Capabilities After Distribution
Traditional software development follows this flow: develop → test → package → distribute → user installs → fixed behavior. Once distributed, the software’s capabilities are locked in unless a new version is released.
Claude Code breaks this pattern. Its core design philosophy is called “on distribution”—running in a distributed state. What does this mean?
Imagine you bought a coffee machine. A traditional coffee machine can only make Americanos, lattes, and cappuccinos—the menu is fixed. But this “coffee machine” is different: it can not only make coffee, but also learn to make new drinks on its own. If you tell it “I want a coconut latte,” it might first learn what a coconut latte is (via tool search), then mix one itself (by combining tools).
This manifests in three layers:
The model selects tools. Each Agent Loop iteration, the model decides which tool to call and what parameters to pass. Tool descriptions and input schemas aren’t documentation for humans—they’re instructions for the model.
The model writes its own tools. Through BashTool, the model can execute arbitrary shell commands; through FileWriteTool, it can create new files; through SkillTool, it can load and execute user-defined prompt templates. While using tools, the model is essentially creating new “capabilities.”
The model acts on its own context. Through Compaction, Microcompact, and Context Collapse, the model participates in managing its own context window. It decides what to remember and what to forget.
This is why testing AI Agents is particularly difficult—the same input might produce different tool call sequences. Traditional software can rely on unit tests to cover all code paths, but Claude Code’s “code paths” are partially determined in real-time inside the model’s head.
Startup Optimization: The Secret of Parallel Prefetching
As a CLI tool, startup speed directly affects user experience. Nobody wants to type claude and wait three seconds before seeing the interface.
The first 20 lines of Claude Code’s entry file main.tsx reveal a carefully designed startup optimization strategy. It moves I/O-intensive operations into the module loading “dead time” for parallel execution:
// main.tsx startup prefetch
import { profileCheckpoint } from './utils/startupProfiler.js';
profileCheckpoint('main_tsx_entry');
import { startMdmRawRead } from './utils/settings/mdm/rawRead.js';
startMdmRawRead(); // Start MDM subprocess (macOS plutil/Windows reg query)
import { startKeychainPrefetch } from './utils/secureStorage/keychainPrefetch.js';
startKeychainPrefetch(); // Parallel Keychain reads (OAuth tokens and API keys)
These three operations follow the same pattern:
- profileCheckpoint: Marks entry time point for performance analysis
- startMdmRawRead: Starts MDM subprocess, parallel with subsequent ~135ms module loading
- startKeychainPrefetch: Launches two parallel macOS Keychain read operations. Without prefetching, these would be read sequentially via synchronous spawn, adding ~65ms per startup
The diagram: main.tsx startup flow with I/O operations parallel to module loading
This design has a characteristic: failures are safe. If Keychain access is denied, ensureKeychainPrefetchCompleted() returns null and the app falls back to interactive credential prompts. If the MDM subprocess times out, subsequent plutil calls retry synchronously. This is “optimistic parallelism + pessimistic fallback.”
The ESLint comment // eslint-disable-next-line custom-rules/no-top-level-side-effects reveals something: the team has rules against top-level side effects, and this is a deliberate exception. Performance optimization isn’t done casually—it follows principles with fallback plans.
Feature Flag: Two Parallel Control Mechanisms
Claude Code has 89 build-time Feature Flags, evidence of its identity as a “rapid iteration experiment platform.” But what many don’t know is it actually has two flag mechanisms:
Build-time feature()—from bun:bundle, evaluated at packaging time. This is a compile-time constant, not a runtime if check. When the Bun bundler encounters feature(‘X’), it replaces it with a true or false literal, and JavaScript engine dead code elimination (DCE) removes unreachable branches.
const WebBrowserTool = feature('WEB_BROWSER_TOOL')
? require('./tools/WebBrowserTool/WebBrowserTool.js').WebBrowserTool
: null;
If WEB_BROWSER_TOOL is false, this code becomes const WebBrowserTool = null;, and WebBrowserTool.js with its entire dependency tree won’t appear in the final bundle. This isn’t runtime hiding—it’s compile-time elimination. The model simply doesn’t know this tool exists.
Runtime GrowthBook—dynamically fetched from server for A/B testing and gradual releases. For example, tengu_ultrathink_enabled controls whether deep thinking mode is enabled.
| Dimension | Build-time feature() | Runtime GrowthBook |
|---|---|---|
| Evaluation Time | During Bun packaging | Fetched from GrowthBook at session start |
| Scope of Impact | Whether code exists in bundle | Runtime branches in code logic |
| Modification Method | Requires rebuild and redeploy | Server config takes effect immediately |
| Typical Use Case | Complete module tree elimination for experimental features | A/B testing, gradual rollout |
They’re complementary: feature() determines “whether this capability exists,” GrowthBook determines “which users have access to this capability.” A feature is typically guarded by feature() for module loading and controlled by GrowthBook for runtime behavior.
Four Strategies for Tool Registration
In the getAllBaseTools() function in tools.ts, we can see four strategies for tool registration:
Strategy 1: Unconditional registration. Core tools are always available, like AgentTool, BashTool, FileReadTool, etc.
Strategy 2: Build-time Feature Flag guard. Like WebBrowserTool—when the flag is false, the code isn’t even bundled.
Strategy 3: Runtime environment variable guard. Like ConfigTool and TungstenTool, controlled by process.env.USER_TYPE === 'ant', for Anthropic internal staff only. This is the A/B testing “staging area” pattern.
Strategy 4: Runtime function guard. Like the conditions for GlobTool and GrepTool:
...(hasEmbeddedSearchTools() ? [] : [GlobTool, GrepTool]),
When search tools (bfs/ugrep) are embedded in the Bun single-file executable, standalone GlobTool and GrepTool are removed instead—the model can access these embedded tools via BashTool. This ensures the model’s search capability is equivalent across different build versions.
Fail-Closed Default Philosophy
In Tool.ts, the buildTool() factory function provides defaults. These defaults follow a safety principle: when uncertain, assume the most dangerous scenario.
const TOOL_DEFAULTS = {
isConcurrencySafe: () => false, // Default unsafe, concurrent execution prohibited
isReadOnly: () => false, // Default non-read-only, requires permission
isDestructive: () => false, // Default non-destructive
// ...
};
This means: if a new tool forgets to declare isConcurrencySafe and isReadOnly, the system automatically treats it as “might modify filesystem and cannot execute concurrently.” This is the most conservative, safest assumption. The system only relaxes restrictions when the tool developer actively declares safety.
GrepTool explicitly overrides both defaults:
isConcurrencySafe() { return true },
isReadOnly() { return true },
BashTool’s concurrency safety is conditional—only read-only commands allow concurrency:
isConcurrencySafe(input) {
return this.isReadOnly?.(input) ?? false;
},
A git status can run concurrently, but git push cannot. This input-aware property control achieves precise permission management.
What This Means for Developers
Understanding Claude Code’s “living system” nature—how does it help in your daily use?
First, calibrate your expectations. Don’t treat it like a traditional CLI tool where input A always produces output B. It’s a collaboration partner, and the same request might follow different solution paths. Sometimes it chooses a more cautious but slower approach; sometimes it takes risks trying shortcuts.
Second, understand response latency. Startup parallel prefetching, tool call permission checks, model API response times—none of these are “bugs,” they’re part of the architecture. If startup is slow, check Keychain access; if responses are slow, the context window might have triggered compaction.
Third, think in Feature Flag terms. If you have experimental features to add to your own AI Agent, consider separating “whether the capability exists” (build-time control) from “who has access to the capability” (runtime control). This lets you test new features internally without affecting external users.
Fourth, design model-friendly tools. If you’re using MCP to extend Claude Code’s capabilities, remember that tool descriptions are instructions for the model, not documentation for humans. Descriptions should explain “what this tool does,” but more importantly, “when the model should use this tool.”
Wrapping Up
Claude Code isn’t a command-line tool in the traditional sense. It’s an intelligent system running in a distributed state, where the model is not just a user, but a decision-maker and creator.
Its three-tier architecture (application layer / runtime layer / external dependencies layer) supports this flexibility. The dual-layer mechanism of build-time Feature Flags and runtime flags lets it keep code lean while flexibly controlling feature rollout. The fail-closed default philosophy makes safety the default option, not an optional configuration.
Understanding these isn’t just satisfying curiosity—it helps you collaborate better with this tool, understand its behavior patterns, and even draw on these designs when building your own AI Agent.
After all, Claude Code might be the most advanced AI coding tool currently available, and its source code is right there, waiting to be studied and surpassed.
That’s the article. Hopefully it helps you understand Claude Code’s true nature. If you found it valuable, feel free to like and share. Want to dive deeper into the underlying principles of AI coding tools? Follow Monster Programming, and we’ll continue dissecting things in the next article.
