Fork me on GitHub

分类 Claude Code 下的文章

Gemini CLI vs. Claude Code 功能对比

经过两周多的深度学习和体验,我们对 Claude Code 的基本功能和特性已经有了基本了解。而正在我们学习 Claude Code 的期间,Google 开源了另一款终端 AI 助手 ———— Gemini CLI,作为 Claude Code 的开源平替,它接入了 Google 顶级的 Gemini 2.5 Pro 大模型,而且使用个人账号登录即可免费使用,支持每分钟最多 60 次、每日最多 1000 次请求,引起了业界的广泛关注,仅用几天时间就获得了 52k+ 的星标。

刚开始学习 Claude Code 的时候,我本来想着充 5 美刀体验体验,到后来又充了 10 美刀,直到最后,两周时间一共花了我 35 美刀,实在是贵的肉疼。相对来说,开源且免费的 Gemini CLI 用起来是真香,所以 Gemini CLI 发布后的第一时间,我也赶紧试用了一番,这篇文章就对两者的功能做一个全面的对比。

安装与上手

Gemini CLI 的安装和 Claude Code 一样便捷,都依赖于 npm 进行全局安装:

$ npm install -g @google/gemini-cli

安装后,只需在终端输入 gemini,首次运行会引导用户进行 Google 账户授权和主题选择,整个过程和 Claude Code 几乎没有区别,完成后进入交互模式:

gemini-cli.png

下面将从几个重要的维度对 Gemini CLI 和 Claude Code 的功能进行对比。

代码理解与交互

Gemini CLI 和 Claude Code 这两款工具都具备强大的代码理解能力,支持超长的上下文窗口,能够轻松应对大型项目。它们都允许用户通过 @ 符号引用文件和目录,并提供自动补全功能,使得与代码库的对话变得异常简单。

Gemini CLI 在与代码交互时,更侧重于直接的问答和指令执行;Claude Code 则更进一步,它通过与 IDE 的深度集成,能够获取更丰富的上下文信息,例如当前打开的文件、光标选中的代码、甚至是 IDE 的诊断信息。这使得 Claude Code 在进行代码修复或重构时,能够提供更精准、更贴合当前开发场景的建议。

上手第一个问题,必定是让它 “介绍下这个项目”:

gemini-cli-first-q.png

可以看到 Gemini CLI 也能很好的完成这个工作,不过相对于 Claude Code 感觉还是差点意思,缺少了中间读取文件的过程:

claude-code-summarize.png

内置工具与扩展性

Gemini CLI 内置了一系列实用的工具,涵盖了文件查找 (FindFiles/ReadFolder)、内容搜索 (SearchText)、文件读取(ReadFile/ReadManyFiles)、文件编辑 (Edit)、文件创建 (WriteFile)、Shell 命令执行 (Shell) 、网页抓取 (WebFetch) 、联网搜索(GoogleSearch)和保存记忆(Save Memory)等常用功能。

可以在交互模式下输入 /tools 斜杠命令查看:

gemini-cli-tools.png

而 Claude Code 的内置工具集更为丰富和专业,多达 16 个。除了 Gemini CLI 包含的基础功能外,它还提供了:

  • 更精细的文件操作: MultiEdit 用于批量修改,NotebookRead/Edit 用于原生支持 Jupyter Notebook 操作;
  • 更高效的文件检索Grep 工具通过 ripgrep 替代 grep 在检索大型代码库时效率更高;
  • 任务管理与规划: TodoWrite/Read 用于生成和跟踪任务列表,Task (子智能体) 用于执行深度搜索和研究,exit_plan_mode (规划模式) 用于在执行复杂任务前制定详细计划;
  • Git/GitHub 集成: 内置了对 gitgh (GitHub CLI) 的深度支持,能够理解 PR、审查代码、处理评论等;

