跪拜 Guibai
← Back to the summary

How Anthropic's 'Helpful, Harmless, Honest' Values Became Claude Code's Architecture

Claude Code's Product Philosophy: When Values Become Architecture

In the previous article, we discussed the technical evolution of TUIs. But when I revisited Claude Code's source code a month ago and compared the design and architecture of four AI coding tools, one question kept echoing in my mind: The four most influential AI coding tools (Claude Code, Codex CLI, Gemini CLI, Aider) all chose the terminal as their primary interface, yet their technical approaches are completely different. What does this divergence signify?

The best answer I can give right now is (maybe this answer will change after a while, but whatever, let me write it down first (¯_(ツ)_/¯)): TUI is not the goal, but the means. The real divergence lies in "what kind of collaborative relationship do we want to build during AI coding."

Technical routes are projections of product intent. Without understanding product intent, technical analysis becomes archaeology without a map. In other words, we can describe the shape of every pottery shard but cannot understand why this civilization shaped them that way. I made this mistake before when reading the React source code, burying my head in the code and analyzing it in isolation.

This is also the goal this article aims to achieve: Establish a value coordinate system before technical deconstruction. We will start from Claude Code's README to understand its product positioning; start from Anthropic's "Helpful, Harmless, Honest" to understand how its values are engineered into a concrete system architecture; and extract engineering thinking with universal significance for frontend development. But this goal is very large, and I may still not be able to reach it. I can only say I will try my best to move in this direction. The historical limitations of thinking may still exist. If there are problems, I hope you will point them out.

Understanding Product Positioning from the README: The Deep Architecture of "AI teammate in the terminal"

Claude Code's source code README is extremely concise—only a version number, build instructions, and a quick start guide. But the original npm package's official description provides a key clue to its product positioning: "your AI teammate in the terminal". These six words are worth dissecting word by word.

"teammate": Collaboration, Not Replacement

"Teammate" rather than "assistant", "copilot", or "tool"—the choice of this word itself constitutes a product manifesto. The relationship between teammates is peer collaboration: you have your expertise, I have mine; we are jointly responsible for the outcome; you can make suggestions, but the final decision-making power rests with us. This peer relationship maps directly to Claude Code's interaction design:

The image above compares the collaboration models of two AI programming assistants. This is not about superiority or inferiority, but about different product intents: Claude Code pursues "expanding the boundary of capability", while Copilot pursues "reducing typing". The former optimizes for problem-solving ability, the latter for input efficiency. For frontend, this is similar to the difference between a "design system" and a "code snippet library"—the former gives us the methodology and toolchain for building components, the latter gives us ready-made components.

"in the terminal": Embedded, Not Attached

"in the terminal" is more precise than "for the terminal" or "with the terminal". "in" implies immersion, embedding, inseparability. Claude Code is not an application outside the terminal, not an external service communicating with the terminal via API, but runs directly inside the terminal process, in the same operating system context as the Shell environment, file system, Git repository, and Node.js runtime.

The architectural implications of this embeddedness are also profound:

The "Concentric Circle" Model of Product Positioning

Combining the analysis above, we can draw the Concentric Circle Model of Claude Code's product positioning:

The concentric circles in the image above, from innermost to outermost, are: Core Identity (AI teammate) → Domain of Existence (in the terminal) → Scope of Capability (software engineering tasks) → Value Constraints (Helpful, Harmless, Honest). Each layer constrains the implementation of the outer layers: because we are a teammate rather than a tool, we need a shared workspace rather than an isolated sandbox; because we are in the terminal, we need to be compatible with Unix pipes rather than outputting closed formats; because we handle software engineering tasks, we need to understand engineering contexts like code, Git, testing, and builds; because we follow three values, we need a permission system, security boundaries, and transparency mechanisms.

This concentric circle model is the starting point for all subsequent technical analysis. When we discuss the decision to self-develop Ink, we can trace it back to the immersion requirement of "in the terminal"; when we discuss the 30+ tools in the tool system, we can trace it back to the capability scope of "software engineering tasks"; when we discuss the three-layer defense of the permission system, we can trace it back to the value constraint of "Harmless".

Helpful: From "Feature Stacking" to "Intent Understanding"

"Helpful" is usually understood at the product level as "many features, fast response". But Claude Code's definition of "Helpful" is more precise: understanding user intent, not just executing user commands.

Agent Positioning in the System Prompt

In src/constants/prompts.ts, Claude Code's system prompt clearly defines its own role at the very beginning:

function getSimpleIntroSection(
  outputStyleConfig: OutputStyleConfig | null,
): string {
  return `
You are an interactive agent that helps users ${
      outputStyleConfig !== null
        ? 'according to your "Output Style" below...'
        : 'with software engineering tasks.'
    } Use the instructions below and the tools available to you to assist the user.`
}

