这是 Anthropic 官方免费课程 Claude Code in Action 学习笔记的第二部分,继续记录 Claude Code 的高级功能和最佳实践。
Hooks 简介
Hooks 允许你在 Claude 尝试运行工具之前或之后执行命令。它们对于实现自动化工作流非常有用,比如在文件编辑后运行代码格式化、在文件更改时执行测试,或阻止对特定文件的访问。
工作原理
当你与 Claude Code 交互时,正常流程是:你的查询连同工具定义一起发送给 Claude 模型,Claude 可能决定使用某个工具并提供格式化的响应,然后 Claude Code 执行该工具并返回结果。
Hooks 将自己插入到这个过程中,允许你在工具执行之前或之后执行代码。

Hook 类型
| 类型 | 执行时机 | 能力 |
|---|---|---|
| PreToolUse | 工具调用之前 | 允许操作继续、阻止工具调用并返回错误信息 |
| PostToolUse | 工具调用之后 | 运行后续操作、向 Claude 提供额外反馈 |
Hook 配置位置
Hooks 在 Claude 配置文件中定义,可以添加到以下位置:
| 文件 | 作用范围 |
|---|---|
~/.claude/settings.json | 全局设置,影响所有项目 |
.claude/settings.json | 项目设置,与团队共享 |
.claude/settings.local.json | 项目本地设置,不提交到版本控制 |
你可以手动编写这些文件中的 hooks,也可以在 Claude Code 内部使用 /hooks 命令进行配置。


PreToolUse Hook 示例
PreToolUse hooks 在工具执行之前运行,包含一个 matcher 来指定要针对的工具类型:
{
"PreToolUse": [
{
"matcher": "Read",
"hooks": [
{
"type": "command",
"command": "node /home/hooks/read_hook.ts"
}
]
}
]
}在 Read 工具执行之前,此配置会运行指定的命令。你的命令会收到 Claude 想要进行的工具调用的详细信息,你可以:
- 允许操作正常进行
- 阻止工具调用并向 Claude 发送错误消息
PostToolUse Hook 示例
PostToolUse hooks 在工具执行之后运行。以下示例在 write、edit 或 multi-edit 操作后触发:
{
"PostToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
"command": "node /home/hooks/edit_hook.ts"
}
]
}
]
}由于工具调用已经发生,PostToolUse hooks 无法阻止操作。但它们可以:
- 运行后续操作(如格式化刚刚编辑的文件)
- 向 Claude 提供关于工具使用的额外反馈

实际应用场景
| 应用 | 说明 |
|---|---|
| 代码格式化 | 在 Claude 编辑文件后自动格式化 |
| 测试 | 文件更改时自动运行测试 |
| 访问控制 | 阻止 Claude 读取或编辑特定文件 |
| 代码质量 | 运行 linter 或类型检查器并向 Claude 提供反馈 |
| 日志记录 | 跟踪 Claude 访问或修改的文件 |
| 验证 | 检查命名约定或编码标准 |
定义 Hooks
创建一个Hook
创建 hook 涉及四个主要步骤:

- 决定使用 PreToolUse 还是 PostToolUse hook - PreToolUse hooks 可以阻止工具调用执行,而 PostToolUse hooks 在工具已经使用后运行
- 确定要监视哪种类型的工具调用 - 你需要精确指定哪些工具应该触发你的 hook
- 编写一个接收工具调用的命令 - 这个命令通过标准输入接收关于提示的工具调用的 JSON 数据
- 如果需要,命令应该向 Claude 提供反馈 - 你的命令的退出码告诉 Claude 是允许还是阻止操作
可用工具
Claude Code 提供了多个内置工具,你可以用 hooks 监视它们:

- Read
- Write
- Edit
- MultiEdit
- Bash
- Glob
- Grep
- WebFetch
- WebSearch
- Task
- TodoRead / TodoWrite
- NotebookRead / NotebookEdit
工具调用数据结构
当你的 hook 命令执行时,Claude 通过标准输入发送包含提示的工具调用详细信息的 JSON 数据:

{
"session_id": "2d6a1e4d-6...",
"transcript_path": "/Users/sg/...",
"hook_event_name": "PreToolUse",
"tool_name": "Read",
"tool_input": {
"file_path": "/code/queries/.env"
}
}你的命令从标准输入读取这个 JSON,解析它,然后根据工具名称和输入参数决定是允许还是阻止操作。
退出码和控制流
你的 hook 命令通过退出码与 Claude 通信:

| 退出码 | 含义 |
|---|---|
| 0 | 一切正常,允许工具调用继续 |
| 2 | 阻止工具调用(仅限 PreToolUse hooks) |
当你在 PreToolUse hook 中以退出码 2 退出时,你写入标准错误的任何错误消息都会作为反馈发送给 Claude,解释为什么操作被阻止。
示例:阻止读取敏感文件
一个常见的用例是阻止 Claude 读取敏感文件,如 .env 文件。由于 Read 和 Grep 工具都可以访问文件内容,你需要监视这两种工具类型,并检查它们是否试图访问受限的文件路径。
这种方法让你完全控制 Claude 的文件系统访问,同时提供关于为什么某些操作被限制的清晰反馈。
实现 Hook
让我们构建一个自定义 hook 来阻止 Claude 读取敏感文件(如 .env)。这是一个实际示例,展示 hooks 如何在开发会话期间保护你的环境变量和其他机密数据。
配置 Hook
首先,我们需要在设置文件中配置 hook。打开 .claude/settings.local.json 文件并找到 hooks 部分。我们将创建一个 PreToolUse hook,因为我们想在工具执行之前拦截调用。
配置需要两个关键部分:
- Matcher - 指定要监视哪些工具
- Command - 当这些工具被调用时运行的脚本
对于 matcher,我们想捕获可能访问 .env 文件的 read 和 grep 操作:
"matcher": "Read|Grep"管道符号(|)作为 OR 运算符,因此这将在任一工具上触发。对于 command,我们将指向一个 Node.js 脚本:
"command": "node ./hooks/read_hook.js"完整的PreToolUse配置:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Read|Grep",
"hooks": [
{
"type": "command",
"command": "node ./hooks/read_hook.js"
}
]
}
]
}理解工具调用数据
当 Claude 尝试使用工具时,你的 hook 通过标准输入以 JSON 形式接收关于该调用的详细信息。这些数据包括:
- Session ID 和 transcript 路径
- Hook 事件名称(在我们的例子中是 PreToolUse)
- 工具名称(Read、Grep 等)
- 工具输入参数,包括文件路径
你的 hook 脚本处理这些数据,可以允许操作继续或通过以特定代码退出来阻止它。
实现 Hook 脚本
hook 脚本需要从标准输入读取工具调用数据,并检查 Claude 是否试图访问 .env 文件。以下是核心逻辑:
async function main() {
const chunks = [];
for await (const chunk of process.stdin) {
chunks.push(chunk);
}
const toolArgs = JSON.parse(Buffer.concat(chunks).toString());
// 提取 Claude 试图读取的文件路径
const readPath =
toolArgs.tool_input?.file_path || toolArgs.tool_input?.path || "";
// 检查 Claude 是否试图读取 .env 文件
if (readPath.includes('.env')) {
console.error("You cannot read the .env file");
process.exit(2);
}
}脚本检查文件路径中是否包含 .env,如果找到则阻止操作。当你以退出码 2 退出时,Claude 会收到错误消息并理解操作被 hook 阻止了。
测试 Hook
保存配置和 hook 脚本后,重启 Claude Code 使更改生效。然后通过要求 Claude 读取你的 .env 文件来测试它。
当 Claude 尝试读取操作时,你的 hook 会拦截它并返回错误消息。Claude 会识别出操作被阻止,并向你解释这一点,通常会提到 read hook 阻止了对文件的访问。
同样的保护也适用于 grep 操作——如果 Claude 试图在 .env 文件中搜索,hook 也会阻止它。
关键优势
| 优势 | 说明 |
|---|---|
| 主动保护 | 在敏感数据被读取之前阻止访问 |
| 透明操作 | Claude 理解为什么操作失败 |
| 灵活匹配 | 适用于多种工具(read、grep 等) |
| 清晰反馈 | 提供有意义的错误消息 |
.env 文件,但相同的模式可以保护项目中的任何敏感文件或目录。你可以扩展逻辑来检查多个文件模式,或根据安全需求实现更复杂的访问控制。Hooks 注意事项
在使用 hooks 时,你可能会注意到 .claude 目录中有两个 settings.json 文件。让我解释一下这是怎么回事。
安全建议
Claude Code 文档列出了一些关于 hooks 安全性的建议,其中一条是使用绝对路径(而不是相对路径)来引用脚本。这有助于减轻路径拦截和二进制文件植入攻击。