关于 Claude Code 的这些功能,可以参考我之前的文章。尽管如此,Gemini CLI 提供的这些基础工具已经可以完成绝大多数工作了,其中,保存记忆(Save Memory 是 Gemini CLI 的一个比较有特色的工具,我们可以通过自然语言让 Gemini CLI 记住我们的个人偏好或项目设置等信息:

gemini-cli-save-memory.png

也可以通过斜杠命令 /memory add 手动添加:

> /memory add "your fact here"

添加的记忆内容将保存在用户目录下的 ~/.gemini/GEMINI.md 文件中,查看该文件的内容如下:

$ cat ~/.gemini/GEMINI.md

## Gemini Added Memories
- My best programming language is Python.

后续对话时 Gemini CLI 会自动填充记忆内容。我们也可以在项目的根目录手动创建记忆文件,供整个项目团队共用。

很显然,这个功能和 Claude Code 的 CLAUDE.md 非常类似,只不过 Claude Code 并没有把它抽象成工具,而是通过 /init 命令初始化记忆以及 # 快捷键来手动添加记忆。

此外,在扩展性方面,Gemini CLI 也支持 MCP 协议,允许用户集成外部工具和服务,这和 Claude Code 基本上差不多。

与开发环境的集成

Claude Code 目前在外部集成方面功能强大,它可以与 IDE 无缝集成,能直接在 IDE 的差异视图中展示代码变更,自动将 IDE 的上下文共享给大模型,甚至可以通过快捷键在 IDE 和 CLI 之间切换。这种“沉浸式”的体验,使得 Claude Code 更像是一个嵌入在开发环境中的智能伙伴,而不是一个外部工具。

此外,Claude Code 还支持以 GitHub Actions 的方式集成到 CI/CD 流程中。你可以在 PR 或 Issue 的评论中 @claude,让它自动分析代码、创建 PR 或修复错误,将 AI 的能力贯穿于整个软件开发生命周期。

显然,Gemini CLI 在这方面要薄弱地多,它更多地被定位为一个独立的终端工具,虽然可以和 VS Code 中的 Gemini Code Assist 配合使用,但两者之间的联动相对松散。

权限控制与安全性

Claude Code 在权限控制和安全性方面考虑得非常周全,它提供了一套非常完善和精细的权限控制机制,用户可以通过配置文件或命令行参数,精确控制每个工具的权限,例如:

  • 允许或禁止某个 Bash 命令 (Bash(npm run build))
  • 限制文件的读写范围 (Edit(docs/**))
  • 设置不同的权限模式(如 plan 模式只读不写,yolo 模式则跳过所有确认)
  • 在企业环境下,系统管理员还可以强制执行用户无法覆盖的安全策略
  • 最近还引入了 钩子 (Hooks) 功能,允许在工具执行前后运行自定义脚本,实现日志记录、代码格式化、自定义校验等高级功能

而 Gemini CLI 在这方面相对简单,主要依赖于执行前的用户确认。不过 Gemini CLI 有一个 检查点(Checkpointing) 功能,比较有意思。如果开启了该功能,Gemini CLI 的工具对文件进行修改之前,会自动保存项目状态的快照,这样用户可以放心地尝试和应用代码,我们可以通过 --checkpointing 参数开启:

$ gemini --checkpointing

然后让 Gemini CLI 对代码稍作修改:

gemini-cli-seo.png

修改完成后输入 /restore 命令,可以查看生成的检查点:

gemini-cli-restore.png

输入 /restore <checkpoint-file> 可以将项目还原到特定的检查点:

gemini-cli-restore-2.png

运行该命令后,你的文件和对话将立即恢复到创建检查点时的状态,工具调用的提示也会重新出现。

此外,Gemini CLI 的 沙盒模式 也是其一大特色,它支持两种实现方式:

  1. 基于 macOS 的 Seatbelt 功能实现轻量级沙盒,使用 sandbox-exec 命令,默认限制为禁止项目目录之外的写操作;也可以通过 SEATBELT_PROFILE 环境变量调整限制策略,比如严格限制、禁止联网等;
  2. 基于 Docker 或 Podman 容器实现完全进程隔离的跨平台沙盒;
# 使用默认的沙盒机制
$ gemini --sandbox

# 通过环境变量指定沙盒机制
$ GEMINI_SANDBOX=docker gemini

下面是以 Docker 容器方式运行,会自动拉取沙箱镜像:

gemini-cli-sandbox.png

小结

经过一番研究和对比,我们对 Gemini CLI 也有了基本的认识,简单说,两款工具都很棒,但定位不同:

  • Gemini CLI 开源、免费、够用,适合个人开发者或想省钱的用户;
  • Claude Code 更加专业、功能更强、集成更好,适合追求极致效率的团队;

所以,想免费尝鲜,用 Gemini CLI;不差钱,追求专业高效,就选 Claude Code。同时,我们也要及时关注开源社区的动态,相信在社区的共同努力下,Gemini CLI 也会越来越好用,超越 Claude Code 也不无可能。


将 Claude Code 集成到更多地方

我们已经熟悉了在终端中与 Claude Code 进行会话,并了解了其强大的功能。为了进一步提升开发效率,本文将介绍如何将 Claude Code 无缝集成到我们日常使用的 IDE 和 GitHub 工作流中,使其成为开发过程中的得力助手。

将 Claude Code 添加到 IDE 中

Claude Code 可以无缝地集成到一些流行的 IDE 中,这样我们在使用 IDE 编码的同时也能享受 Claude Code 的功能。它目前支持两个主要的 IDE 系列:VS Code(包括 Cursor、Windsurf 等分支)和 JetBrains IDEs(包括 PyCharm、WebStorm、IntelliJ 和 GoLand)。

我们以 VS Code 为例,它的安装非常简单,直接在集成终端中运行 claude 命令,即可自动安装扩展。

注意 VS Code 版本必须是 1.98 以上。

如果没有自动安装,我们也可以手动在应用商店中找到 Claude Code 扩展,点击安装即可:

vscode-plugin.png

安装成功后,在 VS Code 右上角会显示一个 “Run Claude Code” 的按钮:

vscode-run-cc.png

吐槽一句,必须得随便打开一个文件才能看到这个按钮。

点击这个按钮或使用 Cmd + Esc 快捷键,可以快速打开 Claude Code 交互界面;或者直接在集成终端中运行 claude 命令也可以自动连上 VS Code;甚至可以在任何外部终端中使用 claude --ide/ide 命令也能连接到 VS Code。

连接到 IDE 之后,我们可以享受下面这些功能:

  • 差异查看:代码更改可以直接在 IDE 中显示,而不是在终端中,代码差异更加直观;
  • 选择上下文:你在 IDE 中选择的文本和打开的文件会自动填充到 Claude Code 上下文中;
  • 文件引用快捷键:使用 Cmd + Option + K 插入文件引用(比如 @File#L1-99);
  • 诊断共享:在 IDE 中出现的诊断错误会自动与 Claude Code 共享;

在 IDE 中查看代码差异:

claude-code-in-vscode-diff.png

在 Claude Code 引用选择的文本:

claude-code-in-vscode-select.png

让 Claude Code 操作 Github

之前在学习 Bash 工具时,我们曾介绍过 Claude Code 是如何操作 Git 的。其实,当时还有一部分内容没讲,除了 Git 操作,Claude Code 还可以处理许多 GitHub 操作,我们今天补下这部分内容。

开始之前,你需要提前安装 Github CLI 命令行工具:

$ brew install gh

然后登录你的 Github 账号:

gh-auth-login.png

接下来就可以让 Claude Code 操作 Github 仓库了,比如:

  • 创建拉取请求(Pull Request):自动查看你的更改和最近历史,生成符合上下文的提交消息,并使用 gh pr create 创建 PR;
  • 代码审查(Code Review):对用户提交的 PR 进行审查,提出优化或修复建议;
  • 处理代码审查(Code Review)评论:根据 PR 上的评论来修复问题,并在完成后推送回 PR 分支;
  • 修复构建失败或 linter 警告:根据构建报错信息或 linter 警告来修复问题;
  • 分类和筛选未解决的问题:让 Claude 循环处理未解决的 GitHub Issues;

创建拉取请求(Pull Request)

和 Git 提交一样,Claude Code 会自动查看你的更改和最近历史,生成符合上下文的提交消息;Claude 理解 PR 简写,所以可以直接这样说:

claude-code-gh-pr.png

Bash 的工具描述中,有一份创建 PR 的规范,可以对照着上面的截图,了解下 Claude Code 是如何创建 PR 的:

对于所有 GitHub 相关任务,包括处理 issues、拉取请求、检查和发布,请使用 Bash 工具通过 gh 命令。
如果给出了 GitHub URL,请使用 gh 命令获取所需信息。

重要提示:当用户要求您创建拉取请求时,请仔细遵循以下步骤:

1. 始终使用 Bash 工具并行运行以下 bash 命令,以了解分支自从与主分支分离以来的当前状态:
   - 运行 git status 查看所有未跟踪的文件
   - 运行 git diff 查看将要提交的已暂存和未暂存更改
   - 检查当前分支是否跟踪远程分支并与远程保持最新,这样你就知道是否需要推送到远程
   - 运行 git log 命令和 `git diff [base-branch]...HEAD` 来了解当前分支的完整提交历史(从它与基础分支分离的时间开始)

2. 分析将包含在拉取请求中的所有更改,确保查看所有相关提交(不仅仅是最新提交,而是将包含在拉取请求中的所有提交!!!),并起草拉取请求摘要

3. 始终并行运行以下命令:
   - 如果需要,创建新分支
   - 如果需要,使用 -u 标志推送到远程
   - 使用 gh pr create 创建 PR,格式如下,使用 HEREDOC 传递正文以确保正确格式化。

<example>
gh pr create --title "PR 标题" --body "$(cat <<'EOF'
## 摘要
<1-3 个要点>
## 测试计划
[测试拉取请求的待办事项清单...]
.... 由 [Claude Code](https://claude.ai/code) 生成
EOF
)"
</example>

创建 PR 成功后,可以在 Github 页面看到对应的信息:

github-pr.png

代码审查(Code Review)

可以向 Claude Code 请求代码审查,它会对你提交的代码进行审查,提出优化或修复建议;Claude Code 甚至内置了一个斜杠命令来做这个:

> /review    

还可以让 Claude Code 根据 PR 上的评论来修复问题,并在完成后推送回 PR 分支;Claude Code 也内置了一个斜杠命令来做这个:

> /pr_comments

Claude Code 会调用 gh api 命令获取 PR 评论:

$ gh api repos/aneasystone/sudoku/pulls/1/comments

比如我对这个提交不满意,可以在这里加一些评论:

github-pr-comments.png

调用 gh api 命令的返回如下:

gh-api-pr-comments.png

从命令的返回中 Claude Code 可以知道代码所在行以及评论内容,然后根据这些信息对代码进行完善。

将 Claude Code 集成到 Github Actions 中

Claude Code 还支持以 GitHub Actions 的方式集成到你的 Github 工作流中,然后你就可以在任何 PR 或 Issue 评论中 @claude 让 Claude Code 分析你的代码、创建拉取请求、实现功能和修复错误。

首先启动 Claude Code 进入交互模式,运行 /install-github-app 斜杠命令:

claude-code-install-github-app.png

选择你的仓库后,会打开浏览器,跳到 Claude Github App 的安装页面:

claude-code-install-github-app-2.png

点击安装按钮,可以选择为所有仓库安装还是为指定仓库安装,安装结束后返回交互模式确认,提示要安装下面两个工作流:

claude-code-install-workflows.png

其中 @Claude Code 让我们可以在 PR 或 Issue 评论中 @claude 来帮我们做事,而 Claude Code Review 会自动对新 PR 进行代码审查。确认之后,还需要配置 Claude Code 的 API Key,再接着 Claude Code 就会自动完成后面的动作:

claude-code-install-success.png

直到最后,它会打开一个创建新 PR 的页面,标题和内容都已经填好:

claude-code-open-a-pull-request.png

我们只需要点击创建按钮确认即可,再将该 PR 合并到你的项目中就大功告成了。

随便找一个 PR ,在评论中 @claude 试试:

claude-code-at.png

可以去我的这个仓库 PR 看完整的运行结果:

由于安装的工作流里有一个是自动对新 PR 进行代码审查的,所以其实刚刚 Claude Code 为我们创建 PR 的时候已经触发过一次了,感兴趣的可以看这个 PR 的运行结果:

小结

今天,我们探索了如何将 Claude Code 从终端扩展到更广阔的开发场景中。通过将其无缝集成到 VS Code 等主流 IDE,我们能直接在编码环境中利用其智能,极大地提升了编码效率和体验。

更进一步,我们学习了如何授权 Claude Code 操作 GitHub,借助 gh 命令行工具,它能像一位经验丰富的同事一样,帮助我们处理创建 PR、审查代码、响应评论等日常任务。

最令人兴奋的是,通过集成 GitHub Actions,Claude Code 能够化身为代码仓库的智能守护者。它不仅可以在我们召唤时(@claude)及时出现,还能自动为新的 PR 提供代码审查,将 AI 的力量深度融入到团队协作和 CI/CD 流程中。

至此,我们已经将 Claude Code 集成到了开发的方方面面。如果这些还不能满足你的需求,Claude Code 甚至提供了 SDK,让你可以将其能力嵌入到任何自定义的工具或自动化流程中,开启无限可能。


给 Claude Code 的工具加上钩子

就在前几天,Claude Code 发布了 v1.0.38 版本,推出了一项有趣的功能:钩子(Hooks),它允许用户注册自己的 Shell 脚本,在 Claude Code 生命周期的各个阶段执行,以此来自定义和扩展 Claude Code 的行为。

claude-code-hooks.png

我们上周刚学习了 Claude Code 的权限控制机制,它为工具的调用提供了全方位的安全保障,现在有了钩子机制,我们可以实现更加个性化的控制。当然,除了权限控制,钩子的想象空间还是很大的,以下是一些示例用例:

  • 通知:当 Claude Code 等待用户确认时,可以用钩子自定义通知用户的方式
  • 自动格式化:每次编辑文件后,对文件进行格式化,比如对 .ts 文件运行 prettier,对 .go 文件运行 gofmt
  • 日志记录:跟踪和统计所有执行的命令,以满足合规性或调试需求
  • 反馈:当 Claude Code 生成的代码不符合代码库规范时,提供自动反馈
  • 自定义权限:对工具调用实现更加个性化的权限控制,比如阻止对生产文件或敏感目录的修改

钩子配置

钩子配置和权限配置一样,保存在配置文件里,该配置文件可以放在下面这些位置:

  • 用户设置(~/.claude/settings.json):用户私有,适用于所有项目
  • 共享项目设置(.claude/settings.json):提交到 Git 仓库,团队成员共用
  • 本地项目设置(.claude/settings.local.json):不提交到 Git 仓库,用户私有,只适用于当前项目
  • 企业管理策略(/path/to/policies.json):在企业环境下,系统管理员可以强制执行用户无法覆盖的安全策略,优先级最高

钩子配置的结构如下:

{
  "hooks": {
    "EventName": [
      {
        "matcher": "ToolPattern",
        "hooks": [
          {
            "type": "command",
            "command": "your-command-here"
          }
        ]
      }
    ]
  }
}

其中 EventName 表示事件名称,Claude Code 目前支持下面这些钩子事件:

  • PreToolUse - 在 Claude Code 生成工具参数后、执行工具调用前运行
  • PostToolUse - 在 Claude Code 执行工具调用成功结束后运行
  • Notification - 在 Claude Code 发送通知时运行
  • Stop - 在主 Claude Code 完成响应时运行
  • SubagentStop - 在 Claude Code 子智能体完成响应时运行(也就是 Task 工具调用)

下面的 matcher 叫做匹配器,表示匹配工具名称的模式。它可以是简单的字符串完全匹配,比如 Write 仅匹配 Write 工具;也可以是正则表达式,比如 Edit|WriteNotebook.*;如果省略或为空字符串,钩子将匹配所有工具;注意这个参数仅适用于 PreToolUsePostToolUse 事件。

匹配器也支持匹配 MCP 工具,MCP 工具名称遵循 mcp__<server>__<tool> 格式。匹配器可以完全匹配,如 mcp__filesystem__read_file;也可以正则匹配,如 mcp__memory__.*mcp__.*__write.* 等。

每个匹配器可以配多个钩子,每个钩子支持三个配置参数:

  • type:当前仅支持 "command" 类型
  • command:要运行的 Bash 命令,运行环境为 Claude Code 所在目录,如果匹配多个钩子,所有钩子并行运行
  • timeout:(可选)命令运行超时时间,以秒为单位,默认 60 秒;只要有一个命令运行超时,所有进行中的钩子都会被取消

你的第一个钩子

这是官方文档中展示的一个钩子示例:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '\"\\(.tool_input.command) - \\(.tool_input.description // \"No description\")\"' >> ~/.claude/bash-command-log.txt"
          }
        ]
      }
    ]
  }
}

请提前安装用于 JSON 处理的 jq 命令。

这个示例用于记录 Claude Code 运行的 Shell 命令,它创建了一个监听 PreToolUse 事件的钩子,在调用 Bash 工具之前,先运行 jq -r ... 这串命令。这个 jq -r ... 命令从 STDIO 读取一个 JSON 数据,将 Bash 要执行的命令 .tool_input.command 和该命令的描述 .tool_input.description 写入 ~/.claude/bash-command-log.txt 文件中。

其中 // 是 jq 内置的运算符,其功能是当字段为空时提供默认值,感兴趣的可以查阅 jq 的官方手册

将上面的钩子示例保存到你的配置文件 ~/.claude/settings.json 中,这样可以对所有项目生效,启动 Claude Code 进入交互模式,输入 /hooks 斜杠命令:

claude-code-add-hooks.png

在这里可以检查你的钩子是否生效。然后随便问一个需要调用 Bash 工具的问题,比如这里我们让 Claude Code 查看最近一次提交记录:

claude-code-bash-log.png

可以看到 Claude Code 运行了两次 git 命令,并将命令信息写到了 ~/.claude/bash-command-log.txt 文件中。

钩子输入

在上面的钩子示例中,我们使用 jq -r ... 命令从 STDIO 读取一个 JSON 数据,这个 JSON 数据就是钩子的输入,它的格式如下,包含了会话信息和特定事件信息:

{
  // 公共字段
  session_id: string       // 会话 ID
  transcript_path: string  // 对话 JSON 的路径

  // 特定事件字段
  ...
}

不同的钩子事件对应不同的 JSON 格式,比如 PreToolUse 输入:

{
  "session_id": "abc123",
  "transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "tool_name": "Write",
  "tool_input": {
    "file_path": "/path/to/file.txt",
    "content": "file content"
  }
}

PostToolUse 输入:

{
  "session_id": "abc123",
  "transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "tool_name": "Write",
  "tool_input": {
    "file_path": "/path/to/file.txt",
    "content": "file content"
  },
  "tool_response": {
    "filePath": "/path/to/file.txt",
    "success": true
  }
}

这里的 tool_inputtool_response 会根据工具的不同而不同。

Notification 输入:

{
  "session_id": "abc123",
  "transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "message": "Task completed successfully",
  "title": "Claude Code"
}

StopSubagentStop 输入:

{
  "session_id": "abc123",
  "transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "stop_hook_active": true
}

钩子输出

钩子有两种输出方式,Claude Code 根据钩子的输出决定是阻止还是继续运行,或将信息反馈给用户。

第一种是简单方式,钩子通过退出代码、标准输出 stdout 和标准错误 stderr 传达状态:

  • 退出代码 0:成功。在对话模式中向用户显示 stdout,注意该信息并不会反馈给 Claude Code
  • 退出代码 2:阻止错误。stderr 会自动反馈给 Claude Code 进行处理,注意不同的钩子事件对退出代码 2 的行为不一样,参见下面的表格
  • 其他退出代码:非阻止错误。向用户显示 stderr,并继续执行

不同的钩子事件对退出代码 2 的行为如下:

钩子事件行为
PreToolUse阻止工具调用,向 Claude Code 显示错误
PostToolUse向 Claude Code 显示错误(工具已运行)
Notification不适用,仅向用户显示 stderr
Stop阻止停止,向 Claude Code 显示错误
SubagentStop阻止停止,向 Claude Code 子代理显示错误

第二种是高级方式,钩子可以在 stdout 中返回结构化 JSON,以实现更复杂的控制:

{
  "continue": true, // Claude 在钩子执行后是否应继续(默认:true)
  "stopReason": "string", // 当 continue 为 false 时显示的消息
  "suppressOutput": true, // 从对话模式隐藏 stdout(默认:false)
}

如果 continue 为 false,Claude 在钩子运行后会立即停止,并将停止原因 stopReason 显示给用户。

如果 continue 为 true,Claude 会继续根据不同的钩子事件来进一步控制,比如 PreToolUsePostToolUse 钩子都可以控制是否继续工具调用,可以多返回两个字段:

{
  "decision": "approve" | "block" | undefined,
  "reason": "决策解释"
}

Claude Code 根据返回的 decision 来决定下一步的动作:

  • approve - 绕过权限系统,并将 reason 显示给用户,但不返回给 Claude。该值对 PostToolUse 不适用,因为工具已经调用过了
  • block - 阻止调用当前工具,并将 reason 返回给 Claude,以便 Claude 选择切换其他工具
  • undefined - 进入现有权限流程,忽略 reason 字段

StopSubagentStop 钩子可以控制 Claude 是否停止,返回的字段和上面一样:

{
  "decision": "block" | undefined,
  "reason": "当阻止 Claude 停止时必须提供"
}

Claude Code 根据返回的 decision 来决定下一步的动作:

  • block - 阻止 Claude 停止,必须返回 reason 字段,以便 Claude 知道如何继续
  • undefined - 允许 Claude 停止,忽略 reason 字段

一个复杂点的例子

下面是一个稍微复杂点的例子,首先添加如下钩子配置:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "python3 ./validate_command.py"
          }
        ]
      }
    ]
  }
}

然后在当前目录下创建一个 validate_command.py 文件:

#!/usr/bin/env python3
import json
import re
import sys

# 验证规则
VALIDATION_RULES = [
    (
        r"\bgrep\b(?!.*\|)",
        "使用 'rg'(ripgrep)代替 'grep' 以获得更好的性能和功能",
    ),
    (
        r"\bfind\s+\S+\s+-name\b",
        "使用 'rg --files | rg pattern' 或 'rg --files -g pattern' 代替 'find -name' 以获得更好的性能",
    ),
]

# 验证命令是否匹配规则
def validate_command(command: str) -> list[str]:
    issues = []
    for pattern, message in VALIDATION_RULES:
        if re.search(pattern, command):
            issues.append(message)
    return issues

# 从 stdin 读取 JSON 输入
try:
    input_data = json.load(sys.stdin)
except json.JSONDecodeError as e:
    print(f"错误:无效的 JSON 输入:{e}", file=sys.stderr)
    sys.exit(1)

tool_name = input_data.get("tool_name", "")
tool_input = input_data.get("tool_input", {})
command = tool_input.get("command", "")

# 只处理 Bash 工具
if tool_name != "Bash" or not command:
    sys.exit(1)

# 对命令进行核查
issues = validate_command(command)
if issues:
    for message in issues:
        print(f"• {message}", file=sys.stderr)
    # 退出代码 2 阻止工具调用并向 Claude 显示 stderr
    sys.exit(2)

这段 Python 脚本通过退出代码、标准输出和标准错误向 Claude Code 传达消息;它对 Bash 工具执行的命令进行核查,阻止 Claude Code 执行 grepfind 命令,而是替换成性能更高的 rg 命令。

小结

本文详细介绍了 Claude Code 新增的钩子(Hooks)功能,它为用户提供了一种强大的机制,通过在工具生命周期的关键节点执行自定义 Shell 脚本来扩展和定制 Claude Code 的行为。

我们学习了钩子的核心概念和功能,包括:

  • 钩子配置:如何通过配置文件,在不同作用域(用户、项目、本地)下定义钩子。
  • 生命周期事件:学习了 PreToolUsePostToolUse 等多种事件类型,以及如何使用匹配器精确触发钩子。
  • 输入与输出:了解了钩子如何通过标准输入(STDIN)接收 JSON 格式的上下文数据,并通过退出码和标准输出(STDOUT)与 Claude Code 交互,实现批准、阻止或提供反馈等高级控制。
  • 实际应用:通过日志记录和命令验证等示例,展示了钩子的实际应用场景。

钩子功能在赋予我们高度灵活性的同时,也带来了重要的安全问题。钩子会在未经用户确认的情况下,以当前用户的完整权限执行 Shell 命令。因此,确保钩子脚本的安全性和可靠性至关重要。在部署任何钩子之前,请务必遵循安全最佳实践,如验证输入、使用绝对路径、避免处理敏感文件,并在受控环境中进行充分测试。

总而言之,钩子机制极大地增强了 Claude Code 的可扩展性,使其能够更好地融入现有的开发工作流和规范。善用钩子,我们能将 Claude Code 打造成更智能、更贴合团队需求的自动化编程伙伴。


管理 Claude Code 的工具权限

我们知道,Claude Code 内置了 16 个强大的工具,加上我们昨天学习的 MCP 服务器,用户可以轻松集成更多的外部工具。通过合理调度这些工具,Claude Code 能够很好地对你的代码库进行理解和修改。但是这些工具中,不乏有一些是比较危险的,比如 Bash 可能执行任意的命令,Edit 可能篡改你的文件,外部工具可能存在安全风险,对此,Claude Code 提供了一套完善的权限控制机制。

claude-code-tool-permissions.png

上图列出了 Claude Code 内置工具的默认权限,对于 BashEdit 这种修改类的工具,必须等待用户确认后才开始执行。

修改工具的默认权限

当然,工具的权限并不是一成不变的,可以通过 --allowedTools--disallowedTools 参数修改工具的默认权限:

$ claude --allowedTools "Edit,MultiEdit,Write"

通过上面的方式启动 Claude Code 后,在编辑或写入文件时,不再需要用户批准,将会直接执行。

$ claude --disallowedTools "WebSearch,WebFetch"

通过上面的方式启动 Claude Code 后,将会禁用联网搜索和网页抓取工具。

注意,--allowedTools 是将工具的权限从用户确认改成自动放行,而 --disallowedTools 是将工具直接从工具列表中移除。貌似不能将工具的权限从自动放行改成用户确认。

这两个参数都可以在会话过程中通过 /permissions/allowed-tools 斜杠命令进行查看和修改:

claude-code-permissions.png

允许和禁止的工具分别位于 AllowDeny 页签下,如果某个工具既配了拒绝规则又配了允许规则,拒绝规则优先于允许规则。

额外的工作目录

默认情况下,Claude Code 只允许访问当前工作目录下的文件,在访问工作目录外的文件时,也会要求用户确认:

claude-code-add-dir.png

我们可以在启动时通过 --add-dir 参数添加额外的工作目录:

$ claude --add-dir ../browser-use

或者在会话中使用 /add-dir 斜杠命令:

> /add-dir ../browser-use

这个参数也可以在会话过程中通过 /permissions/allowed-tools 斜杠命令进行查看和修改:

claude-code-permissions-2.png

所有允许访问的目录均显示在 Workspace 页签下,额外的工作目录遵循和原始工作目录相同的权限规则:读取文件无需确认,编辑文件则根据当前的权限模式决定是否确认。

更细粒度的权限控制

在调用某些工具时,我们可能还需要有更细粒度的权限控制,比如可以允许 Bash 执行特定命令,拒绝 Read 读取某些文件,等等,Claude Code 支持在工具名后面加上特定的匹配规则,比如下面这个例子:

$ claude --allowedTools "Bash(npm run build)"

当使用 Bash 工具运行 npm run build 命令时,直接放行,无需用户确认。也可以在匹配规则中使用通配符:

$ claude --disallowedTools "Bash(git:*)"

当使用 Bash 工具运行以 git 开头的命令时,直接拒绝:

claude-code-permissions-deny.png

Claude Code 能很好的处理 Shell 操作符(比如 &&),因此像 Bash(safe-cmd:*) 这样的前缀匹配规则不会给它运行命令 safe-cmd && other-cmd 的权限。

另外,ReadEdit 也有一套自己的匹配规则,比如:

$ claude --allowedTools "Edit(docs/**)"

上面的命令允许对项目 docs 目录中文件进行编辑,其中的 docs/** 规则 遵循 gitignore 规范。还可以使用 // 引用绝对路径,或者 ~/ 引用用户目录的路径:

  • Edit(//tmp/scratch.txt) 匹配对 /tmp/scratch.txt 的编辑
  • Read(~/.zshrc) 匹配对用户的 ~/.zshrc 文件的读取

值得注意的是,Read 的规则将应用于所有读取文件的内置工具,如 GrepGlobLS

除了命令执行和文件操作,下面这些工具也支持细粒度控制:

  • WebFetch(domain:example.com) 匹配对 example.com 的抓取请求
  • mcp__amap 匹配由 MCP 服务器 amap 提供的任何工具
  • mcp__amap__weather 匹配由 MCP 服务器 amap 提供的 weather 工具

权限模式

Claude Code 支持几种不同的权限模式:

  • 默认模式(default:按照默认或用户配置的权限规则对工具进行验证
  • 自动编辑模式(acceptEdits:自动接受对工作目录下的文件的编辑
  • 规划模式(plan:只能读取文件进行分析,不允许编辑文件或执行命令
  • YOLO 模式(bypassPermissions:跳过所有权限验证,危险!

可以通过 --permission-mode 参数直接开启不同的权限模式:

$ claude --permission-mode <permission-mode>

claude-code-yolo-mode.png

也可以在会话中通过 Shift + Tab 切换,按一次进入自动编辑模式,按两次进入规划模式,再按一次回到默认模式。

YOLO 模式也可以通过 --dangerously-skip-permissions 参数开启:

$ claude --dangerously-skip-permissions

YOLO 模式可以绕过权限提示,实现无人值守操作,但是非常危险,使用时一定要小心。建议在容器环境下使用,通过容器的隔离和防火墙规则等安全措施,最大程度的防止系统遭受攻击。官方提供了一份 devcontainer 设置,可以和 VS Code 的 Remote - Containers 扩展搭配使用,感兴趣的朋友可以参考:

配置文件

除了命令行参数和斜杠命令,Claude Code 还支持将工具的权限保存在配置文件中:

{
  "permissions": {
    "deny": [
      "WebSearch",
      "WebFetch",
      "Bash(curl:*)"
    ],
    "allow": [
      "Bash(git:*)"
    ],
    "additionalDirectories": [
      "../browser-use"
    ]
  }
}

该配置文件可以放在下面这些位置:

  • 用户设置(~/.claude/settings.json):用户私有,适用于所有项目
  • 共享项目设置(.claude/settings.json):提交到 Git 仓库,团队成员共用
  • 本地项目设置(.claude/settings.local.json):不提交到 Git 仓库,用户私有,只适用于当前项目
  • 企业管理策略(/path/to/policies.json):在企业环境下,系统管理员可以强制执行用户无法覆盖的安全策略,优先级最高

对于企业管理策略,系统管理员通常将策略部署到:

  • macOS: /Library/Application Support/ClaudeCode/policies.json
  • Linux 和 WSL: /etc/claude-code/policies.json

当同一个工具的规则出现在多个位置时,优先级从高到低如下:企业管理策略 > 命令行参数 > 本地项目设置 > 共享项目设置 > 用户设置。这样的层次结构确保始终执行企业策略,同时在适当的情况下仍允许在项目和用户级别的灵活性。

小结

我们今天详细学习了 Claude Code 的权限控制机制,包括如何设置权限规则(允许规则、禁止规则、额外目录、细粒度规则),如何选择权限模式(默认、自动编辑、规划、YOLO)以及合理使用配置文件等。Claude Code 的权限控制机制为用户提供了从粗粒度到细粒度的全方位安全保障,通过灵活的权限配置,我们可以在保证开发效率的同时,最大程度地降低安全风险。


使用 MCP 让 Claude Code 集成外部工具

MCP(Model Context Protocol,模型上下文协议)) 是 Anthropic 于 2024 年 11 月 25 日 推出的开放协议,用于标准化大模型与各类外部工具和数据源之间的交互。

Claude Code 作为自家的 AI 编程工具,自然也支持 MCP 协议。除了内置的 16 个工具,用户可以使用 MCP 无缝集成任意数量的自定义工具和外部数据源,从而进一步拓展 Claude Code 的能力边界。

MCP 简介

下面这张图非常形象地展示了 MCP 的基本架构:

mcp-overview.png

可以看到 MCP 采用了非常经典的 C/S 架构(客户端/服务器),主要包括三个部分:

  • 主机(Host): 一般是基于大模型的 AI 应用,比如 Claude Desktop、ChatGPT Desktop、Cursor 等桌面应用,需要访问外部数据或工具;
  • 客户端(Client):内置在应用中,与 MCP 服务器建立一对一的连接;
  • 服务器(Server):连接本地数据源或远程服务,提供特定功能;

    • 本地数据源:文件或数据库;
    • 远程服务:外部 API 或互联网服务;

MCP 协议将所有的外部数据或工具以一种统一的方式接入 AI 应用,这就好比 USB-C 接口,将各种不同的电子设备统一成一种接口,从而让用户不再为准备各种各样不同的线缆插头而烦恼。简单说,MCP 就像一座桥梁,它本身不处理复杂逻辑,只负责协调 AI 应用与外部资源之间的信息流动。

在推出 MCP 之前,AI 应用如果要对接外部工具,通常需要单独整合多个不同的 API,每个 API 的接口可能都各不相同,认证方式和错误处理也可能不同,极大地增加了开发复杂度和维护成本。

所以说,传统 API 就像不同的门,每扇门都有一把不同的钥匙,而 MCP 像一把万能钥匙,AI 应用开发者只要集成了这个万能钥匙,就可以打开任意的门。下面是 MCP 和传统 API 的对比:

mcp-vs-api.png

有关 MCP 的更多信息,请参阅 MCP 文档:

添加 MCP 服务器

在之前的文章中我们曾遇到过 WebFetch 工具调用报错的问题,我们可以将其换成 Fetch MCP Server。通过 claude mcp add 命令添加 MCP 服务器:

$ claude mcp add web-fetch -- uvx mcp-server-fetch

上面的 web-fetch 是我们自定义的 MCP 工具名称,-- 后面的内容是 MCP 服务器的启动命令。添加成功之后,进入 Claude Code 交互模式,输入 /mcp 可查看 MCP 服务器的状态:

claude-code-mcp-status.png

如果状态显示 connected,则说明 MCP 服务器已就绪。可以按下 Enter 键查看 MCP 工具的详细信息:

claude-code-mcp-tool-detail.png

此时就可以使用该工具了,比如对网页内容进行问答或总结:

claude-code-fetch.png

默认情况下,所有的 MCP 工具都需要经过用户确认后才可以运行,同意运行后结果如下:

claude-code-fetch-result.png

如果感兴趣的话,可以拿 Wireshark 对 Claude Code 进行抓包,可以发现请求的 tools 里多了一个工具 mcp__web-fetch__fetch,工具的名称、描述、参数和上面的工具详情是一样的:

claude-code-fetch-tools.png

添加 HTTP/SSE 模式的 MCP 服务器

上面的 Fetch MCP Server 是 STDIO 模式的 MCP 服务器,这也是最常见的 MCP 服务器连接方式。当运行 claude mcp add 命令时,默认就是 STDIO 模式,我们也可以通过 --transport-t 参数添加 HTTP 或 SSE 模式的 MCP 服务器。

下面以 高德地图 为例,演示下如何在 Claude Code 中调用 HTTP 或 SSE 模式的 MCP 服务器。首先,我们需要注册并登录 高德开放平台,然后创建一个应用得到 Key,之后运行下面的命令添加 MCP 服务器:

$ claude mcp add --transport http amap "https://mcp.amap.com/mcp?key=<your-api-key>"

高德地址也支持 SSE 模式:

$ claude mcp add --transport sse amap "https://mcp.amap.com/sse?key=<your-api-key>"

高德地图的 MCP 服务器包含十几个工具,包括导航、定位、打车、路径规划、周边搜索、天气查询等,非常实用:

claude-code-amap-weather.png

设置环境变量

有些 MCP 服务器依赖于额外的环境变量,比如设置 API 密钥,我们可以通过 --env-e 参数来配置。

下面以 Brave Search MCP Server 为例,将内置的 WebSearch 工具替换成 Brave 搜索。首先注册并登录 Brave,订阅 Free 计划(需要提供信用卡信息),得到每月 2000 次免费额度:

brave-search-plans.png

然后生成 API Key,之后运行下面的命令添加 MCP 服务器:

$ claude mcp add brave-search \
    --env BRAVE_API_KEY=<your-api-key> \
    -- npx -y @modelcontextprotocol/server-brave-search

官方的 Brave Search MCP Server 使用 Node.js 的 fetch 方法来发请求,不支持 HTTPS_PROXY 代理配置,如果遇到网络问题,可以换成 @kwp-lab/mcp-brave-search

接着就可以使用 Brave 进行搜索了,比如查询 Gemini CLI 的最新动态:

claude-code-brave-search.png

设置作用域

默认添加的 MCP 服务器仅在当前项目中可用,Claude Code 支持通过 --scope-s 参数改变 MCP 服务器的作用域:

$ claude mcp add brave-search \
    --scope project \
    --env BRAVE_API_KEY=<your-api-key> \
    -- npx -y @modelcontextprotocol/server-brave-search

Claude Code 支持三种不同的作用域:

  • 本地作用域(local):默认配置,用户私有,仅在当前项目中可用;
  • 用户作用域(user):也是用户私有,但是跨所有项目可用;
  • 项目作用域(project):通过将配置存储在项目根目录的 .mcp.json 文件中来实现团队协作;

不同作用域下,MCP 服务器的配置位置也不同。比如项目作用域是将配置保存到当前项目的 .mcp.json 文件中,可以提交到 Git 仓库,确保所有项目成员都能访问相同的 MCP 工具和服务。该文件遵循标准化格式(和 Claude Desktop 的配置格式一致),内容如下:

{
  "mcpServers": {
    "brave-search": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-brave-search"
      ],
      "env": {
        "BRAVE_API_KEY": "<your-api-key>"
      }
    }
  }
}

而本地作用域和用户作用域则是将配置保存到用户的 Claude Code 配置文件 ~/.claude.json 中,只能自己使用,注意它们在 JSON 中的位置:

claude-mcp-config.png

当同名服务器存在于多个作用域时,系统通过优先考虑本地作用域服务器,然后是项目作用域服务器,最后是用户作用域服务器来解决冲突。

添加 MCP 服务器的其他方式

除了 claude mcp add 命令,Claude Code 还提供了另几种添加 MCP 服务器的方式。第一种是使用 JSON 配置添加:

$ claude mcp add-json brave-search -s project '{
    "type": "stdio",
    "command": "npx",
    "args": [
      "-y",
      "@modelcontextprotocol/server-brave-search"
    ],
    "env": {
      "BRAVE_API_KEY": "<your-api-key>"
    }
  }'

这种方式对于配置较复杂的 MCP 服务器来说很方便,因为这种 JSON 格式是 Claude 的标准,一般在 MCP 服务器的说明页面都有类似的配置示例。

第二种是从 Claude Desktop 导入配置,如果你本地安装了 Claude Desktop 且配置了 MCP 服务器,可以使用下面的命令一键导入:

$ claude mcp add-from-claude-desktop

运行后会显示交互式对话框,让你选择要导入的 MCP 服务器。

还有一种是启动 Claude Code 时,直接通过 --mcp-config 参数加载 MCP 服务器配置:

$ claude --mcp-config /path/to/mcp.json

管理 MCP 服务器

Claude Code 还提供了一些子命令对 MCP 服务器进行管理操作,比如列出所有的服务器:

$ claude mcp list

查看特定服务器详情:

$ claude mcp get brave-search

删除特定服务器:

$ claude mcp remove brave-search

检查 MCP 服务器状态:

> /mcp

另外,/mcp 命令还可以对 MCP 服务器进行 OAuth 2.0 身份认证,在需要认证的 MCP 服务器上按 Enter 后,会自动打开浏览器并跳到 OAuth 认证页面,用户在浏览器中完成身份验证后,Claude Code 接收并存储访问令牌,然后 MCP 服务器将变为 connected 状态。

使用 MCP 资源和提示词

MCP 服务器不仅可以暴露 工具 供其他 AI 程序使用,还支持暴露 资源提示词

MCP 服务器暴露的资源可使用 @ 引用,格式为 server:protocol://resource/path,比如:

> 分析 @github:issue://123 并提供修复建议

MCP 服务器暴露的提示词可作为斜杠命令使用,格式为 /mcp__<server-name>__<prompt-name>,比如:

> /mcp__github__list_prs

也可以带参数:

> /mcp__github__pr_review 456

无论是 MCP 资源还是提示词,都是从连接的 MCP 服务器中动态发现的,当键入 @/ 时,资源和提示词会自动显示在下拉菜单中。

将 Claude Code 作为 MCP 服务器

Claude Code 不仅可以作为客户端接入外部 MCP 服务器,也可以作为 MCP 服务器,为其他应用提供服务,比如将其加到 Claude Desktop 的配置文件中:

{
  "mcpServers": {
    "claude-code": {
      "command": "claude",
      "args": ["mcp", "serve"],
      "env": {}
    }
  }
}

重启 Claude Desktop 后,可以看到加载的 16 个工具:

claude-code-in-desktop.png

可以在 Claude Desktop 中,尝试要求 Claude 读取目录中的文件、进行编辑等。

小结

本文详细介绍了如何在 Claude Code 中配置和使用 MCP 服务器,通过统一的协议标准,我们可以轻松集成各类外部工具和数据源,将 Claude Code 从单纯的编程助手升级为功能强大的智能工作平台。

不过,在享受 MCP 带来便利的同时,安全性不容忽视,务必确保所使用的 MCP 服务器是可信的,特别是涉及网络交互的服务器,防范潜在的提示注入攻击和私有数据泄漏。


学习 Claude Code 的工具使用(三)

经过前两天的学习,我们已经掌握了 Claude Code 的命令执行、文件查找、文件读写、网络检索相关的工具,目前还剩下 TaskTodoWriteTodoReadexit_plan_mode 四个工具,今天就来学习下它们。这四个工具都是 Claude Code 用来解决复杂任务的,它们也代表着大模型在解决复杂任务时的几种不同的思路。

代办列表

代办列表(Todo List) 是一种组织复杂任务并跟踪处理进度的常用手段,Claude Code 在面对复杂的多步骤任务时,会使用代办列表将其分解成多个子项,然后按顺序依次处理:

claude-code-todo.png

和代办列表相关的工具有两个:

  • TodoRead - 读取当前会话的代办列表
  • TodoWrite - 创建和管理结构化的代办列表

TodoRead 工具的描述中提到,Claude Code 应该主动且频繁地使用该工具,以了解当前代办列表的状态,确保一直处在正确的轨道上,特别是以下情况:

  • 在对话开始时查看待处理的事项
  • 在开始新任务之前优先安排工作
  • 当用户询问之前的任务或计划时
  • 当你不确定下一步该做什么时
  • 完成任务后更新你对剩余工作的理解
  • 每隔几条消息后确保你在正确的轨道上

不过我测试下来发现很少触发 TodoRead 的调用,一直使用 TodoWrite 就足够完成整个任务,可能是我的任务都比较简单吧。但是我感觉 TodoRead 确实比较鸡肋,因为大模型在每次调用 TodoWrite 的时候,代办列表会反复出现在上下文中,还需要 TodoRead 再去查一次吗?

相对来说,TodoWrite 的使用场景就明确的多,比如下面这些情况:

  • 复杂的多步骤任务 - 当任务需要3个或更多不同的步骤时
  • 不易解决的棘手任务 - 需要仔细规划或多项操作的任务
  • 用户明确请求待办列表 - 当用户直接要求你使用待办列表时
  • 用户提供多个任务 - 当用户提供需要完成的事项列表时(编号或逗号分隔)

代办列表中的每个待办事项有三种状态:

  • pending - 任务尚未开始
  • in_progress - 当前正在处理
  • completed - 任务成功完成

在任务处理的不同阶段实时地更新待办事项的状态:

  • 收到新指令后 - 立即将用户需求记录为待办事项
  • 开始处理任务时 - 在开始工作之前将其标记为进行中,应该只有一个待办事项处于进行中状态
  • 完成任务后 - 将其标记为已完成,并添加在实施过程中发现的任何新后续任务
  • 如果遇到错误、阻碍或无法完成 - 保持待办事项为 in_progress 状态,或者创建一个新的待办事项描述需要解决的问题

TodoWrite 工具的描述中还给出了几个使用示例,供大家参考。

示例一:

用户:我想在应用程序设置中添加一个深色模式切换功能,完成后确保运行测试和构建!
助手:我将帮你在应用程序设置中添加深色模式切换功能,让我创建一个待办列表来跟踪这个实现。
*创建包含以下项目的待办列表:*
1. 在设置页面创建深色模式切换组件
2. 添加深色模式状态管理(上下文/存储)
3. 为深色主题实现 CSS-in-JS 样式
4. 更新现有组件以支持主题切换
5. 运行测试和构建过程,解决发生的任何失败或错误
*开始处理第一个任务*

示例二:

用户:帮我在项目中将函数 getCwd 重命名为 getCurrentWorkingDirectory
助手:让我先搜索你的代码库以找到所有 getCwd 的出现位置。
*使用grep或搜索工具定位代码库中getCwd的所有实例*
助手:我在 8 个不同文件中找到了 15 个 getCwd 实例,让我创建一个待办列表来跟踪这些更改。
*为每个需要更新的文件创建包含具体项目的待办列表*

示例三:

用户:我需要为我的电商网站实现这些功能:用户注册、产品目录、购物车和结账流程。
助手:我将帮助实现这些功能。首先,让我们将所有功能添加到待办列表中。
*创建一个待办列表,基于项目架构将每个功能分解为具体任务*
助手:让我们从用户注册开始。这将涉及创建数据库模型、API端点和与你现有认证系统集成的前端表单。

示例四:

用户:你能帮助优化我的 React 应用程序吗?它渲染很慢,有性能问题。
助手:我将帮助优化你的 React 应用程序。首先,让我检查你的代码库以识别潜在的性能瓶颈。
*审查组件结构、渲染模式、状态管理和数据获取*
助手:在分析你的代码库后,我识别出了几个性能问题。让我创建一个待办列表来跟踪我们的优化工作。
*创建包含以下项目的待办列表:
1) 为 ProductList 中的昂贵计算实现缓存,
2) 为 Dashboard 中的长列表添加虚拟化,
3) 优化 Gallery 组件中的图像加载,
4) 修复 ShoppingCart 中的状态更新循环,
5) 审查包大小并实现代码分割*
让我们从为 ProductList 组件中的昂贵计算实现缓存开始。

子智能体

Task 工具用于启动一个子智能体,该子智能体可以访问除 Task 之外的其他 15 个工具,来解决 Deep Search 或 Deep Research 类的需要深度搜索的复杂任务。比如你正在搜索像 "config" 或 "logger" 这样的关键词,或者遇到 "哪个文件执行了X?" 这样的问题,很有可能就会触发使用这个工具。

在官方文档中,这个工具的名字叫做 Agent,但是看代码里,却叫做 Task

当 Claude Code 搜索关键词或文件时,如果经过几次搜索后还是没能找到匹配项或不能确定答案,就会使用 Task 工具来执行深度搜索。在下面的例子中,我位于 browser-use 的代码库中,想让 Claude Code 解释下 stealth=True 这个参数的含义,这个参数是 0.2.7 版本后才引入的,作用是通过 Playwright 绕过浏览器检测。但是我故意将代码切到老版本,看看它反应如何:

claude-code-agent.jpg

可以看到 Claude Code 先简单的使用 Grep 搜索了两次,发现都没有找到想要的结果,然后就开启了子智能体模式进行深度搜索。每个子智能体都是无状态的,Claude Code 会尽可能同时启动多个子智能体以最大化性能,从上图可以看到,在短短几分钟内就触发了 28 次工具调用。

注意,多个子智能体会并行调用,因此很容易遇到 rate_limit_error 限流错误,而且 token 消耗也非常大。

规划模式

这是 Claude Code 的一个隐藏功能,我翻遍官方文档,也没有找到关于它的详细说明,如果不是在请求报文中看到 exit_plan_mode 这个工具,我都不知道有这个模式。我们之前学过,在 Claude Code 的交互模式下有不少快捷键,比如按下 Shift + Tab 可以进入自动接受文件编辑的模式,如果你不小心按了两下,就会进入规划模式(下面显示 Plan mode 字样):

claude-code-plan-mode-enabled.png

进入规划模式后,Claude Code 将不会执行任何修改操作,比如文件编辑、配置更改、提交代码等,只能调用搜索或文件读取这样的只读工具。Claude Code 会对用户的问题进行全面分析并生成详细的执行计划,之后,调用 exit_plan_mode 退出规划模式,同时向用户展示计划,得到用户确认后,才会真正地执行修改操作:

claude-code-plan-mode.png

上面这个例子很好的展示了规划模式的工作步骤:先分析,再展示计划,等待用户确认。如果没问题,用户可以确认计划,退出规划模式;如果有问题,也可以要求 Claude Code 继续规划。

小结

至此,Claude Code 的 16 个工具总算学完了。通过深入了解每个工具的运行逻辑和使用场景,不仅能够帮助我们更好地发挥 Claude Code 的功能,也能快速定位和解决使用过程中可能出现的问题。对于常见的代码任务,内置工具通常足以应对,但如果遇到更复杂或超出内置功能范围的需求,Claude Code 还支持 MCP 协议,允许用户集成自定义工具和外部数据源,从而进一步拓展其能力边界。至于如何通过 MCP 集成外部工具,以及具体操作步骤,我们明天继续。


学习 Claude Code 的工具使用(二)

在上一篇中,我们学习了 Claude Code 的 BashLSGlobGrep 四个工具,用于命令执行和文件查找相关的任务,我们今天继续看下其他的工具。

文件读写

文件读取和文件写入应该是 Claude Code 最常做的事情了,我们在之前的学习中不止一次使用了这些工具。比如运行 /init 命令生成 CLAUDE.md 文件时,就是通过 Read 去读取文件内容,然后再用 Write 去写入新文件:

claude-code-init.png

Claude Code 推荐使用 Read 工具去读取文件,而不是 catheadtail 等 Bash 命令,这是因为 Read 相对于这些命令来说有几个独特的优势,我们可以从 Read 的工具描述中看到:

  • 默认情况下,最多读取 2000 行
  • 可以指定行偏移量和限制,对于长文件特别有用
  • 任何超过 2000 个字符的行都会被截断
  • 结果使用 cat -n 格式返回,行号从 1 开始,便于大模型了解代码所在的行数
  • 支持读取图像(如 PNG、JPG 等)

其中最大的优势是读取图像,因为 Claude Code 是一个多模态大模型,所以我们可以让 Claude 去分析错误截图或者按产品原型图去开发页面,比如这里将百度首页截图:

baidu-home.png

然后将它丢给 Claude Code 去仿照:

claude-code-baidu-home.png

Claude Code 首先调用 Read 去读取图片,将其转换成 BASE64 格式,然后去调用 Claude 的视觉能力

{
  "model": "claude-sonnet-4-20250514",
  "messages": [
    {
      "role": "user",
      "content": [
        {
          "type": "image",
          "source": {
            "type": "base64",
            "media_type": "image/png",
            "data": "iVBORw0KGgoAAAANSUhEUgAABx..."
          }
        },
        {
          "type": "text",
          "text": "仿照 demo.png 文件写一个静态 html 文件"
        }
      ]
    }
  ],
  "temperature": 1,
  "max_tokens": 32000,
  "stream": true
}

最终生成静态页面如下:

baidu-home-2.png

文件编辑

还有很多任务需要对代码文件进行编辑修改,这是通过 EditMultiEdit 两个工具实现的。这两个工具的本质是字符串替换,可以从工具的描述和 Schema 看出来:

{
  "name": "Edit",
  "description": "Performs exact string replacements in files...",
  "input_schema": {
    "type": "object",
    "properties": {
      "file_path": {
        "type": "string",
        "description": "The absolute path to the file to modify"
      },
      "old_string": {
        "type": "string",
        "description": "The text to replace"
      },
      "new_string": {
        "type": "string",
        "description": "The text to replace it with (must be different from old_string)"
      },
      "replace_all": {
        "type": "boolean",
        "default": false,
        "description": "Replace all occurences of old_string (default false)"
      }
    },
    "required": [
      "file_path",
      "old_string",
      "new_string"
    ],
    "additionalProperties": false,
    "$schema": "http://json-schema.org/draft-07/schema#"
  }
}

这个工具有四个参数:

  • file_path - 文件全路径
  • old_string - 替换前的原字符串
  • new_string - 替换后的新字符串
  • replace_all - 是否全部替换,默认 false

当调用 Edit 工具时,原字符串和新字符串会以 diff 形式显示出来:

claude-code-edit.jpg

在调用 Edit 工具之前,必须先至少调用一次 Read 工具,方便 Claude Code 获得原字符串,Edit 工具一次只能替换一个字符串,如果要批量替换多个字符串,可以使用 MultiEdit 工具。

Notebook 读写

Claude Code 内置了对 Jupyter Notebook 的读写工具,用于读取和编辑 .ipynb 文件:

  • NotebookRead - 读取 Jupyter Notebook 中指定单元格的内容,如果不指定单元格,则返回所有单元格的内容;
  • NotebookEdit - 编辑 Jupyter Notebook 中特定单元格的内容,支持插入、替换和删除三种编辑模式,并支持 codemarkdown 两种单元格类型;

在下面的示例中,我们让 Claude Code 生成一个 Jupyter Notebook 文件,来演示 Python 列表的基本用法:

claude-code-notebook.png

生成的 Jupyter Notebook 结构清晰,而且最大的好处是,它提供了交互式的环境方便我们进行研究和学习:

claude-code-notebook-file.png

Claude Code 通过 NotebookEdit 插入单元格有一个问题,每次都是在文件开头处插入,所以当我们连续生成多个单元格时,顺序就有问题。上面的截图是我倒序后的结果。

网页抓取

WebFetch 工具支持从指定 URL 获取内容并使用 AI 模型进行处理,它首先抓取 URL 内容,将 HTML 转换为 Markdown 格式,然后使用小型快速模型根据用户的提示进行处理。

不过我尝试下来,这个工具一直没有调用,不知道什么原因,总是报 Domain xxx is not allowed to be fetched 这样的错:

claude-code-web-fetch.png

如果有知道原因的朋友,欢迎在评论区交流。

这个工具的描述里有几个点值得关注:

  • 重要提示:如果有 MCP 提供的网页获取工具可用,请优先使用该工具,因为它可能限制更少。所有 MCP 提供的工具都以 "mcp__" 开头
  • HTTP URL 将自动升级为 HTTPS
  • 如果内容非常大,结果可能会被总结
  • 包含自清理的 15 分钟缓存,以便在重复访问同一 URL 时获得更快的响应

所以如果有朋友也遇到和我一样的错误,建议使用 MCP 工具来抓取网页,关于 MCP 的内容,我们后面单独开一篇来介绍。

联网搜索

除了抓取特定网页的内容,Claude Code 还能够通过内置的 WebSearch 工具进行联网搜索,提供最新信息,回答实时问题。比如最近 Google 发布的 Gemini CLI 非常火,我就让它帮我搜一下:

claude-code-web-search.png

联网搜索工具实际上调用的还是 Claude 模型,最新版本的 Claude 模型基本上都具备 联网搜索能力,在调用模型时将 tools 换成了 Claude 内置的 web_search 工具即可:

{
  "model": "claude-sonnet-4-20250514",
  "messages": [
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "Perform a web search for the query: Gemini CLI command line interface features functionality"
        }
      ]
    }
  ],
  "temperature": 1,
  "system": [
    {
      "type": "text",
      "text": "You are Claude Code, Anthropic's official CLI for Claude."
    },
    {
      "type": "text",
      "text": "You are an assistant for performing a web search tool use"
    }
  ],
  "tools": [
    {
      "type": "web_search_20250305",
      "name": "web_search",
      "max_uses": 8
    }
  ],
  "max_tokens": 32000,
  "stream": true
}

但是这也带来了一个问题,如果我们没有使用 Claude 模型,而是自定义的其他模型,那么 WebSearch 工具就不可用了,所以也建议使用 MCP 工具来实现联网搜索。在运行 claude 命令时,通过 --disallowedTools 选项禁用网页抓取和联网搜索工具:

$ claude --disallowedTools "WebSearch,WebFetch"

未完待续

今天我们学习了 Claude Code 的文件操作和网络访问相关的工具,包括:

  • 文件读写ReadWrite 工具,其中 Read 支持图像读取和视觉分析
  • 文件编辑EditMultiEdit 工具,通过精确的字符串替换实现代码修改
  • Notebook 操作NotebookReadNotebookEdit 工具,通过 Jupyter Notebook 提供交互式开发和学习环境
  • 网络功能WebFetchWebSearch 工具,获取联网信息,解决实时性问题

在下一篇中,我们将学习剩下的几个工具,包括 TaskTodoWriteTodoReadexit_plan_mode 四个工具,来解决一些相对复杂和高级的任务。


学习 Claude Code 的工具使用

在前面的学习中我们已经接触了不少 Claude Code 的工具,比如使用 List 工具列出文件列表,使用 ReadWrite 工具对文件进行读写,使用 Bash 工具调用 git addgit commit 等命令。Claude Code 内置了不少工具,但是由于 Claude Code 并没有开源,除了官方文档,我们并没有太多工具相关的资料可参考。

因此我使用 Wireshark 对 Claude Code 的请求抓包分析,看到了它内置的提示词以及 tools 参数:

claude-code-tools.png

从上图可以看到,Claude Code 内置了 16 个工具,这些工具大致可以分为下面几类:

分类分类描述示例工具
命令执行允许在 Shell 会话中执行 Bash 命令Bash
文件查找用于快速查找并匹配文件LSGlobGrep
文件读写用于读取或写入文件,允许进行文件编辑和内容替换ReadWriteEditMultiEdit
Notebook 读写用于读取和编辑 Jupyter Notebook(也就是 .ipynb 文件)NotebookReadNotebookEdit
Web 检索用于检索和分析 Web 内容的工具WebFetchWebSearch
复杂任务处理通过子智能体或任务清单来执行复杂任务TaskTodoWriteTodoReadexit_plan_mode

今天就来仔细学习一下这些工具。

Bash 执行命令

Claude Code 是一款基于终端的 AI 编程助手,它继承了你的 Shell 环境,可以调用常用的 Unix 命令。比如调用 du 查看文件夹大小:

claude-bash-du.png

调用 zip 压缩文件夹:

claude-bash-zip.png

甚至可以使用你安装的任何命令行工具,比如我们之前学过 PDFMathTranslate 这款开源的 PDF 文档翻译工具,让 Claude Code 来试试:

claude-bash-pdf2zh.png

当然,默认情况下 Claude Code 并不知道这些命令,可以通过在 CLAUDE.md 中记录常用的命令,告诉 Claude 可以使用哪些命令以及每个命令的用法:

你可以使用下面这些 Bash 命令:

* pdf2zh - 一款免费开源的 PDF 文档翻译工具,支持多种语言和翻译服务,最大的特色是翻译后保持排版不变。

基本用法,默认将英文 PDF 文件翻译成中文:`pdf2zh example.pdf`
指定源和目标语言:`pdf2zh example.pdf -li en -lo ja`
查看命令文档:`pdf2zh --help`

Bash 命令几乎可以实现任何功能,但是不同的 Bash 命令参数迥异,有些命令的参数还特别复杂,为了防止大模型生成命令时误入歧途,Claude Code 内置了一些工具来替代常见的 Unix 命令。从抓包请求里可以看到 Bash 工具的描述,其中有几个点比较有意思:

  • 含空格的路径必须用双引号包裹
  • 严禁使用 findgrep 搜索命令,改用 Grep / Glob / Task 工具
  • 避免使用 cat / head / tail / ls 等读取工具,改用 Read / LS 工具
  • 如果你仍然要运行 grep,请停止,必须优先使用预装的 rg 来替代,所有 Claude Code 用户都已预安装此工具
  • 尽量使用绝对路径,避免使用 cd,除非用户明确要求

这样做的好处是,大模型通过 function call 生成结构化的命令,比直接生成长长的命令行要可控的多。

LS 列出文件和目录

Bash 的工具描述中可以看到,Claude Code 使用内置的 LS 工具替代 ls 命令:

claude-ls.png

内置 LS 的好处是它可以递归遍历子目录,如上图所示(使用 Ctrl + R 可以展开详情)。

Glob 根据文件名查找文件

另一个内置的 Glob 工具用于替代 find 命令,可以基于模式匹配来查找文件:

claude-glob.png

它有点类似下面这个 find 命令:

$ find . -type f -name "*global*"

但比 find 命令强的地方在于它支持 Glob 模式匹配,比如 **/*.jssrc/**/*.ts 这样。

尽管在 Bash 的工具描述里特别提到 严禁使用 find 命令,但是我验证下来发现,如果内置的工具不足以完成用户的任务,Claude Code 还是会使用这些被限制的命令:

claude-bash-find.png

Grep 搜索文件内容

另外,从 Bash 的工具描述中我们还得知,Claude Code 预装了一个叫 rg 的工具用于替代 grep 命令,这个 rg 全名叫 ripgrep,是一个现代的命令行搜索工具,相对于 grep 来说搜索效率更高。可以在 Claude Code 的安装目录下找到它:

  • @anthropic-ai/claude-code/vendor/ripgrep

ripgrep 使用 Rust 编写,通过先进的搜索算法和内建的索引优化,可以递归地在当前目录中搜索正则表达式模式,它默认会遵循 gitignore 规则,并自动跳过隐藏文件和二进制文件。这些特性使得 ripgrep 成为许多开发者搜索大型代码库的常用工具之一,也是 Claude Code 能处理大型代码库的秘密武器之一。

当我们要搜索代码库中文件内容时,Claude Code 往往就会使用这个命令:

claude-bash-rg.png

这里的 Search 其实就是 Grep 工具,类似于下面的命令:

$ rg "POST|post" **/route.ts

使用 Git 命令

除了执行上面的基本命令,Claude Code 还可以处理大多数的 Git 操作,比如下面几个常见的场景:

  • 一、搜索 Git 历史回答问题,可以在指令中明确要求 Claude Code 查看 git 历史,这样效果会更好:
> v1.2.3 分支中包含哪些更改?

> 根据 git 提交历史,分析这个 API 为什么这样设计?
  • 二、编写提交消息,Claude 会自动查看你的更改和最近历史,生成符合上下文的提交消息,我们在之间的文章中已经见识过:

claude-code-commit.png

Bash 的工具描述中,有一份详细的 Git 提交规范,可以对照着上面的截图,了解下 Claude Code 是如何处理 Git 提交的:

当用户要求您创建新的 Git 提交时,请仔细按照以下步骤操作:

1. 始终并行运行以下 Bash 命令:
   - 运行 git status 查看所有未跟踪的文件
   - 运行 git diff 查看将要提交的已暂存和未暂存的更改
   - 运行 git log 查看最近的提交消息,以便可以遵循此仓库的提交消息风格

2. 分析所有已暂存的更改(包括之前已暂存和新添加的)并起草提交消息:
   - 总结更改的性质(例如:新功能、功能增强、错误修复、重构、测试、文档等)
   - 检查是否有不应提交的敏感信息
   - 起草简洁的(1-2句话)提交消息,重点关注"为什么"而不是"什么"
   - 确保消息准确反映更改及其目的

3. 始终并行运行以下 Bash 命令:
   - 将相关的未跟踪文件添加到暂存区
   - 创建提交,消息以以下内容结尾:
   .... Generated with Claude Code
   Co-Authored-By: Claude noreply@anthropic.com
   - 运行 git status 确保提交成功

4. 若因 pre-commit 钩子失败:
   - 重试一次包含自动变更
   - 仍失败则终止
   - 成功但文件被钩子修改时必须 amend 提交
  • 三、处理复杂的 Git 操作,如恢复文件、解决冲突以及比较和移植补丁等:
> 将 v1 合并到 v2 分支,并尝试解决冲突

未完待续

今天我们学习了 Claude Code 的命令执行和文件查找相关的工具:使用 Bash 运行 Unix 常见命令、用户安装的三方命令和 Git 命令等;使用 LS 列出文件和目录;使用 Glob 根据模式查找文件;使用 Grep 通过正则表达式快速搜索文件内容。文件的查找和搜索是通过 Claude Code 预装的一个叫 rg 的工具实现的,它相对于 grep 速度更快,效率更高,适用于任何规模的代码库。

Claude Code 的工具箱里还有不少其他好玩的工具,我们明天继续。


学习 Claude Code 的命令行操作

我们昨天学习了 Claude Code 的一些实用技巧,包括提问的艺术、图像的处理,文件和网址的处理、扩展思考模式等,还介绍了几个会话管理的小命令,Claude Code 还有不少实用的命令和参数,我们今天来盘点下。

使用 claude --help 查看 Claude Code 支持的所有命令和参数:

claude-help.png

非交互模式

参数 -p--print 可以让 Claude Code 直接打印响应,不进入交互模式,这对于脚本编写和自动化特别有用。比如下面的例子让 Claude Code 充当一个代码检查工具:

$ claude -p "你是一个代码检查工具,请检查主分支的更改,并报告任何与拼写错误相关的问题。报告分两行:第一行是文件名和行号,第二行描述问题。不要返回任何其他文本。"

非交互模式可以让我们很方便地将 Claude Code 无缝地集成到构建脚本或 CI/CD 工作流中。假如你在开发 Node.js 项目,可以将这个命令添加到 package.json 文件:

{
    ...
    "scripts": {
        ...
        "lint:claude": "claude -p '你是一个代码检查工具...'"
    }
}

然后运行 npm run lint:claude 来对提交的代码进行检查:

claude-p-lint.png

除了代码检查,你可以自定义提示词实现更多其他功能。为了防止非交互模式下 Claude Code 陷入死循环,可以使用 --max-turns 参数限制对话的轮数:

$ claude -p --max-turns 3 "query"

非交互模式还可以让我们使用管道将 Claude Code 集成到现有的 Shell 脚本中,与其他 Unix 工具结合使用以实现强大的工作流程:

$ cat build-error.txt | claude -p '详细解释这个构建错误并分析可能的出错原因' > output.txt

默认 Claude Code 的输出为纯文本方式,可以考虑使用 —output-format 参数进行结构化输出:

$ cat package.json | claude -p '找出这个文件中可能存在的问题' --output-format=json > output.json

这种输出结构方便我们以编程方式解析 Claude 的响应,输出内容包含状态、结果、耗时、使用的 tokens 等元数据,如下:

{
    "type": "result",
    "subtype": "success",
    "is_error": false,
    "duration_ms": 14340,
    "duration_api_ms": 17037,
    "num_turns": 3,
    "result": "这个 package.json 文件有以下问题:...",
    "session_id": "ecb8aaf4-4fbe-44c1-a27a-c88f5d85f817",
    "total_cost_usd": 0.06880885,
    "usage": {
        "input_tokens": 9,
        "cache_creation_input_tokens": 15601,
        "cache_read_input_tokens": 14445,
        "output_tokens": 289,
        "server_tool_use": {
            "web_search_requests": 0
        },
        "service_tier": "standard"
    }
}

Claude Code 支持 JSON 和流式 JSON 两种结构化输出格式,当使用流式 JSON 时,Claude Code 会实时输出一系列的 JSON 对象,而不是一个 JSON 对象。可以根据需要来选择不同的输出格式:

  • 对于只需要 Claude 响应的简单集成,使用 --output-format=text
  • 当你需要完整的对话日志时,使用 --output-format=json
  • 当你需要每个对话轮次的实时输出时,使用 --output-format=stream-json

我们除了可以控制输出格式,也可以使用 --input-format 参数指定输入格式,Claude Code 支持两种输入格式:

  • 对于简单集成,使用 --input-format=text
  • 当你需要实时流式输入时,使用 --input-format=stream-json

调试模式

参数 -d--debug 用于开启调试模式:

$ claude --debug

调试模式右下角会显示 “Debug mode” 的标记,在交互过程中会打印出 Claude Code 中 DEBUG 级别的日志:

claude-debug.png

参数 --verbose 用于开启详细模式,或者叫做冗余模式:

$ claude --verbose

详细模式下会显示出工具的完整调用结果,和正常模式下按 Ctrl + R 效果是一样地:

claude-verbose.png

这两个模式对于排查问题都很有帮助,当遇到报错时,比如调用 MCP Server 异常,可以试试这两个模式。

指定模型

参数 --model 用于指定当前会话的模型:

$ claude --model sonnet

可以提供最新模型的别名(例如 sonnetopus)或模型的全名(例如 claude-sonnet-4-20250514)。

参数 --fallback-model 用于指定回退模型:

$ claude --model opus --fallback-model sonnet -p "query"

当默认模型超负荷时,将自动切换到指定的回退模型,注意,仅在非交互模式下有效。

交互模式

在交互模式下有不少键盘快捷键可供使用,输入 ? 查看说明:

claude-shortcuts.png

  • ! - 进入 Bash 模式,可直接运行 Bash 命令
  • / - 输入快捷命令,在交互式会话中控制 Claude 的行为
  • @ - 我们知道在输入文件路径时可以按下 Tab 键自动补全,使用 @ 也可以智能提示并引用文件
  • # - 向 CLAUDE.md 文件中添加新的记忆
  • Ctrl + L - 清空当前输入框的内容
  • Esc + Esc - 当输入框有内容时,连按两次 Esc 键,清空输入框内容,和 Ctrl + L 一样;当输入框没有内容时,连按两次 Esc 键,可以回退到之前的对话记录
  • Ctrl + C - 和 Ctrl + L 一样,也是清空输入框内容,但是如果连按两次 Ctrl + C 就会退出程序
  • Ctrl + Z - 取消上一步操作,注意这个针对的仅仅是输入框中的操作,比如输入、删除、清空等
  • Shift + Tab - 自动接受文件编辑,默认情况下,编辑文件前 Claude Code 会让用户确认
  • Ctrl + R - 开启详细模式,将显示工具的完整调用结果,和上面的 --verbose 一样
  • Shift + Enter - 多行输入,也可以手动输入 \ + Enter 换行,在 macOS 中也可以使用 Option + Enter 换行
  • /vim - 启用 Vim 风格编辑,如果你是一个 Vim 党,在编辑大段文本时会很方便

斜杠命令

上面的 / 快捷键比较有意思,用于快速唤起某些命令,这些命令被称为 斜杠命令(Slash Commands)。我们在之前的学习中已经见过一些斜杠命令了,比如用 /init 创建 CLAUDE.md 记忆文件,用 /clear 清除对话历史,用 /compact 压缩对话等等。在交互式对话框中输入 / 可唤出所有可用的斜杠命令:

claude-slash-commands-0.png

常用的斜杠命令如下所示:

claude-slash-commands.png

自定义斜杠命令

关于斜杠命令的另一个有趣功能是,用户可以将经常使用的提示或指令放在特定位置的 Markdown 文件中,从而创建出属于自己独有的斜杠命令。自定义命令文件位于当前项目的 .claude/commands 目录下或者个人用户的 ~/.claude/commands 目录下,项目目录下的命令叫做 项目命令,可以存储在仓库中并与你的团队共享;用户目录下的命令叫做 用户命令,只能你自己使用,而且可以在所有项目中使用。

自定义斜杠命令的语法如下:

> /<prefix>:<command-name> [arguments]

其中,<prefix> 表示命令作用域,可以是 project 项目命令,或者 user 用户命令;<command-name> 是命令的名称,也就是 Markdown 文件的名称(不包含 .md 扩展名),一个 Markdown 文件对应一个命令;[arguments] 表示传递给命令的可选参数。

下面是一个项目命令的例子,在 .claude/commands 目录下创建一个 optimize.md 文件:

$ mkdir -p .claude/commands
$ echo "分析代码的性能并给出优化建议:" > .claude/commands/optimize.md

然后就可以通过下面的斜杠命令来调用:

> /project:optimize

下面是一个用户命令的例子,在 ~/.claude/commands 目录下创建一个 security-review.md 文件:

$ mkdir -p ~/.claude/commands
$ echo "审查代码的安全漏洞:" > ~/.claude/commands/security-review.md

然后就可以通过下面的斜杠命令来调用:

> /user:security-review

命令目录下还可以创建子目录,这些子目录被称为 命名空间,方便用户对不同类型的命令进行组织,比如对于一个全栈项目,我们可以将命令分为前端命令和后端命令,那么就可以在 .claude/commands 目录下创建 frontendbackend 两个子目录。命名空间命令的语法如下:

> /<prefix>:<namespace>:<command-name> [arguments]

另外,我们可以在 Markdown 文件中使用 $ARGUMENTS 占位符,表示传递给命令的参数,比如下面这个实际的例子:

请分析并解决这个 GitHub 问题 $ARGUMENTS,按照以下步骤进行:

1. 使用 `gh issue view` 获取问题详情
2. 理解问题中描述的问题
3. 在代码库中搜索相关文件
4. 实施必要的更改以解决问题
5. 编写并运行测试以验证修复
6. 确保代码通过 linting 和类型检查
7. 创建一个描述性的提交信息
8. 推送并创建一个 PR

请记住使用 GitHub CLI (`gh`) 进行所有与 GitHub 相关的任务。

将上面的内容保存到 .claude/commands/fix-github-issue.md 文件中,然后调用这个命令来修复 Github 上的问题:

> /project:fix-github-issue 1234

通过传入动态参数,可以创建出更加灵活的自定义命令,比如这些场景:

  • 为指定函数生成测试用例
  • 为指定组件创建文档
  • 审查指定文件中的代码
  • 将内容翻译为指定语言

所有自定义的斜杠命令也会显示在 / 快捷命令列表中:

claude-slash-commands-custom.png

小结

我们今天学习了不少和 Claude Code 命令行相关的技巧,比如使用非交互模式轻松将 Claude Code 集成到构建脚本或 CI/CD 工作流中,使用调试模式和详细模式快速定位和解决各种问题,交互模式下丰富的快捷键和斜杠命令让日常使用更高效,而自定义斜杠命令让我们可以根据项目需求创建专属的命令工具箱。

关于 Claude Code 的命令行操作还有很多,比如关于工具权限的 --allowedTools--disallowedTools 参数,关于 MCP 集成的 claude mcp 子命令,关于配置管理的 claude config 子命令等,我们将在后续的专题学习中逐一介绍。


学习 Claude Code 的基本技巧

昨天我们折腾了一下 LiteLLM 网关,成功让 Claude Code 接入了其他大模型。这下好了,直接用 OpenRouter 的免费 DeepSeek 模型,再也不用担心 API 费用把钱包掏空了,可以放心大胆地体验 Claude Code 的各种功能。

前面我们已经学习了 Claude Code 的安装和基本用法,今天咱们继续深入挖掘一些实用的小技巧,让这个工具用起来更顺手。

提问的艺术

用 Claude Code 就像跟人聊天一样,你说话越清楚,它就越能帮到你。下面是几个建议:

  • 第一,指令越具体越好,比如当你的页面出 BUG 时,不要这样问:
> 修复这个 BUG

这样问才对:

> 修复登录页面的 BUG,用户输错密码后看到的是空白页面而不是错误提示

第一种问法就像对着服务员喊"给我来个菜",第二种才是正常人的沟通方式。

  • 第二,大任务拆成小步骤,复杂的需求别一股脑全说出来,要学会拆解:
> 1. 给用户资料页面加个新的 API 接口

> 2. 添加必填字段的验证逻辑

> 3. 写几个测试用例验证功能

分步解决可以让 Claude Code 更了解用户的意图。

  • 第三,让 Claude Code 先摸清状况,别上来就让它动手改代码,先让它了解一下你的项目:
> 帮我分析一下这个数据库的表结构

> 这个数据库查询异常是怎么回事?

使用扩展思考模式

以往的大语言模型,要么擅长快速响应,要么擅长深度推理,很难兼顾两者,比如 DeepSeek 的 V3 和 R1。Claude Sonnet 3.7 号称是业界首个 混合推理(Hybrid Reasoning) 模型,同时支持 标准模式扩展思考模式

  • 标准模式:对于一些事实性问题或简单指令,能迅速给出答案,快速回复用户;
  • 扩展思考模式(Extended Thinking):模型会在回答之前进行自我反思,进行更深入的思考,并给出更全面、更准确的答案;

所有在 Claude Sonnet 3.7 之后发布的 Opus 和 Sonnet 模型都支持这两种模式。当我们面对下面这些复杂的任务时可以尝试使用扩展思考:

  • 规划复杂的架构更改
  • 调试复杂问题
  • 为新功能创建实现计划
  • 理解复杂的代码库
  • 评估不同方法之间的权衡

Claude 官方出了一份关于扩展思考的高级策略和技巧指南,推荐阅读:

我们在 Claude Code 中对话时,默认使用的是标准模式;如果要处理上面那些复杂的问题时,可以在指令中加上 “think” 或 “think harder” 等触发扩展思考模式:

> 我需要实现 OAuth2 认证,深入思考最佳方法

> 思考下,这种方法可能存在哪些潜在的安全漏洞?

> 更深入地思考我们应该处理的边缘情况

我试了下,无论是英文 “think” 还是中文 “思考” 都可以触发扩展思考模式,而且可以使用类似 “think more”、“think a lot”、“think harder” 或 “think longer” 这样的强化短语触发更深层的思考。

Claude 的思考模式可以通过 budget_tokens 参数控制令牌预算,我猜测不同的提问方式会导致这个参数的值不同,更深层的思考消耗更多的思考令牌,感兴趣的朋友可以验证一下。

我这里还是拿数独项目为例,让它给我提一些 SEO 优化的建议:

claude-extend-thinking.png

和 DeepSeek R1 一样,Claude 的思考过程对用户也是可见的。在上图中,Claude 以斜体灰色文本显示了其思考过程,你可以看到它是如何一步步分析问题、得出结论的。Claude Code 对我的代码经过一番分析,最终输出如下:

claude-extend-thinking-2.png

经过思考后的输出要更详细。

处理图像

Claude 系列模型具有视觉能力,可以理解和分析图像。当我们遇到有些问题用文本描述不清或过于繁琐时,可以给 Claude 提供图像,效果会更好,比如错误截图、UI 设计或图表等,图像比文本包含更多的上下文信息。

我们可以通过下面几种方法向 Claude Code 对话中添加图像:

  • 将图像拖放到 Claude Code 窗口中
  • 复制图像并使用 ctrl+v 粘贴到命令行中(不要使用 cmd+v
  • 提供图像路径,例如:“分析图像: /path/to/your/image.png”

可以在对话中一次性添加多个图像。

下面是使用图像的一些常用场景:

  • 让 Claude 分析图像
> 这张图片显示了什么?

> 描述截图中的用户界面元素

> 这张图中是否有任何问题元素?
  • 使用图像提供上下文
> 这是错误的截图,分析是什么原因引起的?

> 这是我们当前的数据库模式,为了实现新增的功能,我们应该如何修改它?
  • 从视觉内容获取代码建议
> 根据这个设计图生成 CSS

> 什么样的 HTML 结构可以重现这个组件?

处理文件和网址

我们还可以让 Claude Code 查看或处理仓库下的某个文件或目录,一般需要输入全路径,方便 Claude 找到正确的资源。使用 Tab 键自动补全,可以大大方便文件路径的输入:

claude-tab.png

也可以将某个网址丢给 Claude Code 让它分析或总结:

claude-fetch.png

Claude Code 内置了一个 Fetch 工具,用于抓取网页内容。

会话管理

我们每次运行 claude 命令进入交互模式时,实际上都是创建一个新会话,如果我们希望继续之前的会话,可以使用 Claude Code 的会话管理功能。

参数 -c--continue 用于继续最近一次对话:

$ claude -c

参数 -r--resume 用于恢复某个历史会话:

$ claude -r

Claude Code 会弹出一个对话选择列表,列出最近的所有会话:

claude-r.png

列表中显示了会话时间、消息条数、消息摘要等信息,你可以使用上下键导航并按 Enter 选择具体的会话,恢复后,你将看到该会话的整个对话历史。

此外,在交互模式下,还有一些 斜杠命令(Slash Commands) 也可以操作会话。比如当会话中消息过多时,可能会影响模型的效果和速度,这时我们可以执行 /clear 命令清除上下文:

> /clear

实际上 /clear 命令是创建了一个新会话,老的会话不动。

或者使用 /compact 命令压缩当前会话:

> /compact

压缩成功后,会显示如下信息:

claude-compact.png

之后的对话将从压缩后的会话开始。实际上 /compact 也是创建了一个新会话,将压缩后的会话作为新会话的第一条消息。

小结

我们今天简单学习了 Claude Code 的一些实用技巧,从提问的艺术,到处理图像,再到处理文件和网址。还学习了开启扩展思考模式的方法,遇到复杂问题时别忘了加个 "think" 或 "思考",让 AI 先动动脑子再回答。

最后介绍了几个会话管理的小命令,像这样的小命令 Claude Code 还有很多,熟练掌握可以给我们省不少事儿,下一篇我们就来盘点下 Claude Code 的其他命令。