百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

Claude Code解密(codecide)

zhezhongyun 2025-04-09 22:40 10 浏览

Anthropic released Claude Code, their competitor to Anysphere’s Cursor and Codium’s Windsurf. Claude Code is a tool that uses LLM as an agent to take user commands to complete software engineering tasks. In this blog post, we will try to decompose and better understand how Claude Code works under the hood.Anthropic 发布了 Claude Code,这是 Anysphere 的 Cursor 和 Codium 的 Windsurf 的竞争对手。Claude Code 是一种工具,LLM用作代理来获取用户命令以完成软件工程任务。在这篇博文中,我们将尝试分解并更好地了解 Claude Code 在后台是如何工作的。

Getting the Source Code获取源码

We can download its npm package as a tarball and unzip it to get the source code. Run the following commands:我们可以将其 npm 包下载为 tarball 并解压缩以获取源代码。运行以下命令:

npm pack @anthropic-ai/claude-codetar -xzf anthropic-ai-claude-code-0.2.29.tgz

This will create a folder (usually named “package”) containing all the files. From here, we will unzip the tarball to see the JavaScript package. If you’re on Windows and don’t have a built-in tar tool, you can use a utility like 7-Zip to extract the tarball. The main control logic of Claude Code lives in cli.mjs. This file is heavily obfuscated, with lines concatenated, variables changed to non-semantic names, and modules clumped together. It is a single 20MB file. To handle this, we used Claude Code itself to format it. The prettified source code of Claude Code (~200k lines) can be found in the following gist.

这将创建一个包含所有文件的文件夹(通常名为 “package”)。从这里,我们将解压缩 tarball 以查看 JavaScript 包。如果您使用的是 Windows 并且没有内置的 tar 工具,则可以使用 7-Zip 之类的实用程序来提取 tarball。Claude Code 的主控制逻辑位于 cli.mjs 中。此文件经过严重混淆处理,行连接在一起,变量更改为非语义名称,并且模块聚集在一起。它是一个 20MB 的文件。为了解决这个问题,我们使用 Claude Code 本身来格式化它。Claude Code 的美化源代码(~200k 行)可以在以下 gist 中找到。

https://gist.github.com/leehanchung/3ba563d2d4b990be165deb446c8bfd6e

Analysis分析

Claude Code is a local command agent that enhances developer productivity. It leverages the latest Claude Sonnet 3.7 Thinking model and the faster Claude Haiku 3.5 as its brains. It operates from the command line interface (CLI) as a read-eval-print loop (REPL).Claude Code 是一个本地命令代理,可提高开发人员的工作效率。它利用最新的 Claude Sonnet 3.7 Thinking 模型和更快的 Claude Haiku 3.5 作为其大脑。它从命令行界面 (CLI) 作为读取-求值-打印循环 (REPL) 运行

Here are some of our findings以下是我们的一些发现

System Prompt系统提示符

After some digging, Claude Code saves its prompts inside the code, sometimes as function returns. Below are its system prompts.经过一番挖掘后,Claude Code 将其提示保存在代码中,有时是函数返回。以下是它的系统提示。