共享配置的挑战
这个建议也使得共享 settings.json 文件变得更加困难。原因很简单:你机器上任何 hook 脚本的绝对路径可能与我机器上的绝对路径不同,因为我们可能会将项目放在不同的目录中。
解决方案:使用占位符
为了解决这个问题,项目可以使用 settings.example.json 文件。在这个文件中,脚本引用包含一个 $PWD 占位符:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Read|Grep",
"hooks": [
{
"type": "command",
"command": "node $PWD/hooks/read_hook.js"
}
]
}
]
}
}package.json:
{
"name": "queries",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"setup": "npm install && node ./scripts/init-claude.js",
"test": "echo \"Error: no test specified\" && exit 1",
"sdk": "tsx sdk.ts"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "module",
"dependencies": {
"@anthropic-ai/claude-agent-sdk": "^0.1.5",
"@types/node": "^24.0.13",
"sqlite": "^5.1.1",
"sqlite3": "^5.1.7",
"tsx": "^4.20.3",
"typescript": "^5.8.3"
}
}当运行 npm run setup 时,除了安装依赖之外,还会运行一个 init-claude.js 脚本。
import fs from "fs";
import path from "path";
// Get the current working directory
const pwd = process.cwd();
// Define file paths
const templatePath = path.join(".claude", "settings.example.json");
const outputPath = path.join(".claude", "settings.local.json");
try {
// Read the template file
const templateContent = fs.readFileSync(templatePath, "utf8");
// Replace all instances of $PWD with the actual working directory
const processedContent = templateContent.replace(/\$PWD/g, pwd);
// Parse to validate JSON (optional but recommended)
JSON.parse(processedContent);
// Ensure .claude directory exists
const claudeDir = path.dirname(outputPath);
if (!fs.existsSync(claudeDir)) {
fs.mkdirSync(claudeDir, { recursive: true });
}
// Write the processed content to settings.json
fs.writeFileSync(outputPath, processedContent, "utf8");
console.log(`✅ Successfully created ${outputPath}`);
console.log(` Replaced $PWD with: ${pwd}`);
} catch (error) {
if (error.code === "ENOENT") {
console.error(`❌ Error: Could not find ${templatePath}`);
console.error(
" Make sure you run this script from the project root directory."
);
} else if (error instanceof SyntaxError) {
console.error("❌ Error: Invalid JSON after processing");
console.error(error.message);
} else {
console.error("❌ Error:", error.message);
}
process.exit(1);
}这个脚本会:
- 将
$PWD占位符替换为项目在你机器上的绝对路径 - 复制
settings.example.json文件 - 将其重命名为
settings.local.json
这种方法让我们既能共享 settings.json 文件,又能使用推荐的绝对路径!
| 文件 | 用途 |
|---|---|
settings.example.json | 包含 $PWD 占位符的模板文件,提交到版本控制 |
settings.local.json | 由脚本生成,包含实际绝对路径,不提交到版本控制 |
实用 Hooks 示例
Claude Code hooks 可以帮助解决 AI 辅助开发中的常见问题,特别是在大型项目中。这些 hooks 在 Claude 修改代码时自动运行,提供即时反馈并防止常见问题。
TypeScript 类型检查 Hook
最有用的 hooks 之一解决了一个基本问题:当 Claude 修改函数签名时,它通常不会更新项目中调用该函数的所有位置。
例如,如果你要求 Claude 在 schema.ts 中的某个函数添加一个 verbose 参数,它会成功更新函数定义,但可能会遗漏 main.ts 中的调用点。这会产生 Claude 无法立即捕获的类型错误。
解决方案是一个 PostToolUse hook,在每次文件编辑后运行 TypeScript 编译器:
- 运行
tsc --noEmit检查类型错误 - 捕获发现的任何错误
- 立即将错误反馈给 Claude
- 提示 Claude 修复其他文件中的问题
这个 hook 适用于任何可以运行类型检查器的类型化语言。对于非类型化语言,你可以使用自动化测试实现类似的功能。
查询重复预防 Hook
在有许多数据库查询的大型项目中,Claude 有时会创建重复功能而不是复用现有代码。当你给 Claude 复杂的多步骤任务,而数据库操作只是其中一个组件时,这个问题尤为突出。
考虑一个包含多个查询文件的项目结构,每个文件包含许多 SQL 函数。当你要求 Claude “创建一个 Slack 集成,提醒待处理超过 3 天的订单"时,它可能会编写一个新查询,而不是使用现有的 getPendingOrders() 函数。