Note the precision of the wording: "interactive agent" rather than "command executor", "helps users with software engineering tasks" rather than "answers questions". This positioning determines the interaction design of the entire system—Claude Code is not a passive tool waiting for user input and returning results, but a collaborative agent that actively understands context, plans action paths, invokes tools for execution, and feeds back execution results. Seeing this prompt, I suddenly felt that all the prompts I had written before were in vain—the wording was not precise enough, the positioning was not clear enough, the planning was not explicit enough. I only treated AI as a "person" capable of conversation, not as an intern capable of truly executing complete tasks.

This "Agent" positioning directly influences the design of the 30+ tool system. Each tool is not an isolated feature point, but an extension of the Agent's capabilities:

This design philosophy of "tools as extensions of capability" is completely parallel to "components as extensions of UI" in frontend engineering—a Button component is not just a clickable area, it also carries complete interaction semantics like disabled state, loading state, focus management, and ARIA semantics.

From Commands to Intent: A Leap in Interaction Hierarchy

The interaction model of traditional CLI tools is a single-layer structure of "command → execution → output". Claude Code introduces a three-layer interaction model:

  1. Intent Layer: The user expresses a goal in natural language ("Help me optimize the performance of this component").
  2. Planning Layer: The Agent decomposes the intent into an executable sequence of tool calls—first read the file, then analyze the code, then execute optimization, and finally run tests to verify.
  3. Execution Layer: The tool system actually executes operations in the local environment and feeds the results back to the planning layer.

The image above shows Claude Code's three-layer interaction model. This model is not unfamiliar to frontend developers—it has a deep isomorphism with the three-layer architecture of "data layer → state management layer → view layer" in modern frontend frameworks. The user's natural language input corresponds to "user events", the planning layer's tool call sequence corresponds to "state change actions", and the execution layer's local operations correspond to "side effects". Claude Code's "Helpful" philosophy essentially implements an intent-driven side-effect orchestration system in the terminal environment.

Context Awareness: The Foundation of Helpful

True "Helpful" requires understanding context. Claude Code's context system is one of the most sophisticated parts of its product philosophy. The getSystemPrompt() function (source: src/constants/prompts.ts) assembles dozens of system prompt fragments, each serving the purpose of "making the Agent better understand the current situation":

This context information is not simply concatenated strings, but is managed through layered caching via systemPromptSection() and DANGEROUS_uncachedSystemPromptSection() (source: src/constants/systemPromptSections.ts). Static content (like general system instructions) uses a global cache reused across sessions, while dynamic content (like current Git status) is recalculated every round. This engineering decision of "cache layering" directly stems from the dual demands of the "Helpful" philosophy: "comprehensively understand context while efficiently utilizing resources."

The image above shows the cache layering architecture of Claude Code's system prompt (source: the SYSTEM_PROMPT_DYNAMIC_BOUNDARY comment in src/constants/prompts.ts). The brilliance of this boundary design lies in: it is not only a performance optimization measure, but also an engineering guarantee of product transparency—the static part is general instructions shared by all users, and the dynamic part is personalized content specific to the current session. If users inspect the system prompt, they can clearly see "which parts are the product's fixed behavior and which parts are the context information of the current session."

Harmless: Security is Not a Hindrance to Functionality, but the Cornerstone of Trust

"Harmless" is the most difficult of the three values to engineer. It requires establishing a precise boundary between "helping users complete tasks" and "preventing harm". Claude Code's security architecture is not a patch added after the fact, but a Secure-by-Design approach that runs through the entire system.

CYBER_RISK_INSTRUCTION: Textualizing the Security Boundary

In src/constants/cyberRiskInstruction.ts, there is a security instruction explicitly marked as "Owned by Safeguards Team, modification requires approval":

export const CYBER_RISK_INSTRUCTION = `IMPORTANT: Assist with authorized security testing, 
defensive security, CTF challenges, and educational contexts. 
Refuse requests for destructive techniques, DoS attacks, mass targeting, 
supply chain compromise, or detection evasion for malicious purposes. 
Dual-use security tools (C2 frameworks, credential testing, exploit development) 
require clear authorization context: pentesting engagements, CTF competitions, 
security research, or defensive use cases.`

The text of this instruction seems simple, but its engineering value lies in its precision. It does not use vague wording like "don't do bad things", but clearly divides four security zones:

Security Zone Allowed Behaviors Refused Behaviors
Authorized Security Testing Penetration testing, vulnerability scanning Unauthorized system intrusion
Defensive Security Firewall configuration, intrusion detection Development of attack tools
Educational Scenarios CTF competitions, security courses Teaching malicious techniques
Dual-Use Tools Credential testing (under clear authorization) C2 frameworks, exploit development (without authorization)

