Skip to content

上下文构建

概述

Claude Code 在每次 API 调用时,需要将当前环境信息(git 状态、CLAUDE.md 内容、日期等)注入到请求中。这个过程由 context.tsutils/api.ts 协作完成。

Source: src/context.ts (189 行)

两类上下文

类别函数内容注入方式
系统上下文getSystemContext()git 状态追加到系统提示词末尾
用户上下文getUserContext()CLAUDE.md、日期作为 <system-reminder> 前置到消息列表

getGitStatus()

Source: src/context.ts:36-111

记忆化的异步函数,获取当前 git 仓库的状态信息。并行执行 5 个 git 命令:

  • getBranch() — 当前分支名
  • getDefaultBranch() — 默认分支 (main/master)
  • git status --short — 文件变更状态
  • git log -n 5 --oneline — 最近 5 次提交
  • git config user.name — Git 用户名

返回格式化的状态字符串(截断到 2000 字符):

Current branch: main
Main branch: main
Git user: developer
Status:
  M src/query.ts
  ?? docs/
Recent commits:
  abc1234 Fix query loop
  def5678 Add compaction

缓存策略

memoize() 确保在一次会话中只执行一次 git 命令。状态信息在整个对话中保持不变。

getSystemContext()

Source: src/context.ts:116-150

typescript
export const getSystemContext = memoize(async () => {
  const result: { [k: string]: string } = {};
  
  // 跳过条件:远程容器环境、git 指令被禁用
  if (!isCCRMode() && !isGitInstructionsDisabled()) {
    const gitStatus = await getGitStatus();
    if (gitStatus) {
      result.gitStatus = gitStatus;
    }
  }
  
  return result;
});

getUserContext()

Source: src/context.ts:155-189

typescript
export const getUserContext = memoize(async () => {
  const result: { [k: string]: string } = {};
  
  // 加载 CLAUDE.md 内容
  if (!isClaudeMdsDisabled() && !isBareMode()) {
    const claudeMd = await getClaudeMdContents();
    if (claudeMd) {
      result.claudeMd = claudeMd;
    }
  }
  
  // 当前日期
  result.currentDate = `Today's date is ${new Date().toISOString().split('T')[0]}.`;
  
  return result;
});

上下文注入方式

appendSystemContext()

Source: src/utils/api.ts:437-447

将系统上下文追加到系统提示词的末尾:

typescript
export function appendSystemContext(
  systemPrompt: SystemPrompt,
  context: { [k: string]: string },
): string[] {
  return [
    ...systemPrompt,
    Object.entries(context)
      .map(([key, value]) => `${key}: ${value}`)
      .join('\n'),
  ].filter(Boolean);
}

prependUserContext()

Source: src/utils/api.ts:449-474

将用户上下文作为第一条用户消息注入:

typescript
export function prependUserContext(
  messages: Message[],
  context: { [k: string]: string },
): Message[] {
  // 测试模式或空上下文时跳过
  if (isTestMode() || Object.keys(context).length === 0) {
    return messages;
  }
  
  return [
    createUserMessage({
      content: `<system-reminder>
As you answer the user's questions, you can use the following context:
# claudeMd
${context.claudeMd}
# currentDate
${context.currentDate}

IMPORTANT: this context may or may not be relevant to your tasks.
</system-reminder>`,
      isMeta: true,
    }),
    ...messages,
  ];
}

CLAUDE.md 发现

CLAUDE.md 文件从项目目录层级中加载,多级合并:

~/.claude/CLAUDE.md          # 全局用户指令
/project/CLAUDE.md           # 项目级指令
/project/subdir/CLAUDE.md    # 子目录指令

Source: src/utils/claudemd.ts

完整注入流程

下一步