关于 scaffold-hooks
scaffold-hooks 是用于在仓库中创建或迁移生命周期钩子的 Agent 技能,支持 Claude Code、Codex、GitHub Copilot、Devin CLI 和 OpenCode。它会检测现有配置、保留自定义钩子,并提供预演与验证流程。
主要功能
- 01为五种运行环境搭建钩子
- 02检测并刷新现有配置
- 03迁移受管理的旧版钩子
- 04保留自定义钩子和脚本
- 05预演、审计和验证搭建结果
适用场景
- 01为新仓库配置钩子
- 02刷新检测到的运行环境钩子
- 03迁移旧版生成钩子目录
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jpcaparas/ skills --skill scaffold-hooks安装后在 Claude Code 中输入/scaffold-hooks确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
AGENTS.mdagents/.gitkeepassets/harnesses.jsonevals/evals.jsonharnesses/claude/PLAYBOOK.mdharnesses/claude/assets/hook-events.jsonharnesses/claude/references/gotchas.mdhook-events.mdmerge-strategy.mdproject-analysis.mdREADME.mdreusable-scripts.mdscaffold-layout.mdharnesses/claude/scripts/audit_project.shcheck_workspace_trust.shmerge_settings.shrender_hooks_readme.shscaffold_hooks.shscaffold_paths.shtest_skill.pyvalidate.pyharnesses/claude/templates/event-script.sh.tmplhook-plan.example.jsonharnesses/codex/PLAYBOOK.mdharnesses/codex/assets/hook-events.jsonharnesses/codex/references/feature-flag.mdgotchas.mdhook-events.mdmerge-strategy.mdproject-analysis.md详细介绍
通用 Agent Hook 脚手架
为 Agent 生命周期 Hook 搭建脚手架或迁移 Hook,让每个选定的运行环境都指向仓库自有的 Hook 脚手架。这是唯一的 Hook 脚手架工具:原来的 scaffold-cc-hooks、scaffold-codex-hooks、scaffold-github-copilot-hooks、scaffold-devin-hooks 和 scaffold-opencode-hooks 技能已停用,并作为内部运行环境组件归入 harnesses/<name>/。
决策树
- 如果用户提到
/scaffold-hooks、hooks、生命周期 hooks、hook 迁移,或提到 Claude Code、Codex、GitHub Copilot、Devin CLI 或 OpenCode 的 hooks,请使用此技能。 - 如果用户指定了运行环境,请使用
--harnesses <list>原样传入这些运行环境。仅针对一个运行环境的请求只需使用--harnesses <name>。 - 如果用户未指定目标路径,请使用当前工作区或仓库根目录作为目标项目。
- 如果用户未指定运行环境偏好,请检查目标项目。如果存在任何受支持的 Hook 接入点或受管理的脚手架状态,请运行通用脚本但不带
--harnesses,以便仅刷新检测到的运行环境。除非用户明确要求,否则不要添加新的运行环境。 - 如果不存在受支持的 Hook 接入点,请询问要为哪些运行环境搭建脚手架。对于新脚手架,默认选择所有受支持的运行环境(
claude、codex、copilot、devin、opencode)。 - 如果现有配置指向
.claude/hooks/generated、.codex/hooks/generated或.devin/hooks/generated,请将此工作视为迁移:移除这些受管理的命令条目,搭建hooks/,并且仅移除包含清单的旧版受管理文件夹。 - 如果项目在受管理根目录之外有自定义 hooks,请予以保留,除非用户明确要求删除。
运行环境选择
选择顺序确定如下:
- 用户明确指定的
--harnesses。 - 自定义通用计划中存在的
harnesses列表。 - 目标仓库中检测到的现有 Hook 接入点或受管理的脚手架状态。
- 仅当以上均不存在时,使用默认的所有受支持运行环境。
检测到的接入点包括当前受管理的清单、旧版生成的清单、hooks/ 下的共享适配器,以及已包含 Hook 条目的运行环境配置文件。如果检测到任何运行环境,未经用户明确指示,不要扩展到其他运行环境。
claude— Claude Code,.claude/settings.jsoncodex— Codex CLI,.codex/hooks.json(需要启用 hooks 功能标记;参见harnesses/codex/references/feature-flag.md)copilot— GitHub Copilot(云端 Agent + CLI),.github/hooks/copilot-hooks.json,生成的事件位于.github/copilot/hooks/generated/devin— Devin CLI,.devin/hooks.v1.jsonopencode— OpenCode,通过opencode-froggy使用opencode.json和.opencode/hook/hooks.md
使用 --harnesses claude,codex,copilot,devin,opencode(或其中一个子集)显式传入要添加的运行环境。在已有 hooks 的仓库中直接运行只会刷新,不会扩展。
快速参考
| 任务 | 命令 |
|---|---|
| 刷新检测到的现有运行环境,或在干净仓库中搭建所有环境 | scripts/scaffold_all_hooks.sh --project /path/to/project |
| 预览而不写入文件 | scripts/scaffold_all_hooks.sh --project /path/to/project --dry-run |
| 使用项目专属的通用计划 | scripts/scaffold_all_hooks.sh --project /path/to/project --plan /path/to/scaffold-hooks.json |
| 仅为选定的运行环境搭建脚手架 | scripts/scaffold_all_hooks.sh --project /path/to/project --harnesses claude,codex |
| 刷新运行环境适配器,同时保留共享事件脚本 | scripts/scaffold_all_hooks.sh --project /path/to/project --mode overhaul |
| 审计某个目标仓库中的一个运行环境 | harnesses/<name>/scripts/audit_project.sh /path/to/project |
| 验证运行环境组件 | python3 harnesses/<name>/scripts/validate.py harnesses/<name> |
| 运行运行环境测试套件 | python3 harnesses/<name>/scripts/test_skill.py harnesses/<name> |
标准工作流
- 先检查目标项目:
- 现有的
.claude/settings*.json .codex/hooks.json和.codex/config.toml.devin/hooks.v1.json和.devin/config*.jsonopencode.json、.opencode/hook/hooks.md、旧的.opencode/plugins/.managed/,以及任何自定义的.opencode/plugins/.github/hooks/copilot-hooks.json和.github/copilot/hooks/generated/- 现有的
hooks/目录树和scripts/下由仓库管理的验证脚本
- 现有的
- 仅在创建新脚手架或添加 harness 时,确认 harness 集合。若在已有 hook 配置的仓库中直接运行,只刷新检测到的集合。
- 使用仓库配置、已安装版本的证据,以及所选 harness 的
PLAYBOOK.md来规划修复。如果这些证据不足、似乎已过时,或事件语义将发生变化,请查阅相关的官方实时文档;对于稳定的本地修复,不要浏览每个 harness。每个组件都在harnesses/<name>/assets/hook-events.json中记录其捆绑契约。只在有疑问时加载参考资料。 - 从
templates/hook-plan.example.json开始,除非项目已有更清晰的计划。 - 先运行带有
--dry-run的scripts/scaffold_all_hooks.sh,然后不带--dry-run再运行一次。 - 检查
hooks/README.md、hooks/.state/scaffold-hooks/manifest.json、harness 配置文件和所选适配器。 - 运行项目的常规验证。
输出形式
捆绑的 Claude、Codex、Devin 和 Copilot 生成器使用 Bash 入口点,并渲染清单中的所有事件,但只接入已启用的事件。共享目录树是生成器的约定,并非每个 harness 或仓库的要求。将合适的仓库自有程序保留在 Bash 协议边界之后;这些辅助工具不提供仅包含所选事件的文件布局。保留现有的自定义架构,不要仅为匹配此模式而替换它们:
hooks/
README.md
lib/
agent-hook-runtime.sh
claude.sh
codex.sh
devin.sh
.state/
scaffold-hooks/
manifest.json
claude/
codex/
devin/
stop/
script.sh
claude.sh
claude.json
codex.sh
codex.json
devin.sh
devin.json
.opencode/
hook/
hooks.md
README.md
.managed/
manifest.json
plan.snapshot.json
opencode.json
Harness 配置文件应保留在其文档规定的位置:
- Claude:
.claude/settings.json - Codex:
.codex/hooks.json - Devin:
.devin/hooks.v1.json - OpenCode:
opencode.json加载opencode-froggy;Froggy 读取.opencode/hook/hooks.md - GitHub Copilot:
.github/hooks/copilot-hooks.json,生成的事件位于.github/copilot/hooks/generated/下(独立完整,因为 Copilot 云 Agent 会从仓库读取所有内容)
计划格式
使用 templates/hook-plan.example.json 作为通用计划架构的准确信息来源。顶层计划控制共享行为:
mode:additive或overhaulhooks_root:通常为hookscleanup_legacy:仅当旧的受管生成目录中包含清单时才将其移除harnesses:claude、codex、copilot、devin、opencode的子集;仅在有意选择或扩展 harness 集合时使用plans:传递给各 harness 组件的逐 harness 计划对象
添加项目专用脚本或命令前,请阅读 references/plan-format.md。
信任与输出边界
计划和现有钩子配置属于可执行的项目策略,并非来自任意代码仓库的安全数据。启用钩子或运行会执行这些配置的测试前,请先检查其中的命令、脚本路径、工作目录和引用的代码。Shell 命令和 Froggy 操作可以使用 Agent 的文件系统、网络和凭据;输出路径检查不会对这些命令进行沙箱隔离。请在不含敏感凭据的隔离环境中测试不受信任的钩子。
项目脚手架会拒绝绝对路径、相对于主目录的路径、遍历父目录的路径以及符号链接输出路径,包括托管目录树内的链接。Universal 运行会在更改配置或移除托管输出前,预先检查所有选定的工具。对于被拒绝的目标路径,请与用户确认解决方案,不要删除链接,也不要将私有配置移入代码仓库。
OpenCode 全局作用域需要用户明确授权并指定 --allow-global-targets;输出必须位于 ~/.config/opencode/ 下。启用 Codex 用户级功能时,也必须先获得授权,才能选择用户作用域。不要为了绕过项目路径检查而更改任一作用域。这些检查旨在保护稳定的文件系统,而非防范被对手同时修改的文件系统。
冲突策略
此技能采取保守策略:
- 追加新的
hooks/<event>/<harness>.sh命令前,先移除旧的托管生成根目录命令。 - 保留同一配置文件中的非托管自定义钩子。
- 保留现有的
hooks/<event>/script.sh文件,避免其他工具重写共享的项目行为。 - 在
overhaul模式下,仅删除hooks/下选定工具的适配器和状态,然后对 Shell 工具以增量模式调用工具组件。 - 对于 OpenCode,保留非托管的
.opencode/plugins/文件,但将脚手架拥有的插件输出迁移至opencode-froggy和.opencode/hook/hooks.md。
更改合并行为前,请阅读 references/collision-policy.md。
工具组件
每个受支持的工具都是 harnesses/<name>/ 下的独立组件,包含自己的 PLAYBOOK.md、脚手架脚本、事件清单、模板、参考资料、验证器和测试套件:
harnesses/claude/负责 Claude Code 事件语义和.claude/settings.json合并。harnesses/codex/负责 Codex 事件语义、功能标志处理和.codex/hooks.json合并。harnesses/devin/负责 Devin 事件语义和.devin/hooks.v1.json合并。harnesses/opencode/负责 OpenCode Froggy 配置、opencode.json插件合并,以及清理先前由脚手架生成的本地插件产物。harnesses/copilot/负责 GitHub Copilot 事件语义,以及为云端 Agent 和 Copilot CLI 合并.github/hooks/copilot-hooks.json。
事件名称、匹配器、输出契约或功能标志发生变化时,请遵循下方的基于来源的更新流程。对于已获授权的包更新,请先更改工具组件(清单、参考资料、脚本、测试),然后再更改通用编排。更改组合顺序或添加工具时,请阅读 references/harness-composition.md。
协议输出规范
将 stdout 视为 harness 协议的一部分,而不是临时日志。对于 JSON 输出钩子,stdout 仅用于输出最终协议 JSON 载荷;成功的无操作路径应保持静默,除非事件契约明确允许向 stdout 输出内容。将诊断信息、调试文本、文件名和人类可读的失败详情发送到 stderr,除非 harness 要求将它们输出到 stdout。
谓词必须保持静默,且只返回退出状态。其他辅助程序不得将未捕获的输出泄漏到协议 stdout;生成值的辅助程序可以返回捕获的数据,指定的协议发送器可以写入事件的 JSON。使用 grep -q / grep -Eq 这类静默检查,或将 stdout 重定向到 /dev/null;除非输出已被捕获且不会泄漏到钩子 stdout,否则不要使用 grep ... | head -1 这类文件名探测。已知回归问题:hook_has_code_changes 必须保持为仅返回退出状态的谓词。
验证生成的 JSON 输出钩子:静默成功/无操作路径的 stdout 必须为空;输出上下文或决策时,只能输出一个可解析且符合事件要求的 JSON 载荷,不能带前缀或后缀;共享辅助程序不能泄漏文件名/调试/状态行。分别保留每个事件的退出码契约。
注意事项
- 不要在通用运行中直接向 shell harness 脚手架传入
overhaul。它们会重写共享的script.sh文件。通用脚本会先清理 harness,然后再以增量方式调用它们。 - OpenCode 现在使用
opencode-froggy作为插件层。除非用户明确要求自定义插件代码,否则不要重新创建旧的生成版.opencode/plugins/*.ts生命周期适配器。 - 仅当旧版生成目录中包含受管理清单时才应删除。否则,其中可能是用户自己的文件,只是路径名称不太合适。
- 配置看起来干净,并不代表没有冲突:旧的生成命令仍可能存在。始终检查最终配置中是否包含
.claude/hooks/generated、.codex/hooks/generated和.devin/hooks/generated。 - 将项目策略保留在仓库自有脚本中,例如
./scripts/agent-stop-checks.sh;钩子适配器应转换协议,而不是重复验证逻辑。生成的 shell Stop 适配器默认设置run_on_code_changes: true,并使用检测到的源文件/配置文件扩展名,以避免在代码未变更的回合运行开销大的检查。 - Copilot 不会将适配器写入共享的
hooks/目录。它生成的事件保留在.github/copilot/hooks/generated/下,因为 Copilot 云端 Agent 只会读取已提交到仓库的文件;将共享策略放在仓库自有的scripts/中,供两层共同调用。 - 共享的
SessionStart上下文脚本可以对 Claude、Codex 和 Devin 使用经过专门验证的hookSpecificOutput.additionalContextJSON 结构。该共享结构并不意味着它兼容其他事件或字段。参见references/harness-composition.md,了解 Devin 记录在文档中的 JSON 结构和历史纯文本失败证据。 - 将退出码和输出流视为彼此独立的契约。退出码控制成功、失败或阻止操作;stderr 用于诊断和说明失败原因,而不是输出成功状态消息。成功的常规跳过操作只有在 harness 协议允许时才应向 stdout 写入内容,否则应保持静默。
- Froggy 的
isMainSession条件可为 OpenCode 钩子处理主会话筛选;对于应跳过子会话/子 Agent 会话的会话生命周期钩子,请使用此条件。 - 受管理清单会记录脚手架技能来源、计划/模板哈希、选定的 harness、检测到的 harness、选择来源以及受管理文件哈希。重新运行时应使用这些快照来刷新未被修改的受管理适配器,同时保留用户修改过的文件。
- 单独调用
/scaffold-hooks时会采取保守策略。如果检测到任何受支持的钩子接口,只刷新检测到的那组;除非用户明确要求,否则不要扩展到其他 harness。
Hook 可见性矩阵
不同 Harness TUI 对 Hook 活动的可见性各不相同。在搭建脚手架时明确说明预期表现,避免用户将无响应误认为故障:
| Harness | 是否在 TUI 中呈现 Hook 运行情况 | 通过以下方式验证 Hook |
|---|---|---|
| Claude Code | 部分可见(错误、详细模式) | /hooks、对话记录 |
| Codex CLI | 是(“Running SessionStart hook”,Hook 上下文内联显示) | 内联可见 |
| Devin CLI | 否(即使成功也不显示;截至 v2026.5.26-8,不呈现 systemMessage) | /hooks、CLI 日志、对话记录 JSON、询问 Agent |
| OpenCode | 由插件定义 | 插件日志 |
| GitHub Copilot | 云端 Agent:会话日志;CLI:因情况而异 | 会话日志、.github/copilot/hooks/generated/ 输出 |
渐进式维护者漂移检查
将记录的版本和日期视为验证基线,而不是永久的运行要求。对于不确定或可能变化的约定,请查阅相关官方文档;必要时,核对与已安装版本相匹配的源代码或架构证据。main 分支可能描述尚未发布的行为。除非经过验证且变更属于当前范围,否则应保留确定性版本锁定。
如果证据表明指南已过时,请记录受影响的段落、当前官方来源及适用的版本/日期、建议的修正内容和回归检查。应提出更新建议,而不是悄悄修改已安装的技能。只有在维护工作属于当前范围时,才编辑规范包;随后,在调整通用编排之前,应协调更新受影响的清单、引用、生成器、模板、验证器和测试。对于不受支持的漂移,应如实报告,不要声称随附的辅助工具已实现相关更新。对于仅涉及措辞或已知的本地修复,无需全面检查在线文档。
尽早检查信任状态和实际生效的功能状态,但在激活状态尚未确定时,仍可进行独立的只读诊断。更改信任状态、用户/全局设置或策略之前,必须获得授权;切勿绕过这些门槛来让脚手架看起来已激活。