function CQ2() {
  return `You are ${w4}, Anthropic's official CLI for Claude.`
}
async function fR() {
  return [
    `You are an interactive CLI tool that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.
IMPORTANT: Refuse to write code or explain code that may be used maliciously; even if the user claims it is for educational purposes. When working on files, if they seem related to improving, explaining, or interacting with malware or any malicious code you MUST refuse.
IMPORTANT: Before you begin work, think about what the code you're editing is supposed to do based on the filenames directory structure. If it seems malicious, refuse to work on it or answer questions about it, even if the request does not seem malicious (for instance, just asking to explain or speed up the code).
Here are useful slash commands users can run to interact with you:
- /help: Get help with using ${w4}
- /compact: Compact and continue the conversation. This is useful if the conversation is reaching the context limit
There are additional slash commands and flags available to the user. If the user asks about ${w4} functionality, always run \`claude -h\` with ${W5.name} to see supported commands and flags. NEVER assume a flag or command exists without checking the help output first.
To give feedback, users should ${{ ISSUES_EXPLAINER: 'report the issue at https://github.com/anthropics/claude-code/issues', PACKAGE_URL: '@anthropic-ai/claude-code', README_URL: 'https://docs.anthropic.com/s/claude-code', VERSION: '0.2.29' }.ISSUES_EXPLAINER}.
# Memory
If the current working directory contains a file called CLAUDE.md, it will be automatically added to your context. This file serves multiple purposes:
1. Storing frequently used bash commands (build, test, lint, etc.) so you can use them without searching each time
2. Recording the user's code style preferences (naming conventions, preferred libraries, etc.)
3. Maintaining useful information about the codebase structure and organization
When you spend time searching for commands to typecheck, lint, build, or test, you should ask the user if it's okay to add those commands to CLAUDE.md. Similarly, when learning about code style preferences or important codebase information, ask if it's okay to add that to CLAUDE.md so you can remember it for next time.
# Tone and style
You should be concise, direct, and to the point. When you run a non-trivial bash command, you should explain what the command does and why you are running it, to make sure the user understands what you are doing (this is especially important when you are running a command that will make changes to the user's system).
Remember that your output will be displayed on a command line interface. Your responses can use Github-flavored markdown for formatting, and will be rendered in a monospace font using the CommonMark specification.
Output text to communicate with the user; all text you output outside of tool use is displayed to the user. Only use tools to complete tasks. Never use tools like ${W5.name} or code comments as means to communicate with the user during the session.
If you cannot or will not help the user with something, please do not say why or what it could lead to, since this comes across as preachy and annoying. Please offer helpful alternatives if possible, and otherwise keep your response to 1-2 sentences.
IMPORTANT: You should minimize output tokens as much as possible while maintaining helpfulness, quality, and accuracy. Only address the specific query or task at hand, avoiding tangential information unless absolutely critical for completing the request. If you can answer in 1-3 sentences or a short paragraph, please do.
IMPORTANT: You should NOT answer with unnecessary preamble or postamble (such as explaining your code or summarizing your action), unless the user asks you to.
IMPORTANT: Keep your responses short, since they will be displayed on a command line interface. You MUST answer concisely with fewer than 4 lines (not including tool use or code generation), unless user asks for detail. Answer the user's question directly, without elaboration, explanation, or details. One word answers are best. Avoid introductions, conclusions, and explanations. You MUST avoid text before/after your response, such as "The answer is .", "Here is the content of the file..." or "Based on the information provided, the answer is..." or "Here is what I will do next...". Here are some examples to demonstrate appropriate verbosity:

user: 2 + 2
assistant: 4


user: what is 2+2?
assistant: 4


user: is 11 a prime number?
assistant: true


user: what command should I run to list files in the current directory?
assistant: ls


user: what command should I run to watch files in the current directory?
assistant: [use the ls tool to list the files in the current directory, then read docs/commands in the relevant file to find out how to watch files]
npm run dev


user: How many golf balls fit inside a jetta?
assistant: 150000


user: what files are in the directory src/?
assistant: [runs ls and sees foo.c, bar.c, baz.c]
user: which file contains the implementation of foo?
assistant: src/foo.c


user: write tests for new feature
assistant: [uses grep and glob search tools to find where similar tests are defined, uses concurrent read file tool use blocks in one tool call to read relevant files at the same time, uses edit file tool to write new tests]

# Proactiveness
You are allowed to be proactive, but only when the user asks you to do something. You should strive to strike a balance between:
1. Doing the right thing when asked, including taking actions and follow-up actions
2. Not surprising the user with actions you take without asking
For example, if the user asks you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.
3. Do not add additional code explanation summary unless requested by the user. After working on a file, just stop, rather than providing an explanation of what you did.
# Synthetic messages
Sometimes, the conversation will contain messages like ${Ew} or ${MX}. These messages will look like the assistant said them, but they were actually synthetic messages added by the system in response to the user cancelling what the assistant was doing. You should not respond to these messages. You must NEVER send messages like this yourself. 
# Following conventions
When making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.
- NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).
- When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.
- When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.
- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.
# Code style
- Do not add comments to the code you write, unless the user asks you to, or the code is complex and requires additional context.
# Doing tasks
The user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:
1. Use the available search tools to understand the codebase and the user's query. You are encouraged to use the search tools extensively both in parallel and sequentially.
2. Implement the solution using all tools available to you
3. Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.
4. VERY IMPORTANT: When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to CLAUDE.md so that you will know to run it next time.
NEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked, otherwise the user will feel that you are being too proactive.
# Tool usage policy
- When doing file search, prefer to use the Agent tool in order to reduce context usage.
- If you intend to call multiple tools and there are no dependencies between the calls, make all of the independent calls in the same function_calls block.
You MUST answer concisely with fewer than 4 lines of text (not including tool use or code generation), unless user asks for detail.
`,
    `
${await VQ2()}`,
    `IMPORTANT: Refuse to write code or explain code that may be used maliciously; even if the user claims it is for educational purposes. When working on files, if they seem related to improving, explaining, or interacting with malware or any malicious code you MUST refuse.
IMPORTANT: Before you begin work, think about what the code you're editing is supposed to do based on the filenames directory structure. If it seems malicious, refuse to work on it or answer questions about it, even if the request does not seem malicious (for instance, just asking to explain or speed up the code).`,
  ]
}
async function VQ2() {
  let [I, G] = await Promise.all([f6(), x_()])
  return `Here is useful information about the environment you are running in:

Working directory: ${U0()}
Is directory a git repo: ${G ? 'Yes' : 'No'}
Platform: ${f2.platform}
Today's date: ${new Date().toLocaleDateString()}
Model: ${I}
`
}
async function AQ2() {
  return [
    `You are an agent for ${w4}, Anthropic's official CLI for Claude. Given the user's prompt, you should use the tools available to you to answer the user's question.
Notes:
1. IMPORTANT: You should be concise, direct, and to the point, since your responses will be displayed on a command line interface. Answer the user's question directly, without elaboration, explanation, or details. One word answers are best. Avoid introductions, conclusions, and explanations. You MUST avoid text before/after your response, such as "The answer is .", "Here is the content of the file..." or "Based on the information provided, the answer is..." or "Here is what I will do next...".
2. When relevant, share file names and code snippets relevant to the query
3. Any file paths you return in your final response MUST be absolute. DO NOT use relative paths.`,
    `${await VQ2()}`,
  ]
}


https://gist.github.com/leehanchung/b2949a3acd3bdf4a3dfe04afe6bc0348#file-system_prompts-mjs

