Skip to content

A15: Claude Code 内部机制 ​

相关章节:第 3 章 上下文窗口与会话管理、第 14 章 高级自动化与 CI/CD

Claude Code 并不是对 Claude API 的简单包装。它是一个精密的运行时——一个 Harness(运行框架)——管理着 Agent 循环、编排工具执行、维护对话状态、执行上下文压缩(Context Compaction),并协调你与模型之间的交互。理解这些内部机制有助于你调试意外行为、优化工作流,并将 Claude Code 发挥到极致。

Harness 循环 ​

Claude Code 的核心是一个循环。每次交互都遵循相同的流程:

┌──────────────────────────────────────────────────────┐
│                   The Harness Loop                    │
│                                                      │
│  ┌─────────┐                                         │
│  │  User   │                                         │
│  │ Message  │                                         │
│  └────┬────┘                                         │
│       │                                              │
│       ▼                                              │
│  ┌─────────────────────────────────────────────┐     │
│  │ Assemble Full Prompt                         │     │
│  │  • System prompt (Claude Code's identity)   │     │
│  │  • CLAUDE.md content                        │     │
│  │  • Tool definitions                         │     │
│  │  • Conversation history                     │     │
│  │  • System reminders                         │     │
│  │  • User message                             │     │
│  └────────────────────┬────────────────────────┘     │
│                       │                              │
│                       ▼                              │
│  ┌─────────────────────────────────────────────┐     │
│  │ Send to Claude API                           │     │
│  └────────────────────┬────────────────────────┘     │
│                       │                              │
│                       ▼                              │
│  ┌─────────────────────────────────────────────┐     │
│  │ Parse Response                               │     │
│  │  • Text content → display to user           │     │
│  │  • Tool calls → execute tools               │     │
│  │  • Stop reason → check if done              │     │
│  └────────────────────┬────────────────────────┘     │
│                       │                              │
│               ┌───────┴───────┐                      │
│               │               │                      │
│           Tool calls?     end_turn?                   │
│               │               │                      │
│               ▼               ▼                       │
│         Execute tools    Display final text           │
│         Collect results  Wait for next user message   │
│               │                                      │
│               ▼                                      │
│         Append tool results to conversation           │
│               │                                      │
│               └──────── Loop back to API call         │
│                                                      │
└──────────────────────────────────────────────────────┘

一次"回合"的详细过程 ​

一条用户消息通常会触发多次 API 调用。以下是一个具体示例:

User: "Fix the failing test in auth.test.ts"

API Call 1:
  Claude responds: "Let me look at the failing test."
  Tool call: Read("src/tests/auth.test.ts")
  → Harness executes Read, returns file contents

API Call 2:
  Claude responds: "I see the issue. The mock is outdated."
  Tool call: Read("src/auth/service.ts")
  → Harness executes Read, returns file contents

API Call 3:
  Claude responds: "The function signature changed. Let me update the test."
  Tool call: Edit("src/tests/auth.test.ts", old_string, new_string)
  → Harness executes Edit, returns success

API Call 4:
  Claude responds: "Now let me run the test to verify."
  Tool call: Bash("npm test -- --grep auth")
  → Harness executes Bash, returns test output

API Call 5:
  Claude responds: "The test passes now. Here's what I changed..."
  Stop reason: end_turn
  → Harness displays final response, waits for user

这个序列中的每次 API 调用都包含截至该时刻的完整对话历史——包括所有先前的工具调用及其结果。这就是 Claude 在循环中保持上下文的方式。

为什么这种架构很重要 ​

理解这个循环可以解释 Claude Code 的许多行为:

  • 为什么长会话变得昂贵:每次 API 调用都发送完整历史。随着对话增长,每次调用的成本都会增加。
  • 为什么 Claude 有时会重新读取文件:如果对话被压缩过,Claude 可能已经丢失了文件内容,需要重新读取。
  • 为什么工具执行是顺序的:Harness 一次执行一个工具(虽然 Claude 可以在单个响应中请求多个工具,这些工具会被批量处理)。
  • 为什么中断 Claude 有效:你可以按 Ctrl+C 停止当前 API 调用。Harness 只是不再发送下一个请求。

会话管理与持久化 ​

会话的工作方式 ​

会话(Session)是你与 Claude Code 之间的一次对话。它包含:

  • 一个唯一的会话 ID
  • 对话历史(所有消息、工具调用和结果)
  • 关联的元数据(模型、开始时间、工作目录)
~/.claude/sessions/
├── abc123-session-id/
│   ├── conversation.json    # Full message history
│   ├── metadata.json        # Session configuration
│   └── summary.json         # Compacted summary (if compaction occurred)

--resume 的工作方式 ​

当你运行 claude --resume 时,Harness 会:

  1. 查找最近的会话(如果提供了会话 ID 则查找特定会话)
  2. 从磁盘加载对话历史
  3. 重建完整的提示,就像对话一直连续进行一样
  4. 发送下一条用户消息及完整历史
bash
# Resume the most recent session
claude --resume

# Resume a specific session by ID
claude --resume abc123-session-id

# List recent sessions to find the one you want
claude --resume  # Shows a picker if multiple sessions exist

被保留的内容:所有消息、工具调用、工具结果以及任何压缩后的摘要。

不被保留的内容:文件系统的实际状态。如果你在会话之间修改了文件,Claude 不会知道这些变化,除非它重新读取文件。

实际意义:恢复会话后,如果代码库发生了变化,请告诉 Claude:

I've made some changes since our last session. Please re-read src/auth/ 
before continuing.

/compact 的实际工作原理 ​

当对话变长时,每次 API 调用会消耗更多的 Token,并最终接近上下文窗口的限制。/compact 命令会触发压缩(Compaction)——一个将对话摘要化以释放上下文空间的过程。

压缩过程 ​

Before compaction:
┌──────────────────────────────────────┐
│ System prompt           (~2K tokens) │
│ CLAUDE.md               (~1K tokens) │
│ Turn 1: message + tools (~5K tokens) │
│ Turn 2: message + tools (~8K tokens) │
│ Turn 3: message + tools (~12K tokens)│
│ Turn 4: message + tools (~6K tokens) │
│ Turn 5: message + tools (~9K tokens) │
│ ─────────────────────────────────────│
│ Total:                  ~43K tokens  │
└──────────────────────────────────────┘

After compaction:
┌──────────────────────────────────────┐
│ System prompt           (~2K tokens) │
│ CLAUDE.md               (~1K tokens) │
│ [Summary of turns 1-4]  (~2K tokens) │
│ Turn 5: message + tools (~9K tokens) │
│ ─────────────────────────────────────│
│ Total:                  ~14K tokens  │
└──────────────────────────────────────┘

压缩过程中发生了什么 ​

  1. Harness 确定需要摘要化的回合(通常是较早的回合,保留最近的)
  2. 将需要摘要化的回合发送给 Claude API,附带一个摘要化提示
  3. API 返回一个精简的摘要,捕获关键决策、所做的更改和当前状态
  4. Harness 用摘要替换对话历史中的原始回合
  5. 后续 API 调用使用压缩后的历史

压缩后保留了什么 ​

摘要会保留:

  • 修改了哪些文件以及更改内容(概念层面)
  • 关键决策
  • 当前状态(已完成什么,还剩什么)
  • 遇到的错误以及如何解决

摘要会丢失:

  • 读取的确切文件内容(Claude 需要重新读取)
  • 逐字的工具输出(命令输出、测试结果)
  • 推理中的细微差别(详细的思考过程被压缩了)

自动压缩与手动压缩 ​

bash
# Manual compaction (you decide when)
> /compact

# Compaction with a custom instruction
> /compact Focus on preserving the database migration decisions

# Automatic compaction happens when context approaches the limit
# The harness triggers it transparently

提示:如果你正在处理需要关键上下文的任务(例如,一个复杂的调试会话,其中确切的错误消息很重要),请使用 /compact 并附带保留指令来保留特定细节:

/compact Preserve the exact error messages from the test failures 
and the database connection pooling configuration values.

检查点系统 ​

Claude Code 使用 git 创建安全检查点,允许你撤销更改。

检查点的工作方式 ​

Before Claude makes changes:
  1. Harness creates a git stash or commit of current state
  2. Records the checkpoint ID

Claude makes changes:
  3. Edit/Write/Bash tool calls modify files

If you want to undo:
  4. /undo restores the checkpoint
  5. Files return to pre-change state

检查点内部机制 ​

检查点通过 git 的内部机制实现:

bash
# What the harness does internally (simplified):

# Before changes: snapshot current state
git stash push -m "claude-checkpoint-$(date +%s)" --include-untracked

# After changes: if user wants to undo
git stash pop  # Restores the saved state

对于更复杂的场景(跨多个工具调用的更改),Harness 可能会在临时引用上创建轻量级提交:

refs/claude/checkpoints/
├── cp-001  (state before first edit)
├── cp-002  (state before second edit)
└── cp-003  (state before bash command)

重要:检查点仅覆盖 git 仓库中的已跟踪和未跟踪文件。仓库外的文件、环境变量、数据库状态和运行中的进程不在覆盖范围内。

/undo 命令 ​

bash
> /undo          # Undo the most recent change
> /undo 3        # Undo the last 3 changes

每次 /undo 都会将文件系统恢复到对应检查点之前的状态。这就是 Claude Code 要求 git 仓库的原因——git 就是撤销机制。

扩展架构 ​

Claude Code 运行在多种环境中,每种环境有不同的扩展:

┌─────────────────────────────────────────────────────────┐
│                    Claude Code Core                      │
│  (harness loop, tool execution, session management)     │
└──────────────┬──────────────────────────────────────────┘
               │
    ┌──────────┼──────────┬──────────┬──────────┐
    │          │          │          │          │
    ▼          ▼          ▼          ▼          ▼
┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐
│  CLI   │ │VS Code │ │JetBrains│ │Desktop │ │  Web   │
│Terminal│ │Extension│ │ Plugin │ │  App   │ │  App   │
└────────┘ └────────┘ └────────┘ └────────┘ └────────┘
扩展独特功能
CLI(终端)完全的终端控制,与 Unix 工具的管道集成(echo "..." | claude -p),可脚本化用于 CI/CD
VS Code 扩展内联差异视图,逐项接受/拒绝更改,显示 Agent 活动的文件树
JetBrains 插件与 IntelliJ/PyCharm/WebStorm 差异查看器和运行配置集成
桌面应用独立的 Electron 应用,无需终端或 IDE,简化设置
Web 界面基于浏览器,无需本地安装,在远程环境中运行

所有扩展共享相同的核心引擎。差异在于展示层(如何显示结果)和输入层(如何交互)。在 VS Code 中启动的会话可以在 CLI 中恢复,因为对话状态的格式是相同的。

CI/CD 模式与交互模式的区别 ​

Claude Code 有两种基本运行模式:

方面交互模式CI/CD 模式(-p 标志)
权限处理询问用户仅使用预配置
澄清问题支持不可能
会话长度开放式单一任务
输出格式人类可读机器可解析(JSON 选项)
错误恢复人类可引导必须自行恢复或失败

CI/CD 模式通过 -p 标志或管道输入触发:

bash
# CI/CD mode: pre-configure permissions, no interactive prompts
claude -p "Review the diff" \
  --model claude-sonnet-4-6-20250514 \
  --output-format json \
  --permission-mode deny-all \
  --allowedTools "Read,Glob,Grep,Bash(git diff*)"

--permission-mode deny-all 标志至关重要:它确保没有交互式提示。在 CI 流水线中出现权限提示意味着任务挂起。

环境变量及其影响 ​

Claude Code 的行为受多个环境变量影响:

变量用途示例
ANTHROPIC_MODEL选择模型claude-sonnet-4-6-20250514
ANTHROPIC_API_KEYAPI 身份验证sk-ant-...
ANTHROPIC_BASE_URL自定义 API 端点/代理https://api.anthropic.com
CLAUDE_MAX_COST最大会话成本(安全限制)10.00
CLAUDE_MAX_TURNS停止前的最大回合数100
CLAUDE_CODE_DISABLE_TELEMETRY禁用遥测1
CLAUDE_WORKING_DIR覆盖工作目录/path/to/project
CLAUDE_CODE_VERBOSE启用详细日志1
GITHUB_TOKEN用于 PR 操作的 GitHub Tokenghp_...
CI指示在 CI 中运行true
NO_COLOR禁用彩色输出1

变量解析顺序 ​

环境变量按以下顺序解析(后者覆盖前者):

1. System environment        (lowest priority)
2. .env file in project root
3. ~/.claude/.env            (user-level)
4. CLI flags                 (highest priority)

claude-code(CLI)与 claude-code-sdk(库)的区别 ​

Claude Code 以两个包的形式发布,服务于不同的目的:

claude-code(CLI) ​

bash
# Install
npm install -g @anthropic-ai/claude-code

# Use interactively
claude

# Use in scripts
claude -p "Do something"

CLI 是一个完整的应用程序:它包含 Harness 循环、工具实现、权限系统、会话管理和终端 UI。它是你直接使用的工具。

claude-code-sdk(库) ​

typescript
// Install
// npm install @anthropic-ai/claude-code-sdk

import { ClaudeCode } from "@anthropic-ai/claude-code-sdk";

// Use programmatically
const claude = new ClaudeCode({
  model: "claude-sonnet-4-6-20250514",
  workingDirectory: "/path/to/project",
});

const result = await claude.run("Review this codebase for security issues");
console.log(result.text);

SDK 是一个库,用于将 Claude Code 嵌入到你自己的应用程序中。它提供相同的核心功能(Harness 循环、工具、权限),但没有终端 UI。你可以控制:

  • 会话何时开始和停止
  • 如何显示输出
  • 如何处理权限
  • 如何呈现错误

何时使用哪个 ​

使用场景CLISDK
日常开发工作是否
CI/CD 流水线(简单)是(-p 标志)否
CI/CD 流水线(复杂编排)否是
自定义 IDE 扩展否是
构建 AI 驱动的开发工具否是
多 Agent 系统是(多进程)是(编程控制)
批处理是(脚本)是(更好的控制)

SDK 让你以编程方式控制 Claude Code 行为的方方面面。CLI 提供开箱即用的工具。大多数开发者使用 CLI;工具构建者使用 SDK。

配置解析 ​

Claude Code 从多个来源读取配置,按特定顺序合并:

1. Default values (built into Claude Code)
       │
       ▼
2. Enterprise settings (managed by organization admin)
       │  ~/.claude/settings.json (enterprise-managed)
       ▼
3. User settings
       │  ~/.claude/settings.json (user-managed section)
       ▼
4. Project settings
       │  .claude/settings.json (in the repo)
       ▼
5. CLAUDE.md files (project root, then nested)
       │
       ▼
6. CLI flags and environment variables
       │  (highest priority -- overrides everything)
       ▼
Final resolved configuration

冲突解决:对于大多数设置,后面的来源会覆盖前面的。对于权限,规则会被合并(任何级别的拒绝规则都优先于允许规则)。

json
// Enterprise policy: deny destructive operations
// ~/.claude/settings.json (enterprise)
{
  "permissions": {
    "deny": ["Bash(rm -rf*)", "Bash(git push --force*)"]
  }
}

// Project settings: allow project-specific commands
// .claude/settings.json
{
  "permissions": {
    "allow": ["Bash(npm test*)", "Bash(npm run build*)"]
  }
}

// Resolved: deny rules from enterprise + allow rules from project
// Enterprise deny rules CANNOT be overridden by project settings

这种层次结构确保即使个别项目配置了更宽松的设置,组织级别的安全策略仍然会被强制执行。

性能优化 ​

任何 Claude Code 交互中的主要延迟来自模型推理(1-30 秒,取决于模型和复杂度)。提示组装、网络和工具执行是次要因素。优化方法:

  • 减少输入 Token:保持 CLAUDE.md 简洁,在上下文增长过大之前使用 /compact,指向特定文件而不是让 Claude 自行搜索
  • 减少往返次数:给 Claude 足够的上下文以在更少的回合中完成操作,预授权常见操作的权限
  • 利用提示缓存(Prompt Caching):系统提示和 CLAUDE.md 在各回合之间被缓存,因此较长的 CLAUDE.md 文件从缓存中获益更多(参见 A10 提示缓存)

核心要点 ​

  1. Harness 循环(提示组装、API 调用、工具执行、重复)是基本架构。理解它可以解释 Claude Code 的大多数行为。
  2. 会话是持久化的,可以恢复。但文件系统状态不被跟踪——请告诉 Claude 外部变化。
  3. 压缩保留了决策和状态,但丢失了确切的文件内容和命令输出。对于关键上下文,使用手动压缩并附带保留指令。
  4. 检查点基于 git。/undo 命令由 git stash/refs 驱动,这就是为什么需要 git 仓库。
  5. CI/CD 模式移除了所有交互元素。预配置权限并使用有限执行来防止流水线挂起。
  6. CLI 用于使用 Claude Code;SDK 用于基于它构建。 大多数开发者使用 CLI;工具构建者使用 SDK。
  7. 配置是分层的:企业 > 用户 > 项目 > CLI 标志,拒绝规则在所有级别优先。

参见:A05 工具调用内部机制 了解 Claude 如何决定调用哪些工具,以及 A10 提示缓存 了解如何优化 Harness 循环中的重复部分。

基于 MIT 许可发布