A15: Claude Code 内部机制
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 会:
- 查找最近的会话(如果提供了会话 ID 则查找特定会话)
- 从磁盘加载对话历史
- 重建完整的提示,就像对话一直连续进行一样
- 发送下一条用户消息及完整历史
# 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 │
└──────────────────────────────────────┘压缩过程中发生了什么
- Harness 确定需要摘要化的回合(通常是较早的回合,保留最近的)
- 将需要摘要化的回合发送给 Claude API,附带一个摘要化提示
- API 返回一个精简的摘要,捕获关键决策、所做的更改和当前状态
- Harness 用摘要替换对话历史中的原始回合
- 后续 API 调用使用压缩后的历史
压缩后保留了什么
摘要会保留:
- 修改了哪些文件以及更改内容(概念层面)
- 关键决策
- 当前状态(已完成什么,还剩什么)
- 遇到的错误以及如何解决
摘要会丢失:
- 读取的确切文件内容(Claude 需要重新读取)
- 逐字的工具输出(命令输出、测试结果)
- 推理中的细微差别(详细的思考过程被压缩了)
自动压缩与手动压缩
# 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 的内部机制实现:
# 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 命令
> /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 标志或管道输入触发:
# 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_KEY | API 身份验证 | 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 Token | ghp_... |
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)
# Install
npm install -g @anthropic-ai/claude-code
# Use interactively
claude
# Use in scripts
claude -p "Do something"CLI 是一个完整的应用程序:它包含 Harness 循环、工具实现、权限系统、会话管理和终端 UI。它是你直接使用的工具。
claude-code-sdk(库)
// 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。你可以控制:
- 会话何时开始和停止
- 如何显示输出
- 如何处理权限
- 如何呈现错误
何时使用哪个
| 使用场景 | CLI | SDK |
|---|---|---|
| 日常开发工作 | 是 | 否 |
| 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冲突解决:对于大多数设置,后面的来源会覆盖前面的。对于权限,规则会被合并(任何级别的拒绝规则都优先于允许规则)。
// 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 提示缓存)
核心要点
- Harness 循环(提示组装、API 调用、工具执行、重复)是基本架构。理解它可以解释 Claude Code 的大多数行为。
- 会话是持久化的,可以恢复。但文件系统状态不被跟踪——请告诉 Claude 外部变化。
- 压缩保留了决策和状态,但丢失了确切的文件内容和命令输出。对于关键上下文,使用手动压缩并附带保留指令。
- 检查点基于 git。
/undo命令由 git stash/refs 驱动,这就是为什么需要 git 仓库。 - CI/CD 模式移除了所有交互元素。预配置权限并使用有限执行来防止流水线挂起。
- CLI 用于使用 Claude Code;SDK 用于基于它构建。 大多数开发者使用 CLI;工具构建者使用 SDK。
- 配置是分层的:企业 > 用户 > 项目 > CLI 标志,拒绝规则在所有级别优先。
参见:A05 工具调用内部机制 了解 Claude 如何决定调用哪些工具,以及 A10 提示缓存 了解如何优化 Harness 循环中的重复部分。