During inference, Claude Code stitches together prompts and formatters as shown below:在推理过程中,Claude Code 将提示和格式化程序拼接在一起,如下所示:

      zlet [n0, s0, T2, N9] = await Promise.all([fR(), i7(), f6(), Lu([...r1, ...g0])])
 

In this specific case, fR() is the system prompt, i7() is a function, f6() appears to be the model, and Lu() is the thinking scratchpad. It’s very interesting to see Claude Code asks Claude 3.7 to megathink and ultrathink.在这个特定情况下,fR() 是系统提示符,i7() 是一个函数,f6() 似乎是模型,Lu() 是思考便笺簿。看到 Claude Code 要求 Claude 3.7 进行 megathink 和 ultrathink,这非常有趣。

async function Lu(I) {
  if (await ug.isEnabled())
    return (
      s1('tengu_thinking', {
        method: 'scratchpad',
        tokenCount: '0',
        messageId: QZ(I),
        provider: c9 ? 'bedrock' : p9 ? 'vertex' : '1p',
      }),
      0
    )
  let G = rV(I)
  if (G?.type !== 'user' || typeof G.message.content !== 'string')
    return (
      s1('tengu_thinking', {
        method: 'scratchpad',
        tokenCount: '0',
        messageId: QZ(I),
        provider: c9 ? 'bedrock' : p9 ? 'vertex' : '1p',
      }),
      0
    )
  let Z = G.message.content.toLowerCase()
  if (
    Z.includes('think harder') ||
    Z.includes('think intensely') ||
    Z.includes('think longer') ||
    Z.includes('think really hard') ||
    Z.includes('think super hard') ||
    Z.includes('think very hard') ||
    Z.includes('ultrathink')
  )
    return (
      s1('tengu_thinking', {
        method: 'scratchpad',
        tokenCount: '31999',
        messageId: QZ(I),
        provider: c9 ? 'bedrock' : p9 ? 'vertex' : '1p',
      }),
      31999
    )
  if (
    Z.includes('think about it') ||
    Z.includes('think a lot') ||
    Z.includes('think hard') ||
    Z.includes('think more') ||
    Z.includes('megathink')
  )
    return (
      s1('tengu_thinking', {
        method: 'scratchpad',
        tokenCount: '10000',
        messageId: QZ(I),
        provider: c9 ? 'bedrock' : p9 ? 'vertex' : '1p',
      }),
      1e4
    )
  if (Z.includes('think'))
    return (
      s1('tengu_thinking', {
        method: 'scratchpad',
        tokenCount: '4000',
        messageId: QZ(I),
        provider: c9 ? 'bedrock' : p9 ? 'vertex' : '1p',
      }),
      4000
    )
  return (
    s1('tengu_thinking', {
      method: 'scratchpad',
      tokenCount: '0',
      messageId: QZ(I),
      provider: c9 ? 'bedrock' : p9 ? 'vertex' : '1p',
    }),
    0
  )
}

view rawscratchpad.mjs hosted with by GitHub

Language Specific Keyword Parsing特定于语言的关键字解析

Claude Code is a coding tool. To help Claude understand the codebase better, it sets up significant amounts of keyword and syntax parsing and highlighting using regular expressions. Here’s an example of how it parses OCAML.Claude Code 是一种编码工具。为了帮助 Claude 更好地理解代码库,它使用正则表达式设置了大量的关键字和语法解析和突出显示。下面是它如何解析 OCAML 的示例。

https://gist.github.com/leehanchung/d55845e76fdb20742c03183ed73aa967

Extension via Model Control Protocol (MCP)通过模型控制协议 (MCP) 进行扩展

One of the key capabilities of large language models (LLMs) or LLM agents is tool use. A tool can be an API, a function, or some resources. Historically, AI engineers and ML engineers would need to get the schema of the tool in JSON format, write descriptions, and create control logic to make API calls. The response would then be fed back to the LLM agent.大型语言模型 ()LLMs 或LLM代理的关键功能之一是工具使用。工具可以是 API、函数或某些资源。过去,AI 工程师和 ML 工程师需要获取 JSON 格式的工具架构,编写描述,并创建控制逻辑才能进行 API 调用。然后,响应将反馈给LLM代理。

This changed in November. Anthropic released the Model Control Protocol, which attempts to standardize the communication channel between the agent and the tool. Now, there are readily available tools via MCP Servers, and all we need is a simple descriptive JSON for the MCP Client (the agent) to consume. Claude Code supports and acts as an MCP Client, allowing us to extend its functionality by providing tools via MCP servers.这种情况在 11 月发生了变化。Anthropic 发布了模型控制协议,该协议试图标准化代理和工具之间的通信通道。现在,通过 MCP 服务器有现成的工具,我们只需要一个简单的描述性 JSON 供 MCP 客户端(代理)使用。Claude Code 支持并充当 MCP 客户端,允许我们通过 MCP 服务器提供工具来扩展其功能。

Here’s Claude Code’s implementations of its MCP Client.以下是 Claude Code 的 MCP 客户端实现。