查询重复 hook 通过实现审查流程来解决这个问题:

- 当 Claude 修改
./queries目录中的文件时触发 - 以编程方式启动一个单独的 Claude Code 实例
- 让第二个实例审查更改并检查是否存在类似的现有查询
- 如果发现重复,向原始 Claude 实例提供反馈
- 提示 Claude 删除重复并使用现有功能
./hooks/query_hook.js:
// Note: the "@anthropic-ai/claude-code" package has been renamed
// to "@anthropic-ai/claude-agent-sdk"
import { query } from "@anthropic-ai/claude-agent-sdk";
import path from "path";
const REVIEW_DIR = "src/queries";
async function main() {
// process.exit(0);
// Read JSON input from stdin
const input = await new Promise((resolve) => {
let data = "";
process.stdin.on("data", (chunk) => (data += chunk));
process.stdin.on("end", () => resolve(data));
});
const hookData = JSON.parse(input);
const toolInput = hookData.tool_input;
// Check if this is a file modification in ./queries
const filePath = toolInput.file_path || toolInput.path;
if (!filePath) {
process.exit(0);
}
// Normalize paths for comparison
const normalizedFilePath = path.resolve(filePath);
const queriesDir = path.resolve(process.cwd(), REVIEW_DIR);
// Check if file is within queries directory (handles subdirectories too)
if (!normalizedFilePath.startsWith(queriesDir + path.sep)) {
process.exit(0);
}
// Prepare prompt for analysis
const newContent =
toolInput.content || toolInput.contents || toolInput.new_string;
const prompt = `You are reviewing a proposed change to a database query file.
Your task is to analyze if the new or modified query functions could be
accomplished by reusing or slightly modifying existing query functions.
Within reason, we want to prevent duplicate queries from being added into this project,
so you are seeing if the proposed change will duplicate any existing functionality.
File: ${filePath}
New content:
<new_content>
${newContent}
</new_content>
Please research and analyze the existing queries in the ./queries directory and:
1. Identify any new query functions being added in this change
2. For each new query function, determine if it could be accomplished by:
- Using an existing query function as-is
- Slightly modifying an existing query function, perhaps by adding additional
arguments or expanding a select statement
If yes, provide specific feedback on which existing functions could be used instead. Be concise and specific.
If no, just say "Changes look appropriate."`;
const messages = [];
for await (const message of query({
prompt,
})) {
messages.push(message);
}
// Extract the analysis result
const resultMessage = messages.find((m) => m.type === "result");
if (!resultMessage || resultMessage.subtype !== "success") {
process.exit(0);
}
// If changes are appropriate, allow them
if (resultMessage.result.includes("Changes look appropriate")) {
process.exit(0);
}
// Otherwise, block with feedback
console.error(`Query duplication detected:\n\n${resultMessage.result}`);
process.exit(2);
}
main().catch((err) => {
console.error(`Hook error: ${err.message}`);
process.exit(1);
});./hooks/query_hook.js 是一个 Claude Code 的 PreToolUse Hook,用于在 Claude Code 修改 src/queries 目录下的文件之前进行代码审查,防止添加重复的查询函数。
整体流程:
Claude Code 尝试编辑文件
↓
Hook 被触发
↓
检查是否是 queries 目录
↓
是 → 调用 Claude SDK 分析代码
↓
检测到重复 → 阻止编辑并给出建议
没有重复 → 允许编辑继续代码分析:
读取 Hook 输入 - Claude Code 通过 stdin(标准输入)传递 JSON 格式的 hook 数据。由于 stdin 是流式的,需要用 Promise 包装来收集完整数据:
const input = await new Promise((resolve) => { let data = ""; process.stdin.on("data", (chunk) => (data += chunk)); process.stdin.on("end", () => resolve(data)); }); const hookData = JSON.parse(input);这里涉及 Node.js 的 Stream(流) 概念。
process.stdin是一个可读流,数据不是一次性到达的,而是分块(chunk)传输:data事件 - 每当有新的数据块到达时触发,可能触发多次。比如传输 1000 字节的数据,可能分 3 次触发:第一次 400 字节,第二次 400 字节,第三次 200 字节。每次触发时,回调函数将收到的 chunk 拼接到data变量end事件 - 当数据流完全结束时触发,只触发一次。此时所有数据块都已收到,可以安全地处理完整数据
这种模式是 Node.js 处理流数据的标准写法。解析后的数据包含
tool_name和tool_input(文件路径、新内容等)路径检查 - 使用
path.resolve()将路径转为绝对路径,只有src/queries目录下的文件才触发审查调用 Claude SDK -
query()是 Claude Agent SDK 提供的核心函数,用于以编程方式调用 Claude 模型。它是一个异步生成器,会流式返回多种类型的消息:const messages = []; for await (const message of query({ prompt })) { messages.push(message); }返回的消息类型包括:
assistant- Claude 的文本响应tool_use- Claude 请求使用工具result- 最终结果,包含subtype(如success)和result字段
在这个 Hook 中,我们收集所有消息后查找
type === "result"的消息来获取分析结论退出码控制 -
process.exit(0)允许操作继续,process.exit(2)阻止操作并将 stderr 内容作为反馈显示给用户
Hook 配置示例:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "node hooks/query_hook.js"
}
]
}
]
}
}实际效果: 当尝试添加重复的查询函数时,Hook 会阻止操作并给出建议:
❌ Hook blocked the operation:
Query duplication detected:
The new function `getStalePendingOrders` duplicates functionality
already available in `getPendingOrders`. Consider modifying the
existing function to accept an optional `minDaysOld` parameter instead.实现考虑
两个 hooks 都使用 PreToolUse 或 PostToolUse hook 系统。TypeScript hook 相对轻量,运行速度快。查询重复 hook 需要更多资源,因为它为每次审查启动一个单独的 Claude 实例。
对于查询 hook,需要考虑以下权衡:
| 方面 | 说明 |
|---|---|
| 优势 | 更干净的代码库,更少的重复 |
| 成本 | 每次查询目录编辑都需要额外的时间和 API 使用 |
| 建议 | 只监控关键目录以最小化开销 |
这些 hooks 使用 Claude 的 TypeScript SDK 以编程方式与 AI 交互。这允许你创建复杂的工作流,其中一个 Claude 实例可以审查另一个实例的工作并提供反馈。
扩展这些概念
这些 hooks 展示了你可以应用到自己项目的更广泛原则:
- 使用编译器/linter 输出提供即时反馈
- 使用单独的 AI 实例实现代码审查流程
- 将监控重点放在一致性最重要的高价值目录上
- 在自动化收益和性能成本之间取得平衡
关键是识别开发工作流中的具体痛点,并创建针对性的 hooks 自动解决这些问题。
其他 Hook 类型
除了本课程讨论的 PreToolUse 和 PostToolUse hooks 之外,还有其他类型的 hooks:
| Hook 类型 | 触发时机 |
|---|---|
| Notification | Claude Code 发送通知时(需要工具权限或空闲 60 秒后) |
| Stop | Claude Code 完成响应时 |
| SubagentStop | 子代理(UI 中显示为 “Task”)完成时 |
| PreCompact | 压缩操作发生之前(手动或自动) |
| UserPromptSubmit | 用户提交提示时,在 Claude 处理之前 |
| SessionStart | 启动或恢复会话时 |
| SessionEnd | 会话结束时 |
stdin 输入结构的差异
这里有一个容易混淆的地方:你的命令收到的 stdin 输入会根据 hook 类型而变化。对于 PreToolUse 和 PostToolUse hooks,tool_input 的内容还会根据被调用的工具而不同。
以下是一个 PostToolUse hook 监视 TodoWrite 工具的 stdin 输入示例:
{
"session_id": "9ecf22fa-edf8-4332-ae85-b6d5456eda64",
"transcript_path": "<path_to_transcript>",
"hook_event_name": "PostToolUse",
"tool_name": "TodoWrite",
"tool_input": {
"todos": [{ "content": "write a readme", "status": "pending", "priority": "medium", "id": "1" }]
},
"tool_response": {
"oldTodos": [],
"newTodos": [{ "content": "write a readme", "status": "pending", "priority": "medium", "id": "1" }]
}
}作为对比,以下是 Stop hook 的输入示例:
{
"session_id": "af9f50b6-f042-4773-b3e2-c3a4814765ce",
"transcript_path": "<path_to_transcript>",
"hook_event_name": "Stop",
"stop_hook_active": false
}可以看到,stdin 输入的结构会根据 hook 类型(PreToolUse、PostToolUse、Stop 等)和 matcher(对于 PreToolUse 和 PostToolUse)而显著不同。这使得编写 hooks 变得具有挑战性——你可能不知道命令输入的确切结构!
调试技巧:记录 Hook 输入
为了解决这个问题,可以创建一个辅助 hook 来记录输入:
{
"PostToolUse": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "jq . > post-log.json"
}
]
}
]
}注意这里的命令:它会将 hook 的输入写入 post-log.json 文件,让你可以检查实际传递给命令的数据结构。这使得理解你的命令应该检查哪些数据变得更加容易。
PostToolUse 替换为你想要调试的 hook 类型,并相应地更改输出文件名即可。Claude Agent SDK
Claude Agent SDK(原名 Claude Code SDK)让你可以在自己的应用程序和脚本中以编程方式运行 Claude Code。它支持 TypeScript、Python 以及 CLI 调用,提供与终端中相同的 Claude Code 功能,但可以集成到更大的工作流中。
包名变更提示:如果你在旧代码或教程中看到 @anthropic-ai/claude-code,请使用新包名 @anthropic-ai/claude-agent-sdk。

