Superpowers - 07 从 SessionStart Hook 看 Superpowers:把「技能库」变成「行为操作系统」

张开发
2026/4/13 1:35:09 15 分钟阅读

分享文章

Superpowers - 07 从 SessionStart Hook 看 Superpowers:把「技能库」变成「行为操作系统」
文章目录Pre一、为什么 SessionStart Hook 如此重要1. 被动工具箱 vs 主动行为系统2. 三阶段注入管线从平台事件到系统提示二、钩子注册与触发Claude、Cursor 与 Copilot 各有各的规矩1. hooks.json服务 Claude Code 与 Copilot CLI2. hooks-cursor.json为 Cursor 定制的扁平结构三、平台检测与 JSON 输出一不小心就会“注入两遍”1. 三种 JSON 结构对应三类平台2. 检测顺序为何如此讲究四、注入的究竟是什么using-superpowers 作为引导技能1. 引导技能的角色行为契约而非业务逻辑2. “反合理化”护栏防止 agent 偷懒五、Bash 实现细节JSON 转义与可移植性踩坑指南1. 纯 Bash 的 escape_for_json不依赖 sed/awk2. 避免 Bash 5.3 heredoc 挂起为什么必须用 printf六、跨平台执行polyglot run-hook.cmd 的巧妙设计1. 同一个文件同时是 CMD 和 Bash2. 常见问题脚本被编辑器打开、bash 不存在……七、旧版路径迁移用“侵入式提醒”确保不被忽略八、注入故障排查从症状倒推根因九、与 Superpowers 整体架构的关系与实践建议1. 唯一引导机制不注入就等于没系统2. 几个实践建议十、结语从一个 Hook 看未来的 Agent 工程PreSuperpowers - 01 让 AI 真正“懂工程”Superpowers 软件开发工作流深度解析Superpowers - 02 用 15 个技能给你的 AI 装上「工程大脑」Superpowers 快速开始深度解析Superpowers - 03 一文搞懂 Superpowers面向多平台 AI 编码助手的安装与实践指南Superpowers - 04 从“会写代码”到“会做工程”Superpowers 工作流引擎架构深度剖析Superpowers - 05 构建一个“会自己找插件用”的 Agent深入解析 Superpowers 的技能发现与激活机制Superpowers - 06 从文档到“结构契约”Superpowers 技能剖析与 Frontmatter 深度解读面对越来越复杂的 AI 开发场景单纯“给模型一个工具箱”已经不够了你需要的是一个能主动使用工具的 agent 行为系统。Superpowers 项目正是为此设计而其中最关键的一块基础设施就是本文要展开的主角SessionStartHook 注入机制。本文面向以下读者经常使用 Claude Code / Cursor / Copilot 等 AI 开发环境希望把自己的工作流沉淀为可复用技能的工程师正在折腾“插件化 agent 能力”、MCP、工具路由、行为注入的研究者或开发者想深入理解 Superpowers 架构、尤其是「技能发现与激活」底层机制的技术爱好者我们将从整体架构讲起再下潜到平台检测、JSON 构造、Bash 转义、跨平台脚本等实现细节最后结合实际场景给出一些最佳实践建议。一、为什么 SessionStart Hook 如此重要在 Superpowers 的设计中所有复杂的 TDD、调试、代码审查、子 agent 工作流……都被抽象为一个个技能文件SKILL.md等。但如果 agent 自己不知道这些技能存在它们就等同于「死代码」。SessionStart Hook 的目标就是在每次会话启动时把整个技能系统“挂到 agent 的大脑里”。1. 被动工具箱 vs 主动行为系统Superpowers 的核心理念可以简单概括为一句话无论 agent 在做什么它都必须先检查有没有合适的技能能帮上忙。为此插件通过SessionStart钩子在每个新会话甚至上下文被清空、压缩时自动注入一个叫using-superpowers的引导技能让 agent 在系统提示中“记住”你现在有一个技能系统所有技能都通过一个统一的Skill工具访问在任何响应前你必须先看技能能否帮忙宁愿多用、不准少用。换句话说SessionStart Hook 是整个 Superpowers 行为系统的唯一引导入口没有它后面的技能、工作流、约束体系统统无法生效。2. 三阶段注入管线从平台事件到系统提示注入管道分三步走平台原生钩子触发Claude Code / Cursor / Copilot CLI 的 SessionStart 事件。调用一个跨平台 shell 包装器run-hook.cmd。包装器再调用真正的hooks/session-start脚本读取skills/using-superpowers/SKILL.md构造平台需要的 JSON并通过标准输出返回给平台由平台注入到 agent 的系统提示中additionalContext/additional_context等。这样无论你在哪个平台使用 Superpowers只要会话启动agent 的系统提示里就会多出一段引导性的技能说明。二、钩子注册与触发Claude、Cursor 与 Copilot 各有各的规矩要让 SessionStart Hook 生效首先得告诉各个平台“我有这么个钩子”。Superpowers 为此维护了两个配置文件hooks.json与hooks-cursor.json。1. hooks.json服务 Claude Code 与 Copilot CLIhooks.json使用的是 Claude 插件格式关键点包括事件名使用SessionStartPascalCase。命令配置为${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd session-start。支持匹配器startup|clear|compact不仅在新会话启动时触发还会在清除对话历史clear上下文压缩compact这种“上下文重置”场景下重新注入技能保证 agent 在上下文被重置后仍然记得技能系统。特别要注意async: false的配置这意味着注入必须在 agent 处理任何一条用户消息之前完成否则就会出现“首轮回复没带技能感知”的竞态条件直接影响用户体验。2. hooks-cursor.json为 Cursor 定制的扁平结构Cursor 的钩子系统与 Claude 略有不同需要单独一个hooks-cursor.json。主要区别体现在属性Claude / Copilot (hooks.json)Cursor (hooks-cursor.json)事件键SessionStartPascalCasesessionStartcamelCase命令run-hook.cmd session-start./hooks/session-start匹配器支持 startupclear版本字段不需要必须有version: 1Cursor 的 agent 直接调用 bash 脚本因此不需要 polyglot 包装器命令直接指向hooks/session-start即可。三、平台检测与 JSON 输出一不小心就会“注入两遍”实现 SessionStart Hook 最难的部分不在“怎么注入”而在“在不同平台上输出正确的 JSON 结构”。1. 三种 JSON 结构对应三类平台hooks/session-start会根据环境变量识别当前运行的平台并输出不同结构的 JSONCursor检测条件CURSOR_PLUGIN_ROOT存在。输出字段顶层additional_context蛇形命名。Claude Code检测条件CLAUDE_PLUGIN_ROOT存在且没有COPILOT_CLI。输出字段{hookSpecificOutput:{hookEventName:SessionStart,additionalContext:...}}注意这里是嵌套在hookSpecificOutput下的additionalContext。Copilot CLI 或未知平台检测条件其他情况可能只有COPILOT_CLI或都没有。输出字段顶层additionalContext。这三种结构差别看似微小但对 Claude 来说如果你在同一平台同时输出additional_context和hookSpecificOutput.additionalContext它会两者都读导致相同的技能文本在上下文中出现两遍白白浪费 token。2. 检测顺序为何如此讲究session-start中的平台检测顺序是刻意设计的先看CURSOR_PLUGIN_ROOT。因为 Cursor 会顺带设置CLAUDE_PLUGIN_ROOT如果不优先判断会误把 Cursor 当作 Claude。再看CLAUDE_PLUGIN_ROOT且无COPILOT_CLI。Copilot 可能同时设置这两个变量所以必须确认没有COPILOT_CLI才能断言是 Claude。最后归类为 Copilot 或未知平台使用顶层additionalContext。如果你在移植或改脚本时随手改了顺序很容易在某些平台上输出错误结构表现为技能文本出现两次上下文膨胀。或者平台根本解析不到你注入的内容导致 agent 完全“失忆”。四、注入的究竟是什么using-superpowers作为引导技能SessionStart Hook 注入的并不是所有技能的内容而是一个非常特殊的引导技能skills/using-superpowers/SKILL.md。1. 引导技能的角色行为契约而非业务逻辑using-superpowers本身不会直接帮你写代码、跑测试它更像是 agent 的「行为守则」。注入后的系统提示中主要完成这几件事告诉 agent你当前处于一个带 Superpowers 的环境。所有技能都通过一个统一的Skill工具被发现和调用。约定行为优先级用户指令 技能指令 默认系统行为。定义“必须调用技能”的规则只要存在 1% 的可能某个技能有用你就应该调用。在任何回答哪怕只是澄清提问之前都要先检查技能列表。这样其他具体技能TDD、调试、代码审查、子任务拆分等就可以专注于“解决问题”而using-superpowers负责保证 agent 一定会去用它们。2. “反合理化”护栏防止 agent 偷懒为了避免 agent 出现“我大概知道这些技能但懒得用”这类行为SKILL.md中还设计了一个有趣的机制列出了一张包含 12 条“危险信号”的思维表格用来识别 agent 在「给自己找理由不查技能」。一旦出现类似“这次不需要用技能也能搞定”这样的内部推理模式就会被视为违反规范。通过这种带有元认知风格的约束Superpowers 在提示层面尽可能压制“模型偷懒”让技能系统真正成为默认路径。五、Bash 实现细节JSON 转义与可移植性踩坑指南当你要把一个富文本 Markdown 文件SKILL.md塞进 JSON 字符串时就会遇到各种转义问题引号、反斜杠、换行、制表符……如果转义不正确要么 JSON 解析失败要么注入内容错乱。Superpowers 在这里做了不少工程优化。1. 纯 Bash 的 escape_for_json不依赖 sed/awkhooks/session-start实现了一个完全用 Bash 字符串替换实现的escape_for_json函数首先处理反斜杠\\→\\\\。处理双引号→\。将换行、回车、制表符替换为字面量\n、\r、\t。使用${s//old/new}这种内建替换而不是逐字符循环。这样做有几个好处不依赖sed/awk等外部命令在各种奇怪的 shell 环境尤其是 Windows 上被 PATH 折腾过的 Git Bash更稳。性能远好于逐字符循环适合处理动辄上 KB 的技能内容。对于想在自己项目中采用类似模式的人来说这是一个很实用的模式在 shell 脚本里构造 JSON 时优先用内建字符串替换 printf避免多进程多工具带来的不确定性。2. 避免 Bash 5.3 heredoc 挂起为什么必须用 printf文章中特别强调了一个看似冷门但非常致命的 bugBash 5.3 在处理包含大量转义内容的 heredoc 时存在可复现的挂起问题。这会导致你的 SessionStart 脚本在会话启动时直接卡死表现为“agent 没反应”或“首条消息超时”。为规避这一点Superpowers 统一使用printf输出最终 JSON而不是catEOF { additionalContext: ... } EOF任何对脚本输出逻辑的修改都被强烈建议继续使用printf否则就有可能重新踩到这个坑。六、跨平台执行polyglotrun-hook.cmd的巧妙设计在 Claude Code 和 Copilot CLI 上hooks.json里配置的命令不是直接调用session-start而是调用run-hook.cmd。这背后是一套“多语言钩子包装器”模式用来解决 Windows CMD 与 Unix shell 的兼容问题。1. 同一个文件同时是 CMD 和 Bashrun-hook.cmd这个脚本有点魔法性质对 Windows CMD 来说它是一个合法的.cmd文件执行逻辑大致是echo off处理参数。调用 Git Bash并通过cygpath做路径转换。执行对应的 bash 脚本比如hooks/session-start。在进入任何 Bash 代码之前就通过exit /b结束 CMD 流。对 Bash 来说同一个文件又是合法的 shell 脚本使用: CMDBLOCK这样一个空操作 heredoc 把所有 CMD 段落“吃掉”。之后执行真正的SCRIPT_DIR/SCRIPT_NAME。这种 polyglot 写法的好处是Windows 环境可以通过.cmd直接调用不需要用户去手动指定 Bash。Unix 环境又可以把它当普通 shell 脚本使用。所有钩子共享这一包装器只需通过第一个参数指定脚本名例如session-start配置简单、复用性高。2. 常见问题脚本被编辑器打开、bash 不存在……在故障排查表里关于run-hook.cmd的问题主要有两类配置指向了.sh结果是在 Windows 上点击时直接被文本编辑器打开而不是执行。正确做法是始终指向run-hook.cmd再由它去执行 bash 版本。bash is not recognized通常是用户没安装 Git for Windows或者安装路径没有被包装器正确找到。解决方案是安装/修正 Git并必要时调整run-hook.cmd中的bash路径。如果你正在为自家项目设计跨平台钩子执行机制这个 polyglot 模式非常值得参考。七、旧版路径迁移用“侵入式提醒”确保不被忽略Superpowers 在演进过程中曾使用~/.config/superpowers/skills作为自定义技能目录后来迁移到~/.claude/skills。为了避免用户“悄悄在旧目录继续放技能”session-start在注入主内容前会做一次检查如果检测到旧目录存在就在注入载荷末尾追加一段警告文本。这段警告被特殊标签包起来并要求 agent 在首次回复时明确提醒用户进行迁移。这种设计看似“有点烦”但从迁移可靠性角度看非常合理迁移提示不会静默消失。在迁移完成并删除旧目录后这个检查也不再带来额外开销。对于需要迁移配置路径、数据目录的项目来说这是一个值得借鉴的模式通过 agent 主动提醒用户完成迁移而不是悄悄写在 README 里指望用户自己发现。八、注入故障排查从症状倒推根因实际使用中最让人头疼的往往不是“怎么注入”而是“为什么不生效”。文中给出了一张非常实用的故障排查表我们可以归纳成几个典型场景Agent 完全忽略技能通常是钩子根本没触发插件没安装好、hooks.json未被平台加载。环境变量如CLAUDE_PLUGIN_ROOT未配置。技能文本出现两次多见于 JSON 结构输出错误对 Claude 同时输出additional_context与hookSpecificOutput.additionalContext。平台检测顺序与实际运行环境不匹配。会话启动时卡死大概率是 Bash 5.3 heredoc bug解决方案是确认改脚本使用的是printf而不是 heredoc。Windows 上脚本被编辑器打开命令误指向.sh文件而不是run-hook.cmd。Cursor 完全没收到注入内容把 Cursor 错误地配置成使用hooks.json。Cursor 需要hooks-cursor.json且字段必须是additional_context蛇形命名。文中还给了一个非常推荐的调试方法CLAUDE_PLUGIN_ROOT$(pwd)bashhooks/session-start直接在仓库根目录手动执行钩子脚本检查输出的 JSON 是否符合目标平台预期。这比在完整 agent 环境中“盲调”要高效得多。九、与 Superpowers 整体架构的关系与实践建议理解了 SessionStart Hook 的细节之后更关键的是把它放到整个 Superpowers 架构中去看。1. 唯一引导机制不注入就等于没系统文中明确指出SessionStart 是 Superpowers 唯一的引导机制所有后续技能头脑风暴、TDD、调试、代码审查、Git 工作流等都依赖于最初注入的using-superpowers。如果 SessionStart 注入失败整个技能系统就处于“冬眠”状态agent 只剩下模型本身的通用能力。这也意味着在扩展或移植 Superpowers 时你可以改技能可以改工作流但绝不能忽略 SessionStart Hook 这一层的兼容性与稳定性。2. 几个实践建议结合文中内容可以给出一些面向真实工程场景的建议在新平台集成时先搞清楚平台支持的钩子事件与 JSON 格式。优先实现一个最小可用的 SessionStart 注入再逐步扩展技能体系。在调试注入问题时始终先在命令行单独运行脚本确认 JSON 输出无误。再检查平台配置hooks.json/hooks-cursor.json是否指向正确脚本。在扩展 SessionStart 注入内容时小心控制注入体积只注入“索引型”“行为契约型”内容。把真正大体量的说明、例子、模板留在技能内部通过Skill调用时按需加载。在设计自家技能系统时借鉴using-superpowers的做法把“必须查技能”“不准偷懒”写成清晰的行为约束。使用类似“危险信号表格”的方式约束 agent 的元推理。十、结语从一个 Hook 看未来的 Agent 工程SessionStart Hook 看起来只是一个“会话启动时执行的脚本”但在 Superpowers 的架构设计里它承载的是把一堆静态技能文件变成一个真正“驱动 agent 行为”的操作系统。它解决的不是“多一个工具能干什么”而是“如何让 agent 每一步行动都在技能系统的监管与帮助下进行”。在未来更复杂的 AI 工程实践中这种“以引导钩子为中心”的设计很可能会成为构建可控、可审计、多工具协作 agent 的标准模式之一。如果你正在搭建自己的 agent 能力体系建议亲手读一遍 Superpowers 的hooks与skills/using-superpowers代码与文档尝试在自己的项目中实现一个最小版本的 SessionStart 引导机制。这会比单纯在提示词里堆规则有更高的可维护性与可迁移性。

更多文章