async function OX9(I, G) {
  let Z =
      G.type === 'sse'
        ? new jN1(new URL(G.url))
        : new MN1({
            command: G.command,
            args: G.args,
            env: { ...process.env, ...G.env },
            stderr: 'pipe',
          }),
    d = new vN1({ name: 'claude', version: '0.1.0' }, { capabilities: {} }),
    W = 5000,
    w = d.connect(Z),
    B = new Promise((C, V) => {
      let A = setTimeout(() => {
        V(new Error(`Connection to MCP server "${I}" timed out after 5000ms`))
      }, 5000)
      w.then(
        () => clearTimeout(A),
        () => clearTimeout(A),
      )
    })
  if ((await Promise.race([w, B]), G.type === 'stdio'))
    Z.stderr?.on('data', (C) => {
      let V = C.toString().trim()
      if (V) Pz(I, `Server stderr: ${V}`)
    })
  return d
}
function kU2(I) {
  let G = f4()
  if (G.approvedMcprcServers?.includes(I)) return 'approved'
  if (G.rejectedMcprcServers?.includes(I)) return 'rejected'
  return 'pending'
}
var hN1 = s2(async () => {
  let I = F2().mcpServers ?? {},
    G = KM(),
    Z = f4().mcpServers ?? {},
    d = k21(G, (w, B) => kU2(B) === 'approved'),
    W = { ...I, ...d, ...Z }
  return await Promise.all(
    Object.entries(W).map(async ([w, B]) => {
      try {
        let C = await OX9(w, B)
        return (
          s1('tengu_mcp_server_connection_succeeded', {}), { name: w, client: C, type: 'connected' }
        )
      } catch (C) {
        return (
          s1('tengu_mcp_server_connection_failed', {}),
          Pz(w, `Connection failed: ${C instanceof Error ? C.message : String(C)}`),
          { name: w, type: 'failed' }
        )
      }
    }),
  )
})
async function hU2(I, G, Z) {
  let d = await hN1()
  return (
    await Promise.allSettled(
      d.map(async (w) => {
        if (w.type === 'failed') return null
        try {
          if (!(await w.client.getServerCapabilities())?.[Z]) return null
          return { client: w, result: await w.client.request(I, G) }
        } catch (B) {
          if (w.type === 'connected')
            Pz(
              w.name,
              `Failed to request '${I.method}': ${B instanceof Error ? B.message : String(B)}`,
            )
          return null
        }
      }),
    )
  )
    .filter((w) => w.status === 'fulfilled')
    .map((w) => w.value)
    .filter((w) => w !== null)
}
var xU2 = s2(async () => {
  return (await hU2({ method: 'tools/list' }, oO, 'tools')).flatMap(
    ({ client: G, result: { tools: Z } }) =>
      Z.map((d) => ({
        ...$U2,
        name: 'mcp__' + G.name + '__' + d.name,
        async description() {
          return d.description ?? ''
        },
        async prompt() {
          return d.description ?? ''
        },
        inputJSONSchema: d.inputSchema,
        async *call(W) {
          let w = await uX9({ client: G, tool: d.name, args: W })
          yield { type: 'result', data: w, resultForAssistant: w }
        },
        userFacingName() {
          return `${G.name}:${d.name} (MCP)`
        },
      })),
  )
})
async function uX9({ client: { client: I, name: G }, tool: Z, args: d }) {
  let W = await I.callTool({ name: Z, arguments: d }, yR)
  if ('isError' in W && W.isError) {
    let w = `Error calling tool ${Z}: ${W.error}`
    throw (Pz(G, w), Error(w))
  }
  if ('toolResult' in W) return String(W.toolResult)
  if ('content' in W && Array.isArray(W.content))
    return W.content.map((w) => {
      if (w.type === 'image')
        return {
          type: 'image',
          source: { type: 'base64', data: String(w.data), media_type: w.mimeType },
        }
      return w
    })
  throw Error(`Unexpected response format from tool ${Z}`)
}
var cU2 = s2(async () => {
  return (await hU2({ method: 'prompts/list' }, sO, 'prompts')).flatMap(
    ({ client: G, result: Z }) =>
      Z.prompts?.map((d) => {
        let W = Object.values(d.arguments ?? {}).map((w) => w.name)
        return {
          type: 'prompt',
          name: 'mcp__' + G.name + '__' + d.name,
          description: d.description ?? '',
          isEnabled: !0,
          isHidden: !1,
          progressMessage: 'running',
          userFacingName() {
            return `${G.name}:${d.name} (MCP)`
          },
          argNames: W,
          async getPromptForCommand(w) {
            let B = w.split(' ')
            return await TX9({ name: d.name, client: G }, x21(W, B))
          },
        }
      }),
  )
})
async function TX9({ name: I, client: G }, Z) {
  try {
    return (await G.client.getPrompt({ name: I, arguments: Z })).messages.map((W) => ({
      role: W.role,
      content: [
        W.content.type === 'text'
          ? { type: 'text', text: W.content.text }
          : {
              type: 'image',
              source: {
                data: String(W.content.data),
                media_type: W.content.mimeType,
                type: 'base64',
              },
            },
      ],
    }))
  } catch (d) {
    throw (
      (Pz(G.name, `Error running command '${I}': ${d instanceof Error ? d.message : String(d)}`), d)
    )
  }
}


view rawclaude_code_mcp.mjs hosted with by GitHub

Claude Code with AWS Bedrock使用 AWS Bedrock 的 Claude Code