主要特性
| 特性 | 说明 |
|---|---|
| 编程式运行 | 在代码中调用 Claude Code |
| 功能一致 | 与终端版本相同的 Claude Code 功能 |
| 继承设置 | 继承同一目录下 Claude Code 实例的所有设置 |
| 默认只读 | 默认情况下只有读取权限 |
| 管道集成 | 最适合作为更大管道或工具的一部分使用 |
基本用法
以下是一个简单的 TypeScript 示例,让 Claude 分析代码中的重复查询:
import { query } from "@anthropic-ai/claude-agent-sdk";
const prompt = "Look for duplicate queries in the ./src/queries dir";
for await (const message of query({
prompt,
})) {
console.log(JSON.stringify(message, null, 2));
}运行这段代码时,你会看到本地 Claude Code 与 Claude 语言模型之间的原始对话,逐条消息显示。最后一条消息包含 Claude 的完整响应。
权限和工具
默认情况下,SDK 只有只读权限。它可以读取文件、搜索目录和执行 grep 操作,但不能写入、编辑或创建文件。
要启用写入权限,可以在查询中添加 allowedTools 选项:
for await (const message of query({
prompt,
options: {
allowedTools: ["Edit"]
}
})) {
console.log(JSON.stringify(message, null, 2));
}或者,你可以在 .claude 目录的设置文件中配置项目范围的权限。
示例
sdk.ts:
// Note: the "@anthropic-ai/claude-code" package has been renamed
// to "@anthropic-ai/claude-agent-sdk"
import { query } from "@anthropic-ai/claude-agent-sdk";
const prompt = "Hi, please get the new version number of the claude code?";
for await (const message of query({
prompt,
options: {
allowedTools: ["WebSearch", "WebFetch"]
}
})) {
console.log(JSON.stringify(message, null, 2));
}运行:
tsx sdk.ts实际应用场景
Claude Agent SDK 在集成到更大的开发工作流时表现出色。考虑将其用于:
| 场景 | 说明 |
|---|---|
| Git hooks | 自动审查代码变更 |
| 构建脚本 | 分析和优化代码 |
| 辅助命令 | 代码维护任务 |
| 文档生成 | 自动生成文档 |
| CI/CD 管道 | 代码质量检查 |
这些场景都需要在项目中集成 SDK 来实现。例如:
- TypeScript/JavaScript 项目:安装
@anthropic-ai/claude-agent-sdk,在脚本中import { query } from "@anthropic-ai/claude-agent-sdk"调用 - Python 项目:安装对应的 Python SDK 包
- Shell 脚本:通过 CLI 方式调用
claude命令
SDK 本质上让你可以在开发过程中任何需要编程访问的地方添加 AI 驱动的智能。
课程测验
以下是课程测验的问题和正确答案:
Q1: 语言模型的什么基本限制使得编码助手需要使用工具系统?
A: 它们只能处理文本输入/输出,无法直接与外部系统交互。
Q2: 在 GitHub Actions 中集成 MCP 服务器与 Claude Code 时需要什么权限配置?
A: 每个 MCP 服务器工具必须在权限中单独列出。
Q3: Claude Code 中 Plan Mode 和 Thinking Mode 的主要区别是什么?
A: Plan Mode 处理广度(多步骤任务),而 Thinking Mode 处理深度(复杂逻辑)。
Q4: 三种类型的 Claude.md 文件及其用途是什么?
A: Project level(与团队共享,提交到版本控制)、Local level(个人使用,不提交)、Machine level(所有项目的全局设置)。
Q5: 如何在 Claude Code 中创建接受运行时参数的自定义命令?
A: 在 markdown 命令文件中包含 $ARGUMENTS 占位符。
Q6: 哪种类型的 hook 可以在满足特定条件时阻止工具调用?
A: PreToolUse hook。
Q7: 开发者想阻止 Claude 读取敏感的 .env 文件,应该设置哪种类型的 hook,匹配哪些工具名称?
A: PreToolUse hook,匹配 Read 和 Grep。
Q8: Claude Code 中 hooks 的主要目的是什么?
A: 在 Claude 执行工具之前或之后运行命令。
总结
本课程涵盖了 Claude Code 的高级功能,包括 Hooks 系统、Claude Agent SDK 等。以下是课程建议的下一步行动:
关注更新
Claude Code 仍在快速发展中,建议关注 anthropic.com/claude-code 获取最新功能和更新。
动手实验
尝试自定义你的 Claude Code 环境:
- 创建自定义命令(Custom Commands)
- 编写 CLAUDE.md 文件来指导 Claude 的行为
- 配置 MCP 服务器扩展功能
自动化工作流
利用 GitHub 集成将常见任务委托给 Claude:
- 代码审查
- PR 创建和管理
- 自动化测试和检查
通过这些实践,你可以充分发挥 Claude Code 的潜力,提升开发效率。