本站点文档内容均翻译自code.visualstudio.com,仅供个人学习,如有差异请以官网为准。

代理挂钩在Visual Studio Code(预览版)

Hooks允许您在代理会话的关键生命周期点执行自定义 shell 命令。使用 Hooks 自动化工作流程、强制执行安全策略、验证操作并与其他外部工具集成。Hooks 以确定性方式运行,并可以控制代理行为,包括阻止工具执行或注入上下文到对话中。

注意

Agent hooks 目前在 VS Code 1.109.3 中处于预览状态。配置格式和行为可能会在未来的版本中发生变化。

重要

您的组织可能已经禁用了 VS Code 中的 hooks。请联系您的管理员以获取更多信息。请参阅 企业策略 了解详情。

钩子被设计为可以跨多种代理类型工作,包括本地代理、后台代理和云代理。每个钩子接收结构化的JSON输入,并可以返回JSON输出以影响代理行为。

为什么使用钩子?

钩子提供确定性、代码驱动的自动化。与指导智能体行为的指令或自定义提示不同,钩子在特定的生命周期点执行您的代码,并保证结果:

  • 强制执行安全策略:阻止危险的命令,例如删除所有文件和目录删除表在他们执行之前,无论代理是如何被提示的。

  • 自动化代码质量:在文件修改后自动运行格式化程序、检查器或测试。

  • 创建审计记录:记录每次工具调用、命令执行或文件更改,以满足合规性和调试需求。

  • 注入上下文:添加项目特定的信息、API密钥或环境细节,以帮助代理做出更好的决策。

  • 控制批准:自动批准安全操作,而对于敏感操作则需要确认。

钩子生命周期事件

VS Code 支持在代理会话的特定点触发的八种钩子事件:

钩子事件 当它发射时 常见用例
会话开始 用户提交了新会话的第一个提示 初始化资源,记录会话开始,验证项目状态
用户提示提交 用户提交一个提示 审计用户请求,注入系统上下文
预工具使用 在智能体调用任何工具之前 阻止危险操作,要求批准,修改工具输入
发布工具使用 工具成功完成后 运行格式化程序,记录结果,触发后续操作
预紧 在对话上下文被压缩之前 导出重要上下文,保存截断前的状态
子代理开始 子代理已生成 跟踪嵌套代理的使用情况,初始化子代理资源
子代理停止 子代理完成 聚合结果,清理子代理资源
停止 代理会话结束 生成报告,清理资源,发送通知

配置钩子

钩子在你的工作区或用户目录中存储的JSON文件中进行配置。

钩子文件位置