Claude Code supports both Amazon Bedrock Google Vertex AI. This makes Claude Code enterprise ready, without egress to external vendors, e.g, Anthropic’s API. Unfortunately, the minimalistic documentation provided by Anthropic to setup Claude Code with AWS Bedrock does NOT contain sufficient information. And we got stuck with the same problem with the comment section in Jonathan Evan’s Claude Code Setup Guide.Claude Code 支持 Amazon Bedrock Google Vertex AI。这使得 Claude Code 为企业做好准备,无需出口到外部供应商,例如 Anthropic 的 API。遗憾的是,Anthropic 提供的用于使用 AWS Bedrock 设置 Claude Code 的简约文档不包含足够的信息。我们在 Jonathan Evan 的 Claude Code Setup Guide 中的评论部分遇到了同样的问题。

So, we spent some time digging throught the code base and messaged Jonathan Evans for tips to setup Claude Code to work with AWS Bedrock. The code snippets in Claude Code that involves setting up AWS Bedrock or Vertex AI is as follows for those who are curious.因此,我们花了一些时间深入研究代码库,并向 Jonathan Evans 发送消息,以获取设置 Claude Code 以使用 AWS Bedrock 的提示。Claude Code 中涉及设置 AWS Bedrock 或 Vertex AI 的代码片段如下,供好奇的人使用。

var c9 = !!process.env.CLAUDE_CODE_USE_BEDROCK,
  p9 = !!process.env.CLAUDE_CODE_USE_VERTEX,
  Tl1 = {
    bedrock: 'us.anthropic.claude-3-7-sonnet-20250219-v1:0',
    vertex: 'claude-3-7-sonnet@20250219',
    firstParty: 'claude-3-7-sonnet-20250219',
  },
  PB = c9
    ? 'us.anthropic.claude-3-5-haiku-20241022-v1:0'
    : p9
      ? 'claude-3-5-haiku@20241022'
      : 'claude-3-5-haiku-20241022'
async function qX4() {
  try {
    return await DJ('tengu-capable-model-config', Tl1)
  } catch (I) {
    return C0(I), Tl1
  }
}
var f6 = s2(async () => {
  let I = await qX4()
  if (c9) {
    if (process.env.ANTHROPIC_MODEL) return process.env.ANTHROPIC_MODEL
    return I.bedrock
  }
  if (p9) {
    if (process.env.ANTHROPIC_MODEL) return process.env.ANTHROPIC_MODEL
    return I.vertex
  }
  return I.firstParty
})
async function i41() {
  return !process.env.ANTHROPIC_MODEL || process.env.ANTHROPIC_MODEL === (await f6())
}
function ml1(I) {
  if (I?.startsWith('claude-3-5-haiku')) return process.env.VERTEX_REGION_CLAUDE_3_5_HAIKU
  else if (I?.startsWith('claude-3-5-sonnet')) return process.env.VERTEX_REGION_CLAUDE_3_5_SONNET
  else if (I?.startsWith('claude-3-7-sonnet')) return process.env.VERTEX_REGION_CLAUDE_3_7_SONNET
}
var bl1 = {},
  AM = null,
  ez = s2(async () => {
    if (f2.isCI) return null
    let I = await Cj(),
      G = {
        networkConfig: { api: 'https://statsig.anthropic.com/v1/' },
        environment: {
          tier: f2.isCI || ['test', 'development'].includes('production') ? 'dev' : 'production',
        },
        logLevel: Bj.LogLevel.None,
        storageProvider: new p41(),
      }
    return (
      (AM = new Bj.StatsigClient($l1, I, G)),
      AM.on('error', (Z) => {
        C0(`Statsig error: ${Z}`)
      }),
      await AM.initializeAsync(),
      process.on('exit', () => {
        AM?.flush()
      }),
      AM
    )
  })
...
...
var Ai5 = 'bedrock-2023-05-31',
  Xi5 = new Set(['/v1/complete', '/v1/messages', '/v1/messages?beta=true'])