This precision has an important implication for frontend: Ambiguity in security policies is a breeding ground for vulnerabilities. In web applications, we often see vague security policies like "filter user input"; Claude Code's approach is to make the security boundary textual, auditable, and testable—every system prompt fragment is reviewed by the Safeguards Team, and every modification has a clear approval process.

Three-Layer Defense of the Permission System

Claude Code's permission system (src/utils/permissions/ directory) is an engineering masterpiece of its "Harmless" thinking. It is not a simple "allow/deny" switch, but a three-layer defense system:

Layer 1: Permission Mode

PermissionMode.ts defines six permission modes, forming a hierarchy from "most conservative" to "most open" (source: src/utils/permissions/PermissionMode.ts):

const PERMISSION_MODE_CONFIG = {
  default:     { title: 'Default',      color: 'text' },      // Ask one by one
  plan:        { title: 'Plan Mode',    color: 'planMode' },  // Read-only + plan
  acceptEdits: { title: 'Accept edits', color: 'autoAccept' },// Auto-accept file edits
  auto:        { title: 'Auto mode',    color: 'warning' },   // Classifier judges
  bypassPermissions: { title: 'Bypass Permissions', color: 'error' }, // Dangerous
  dontAsk:     { title: "Don't Ask",    color: 'error' },     // Extremely dangerous
}

The design of this hierarchy itself embodies the product philosophy: Security is not a binary opposition, but a progressively increasing hierarchy. Users can start from the most conservative "ask one by one" and, as their trust in Claude Code deepens, gradually transition to "auto-accept edits" or even "auto mode". But even the most open auto mode has a safety net—a classifier evaluates the risk level of each tool call in the background.

Layer 2: Permission Rule Engine

Permission rules are not simple global switches, but fine-grained matching based on content. The data structure of PermissionRule (source: src/utils/permissions/PermissionRule.ts) contains four dimensions: tool name, rule content, behavior (allow/ask/deny), and rule source. This four-dimensional structure allows permission rules to be precise to "only allow BashTool to execute npm install and git status, but other commands still require asking."

Layer 3: Dangerous Pattern Detection

Even if a permission rule allows a certain tool, the system performs runtime danger detection. dangerousPatterns.ts defines DANGEROUS_BASH_PATTERNS and CROSS_PLATFORM_CODE_EXEC (source: src/utils/permissions/dangerousPatterns.ts). The isDangerousBashPermission() function uses heuristic rules to determine if a Bash permission configuration is dangerous: if a rule allows prefix matches like python:* or node*, the system marks it as dangerous and prevents the activation of automatic mode.

The image above shows the three-layer defense system of Claude Code's permission system. If any layer detects an anomaly, the decision is downgraded to "ask the user". This is a perfect practice of the classic "Defense in Depth" strategy in a terminal tool.

Sandboxing and Isolation: The Physical Guarantee of Harmless

When the permission system cannot completely eliminate risk, Claude Code resorts to process-level isolation. forkedAgent.ts (source: src/utils/forkedAgent.ts) implements isolated execution of sub-agents: each sub-agent runs in an independent Node.js process, with its own memory space and file system view. This isolation strategy has an interesting parallel with the micro-frontend architecture in frontend engineering—micro-frontends achieve runtime isolation through iframes or Shadow DOM, while Claude Code achieves execution isolation through child processes and Git worktrees. Both follow the same principle: Do not trust the default security of any component/agent; control the blast radius of potential damage to the minimum through architectural isolation.

Honest: Transparency is Verifiable Trust

"Honest" at the engineering level means two things: transparency to the user (the user knows what the system is doing and why), and honesty with data (the system does not conceal, tamper with, or excessively collect data).

System Prompt Transparency: The User-Inspectable "Brain"

One of the designs that best embodies the "Honest" philosophy in Claude Code is: users can inspect the system prompt. In most AI products, the system prompt is a black box—users don't know what instructions the model has been fed, nor why the model behaves in a certain way. Claude Code displays the complete system prompt structure through the /status command, even dividing the prompt into "cacheable static parts" and "session-specific dynamic parts".

The architectural design in systemPromptSections.ts (source: src/constants/systemPromptSections.ts) makes the prompt assembly process fully traceable:

type SystemPromptSection = {
  name: string        // Fragment name, e.g., "System", "Hooks", "DoingTasks"
  compute: ComputeFn  // Compute function, returns the text content of the fragment
  cacheBreak: boolean // Whether to break the cache (dynamic content)
}

Each prompt fragment has a name and a compute function. Users can see "which fragments the current system prompt is composed of and what the content of each fragment is" through debug output or /status. This design makes Claude Code's "brain" not a black box, but a white box that users can understand and verify.

Explainability of Permission Decisions: Why Allow/Deny

