☰
Trellis 平台接入指南:hooks 与 settings 的职责、注册与故障排查(EcoPaste 仓库实例)
2026/9/28 2:35:27 网站建设 项目流程
  • 桌面应用

【免费下载链接】EcoPaste

🎉跨平台的剪贴板管理工具 | Cross-platform clipboard management tool

项目地址:https://gitcode.com/ayangweb/EcoPaste
点击查看免费下载

本文以 hooks-and-settings.md 为核心骨架,结合 EcoPaste 仓库中已落地的.claude/、.cursor/、.codex/、.opencode/、.gemini/、.kiro/等平台目录与.trellis/运行时进行源码级佐证,讲解:settings/config 文件负责"注册钩子",钩子脚本负责"注入行为",两者如何协作让不同 AI 工具(Claude Code、Cursor、Codex、OpenCode、Gemini CLI、Kiro 等)在正确的时机读取同一个 Trellis 会话状态。读完本文,你将能:① 分清哪些平台文件负责注册、哪些负责行为;② 针对"AI 没读到 Trellis 状态"给出完整的排查路径;③ 按"本地修改顺序"正确落地一次上下文策略调整,而不会改错层级。

一、先厘清概念:平台文件与 Trellis 共享文件的边界

在进入 hooks/settings 之前,必须先确立一个边界,否则后面的所有判断都会出错。Trellis 采用"同一套本地架构、多个 AI 工具适配"的设计,platform-files/overview.md 把仓库根目录下的文件划分成两类:

  • 共享文件(Shared files):.trellis/workflow.md、.trellis/tasks/、.trellis/spec/、.trellis/scripts/。这是 Trellis 的业务状态与脚本所在地,所有平台共用,不归属任何一个 AI 工具。
  • 平台文件(Platform files):.claude/、.codex/、.cursor/、.opencode/、.kiro/、.gemini/、.qoder/、.codebuddy/、.github/、.factory/、.pi/、.trae/等目录。这些目录不存储业务状态,只负责让对应 AI 工具"看得见"Trellis 状态、能调用 Trellis 脚本、能加载 Trellis 的 skills/agents/hooks。

换句话说,hooks/settings 是连接平台与 Trellis 的入口层(entry layer)——它决定某个平台在哪些事件上运行哪些脚本、插件或扩展。以 EcoPaste 仓库为例,可以直观看到这套布局同时存在:.claude/、.cursor/、.codex/、.gemini/、.kiro/、.opencode/六个平台目录都已生成,而.trellis/下同时存在workflow.md、tasks/、spec/、scripts/等共享内容。这些平台目录是否存在于某个项目,完全取决于用户当初执行过哪些trellis init --<platform>参数。

二、Settings 的职责:它们到底注册了什么

settings/config 文件的核心职责是注册(register),而不是实现。文档明确列出它们通常注册的五类能力:

注册项作用
session-start hook新会话启动或上下文重置时,注入一份 Trellis 总览
workflow-state hook每次用户输入时,解析.trellis/workflow.md中的[workflow-state:STATUS]块,并输出与当前任务status匹配的正文;纯解析器,脚本内不内置兜底内容
sub-agent context hook当 implement/check/research 等子代理启动时注入任务上下文
shell/session bridge让 shell 命令看到与当前 Trellis 会话一致的会话身份
platform plugin / extension 入口平台自身的插件或扩展注册点

下面逐项看 EcoPaste 仓库中的真实落地,并对照文档给出的"常见文件"清单逐一验证。

2.1 各平台 settings/config 常见路径与仓库实证

文档给出如下平台到配置文件的映射表,EcoPaste 仓库中已生成的五个平台均可逐条对应上:

平台settings/config 路径仓库实测(已存在)
Claude Code.claude/settings.json✅.claude/settings.json
Cursor.cursor/hooks.json✅.cursor/hooks.json
Codex.codex/hooks.json、.codex/config.toml✅ 两者均存在
OpenCode.opencode/package.json、.opencode/plugins/*✅package.json声明插件依赖,plugins/下有三个插件
Kiro.kiro/hooks/+ 平台配置✅.kiro/hooks/下含 4 个脚本/配置文件
Gemini CLI.gemini/settings.json✅.gemini/settings.json
GitHub Copilot.github/copilot/hooks.json文档列出;本仓库未生成(取决于 init 参数)
Trae IDE.trae/hooks.json文档列出;本仓库未生成
Reasonix / ZCode不使用 hooks/settingspull 式平台,见下文第四节

说明:.claude/、.cursor/、.codex/、.opencode/、.gemini/、.kiro/六个目录在仓库根目录中真实存在,其余平台(Copilot、Qoder、CodeBuddy、Factory Droid、Pi Agent、Trae 等)属于文档列出的映射,不在当前仓库生成范围内。不要因为某平台目录缺失就推断其不支持 hooks——这只是 init 参数没选到它。

2.2 逐平台解读注册内容(仓库源码级)

Claude Code ——.claude/settings.json注册了 3 类事件、共 4 个钩子注册块:

  • SessionStart:matcher 分别为startup、clear、compact,统一执行python3 .claude/hooks/session-start.py,timeout 30 秒。也就是说,新开会话、/clear清空上下文、/compact压缩上下文这三种"上下文重置"场景都会触发会话总览注入。
  • UserPromptSubmit:每次用户提交提示词时执行python3 .claude/hooks/inject-workflow-state.py,timeout 15 秒——这就是逐轮 workflow 面包屑。
  • PreToolUse:matcher 为Task与Agent,执行python3 .claude/hooks/inject-subagent-context.py,timeout 30 秒——在调用子代理工具前注入 PRD/spec 上下文。

Cursor ——.cursor/hooks.json采用与 Claude 不同的事件命名,注册 3 个钩子:

  • sessionStart:执行.cursor/hooks/session-start.py。
  • preToolUse:matcherTask|Subagent,执行.cursor/hooks/inject-subagent-context.py。
  • beforeShellExecution:执行.cursor/hooks/inject-shell-session-context.py,timeout 仅 5 秒——这是 Cursor 独有的 shell 会话桥,见 2.4 节。

Codex —— 注册文件拆成两个:

  • .codex/hooks.json只注册了UserPromptSubmit→python3 -X utf8 .codex/hooks/inject-workflow-state.py(timeout 15)。注意-X utf8:这是对 Windows 代码页(cp936 等)下非 ASCII 内容(中文任务名、PRD 片段)的显式 UTF-8 兜底。
  • .codex/config.toml本身不注册钩子,而是配置项目级行为:project_doc_fallback_filenames = ["AGENTS.md"]声明 AGENTS.md 为主项目指令文件;文件内注释还给出了两条重要的运行时前提——① Codex hooks 只有在用户级~/.codex/config.toml中开启[features].hooks = true才生效(Codex 0.129+;旧名codex_hooks = true会触发弃用警告);② Codex 0.129+ 还要求用户在/hooksTUI 中逐个审批安装的钩子,未审批前钩子保持不激活。这是一处很好的"settings 与运行时前提"对照:注册了 ≠ 生效了。

Gemini CLI ——.gemini/settings.json是逐轮事件命名差异的典型样本。它注册两个钩子:

  • SessionStart→.gemini/hooks/session-start.py(timeout 30000ms,注意 Gemini 的 timeout 单位是毫秒)。
  • BeforeAgent→.gemini/hooks/inject-workflow-state.py(timeout 15000ms)。

为什么是BeforeAgent而不是UserPromptSubmit?inject-workflow-state.py 的文件头注释给出答案:Gemini CLI 0.40.x 把逐轮事件改名为BeforeAgent,其 schema 校验器会拒绝旧事件名,因此脚本用_detect_platform在运行时从输入数据中探测平台(例如检测cursor_version字段、CLAUDE_PROJECT_DIR/CURSOR_PROJECT_DIR环境变量),再决定输出hookEventName用哪个名字。这就是"不同平台对同一事件有不同的命名"的实证。

Kiro ——.kiro/hooks/+ 平台配置。Kiro 的注册方式与以上都不同:.kiro/hooks/trellis-workflow-state.kiro.hook是一个独立 JSON 声明文件,结构为:

{ "version": "1.0.0", "enabled": true, "name": "trellis-workflow-state", "description": "Inject Trellis workflow state on each prompt", "when": { "type": "promptSubmit" }, "then": { "type": "runCommand", "command": "python3 .kiro/hooks/inject-workflow-state.py", "timeout": 30 } }

它把"触发事件"(when.type = promptSubmit)与"要执行的命令"(then)显式分离,是"hooks 文件描述事件接线、脚本定义行为"这一原则最直白的体现。inject-workflow-state.py 的注释还补充说明:Kiro 有两条接线路径——CLI 自定义 agent 的hooks.userPromptSubmit与 IDE 的.kiro.hookpromptSubmit事件,且 Kiro 会直接把 hook 的 stdout 拼进对话上下文,因此它的输出分支是纯文本面包屑。

OpenCode —— 插件体系。OpenCode 不走 CLI hooks 文件,而是.opencode/package.json声明插件依赖 +plugins/*.js实现三个插件:

{ "dependencies": { "@opencode-ai/plugin": "^1.14.39" } }
  • .opencode/plugins/session-start.js:监听chat.message事件(用户发送首条消息时),把构建好的会话上下文直接改写进消息本身,从而持久化在历史中(文件头注释明确说明选择chat.message而非chat.init正是为了让它留在历史里)。
  • .opencode/plugins/inject-subagent-context.js:监听tool.execute.before,在 Task 工具被调用且子代理类型为 implement/check/research 时注入 PRD、spec、research 上下文;它还用正则^\s*Active task:\s*(\S+)\s*$从派发提示词首行解析出目标任务路径,支持多窗口下区分任务。
  • .opencode/plugins/inject-workflow-state.js:OpenCode 版的逐轮面包屑。

2.3 OpenCode 作为"三模式融合"的样本

对照 platform-files/overview.md 的"三种平台集成模式",OpenCode 恰好是叠加态:

  • Hook/Extension 驱动:plugins/*三个插件做事件注入;
  • Agent Prelude / Pull 式:.opencode/agents/trellis-implement.md、trellis-check.md、trellis-research.md三个 agent 文件通过 prelude 指令指导子代理"启动后读什么";
  • Main-Session Workflow:.opencode/commands/trellis/下的start.md、continue.md、finish-work.md三个命令作为显式入口。

同时它把插件共享逻辑抽到.opencode/lib/(session-utils.js、trellis-context.js),三个插件都复用同一套上下文构建与去重逻辑(hasPersistedInjectedContext/markContextInjected防止重复注入)。

2.4 shell 会话桥:让 shell 命令继承会话身份

"shell/session bridge"是 settings 注册项里最容易被忽略的一项。它在 Cursor 的落地是.cursor/hooks/inject-shell-session-context.py(beforeShellExecution,timeout 5 秒),脚本头部注释解释了问题与解法:

Cursor 的 shell 命令环境不会继承 SessionStart 数据。此钩子在 Cursor 运行一个会调用task.py start/current/finish的 shell 命令之前,写入一张短生命周期的 runtime 票据(ticket);task 脚本只有在没有原生会话环境时才消费这张票据。

脚本定义了DIR_RUNTIME = ".runtime"、DIR_CURSOR_SHELL = "cursor-shell"、SESSION_SUBCOMMANDS = {"start", "current", "finish"}、TICKET_TTL_SECONDS = 30。也就是说,如果你在 Cursor 的终端里跑task.py current却发现"没有活跃任务",问题极可能出在这一层会话身份的传递上(见第六节排查路径第 5 步)。

三、Hook 脚本类型:四种脚本各管一件事

文档给出四种 hook 脚本的职责矩阵,仓库中各平台 hooks 目录的实际情况完全对应:

脚本职责仓库分布实证
session-start.py生成会话起始上下文.claude/hooks/、.cursor/hooks/、.codex/hooks/、.gemini/hooks/、.kiro/hooks/(均存在)
inject-workflow-state.py解析.trellis/workflow.md中[workflow-state:STATUS]块,输出与当前任务状态匹配的正文;找不到匹配块时回退到固定行Refer to workflow.md for current step..claude/hooks/、.codex/hooks/、.gemini/hooks/、.kiro/hooks/;OpenCode 侧为inject-workflow-state.js
inject-subagent-context.py向子代理注入 PRD、JSONL 上下文及关联 spec/research.claude/hooks/、.cursor/hooks/、.kiro/hooks/;OpenCode 侧为inject-subagent-context.js
inject-shell-session-context.py让 shell 命令继承 Trellis 会话身份仅.cursor/hooks/

两点重要的运行时事实需要强调:

1. workflow-state 是纯解析器,脚本里没有兜底字典。inject-workflow-state.py 头部注释明确:"Breadcrumb text is pulled exclusively from workflow.md [workflow-state:STATUS] tag blocks — workflow.md is the single source of truth. There are no fallback dicts in this script"。当.trellis/目录不存在或对应 tag 缺失时,脚本只会输出那一句通用回退文案,让用户看得见并去修复,而不是静默掩盖问题。它还区分了"安静退出"(exit 0 且无输出)的场景:非 Trellis 项目(无.trellis/目录)、task.json 损坏或缺少 status。

2. 不是每个平台都有每一种 hook。对比六个平台目录能清晰看到差异:inject-shell-session-context.py只存在于.cursor/hooks/(因为只有 Cursor 暴露了beforeShellExecution事件);.codex/hooks/只有inject-workflow-state.py和session-start.py,没有 subagent 注入脚本——Codex 的 sub-agent 上下文由 agent 文件 prelude 承担。修改时严禁把别的平台的脚本复制过来硬凑,第一步永远是确认该平台是否支持对应事件(见第五节原则 2)。

四、pull 式平台:不需要 hooks/settings

文档特别指出:Reasonix 与 ZCode 是 pull 式平台,不使用 hooks 或 settings 文件;它们的 agent 文件内包含"启动后读取上下文"的 prelude 指令。这与 overview.md 的"三种平台集成模式"中的第二种(Agent Prelude / Pull-Based)一致:这类平台无法可靠地让 hooks 改写子代理提示词,因此改为在 agent 文件里写死"启动后读活跃任务、PRD、JSONL 上下文"的指令。

这也是一个重要的判断准则:一个平台目录里没有 hooks/settings,不代表它没有接入 Trellis,只是接法不同。判断平台如何接入,应该先看它属于三种模式中的哪一种,再决定去检查 hooks/plugins 还是 agent prelude。

五、修改原则:settings 接线、hooks 定义行为

文档给出四条修改原则,全部有仓库实证支撑:

原则 1:Settings 负责接线,hooks 负责定义行为。只改 hook 脚本,平台可能根本不会调用它(没注册);只改 settings,行为可能不变。举例:若你想改逐轮提示的措辞,正确动作是编辑.trellis/workflow.md中的[workflow-state:STATUS]块——因为 hook 是"verbatim"解析 workflow.md 的,无需改任何脚本;而如果你想让"每次输入都注入"变成"只在某个事件注入",那才需要改 settings(如.claude/settings.json的UserPromptSubmit注册块)。

原则 2:先确认平台事件名。SessionStart、UserPromptSubmit、AgentSpawn、shell 执行等事件在各平台的命名不同:Claude Code 用UserPromptSubmit,Gemini CLI 0.40.x 改名BeforeAgent,Cursor 用sessionStart/preToolUse/beforeShellExecution,Kiro 用promptSubmit,OpenCode 用chat.message/tool.execute.before。跨平台复制注册配置前,务必核对目标平台文档的事件名。

原则 3:hooks 读本地.trellis/,不读上游源码。脚本默认目标是用户项目里的.trellis/scripts/与.trellis/workflow.md。例如.trellis/scripts/get_context.py就是 session-start 注入所依赖的上下文脚本:它以python3 get_context.py输出文本格式、python3 get_context.py --json输出 JSON 格式,底层委托给.trellis/scripts/common/git_context.py的main()。

原则 4:错误必须可见。hook 失败时应明确告诉用户"哪一段没有被注入",而不是让 AI 在缺上下文的静默状态下继续工作。这就是 workflow-state 脚本刻意不做兜底字典、只输出Refer to workflow.md for current step.的原因——可见的退化优于静默的缺失。

5.1 workflow-state 块的实际形态(以 EcoPaste 为例)

.trellis/workflow.md是面包屑的唯一数据源。它的## Phase Index之前有一段WORKFLOW-STATE BREADCRUMB CONTRACT注释,定义了完整的契约:

  • STATUS 字符集:[A-Za-z0-9_-]+;
  • TAG ↔ PHASE 作用域映射:no_task(无活跃任务,Phase 1 前)、planning(整个 Phase 1,status='planning')、planning-inline(Codex 内联变体)、in_progress(Phase 2 + Phase 3.2-3.4,status 从task.py start一直保持到task.py archive)、in_progress-inline(Codex 内联变体)、completed(当前是死块——task.py archive在同一调用里写 status 并移动目录,resolver 会丢失指针,保留给未来的显式状态迁移);
  • 不变量(对应 regression 测试):每个标记[required · once]的 walkthrough 步骤,必须在其所在阶段的[workflow-state:*]块里有对应的强制执行行——面包屑是唯一的逐轮通道,若某个必做步骤没被提及,AI 会静默跳过(Phase 1 计划门禁与 Phase 3.4 提交门禁都曾通过这个缺口暴露过 bug);
  • 编辑检查清单:改某个[workflow-state:STATUS]块时,要同步核对对应阶段的[required · once]步骤;改完运行trellis update把新正文推送到下游用户项目。

真实块示例(in_progress,workflow.md):

[workflow-state:in_progress] Tools: `trellis-implement` / `trellis-research` are sub-agent types only (Task/Agent tool, NOT Skill; there is no skill by these names). `trellis-update-spec` is a skill. `trellis-check` exists as both; prefer the Agent form when verifying after code changes. Flow: `trellis-implement` -> `trellis-check` -> `trellis-update-spec` -> commit (Phase 3.4) -> `/trellis:finish-work`. Main-session default: dispatch implement/check sub-agents. ... Dispatch prompt starts with `Active task: <task path from task.py current>`. Read context: jsonl entries -> `prd.md` -> `design.md if present` -> `implement.md if present`. [/workflow-state:in_progress]

这条"逐轮提示策略要变 → 改 workflow.md 的块,不需要改脚本"的链路,与文档"Local Change Scenarios"表中第二行完全对应。

六、本地修改场景速查表(文档原表,附仓库落点)

文档给出的"用户需求 → 修改位置"映射,结合仓库可归纳为:

用户需求修改位置仓库中的具体落点
新会话中 AI 看到更多/更少的上下文平台session-starthook.claude/hooks/session-start.py、.cursor/hooks/session-start.py等,及对应 settings 注册块
逐轮提示策略要变.trellis/workflow.md中的[workflow-state:STATUS]块;hook 原样解析,无需改脚本workflow.md 的 Phase Index 块
子代理读不到 PRD/specinject-subagent-contexthook 或 agent prelude.claude/hooks/inject-subagent-context.py、.cursor/hooks/inject-subagent-context.py、.opencode/plugins/inject-subagent-context.js;或.claude/agents/trellis-implement.md的 Context Loading Protocol
shell 里task.py current没有活跃任务shell/session bridge hook 或平台环境变量配置.cursor/hooks/inject-shell-session-context.py(票据 TTL 30 秒)
禁用某个自动注入对应 settings/config 中的 hook 注册项如.claude/settings.json的 hooks 段、.cursor/hooks.json、.gemini/settings.json

其中"子代理上下文"这一行值得展开:.claude/agents/trellis-implement.md里有一段Trellis Context Loading Protocol,子代理先查找输入中的<!-- trellis-hook-injected -->标记——标记存在说明 PRD/spec/research 已由 hook 自动加载,直接开工;标记缺失(Windows + Claude Code、--continue续会话、fork 分发、hooks 被禁用等场景)则回退到"从派发提示词首行Active task: <path>找任务路径,手动读implement.jsonl、各清单文件、prd.md、design.md(若有)、implement.md(若有)"。这证明了 hooks 与 agent prelude 是一对互为兜底的机制。

七、故障排查路径:当用户说"AI 没有读到 Trellis 状态"

文档给出五步排查路径,这里结合源码逐条给出验证手段:

第 1 步:检查平台 settings 是否注册了 hook。直接核对注册文件:.claude/settings.json、.cursor/hooks.json、.codex/hooks.json(注意 Codex 还要先满足.codex/config.toml注释中提到的用户级[features].hooks = true与/hooksTUI 审批)、.gemini/settings.json、.kiro/hooks/*.kiro.hook的enabled字段。

第 2 步:检查 hook 文件是否存在。ls对应平台的 hooks/plugins 目录。注意各平台文件名与实现语言可能不同:Python 系.claude/hooks/*.py、.cursor/hooks/*.py、.codex/hooks/*.py、.gemini/hooks/*.py、.kiro/hooks/*.py;OpenCode 是.opencode/plugins/*.js。

第 3 步:手动运行 hook 依赖的命令。

  • python3 .trellis/scripts/get_context.py(或加--json)——session-start 注入依赖的会话上下文;
  • python3 .trellis/scripts/task.py current --source——活跃任务状态查询,--source让脚本输出任务来源,便于判断会话身份链路是否通。

第 4 步:检查活跃任务状态是否存在。活跃任务指针存储在.trellis/.runtime/sessions/下(按 AI 会话/窗口维度存文件)。workflow.md 的 "Current-task mechanism" 一节说明:task.py create在会话身份可用时自动写入 per-session 活跃任务指针;task.py start重复写入该指针(幂等)并把task.json.status从planning翻转为in_progress;task.py finish删除当前会话文件(status 不变);task.py archive <task>写status=completed、把目录移入archive/并清理遗留的 runtime 会话文件。若.trellis/.runtime/sessions/里没有对应文件,说明没有活跃任务或会话身份未建立。

第 5 步:检查平台 shell 是否传递了会话身份。这正是 Cursor 的beforeShellExecution钩子(inject-shell-session-context.py)要解决的问题——写 30 秒 TTL 票据给task.py消费;同时.trellis/scripts/common/active_task.py也证实:活跃任务解析按每个 AI 会话/窗口存于.trellis/.runtime/sessions/,"没有稳定的会话身份"会导致task.py start直接失败并给出会话身份提示(提示语见 workflow.md 的 current-task 段落)。

排查时的另一个重要提醒:hooks 只在事件触发时注入。如果你改了.claude/hooks/inject-subagent-context.py,但对应的PreToolUse注册块还指向旧命令路径,改动不会生效;反之,只在.claude/settings.json里加了注册、脚本文件却不存在,平台会因找不到命令而报错或静默跳过。

八、综合修改顺序:从需求到落地的五步走

当用户要求"为某平台定制行为"时,platform-files/overview.md 给出的是自上而下逐层定位的顺序,本文结合 hooks-and-settings 的职责把它收敛为一个可操作清单:

  1. 先读.trellis/workflow.md,确认共享流程:这个平台的逐轮行为到底应该长什么样、哪些步骤是[required · once]。因为 hooks 是它的"只读解析器",改任何注入行为前必须知道共享流程本身。
  2. 读目标平台的 settings/config,看它注册了哪些 hooks/agents/skills/commands(对应本文第二节各平台注册清单)。
  3. 读目标平台的 agents/skills/commands/hooks具体实现,确认"已注册的接线"对应的"行为"是什么。
  4. 改"离需求最近"的那个本地文件:逐轮提示改workflow.md的块;注入量改 session-start 钩子/脚本;子代理上下文改 subagent 钩子或 agent prelude;shell 会话改 bridge 钩子;禁用注入改 settings 注册。
  5. 若改动影响共享流程,同步.trellis/workflow.md或.trellis/spec/。反向同理——不能只改共享流程而忘了平台入口文件里可能还残留旧描述。

最后再强调一遍文档中反复出现的两种错误形态:只改平台文件而忘记共享流程(hooks 解析的还是旧的 workflow.md),以及只改.trellis/workflow.md而忘了平台入口文件里旧的描述(agents 的 prelude 还在指老路径)。每一次上下文策略调整,本质上都是在"共享事实(workflow.md)"与"平台接线(settings/hooks)"之间保持同步,这就是 Trellis 多平台接入能够稳定运行的底层原因。

  • 桌面应用

【免费下载链接】EcoPaste

🎉跨平台的剪贴板管理工具 | Cross-platform clipboard management tool

项目地址:https://gitcode.com/ayangweb/EcoPaste
点击查看免费下载

相关推荐

上一篇:React Bits 实战指南:JSX 条件渲染的六种模式与最佳实践(短路求值、IIFE、do 表达式与提前返回)
下一篇:告别模糊标注:LabelImg低光照图像优化的3个实用技巧

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询