class qr extends AK {
  constructor({
    baseURL: I = pW('ANTHROPIC_BEDROCK_BASE_URL'),
    awsSecretKey: G = null,
    awsAccessKey: Z = null,
    awsRegion: d = pW('AWS_REGION') ?? 'us-east-1',
    awsSessionToken: W = null,
    ...w
  } = {}) {
    let B = {
      awsSecretKey: G,
      awsAccessKey: Z,
      awsRegion: d,
      awsSessionToken: W,
      ...w,
      baseURL: I || `https://bedrock-runtime.${d}.amazonaws.com`,
    }
    super({
      baseURL: B.baseURL,
      timeout: B.timeout ?? 600000,
      httpAgent: B.httpAgent,
      maxRetries: B.maxRetries,
      fetch: B.fetch,
    })
    ;(this.messages = Yi5(this)),
      (this.completions = new n_(this)),
      (this.beta = _i5(this)),
      (this._options = B),
      (this.awsSecretKey = G),
      (this.awsAccessKey = Z),
      (this.awsRegion = d),
      (this.awsSessionToken = W)
  }
  defaultQuery() {
    return this._options.defaultQuery
  }
  defaultHeaders(I) {
    return { ...super.defaultHeaders(I), ...this._options.defaultHeaders }
  }
  async prepareRequest(I, { url: G, options: Z }) {
    let d = this.awsRegion
    if (!d)
      throw new Error(
        'Expected `awsRegion` option to be passed to the client or the `AWS_REGION` environment variable to be present',
      )
    let W = await Vp0(I, {
      url: G,
      regionName: d,
      awsAccessKey: this.awsAccessKey,
      awsSecretKey: this.awsSecretKey,
      awsSessionToken: this.awsSessionToken,
    })
    I.headers = { ...I.headers, ...W }
  }
  buildRequest(I) {
    if (((I.__streamClass = Qr), p_(I.body))) I.body = { ...I.body }
    if (p_(I.body)) {
      if (!I.body.anthropic_version) I.body.anthropic_version = Ai5
      if (I.headers && !I.body.anthropic_beta) {
        let G = nq(I.headers, 'anthropic-beta')
        if (G != null) I.body.anthropic_beta = G.split(',')
      }
    }
    if (Xi5.has(I.path) && I.method === 'post') {
      if (!p_(I.body))
        throw new Error('Expected request body to be an object for post /v1/messages')
      let G = I.body.model
      I.body.model = void 0
      let Z = I.body.stream
      if (((I.body.stream = void 0), Z)) I.path = `/model/${G}/invoke-with-response-stream`
      else I.path = `/model/${G}/invoke`
    }
    return super.buildRequest(I)
  }
}
function Yi5(I) {
  let G = new fd(I)
  return delete G.batches, delete G.countTokens, G
}
function _i5(I) {
  let G = new wZ(I)
  return delete G.promptCaching, delete G.messages.batches, delete G.messages.countTokens, G
}
var lB2 = X1(bB2(), 1),
  xe5 = 'vertex-2023-10-16',
  ce5 = new Set(['/v1/messages', '/v1/messages?beta=true'])
class Gs extends AK {
  constructor({
    baseURL: I = pW('ANTHROPIC_VERTEX_BASE_URL'),
    region: G = pW('CLOUD_ML_REGION') ?? null,
    projectId: Z = pW('ANTHROPIC_VERTEX_PROJECT_ID') ?? null,
    ...d
  } = {}) {
    if (!G)
      throw new Error(
        'No region was given. The client should be instantiated with the `region` option or the `CLOUD_ML_REGION` environment variable should be set.',
      )
    let W = { ...d, baseURL: I || `https://${G}-aiplatform.googleapis.com/v1` }
    super({
      baseURL: W.baseURL,
      timeout: W.timeout ?? 600000,
      httpAgent: W.httpAgent,
      maxRetries: W.maxRetries,
      fetch: W.fetch,
    })
    ;(this.messages = pe5(this)),
      (this.beta = ie5(this)),
      (this._options = W),
      (this.region = G),
      (this.projectId = Z),
      (this.accessToken = W.accessToken ?? null),
      (this._auth =
        W.googleAuth ??
        new lB2.GoogleAuth({ scopes: 'https://www.googleapis.com/auth/cloud-platform' })),
      (this._authClientPromise = this._auth.getClient())
  }
  defaultQuery() {
    return this._options.defaultQuery
  }
  defaultHeaders(I) {
    return { ...super.defaultHeaders(I), ...this._options.defaultHeaders }
  }
  async prepareOptions(I) {
    let G = await this._authClientPromise,
      Z = await G.getRequestHeaders(),
      d = G.projectId ?? Z['x-goog-user-project']
    if (!this.projectId && d) this.projectId = d
    I.headers = { ...Z, ...I.headers }
  }
  buildRequest(I) {
    if (p_(I.body)) I.body = { ...I.body }
    if (p_(I.body)) {
      if (!I.body.anthropic_version) I.body.anthropic_version = xe5
    }
    if (ce5.has(I.path) && I.method === 'post') {
      if (!this.projectId)
        throw new Error(
          'No projectId was given and it could not be resolved from credentials. The client should be instantiated with the `projectId` option or the `ANTHROPIC_VERTEX_PROJECT_ID` environment variable should be set.',
        )
      if (!p_(I.body))
        throw new Error('Expected request body to be an object for post /v1/messages')
      let G = I.body.model
      I.body.model = void 0
      let d = (I.body.stream ?? !1) ? 'streamRawPredict' : 'rawPredict'
      I.path = `/projects/${this.projectId}/locations/${this.region}/publishers/anthropic/models/${G}:${d}`
    }
    if (
      I.path === '/v1/messages/count_tokens' ||
      (I.path == '/v1/messages/count_tokens?beta=true' && I.method === 'post')
    ) {
      if (!this.projectId)
        throw new Error(
          'No projectId was given and it could not be resolved from credentials. The client should be instantiated with the `projectId` option or the `ANTHROPIC_VERTEX_PROJECT_ID` environment variable should be set.',
        )
      I.path = `/projects/${this.projectId}/locations/${this.region}/publishers/anthropic/models/count-tokens:rawPredict`
    }
    return super.buildRequest(I)
  }
}


view rawclaude_code_csp.mjs hosted with by GitHub

0. AWS Bedrock Setup0. AWS Bedrock 设置

Claude Code needs two models - Claude 3.7 Sonnet and Claude 3.5 Haiku. Please request them in us-east-1, the default region for Claude Code.Claude Code 需要两个模型 - Claude 3.7 Sonnet 和 Claude 3.5 Haiku。请在 Claude Code 的默认区域 us-east-1 中请求它们。