Claude Code's permission system not only gives the conclusion of "allow" or "deny", but also provides the reason for the decision. The createPermissionRequestMessage() function (source: src/utils/permissions/permissions.ts) generates different prompt texts based on the decision reason: when the classifier in auto mode decides that a tool call needs user confirmation, it tells the user: "which classifier made this judgment" and "what is the reason for the judgment". This explainability is crucial for building user trust—users will not feel frustrated because "the system inexplicably blocked me", but will understand "what potential risk the system detected".

PII Protection in Telemetry Data: The Other Side of Honesty

"Honest" means not only "telling users what we are doing", but also "not collecting data we shouldn't collect". Claude Code's telemetry system (src/services/analytics/index.ts) has a subtle type design (source: src/services/analytics/index.ts):

export type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS = never

This type is a compile-time marker: any string to be recorded in the telemetry system must undergo an explicit type assertion, proving that it does not contain code snippets, file paths, or other sensitive information. This is not a runtime check (which could be bypassed), but a mandatory constraint of the TypeScript type system—if we try to pass in an unreviewed string, the compilation will fail.

This design reflects the engineering depth of the "Honest" philosophy: Privacy protection does not rely on engineers' self-discipline, but is encoded into the compilation process through the type system. This is completely consistent with the practice of "using the TypeScript type system to prevent runtime errors" in frontend engineering, except the object of protection extends from "code correctness" to "data privacy".

The image above shows the relationship between Claude Code's transparency mechanisms and user trust. The three transparency mechanisms correspond to three trust needs: the visibility of the system prompt answers "what is it thinking", the explainability of permission decisions answers "why did it do that", and the desensitization constraint of telemetry data answers "what does it know".

User Sovereignty: A Trust Model of Progressive Authorization

"User Sovereignty" is an implicit but pervasive theme in Claude Code's product philosophy. It is not one of the three values publicly advocated by Anthropic, but it is ubiquitous in the engineering implementation.

Seven-Level Configuration Waterfall: Fine-Grained Allocation of Control

Claude Code's configuration system is the most direct embodiment of its user sovereignty philosophy. settings.ts implements a seven-level configuration source (source: src/utils/settings/constants.ts):

  1. Defaults: Product default settings.
  2. Bundled: Bundled settings (like built-in skill configurations).
  3. Plugin: Settings provided by plugins.
  4. Managed: Policy settings pushed by enterprise/team administrators.
  5. Project: Project-level settings (.claude/settings.json).
  6. User: User-level settings (~/.claude/settings.json).
  7. CLI Args: Command-line arguments (highest priority).

This seven-level architecture is not over-engineering, but a democratization of control allocation: administrators can set security policies (Managed), project leads can set project norms (Project), individual developers can set personal preferences (User), and temporary scenarios can be overridden via CLI arguments (CLI Args). Each layer exercises control within its scope of authority while respecting higher-priority constraints.

The image above shows Claude Code's seven-level configuration waterfall. This design has a direct implication for frontend: A configuration system is essentially a power distribution system. When designing a component library or application framework, we often need to answer "who has the power to modify this behavior?" Claude Code's answer is a fine-grained hierarchical structure, not a simple "global config vs. local config" binary opposition.

From "Default Deny" to "Progressive Trust"

Another manifestation of user sovereignty is Claude Code's default security posture. When a new user starts for the first time, the permission mode is default—every tool call requires confirmation. This is not because Claude Code does not trust the user, but because trust takes time to build.

As users become more familiar with Claude Code, they can: use the /accept-edits command to switch to "auto-accept file edits" mode; configure permission rules to allow specific safe commands (like git status, npm test) to execute automatically; after sufficient trust is established, enable auto mode to let the classifier judge automatically. This "progressive trust" model is completely parallel to Progressive Enhancement of Permissions in web applications. Modern browsers also ask the user first when requesting geolocation, notification, or camera permissions, and then remember the user's choice, rather than requesting all permissions upfront.

Conclusion

As frontend developers, we are accustomed to discussing framework choices, performance optimization, and component design—these are undoubtedly important. But Claude Code's engineering practice reminds us: The bottom layer of technical decisions is value judgment.

Claude Code's value does not lie in its choice of React or TypeScript or self-developed Ink, but in its conscious weaving of these choices into a coherent web of values. Every architectural decision can be traced back to the three words "Helpful, Harmless, Honest", and the relationship between these three—how to protect users while helping them, how to remain honest while protecting them.

Comments

Top 1 of 2 from juejin.cn, machine-translated. The original thread is authoritative.

ToCodex_AI

Claude Code making 'minimize prompts' an architectural principle is really interesting. In a way, it forces developers to write more self-describing code. I get a similar feeling with ToCodex—the rules+memory mechanism lets the AI maintain a consistent understanding across the whole project, without needing to re-explain the context every time.

老王以为

Yeah, that way developers only need to focus on the functionality they want to implement, without having to think about the entire project's context.