VS Code 在这些位置搜索 hook 配置文件:

  • 工作区.github/hooks/*.json- 项目特定的钩子与您的团队共享
  • 工作区.claude/settings.local.json- 本地工作区挂钩(未提交)
  • 工作区.claude/settings.json- 工作区级别的钩子
  • 用户~/.claude/settings.json- 在所有工作区应用个人钩子

工作区钩子在相同事件类型上优先于用户钩子。

钩配置格式

创建一个JSON文件钩子对象包含每个事件类型的钩子命令数组。VS Code 使用与 Claude Code 和 Copilot CLI 相同的钩子格式以保持兼容性:

{
  "hooks": {
    "PreToolUse": [
      {
        "type": "command",
        "command": "./scripts/validate-tool.sh",
        "timeout": 15
      }
    ],
    "PostToolUse": [
      {
        "type": "command",
        "command": "npx prettier --write \"$TOOL_INPUT_FILE_PATH\""
      }
    ]
  }
}

钩子命令属性

每个钩子条目都必须有类型: "命令"并且至少有一个命令属性:

财产 类型 描述
类型 字符串 必须是"命令"
命令 字符串 默认命令运行(跨平台)
Windows 字符串 Windows 特定命令覆盖
Linux 字符串 Linux特定命令覆盖
osx 字符串 macOS特定命令覆盖
当前工作目录 字符串 工作目录(相对于仓库根目录)
环境 对象 附加环境变量
超时 数字 超时时间(秒)(默认:30)
注意

OS-specific命令是根据扩展主机平台选择的。在远程开发场景(SSH、容器、WSL)中,这可能与您的本地操作系统不同。

操作系统特定命令

为每个操作系统指定不同的命令:

{
  "hooks": {
    "PostToolUse": [
      {
        "type": "command",
        "command": "./scripts/format.sh",
        "windows": "powershell -File scripts\\format.ps1",
        "linux": "./scripts/format-linux.sh",
        "osx": "./scripts/format-mac.sh"
      }
    ]
  }
}

执行服务根据您的操作系统选择适当的命令。如果未定义特定于操作系统的命令,则回退到命令财产。

钩输入和输出

Hooks 通过 stdin(输入)和 stdout(输出)使用 JSON 与 VS Code 进行通信。

常见输入字段

每个钩子通过stdin接收一个包含这些公共字段的JSON对象:

{
  "时间戳": "2026-02-09T10:30:00.000Z",
  "当前工作目录": "/path/to(workspace",
  "会话ID": "session-identifier",
  "钩子事件名称": "PreToolUse",
  "转录路径": "/path/to/transcript.json"
}

常见输出格式

钩子可以通过stdout返回JSON以影响代理行为。所有钩子都支持这些输出字段:

{
  "继续": false,
  "停止原因": "安全策略违规",
  "系统消息": "操作被安全钩阻止"
}
领域 类型 描述
继续 布尔 设置为停止处理(默认:)
停止原因 字符串 停止的原因(展示给模型)
系统消息 字符串 显示给用户的消息

退出代码

挂钩的退出代码决定 VS Code 如何处理结果:

退出代码 行为
0 成功:将stdout解析为JSON
2 阻止错误:停止处理并显示错误给模型
其他 非阻塞警告:向用户显示警告,继续处理

预工具使用

预工具使用钩子在代理调用工具之前触发。

预工具使用输入

除了常见的字段,预工具使用钩子接收:

{
  "工具名称": "编辑文件",
  "工具输入": { "文件": ["src/main.ts"] },
  "工具使用ID": "工具-123"
}

预工具使用输出

预工具使用钩子可以通过一个来控制工具的执行钩子特定输出对象:

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "破坏性命令被策略阻止",
    "updatedInput": { "files": ["src/safe.ts"] },
    "additionalContext": "用户对生产文件具有只读访问权限"
  }
}
领域 价值观 描述
许可决定 允许"拒绝" 控制工具批准
许可决定原因 字符串 显示给用户的理由
更新输入 对象 修改工具输入(可选)
附加上下文 字符串 额外的模型上下文

许可决策优先级:当多个钩子为同一工具调用运行时,最严格的决策获胜:

  1. 拒绝(最严格):阻止工具执行
  2. 需要用户确认
  3. 允许(最不限制):自动批准执行

更新输入 格式:确定 更新输入运行命令“Show Chat Debug View”并找到已记录的工具方案。如果更新输入不匹配预期的模式,将被忽略。

发布工具使用

发布工具使用钩子在工具成功完成后触发。

工具使用后输入

除了常见的字段,发布工具使用钩子接收:

{
  "工具名称": "编辑文件",
  "工具输入": { "文件": ["src/main.ts"] },
  "工具使用ID": "tool-123",
  "工具响应": "文件已成功编辑"
}

工具使用后输出

发布工具使用钩子可以为模型提供额外的上下文,或阻止进一步处理:

{
  "决策": "阻止",
  "原因": "后处理验证失败",
  "钩子特定输出": {
    "钩子事件名称": "后工具使用",
    "附加上下文": "编辑的文件有需要修复的代码错误"
  }
}
领域 价值观 描述
决策 “块” 阻止进一步处理(可选)
原因 字符串 屏蔽原因(向模型显示)
钩子特定输出.附加上下文 字符串 额外的上下文注入到对话中

用户提示提交

用户提示提交钩子在用户提交提示时触发。

用户提示提交输入

除了常见的字段,用户提示提交钩子接收一个提示用户提交的文本字段。

用户提示提交钩子仅使用常见的输出格式。

会话开始

会话开始钩子在新的代理会话开始时触发。

会话开始输入

除了常见的字段,会话开始钩子接收:

{
  "来源": "新"
}
领域 类型 描述
字符串 会话如何启动。目前总是“新”输入:.

会话开始输出

会话开始钩子可以将额外的上下文注入到代理的对话中:

{
  "hookSpecificOutput": {
    "hookEventName": "会话开始",
    "附加上下文": "项目: my-app v2.1.0 | 分支: main | 节点: v20.11.0"
  }
}
领域 类型 描述
附加上下文 字符串 上下文已添加到代理的对话中

停止

停止钩子在代理会话结束时触发。

停止输入

除了常见的字段,停止钩子接收:

{
  "stop_hook_active": false
}
领域 类型 描述
停止钩子活动 布尔 当代理由于先前的停止挂钩而已经在继续时。检查此值以防止代理无限期运行。

停止输出

停止钩子可以防止代理停止:

{
  "hookSpecificOutput": {
    "hookEventName": "停止",
    "决策": "阻止",
    "原因": "在完成之前运行测试套件"
  }
}
领域 价值观 描述
决策 “块” 防止代理停止
原因 字符串 当决策是 时需要“块”告诉智能体它应该继续的原因。
重要

当一个停止 hook阻止代理停止,代理继续运行,额外的回合消耗 高级请求。请始终检查 停止钩子活动字段以防止代理程序无限期运行。

子代理开始

子代理开始钩子在生成子代理时触发。

子代理开始输入

除了常见的字段,子代理开始钩子接收:

{
  "agent_id": "subagent-456",
  "agent_type": "计划"
}
领域 类型 描述
代理编号 字符串 子代理的独特标识符
代理类型 字符串 代理名称(例如,“计划”内置代理或自定义代理名称

子代理开始输出

子代理开始钩子可以将额外的上下文注入到子代理的对话中:

{
  "hookSpecificOutput": {
    "hookEventName": "子代理启动",
    "附加上下文": "此子代理应遵循项目编码规范"
  }
}
领域 类型 描述
附加上下文 字符串 上下文已添加到子代理的对话中

子代理停止

子代理停止钩子在子代理完成时触发。

子代理停止输入

除了常见的字段,子代理停止钩子接收:

{
  "agent_id": "subagent-456",
  "agent_type": "计划",
  "停止钩子激活": false
}
领域 类型 描述
代理编号 字符串 子代理的独特标识符
代理类型 字符串 代理名称(例如,“计划”内置代理或自定义代理名称
停止钩子活动 布尔 当子代理已经由于先前的停止钩子而继续执行时,请检查此值以防止子代理无限期运行。

子代理停止输出

子代理停止钩子可以防止子代理停止:

{
  "决策": "阻止",
  "原因": "在完成之前验证子代理结果"
}
领域 价值观 描述
决策 “块” 防止子代理停止
原因 字符串 当决策是 时需要“块”告诉子代理为什么它应该继续。

预紧

预紧钩子在对话上下文被紧凑之前触发。

预紧凑输入

除了常见的字段,预紧钩子接收:

{
  "触发器": "自动"
}
领域 类型 描述
触发器 字符串 触发压实的机制是什么。"自动"当对话太长,无法在提示预算内完成。

预紧钩子仅使用常见的输出格式。

使用 /hooks 命令配置钩子

使用/挂钩在聊天中使用斜线命令通过交互式用户界面配置钩子:

  1. 类型/挂钩 在聊天输入框中输入并按 回车键

  2. 从列表中选择一个钩子事件类型。

  3. 选择一个现有的钩子进行编辑或选择 添加新的钩子 来创建一个。

  4. 选择或创建一个钩子配置文件。

该命令在编辑器中打开钩子文件,并将光标定位在命令字段,准备进行编辑。

使用场景

以下示例演示了常见的钩子模式。

阻止危险的终端命令

创建一个预工具使用钩子防止执行破坏性命令:

.github/hooks/security.json

{
  "钩子": {
    "预工具使用": [
      {
        "类型": "命令",
        "命令": "./scripts/block-dangerous.sh",
        "超时秒数": 5
      }
    ]
  }
}

脚本/阻止危险行为.sh:

#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
TOOL_INPUT=$(echo "$INPUT" | jq -r '.tool_input')

if [ "$TOOL_NAME" = "runTerminalCommand" ]; then
  COMMAND=$(echo "$TOOL_INPUT" | jq -r '.command // empty')

```plaintext
if echo "$COMMAND" | grep -qE '(rm\s+-rf|DROP\s+TABLE|DELETE\s+FROM)'; then
    echo '{ "hookSpecificOutput": { "permissionDecision": "deny", "permissionDecisionReason": "Destructive command blocked by security policy" } }'
    exit 0
fi
fi
```





回声 '{"继续":true}'
在编辑后自动格式化代码

在任何文件修改后自动运行 Prettier:

.github/hooks/formatting.json

{
  "hooks": {
    "PostToolUse": [
      {
        "type": "command",
        "command": "./scripts/format-changed-files.sh",
        "windows": "powershell -File scripts\\format-changed-files.ps1",
        "timeout": 30
      }
    ]
  }
}

scripts/format-changed-files.sh:

#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')

if [ "$TOOL_NAME" = "editFiles" ] || [ "$TOOL_NAME" = "createFile" ]; then
  FILES=$(echo "$INPUT" | jq -r '.tool_input.files[]? // .tool_input.path // empty')

 文件 $FILES 中; 执行
    如果 [ -f "$FILE" ]; 那么
      npx prettier --write "$FILE" 2>/dev/null
    结束如果
  循环结束
结束如果

回声 '{"继续":true}'
记录工具使用情况以供审计

创建所有工具调用的审计记录:

.github/hooks/audit.json

{
  "hooks": {
    "PreToolUse": [
      {
        "type": "command",
        "command": "./scripts/log-tool-use.sh",
        "env": {
          "AUDIT_LOG": ".github/hooks/audit.log"
        }
      }
    ]
  }
}

scripts/log-tool-use.sh:

#!/bin/bash
INPUT=$(cat)
TIMESTAMP=$(echo "$INPUT" | jq -r '.timestamp')
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
SESSION_ID=$(echo "$INPUT" | jq -r '.sessionId')

echo "[$TIMESTAMP] 会话: $SESSION_ID, 工具: $TOOL_NAME" >> "${AUDIT_LOG:-audit.log}"
echo '{"继续":true}'
需要特定工具的批准

强制手动确认修改基础设施的工具:

.github/hooks/approval.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "type": "command",
        "command": "./scripts/require-approval.sh"
      }
    ]
  }
}

scripts/require-approval.sh:

#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')

# 应始终需要批准的工具
SENSITIVE_TOOLS="runTerminalCommand|deleteFile|pushToGitHub"

if echo "$TOOL_NAME" | grep -qE "^( $SENSITIVE_TOOLS )$"; then echo '{ "hookSpecificOutput": { "permissionDecision": "ask", "permissionDecisionReason": "This operation requires manual approval" } }' else echo '{ "hookSpecificOutput": { "permissionDecision": "allow" } }' fi




在会话开始时注入项目上下文

在会话开始时提供项目特定信息:

.github/hooks/context.json:

{
  "hooks": {
    "SessionStart": [
      {
        "type": "command",
        "command": "./scripts/inject-context.sh"
      }
    ]
  }
}

scripts/inject-context.sh:

#!/bin/bash
PROJECT_INFO=$(cat package.json 2>/dev/null | jq -r '.name + " v" + .version' || echo "Unknown project")
BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")

 <<EOF
{
  "hookSpecificOutput": {
    "hookEventName": "会话开始",
    "附加上下文": "项目: $PROJECT_INFO | 分支: $BRANCH | 节点: $(node -v 2>/dev/null || echo '未安装')"
  }
}
EOF

安全

如果代理可以编辑通过钩子运行的脚本,那么它在运行过程中有能力修改这些脚本并执行它编写的代码。我们建议使用chat.tools.edits.autoApprove不允许代理在没有手动批准的情况下编辑钩子脚本。

故障排除

查看钩子诊断

查看已加载的钩子并检查配置错误:

  1. 在聊天视图中右键单击并选择诊断

  2. 查找钩子部分以查看已加载的钩子和任何验证错误。

查看钩子输出

要检查钩子输出和错误:

  1. 打开输出面板。

  2. 选择 GitHub Copilot 聊天钩子 从频道列表中。

常见问题

钩子未执行:请确认钩子文件位于.github/hooks/并且有一个.json扩展。检查类型属性设置为"命令"输入:.

权限被拒绝错误:确保您的钩子脚本具有执行权限 (chmod +x script.sh)。

超时错误:增加超时值或优化您的钩子脚本。默认值是30秒。

JSON解析错误:确保您的钩子脚本将有效的JSON输出到标准输出。使用jq或使用JSON库来构建输出。

常见问题

VS Code如何处理Claude Code钩子配置?

VS Code解析Claude Code的钩子配置格式,包括匹配器语法。目前,VS Code忽略匹配器值,因此钩子适用于所有工具。Claude Code使用空字符串匹配器 (") 代表所有工具。

VS Code如何处理Copilot CLI挂钩配置?

VS Code解析Copilot CLI钩子配置,并将下骆驼命名法的钩子事件名称(如预工具使用) 转换为 VS Code 使用的 PascalCase 格式 (预工具使用). 两者都巴什PowerShell支持命令格式。

安全考虑

警告

Hooks 以与 VS Code 相同的权限执行 shell 命令。仔细审查 hook 配置,特别是在使用来自不可信来源的 hook 时。

  • 查看钩子脚本:在启用钩子脚本之前,请检查所有钩子脚本,特别是在共享仓库中。

  • 限制钩子权限:遵循最小权限原则。钩子应仅具有其所需访问权限。

  • 验证输入:钩子脚本从代理接收输入。验证和清理所有输入以防止注入攻击。

  • 安全凭证:永远不要在钩子脚本中硬编码秘密。使用环境变量或安全凭证存储。