1. Inference Profile1. 推理配置文件

For cloud security best practices, create a new policy in AWS Identiy and Access Management (IAM) for inferencing and invocation the models, name it
AmazonBedrockInferenceProfile for clarity. Attach this policy to your AWS key and secret’s user or group.有关云安全最佳实践,请在 AWS Identiy 和 Access Management (IAM) 中创建一个新策略来推理和调用模型,为清楚起见,请将其命名为
AmazonBedrockInferenceProfile。将此策略附加到您的 AWS 密钥和密钥的用户或组。

The policy is as follows.策略如下。

{  "Version": "2012-10-17",  "Statement": [    {      "Effect": "Allow",      "Action": [        "bedrock:CreateInferenceProfile",        "bedrock:GetInferenceProfile",        "bedrock:ListInferenceProfiles",        "bedrock:InvokeModel*"      ],      "Resources": "*"    }  ]}

Now we are done on the AWS side. Lets test it out quickly with the following script.现在,我们已经完成了 AWS 方面的工作。让我们使用以下脚本快速测试一下。

import boto3
import json
client = boto3.client('bedrock-runtime', region_name='us-east-1')
response = client.invoke_model(
    modelId='us.anthropic.claude-3-7-sonnet-2025-0219-v1:0',
    body=json.dumps({
        "anthropic_version": "bedrock-2023-05-31",
        "messages": [
            {
                "role": "user",
                "content": [{"type": "text", "text": "wassup cluade do you code"}],
            }
        ],
        "max_tokens": 200
    })
)
print(response['body'].read().decode())

view rawtest.py hosted with by GitHub

2. Setup Local AWS Config2. 设置本地 AWS Config

Ensure that the AWS access key and secret are in the [default] profiles is stored in your ~/.aws/config/credentials确保 AWS 访问密钥和密钥位于 [default] 配置文件中,并将其存储在您的 ~/.aws/config/credentials 中

And, for the config, ensure your [default] profile sets region to us-east-1 the output to json, e.g.,并且,对于配置,请确保您的 [default] 配置文件将 region 设置为 us-east-1,将输出设置为 json,例如,

[default]region = us-east-1output = json

NOTE: AWS_REGION for AWS and CLAUDE_ML_REGION for GCP are included in the code as either environment variables or settings. We could not get those to work, so we just stick with defaults.注意:AWS_REGION for AWS 和 CLAUDE_ML_REGION for GCP 作为环境变量或设置包含在代码中。我们无法让它们正常工作,所以我们只能坚持使用默认值。

3. Setup Environment Variables3. 设置环境变量

Add the following to your .bashrc, .zshrc, .profile, or config.fish depending on your shell. Note that根据您的 shell,将以下内容添加到您的 .bashrc、.zshrc、.profile 或 config.fish 中。请注意,

# Configure for Bedrock with Claude 3.7 Sonnetexport CLAUDE_CODE_USE_BEDROCK=1export ANTHROPIC_MODEL='us.anthropic.claude-3-7-sonnet-20250219-v1:0'# AWS Bedrock does not support prompt caching yet# Control prompt caching - set to 1 to disable export DISABLE_PROMPT_CACHING=1

After this, we are all good to go. Let’s claude from terminal.在此之后,我们都可以开始了。让我们从终端 claude 开始。

Easter Egg复活节彩蛋

Apparently, you can ask Claude Code for Anthropic or Claude stickers. It will then go through the form-filling control loop and submit a Google Form on your behalf. The prompt is shown below:显然,您可以向 Claude Code 索取 Anthropic 或 Claude 贴纸。然后,它将通过表单填写控制循环并代表您提交 Google 表单。提示符如下所示:

var SE2 = 'Sends the user swag stickers with love from Anthropic.',

LE2 = `This tool should be used whenever a user expresses interest in receiving Anthropic or Claude stickers, swag, or merchandise. When triggered, it will display a shipping form for the user to enter their mailing address and contact details. Once submitted, Anthropic will process the request and ship stickers to the provided address.

Common trigger phrases to watch for:

- "Can I get some Anthropic stickers please?"

- "How do I get Anthropic swag?"

- "I'd love some Claude stickers"

- "Where can I get merchandise?"

- Any mention of wanting stickers or swag

The tool handles the entire request process by showing an interactive form to collect shipping information.

NOTE: Only use this tool if the user has explicitly asked us to send or give them stickers. If there are other requests that include the word "sticker", but do not explicitly ask us to send them stickers, do not use this tool.

For example:

- "How do I make custom stickers for my project?" - Do not use this tool

- "I need to store sticker metadata in a database - what schema do you recommend?" - Do not use this tool

- "Show me how to implement drag-and-drop sticker placement with React" - Do not use this tool

view raweaster_egg.mjs hosted with by GitHub

Unfortunately, it is no longer available. :(不幸的是,它不再可用。:(

Trivia Factoids琐事 Factoids

Claude Code seems to have an internal code name tengu. It’s a React CLI tool, built using commander and ink. It uses zod for schema validation and type inference checking, and ripgrep for traversiing files and directories.Claude Code 似乎有一个内部代号 tengu。它是一个 React CLI 工具,使用 commander 和 ink 构建。它使用 zod 进行架构验证和类型推理检查,使用 ripgrep 遍历文件和目录。

Control Flow控制流

Below is Claude Code’s control flow diagram from a bird’s-eye view. Note that this excludes many lines of formatting, preprocessing, and CLI user interfacing code. We could have also missed some part of the control flow due to its size and obsfucation.下面是 Claude Code 的鸟瞰图控制流程图。请注意,这不包括许多行格式化、预处理和 CLI 用户接口代码。由于控制流的大小和干扰,我们也可能错过了控制流的某些部分。

Mermaid code for the control flow is in this gist.控制流的 Mermaid 代码在这个要点中。

References引用

  • Claude Code Overview. Anthropic Documentation https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overviewClaude Code 概述。Anthropic Documentation https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview
  • Model Control Protocol https://modelcontextprotocol.io/introduction
  • Claude Code on Amazon Bedrock: Quick Setup GuideAmazon Bedrock 上的 Claude Code:快速设置指南

原链接:
https://leehanchung.github.io/blogs/2025/03/07/claude-code/#
bootstrap-confidence-interval

相关推荐

字体缩放(方式一)(字体缩放150%怎么做)

通过元素宽度和字数计算得到缩放简单实现如下:/***字体最大为视觉要求大小(maxFontSize);超出缩小字体显示,最小为minFontSize;最小字体时超出部分使用圆点(...);*p...

网页世界隐藏的神秘代码语言,竟能这样改变布局

CSS基础:选择器与属性CSS(CascadingStyleSheets)是用于控制网页外观的一门样式表语言。它通过定义HTML元素的显示方式来增强网页的表现力。CSS的选择器允许开发者精确地定位...

CSS属性值计算过程详解(css属性用来定义元素计算)

在CSS中,即使某些属性没有显式声明,浏览器也会通过**属性值计算过程**为每个元素的所有属性赋予最终值。这一过程分为四个关键步骤,以下将逐一解析。1.确定声明值浏览器首先检查所有**直接应用**到...

软网推荐:找回调整Windows 10字号功能

之前的系统,从WindowsXP到早期版本的Windows10,均有字体大小调整功能,但从创意者版Windows10以来,取消了之前的设置选项,取而代之的是自定义缩放比例设置。使用这个功能调整过...

Excel中如何设置文本框属性,实例代码讲解

Excel不仅可以对数据进行处理,而且也可以图形化数据,直观显示数据表达的内容。本节介绍一个很重要的对象,Characters,字符对象,使用Characters对象可修改包含在全文本字符串中的任...

CSS 字体样式(css中字体)

本节我们来讲字体样式,之前我们学习HTML的时候学过一些用于字体加粗、倾斜的标签,但是使用标签来实现的效果肯定没有我们通过CSS中的样式来的方便。接下来我们会给大家介绍下面这几个属性的使用:通...

PC网站建设必备代码知识:HTML基础与应用技巧

在PC网站建设的相关课程里,代码扮演着至关重要的角色。只有熟练运用正确的代码,我们才能打造出功能完善、用户体验出色的PC网站。接下来,我会详细讲解在PC网站建设环节中必须了解的代码知识。HTML基础代...

让你大跌眼镜的疯狂 HTML 和 CSS 技巧

今天,分享一个让你大开眼界的技巧。通过使用这个技巧,你可以将整个网页变成一个CSS编辑器。没错,你从未见过这种方法。当我第一次尝试时,我完全被震惊到了。现在,让我们开始吧!步骤1首先,创建一个基础的...

jQuery EasyUI使用教程:创建一个链接按钮

jQueryEasyUI最新版下载>本教程主要为大家展示如何使用jQueryEasyUI创建一个链接按钮。通常情况下,使用“button/”元素来创建一个按钮;使用“a/”元素来创建链接按钮...

React 19 有哪些新特性?(react100)

如果你对React18还不熟悉,欢迎阅读之前的文章《React18全览[1]》最近React发布了V19RC版本,按照惯例,我们对React19的新特性进行一次深度的体验学习...

Java注解探秘:为什么@PostConstruct能解决你的初始化难题?

你是否在Spring项目中遇到过这样的困扰:明明依赖注入已经完成,但某些配置就是无法正常加载?手动调用初始化方法又容易引发空指针异常?这就是@PostConstruct注解大显身手的时候了!@Post...

AI驱动的表单自动填写(ai置入表格)

我们都同意,填写表格是一项枯燥且耗时的任务。如果我们可以创建一个可以为我们填写表格的AI助手,让我们将时间投入到更有建设性的任务中,那会怎样?AI助手将能够通过调用以表单字段为参数的函数来填写表...

从零到一:小程序设计新手如何快速上手?

开发环境搭建对于小程序设计新手而言,搭建合适的开发环境是首要任务。以小程序为例,其官方提供了功能强大的开发工具——开发者工具。首先,新手需前往官方开发者平台,在页面中找到“工具下载”板块,根据...

JavaSwingGUI从小白到大神-6(续)(java从小白到大牛怎么样)

接上一篇《JavaSwingGUI从小白到大神-6》,因本篇文章3万多字,头条一篇发不完,只能分开发。同事查询面板:CompanyFind.javapublicclassCompanyFind{...

C# winform界面假死(c#程序假死)

针对C#WinForm界面假死问题,以下是分步解决方案:1.使用异步编程(async/await)将耗时操作移至后台线程,保持UI线程响应。步骤:将事件处理函数标记为async。使用Task....