Spec Kit agent-context 扩展深度解析:如何让 CLAUDE.md、AGENTS.md 与 Plan 自动保持同步
Spec Kit 的 agent-context 扩展负责管理编码智能体(Claude Code、Copilot、Cursor、Gemini 等)的上下文/指令文件,例如 CLAUDE.md、AGENTS.md、.github/copilot-instructions.md。它是一个显式安装(opt-in)的可选扩展:安装后,它会在这些文件中维护一段由可配置标记包围的"受管区块",并自动把区块内容指向当前最新的 plan.md 路径;不安装则 Spec Kit 的任何流程都不会改动这些文件。读完本文,你将掌握该扩展的安装/禁用方式、全部配置项含义、受管区块的 upsert 算法、plan 路径的解析优先级,以及 .mdc 文件的 frontmatter 修复机制。
为什么做成一个扩展,而不是内置功能
不是每个 Spec Kit 用户都希望 Spec Kit 去写编码智能体的上下文文件。把这一行为放进一个独立的 opt-in 扩展(见 extensions/agent-context/README.md)带来四个直接好处:
- 可选择是否安装——
specify init默认不会安装它。想要 Spec Kit 托管 agent 上下文文件时才显式添加;未安装时该文件绝不会被修改,已禁用时其自动钩子也不会运行。 - 可自定义标记——编辑项目内的
.specify/extensions/agent-context/agent-context-config.yml,脚本会遵循其中context_markers的取值。 - 可同步多个 agent 锚点——当项目同时使用多份上下文文件(如
AGENTS.md和CLAUDE.md)时,配置context_files列表即可一次更新全部文件。 - 可按需刷新——在 agent 中运行
speckit.agent-context.update命令,或依赖 extension.yml 中声明的after_specify、after_plan钩子自动刷新。
从源码结构看,这一"完全交给扩展自己"的设计在 CLI 侧有对应约束:specify_cli 的集成初始化代码(如 src/specify_cli/integrations/_helpers.py)明确注释"agent 上下文文件完全由 opt-in 的 agent-context 扩展拥有,该函数从不触碰扩展及其配置",并且测试 tests/extensions/test_extension_agent_context.py 中的 test_cli_does_not_resolve_context_placeholder 专门验证了 CLI 不再解析模板中的 __CONTEXT_FILE__ 占位符——当扩展未安装或被禁用时,模板里的 __CONTEXT_FILE__ 会原样保留。
受管区块的生命周期:只动标记之间的内容
该扩展的核心职责是拥有由 start/end 标记(默认 <!-- SPECKIT START --> / <!-- SPECKIT END -->)分隔的受管 section 的完整生命周期:
- 只写标记之间:区块外的任何内容都不受影响;
- 对
.mdc文件额外保证文件顶部 YAML frontmatter 中包含alwaysApply: true(Cursor 只自动加载带此字段的.mdc规则文件); - 幂等:重复运行只会替换旧区块,不会叠加。
受管区块的固定内容由 _build_section 生成:
<!-- SPECKIT START -->
For additional context about technologies to be used, project structure,
shell commands, and other important information, read the current plan
at specs/001-login/plan.md
<!-- SPECKIT END -->
即一句提示语加上"当前 plan 的路径"。这样当编码 agent 读取 CLAUDE.md 时,就能被引导去读最新的实现计划。
安装、禁用与命令
安装
在已初始化的 Spec Kit 项目根目录运行:
specify extension add agent-context
禁用 / 重新启用
specify extension disable agent-context
# 重新启用
specify extension enable agent-context
禁用(或未安装)期间,Spec Kit 中没有任何流程会创建、更新或删除受管区块,模板中的 __CONTEXT_FILE__ 占位符保持原样,扩展自身的配置也永远不会被读取。
提供的命令
| 命令 | 说明 |
|---|---|
speckit.agent-context.update |
用当前 plan 路径刷新 agent 上下文文件中的受管区块 |
命令 ID 是规范的(canonical)写法;实际调用语法取决于你的集成方式:
| 集成类型 | 调用写法 |
|---|---|
| dot-command 集成 | /speckit.agent-context.update |
| hyphen/skills 集成(含 Forge、Cline 等) | /speckit-agent-context-update |
| Codex、ZCode(skills 模式) | $speckit-agent-context-update |
| Kimi | /skill:speckit-agent-context-update |
对应的命令模板见 extensions/agent-context/commands/speckit.agent-context.update.md,其声明的执行入口为:
- Bash:
.specify/extensions/agent-context/scripts/bash/update-agent-context.sh [plan_path] - PowerShell:
.specify/extensions/agent-context/scripts/powershell/update-agent-context.ps1 [plan_path]
当省略 plan_path 参数时,脚本会自动探测最新的 specs/**/plan.md。
配置参考:agent-context-config.yml
所有配置都集中在项目内的 .specify/extensions/agent-context/agent-context-config.yml。仓库中的模板(extensions/agent-context/agent-context-config.yml)完整注释了每个字段的用途,可逐项对照理解:
# 单个 agent 上下文文件路径(相对项目根,即 .specify/ 所在目录)。
# 拒绝绝对路径、反斜杠分隔符和 `..` 路径段。
# 留空时使用你所选编码 agent 的默认上下文文件
# (见 agent-context-defaults.json)。
# 例: context_file: CLAUDE.md
context_file: ""
# 多个 agent 上下文文件列表(相对项目根)。
# 当 context_file 与 context_files 同时存在时,context_files 优先生效。
# 例:
# context_files:
# - AGENTS.md
# - CLAUDE.md
context_files: []
# 受管区块的起止标记。扩展只在这两个标记之间注入信息。
# 仅在希望自定义标记名时修改。
# 例:
# context_markers:
# start: "<!-- AGENT SPEC KIT CONTEXT START -->"
# end: "<!-- AGENT SPEC KIT CONTEXT END -->"
context_markers:
start: "<!-- SPECKIT START -->"
end: "<!-- SPECKIT END -->"
要点归纳:
| 配置项 | 类型 | 行为 |
|---|---|---|
context_file |
字符串(可选) | 指定单个受管文件;留空则回退到集成默认映射 |
context_files |
字符串列表(可选) | 多个受管文件;非空时优先于 context_file,逐一遍历更新 |
context_markers.start / .end |
字符串(可选) | 受管区块分隔符;缺失时使用默认 <!-- SPECKIT START --> / <!-- SPECKIT END --> |
路径安全约束
_validate_context_file(extensions/agent-context/scripts/python/update_agent_context.py#L112-L138)对每个候选路径做硬性校验,违反即报错退出(退出码 1):
- 必须以项目根为相对路径——绝对路径(
/...)与 Windows 盘符路径(C:\...)被拒绝; - 不得包含反斜杠分隔符;
- 不得包含
..路径段; - 最终解析(含符号链接解引用)后仍必须落在项目根之内,防止通过 symlink 逃逸出项目目录。bash 脚本中的
test_bash_script_rejects_symlink_escape对应测试(tests/extensions/test_extension_agent_context.py)专门覆盖了这一逃逸场景。
未配置时的"自播种"(self-seed)
当 context_file 与 context_files 都为空时,脚本并不会报错,而是执行自播种逻辑:读取 .specify/init-options.json 中的 integration(或 ai)键,再通过 extensions/agent-context/agent-context-defaults.json 中的映射得到默认上下文文件。该映射覆盖了全部 36 个支持的集成,摘选如下:
| 集成 key | 默认上下文文件 |
|---|---|
claude |
CLAUDE.md |
copilot |
.github/copilot-instructions.md |
gemini |
GEMINI.md |
cursor-agent |
.cursor/rules/specify-rules.mdc |
codex / copilot 之外的多数 CLI(codex、goose、grok、opencode、qwen 等) |
AGENTS.md |
junie |
.junie/AGENTS.md |
kilocode |
.kilocode/rules/specify-rules.md |
trae |
.trae/rules/project_rules.md |
qwen / qodercli / shai / tabnine / zcode |
QWEN.md / QODER.md / SHAI.md / TABNINE.md / ZCODE.md |
源码注释明确指出,这一映射"按设计独立于 Specify CLI"——扩展自己管理自己的生命周期,脚本内部不 import 任何 specify_cli 模块。若集成在映射表中不存在默认值,脚本会打印"no default context file is known for integration …"的提示,要求用户显式设置 context_file。此外,在 Windows/Cygwin/MSYS 环境下,context_files 的去重比较采用大小写不敏感(casefold)策略,与 bash 脚本中 MINGW/MSYS/CYGWIN 分支的行为一致。
底层实现:Plan 路径如何被解析
这是扩展最有技术含量的部分。受管区块的价值完全取决于 plan_path 是否指向"当前"计划,因此解析采用两级优先策略(见 _resolve_plan_path):
- 优先读取
.specify/feature.json——该文件由/speckit-specify写入,其中feature_directory字段指明当前功能目录;脚本在feature_directory/plan.md存在时以它为准。解析时做了几处细节处理:- 先把路径中的反斜杠(PowerShell 在 Windows 上写入的格式)规范化为正斜杠;
- 支持相对路径、绝对路径与
C:/盘符路径三种形态; - 先
resolve()解引用符号链接再做relative_to比较,使 macOS 上/var/…与/private/var/…被判定为同一路径; - 若 plan 落在项目根外,则直接输出解析后的 POSIX 绝对路径。
- 回退到 mtime 探测——仅当
feature.json不存在或其 plan 尚未生成时,递归遍历specs/下所有plan.md(rglob而非旧的单层specs/*/plan.md通配),选出修改时间最新的一个。递归搜索保证了通过SPECIFY_FEATURE_DIRECTORY创建的作用域化布局(如specs/<scope>/<feature>/plan.md)也能被发现。同样,候选文件在比较前先做符号链接解引用,避免指向项目外的specs/symlink 被误选。
这条解析链有专门的回归测试:tests/extensions/test_update_agent_context_feature_json.py 覆盖 feature.json 路径,test_bash_script_discovers_nested_plan / test_bash_script_finds_nested_plan 等用例覆盖嵌套布局的 mtime 回退。
底层实现:区块 upsert 的四分支算法
_upsert_section(bash/PowerShell 版本逻辑等价)按文件中现有标记的组合分四种情况处理:
| 现有文件状态 | 行为 |
|---|---|
| start 与 end 标记均存在 | 整体替换标记之间的旧区块(保留标记后的换行) |
| 只有 start 标记 | 从 start 标记处开始截断,写入新区块(丢弃残缺尾部) |
| 只有 end 标记 | 保留 end 标记之后的内容,在其前面插入新区块 |
| 都没有标记 | 若文件已有内容则追加到文件末尾(先补齐换行);文件不存在则直接创建,父目录不存在时自动 mkdir -p |
写入前还会把全文 CRLF/CR 统一规范化为 LF(读取时以 utf-8-sig 编码容忍 BOM),保证跨平台换行稳定。bash 入口脚本还负责解释器选择:依次尝试 $SPECKIT_PYTHON 环境变量、python3、python,并要求该解释器可 import yaml 且为 Python 3(见 update-agent-context.sh 第 29-55 行),任何一个不可用则降级为打印警告并跳过更新,而不是让钩子失败。
.mdc 文件的 frontmatter 修复
ensure_mdc_frontmatter(update_agent_context.py 第 216-256 行)只对 .mdc 后缀文件生效,处理三种情形:
- 文件无 frontmatter → 在头部整体前置
---\nalwaysApply: true\n---\n\n; - frontmatter 已有
alwaysApply: true→ 原样返回(幂等); - frontmatter 存在但
alwaysApply缺失或值不是true→ 原地修复该行、保留原有注释与格式;若完全没有该键则在 frontmatter 末尾追加一行。
对应测试 test_bash_script_prepends_mdc_frontmatter、test_bash_script_mdc_frontmatter_is_idempotent、test_bash_script_repairs_existing_mdc_frontmatter 以及"非 .mdc 文件不做 frontmatter 处理"的负向用例,都在 tests/extensions/test_extension_agent_context.py 中可查证。
钩子驱动的自动化
extension.yml 声明了两个可选钩子:
hooks:
after_specify:
command: speckit.agent-context.update
optional: true
description: "Refresh agent context after specification"
after_plan:
command: speckit.agent-context.update
optional: true
description: "Refresh agent context after planning"
也就是说,每次执行 /speckit.specify 与 /speckit.plan 之后,事件系统会自动触发 speckit.agent-context.update,使上下文文件中的 plan 路径始终跟上最新进度——无需手动干预。根据 extensions/EXTENSION-API-REFERENCE.md,钩子挂在 after_specify、after_plan 等由核心命令定义的生命周期事件上,同一事件的多个钩子按 priority 升序执行(默认 10)。extension.yml 同时声明了元信息:schema_version: "1.0"、要求 speckit_version: ">=0.2.0"、标签 agent/context/core,且该扩展以捆绑(bundled)形式随仓库分发,catalog 中将其列为 bundled 条目(测试 test_catalog_lists_agent_context_as_bundled 守护此约定)。
环境要求与故障排查
捆绑的更新脚本要求 Python 3 + PyYAML 做 YAML 解析/写入(PowerShell 侧在可用时也可用 ConvertFrom-Yaml)。PyYAML 随 specify CLI 一起分发,正常情况下同一个 python3 解释器即可满足。如果钩子报告 "PyYAML is required … not available in the current Python environment",说明系统 python3 与安装 Spec Kit 所用的解释器不是同一个,解决方式:
pip install pyyaml
# 或者针对 Spec Kit 实际使用的那个解释器:
/path/to/speckit-python -m pip install pyyaml
脚本在 PyYAML 缺失时的行为是优雅降级:打印指引信息后以退出码 0 跳过本次更新(上下文文件不被修改),避免破坏宿主命令流程;测试 test_bash_script_falls_back_from_invalid_speckit_python 验证了无效 SPECKIT_PYTHON 会被自动回退到 PATH 上其他可用解释器。
验证与测试入口
该扩展的行为有相当完整的测试护栏,均位于 tests/extensions/ 目录,可作为"实现是否符合文档"的一手证据:
- tests/extensions/test_extension_agent_context.py——扩展清单/文件完整性、bash 与 PowerShell 脚本的路径拒绝、去重、嵌套 plan 发现、
.mdcfrontmatter 幂等与修复、符号链接/junction 逃逸拒绝,以及"CLI 不解析__CONTEXT_FILE__占位符"的职责边界; - tests/extensions/test_update_agent_context_feature_json.py——feature.json 驱动的 plan 解析;
- tests/extensions/test_update_agent_context_python_parity.py 与 tests/extensions/test_agent_context_cli_free.py——Python 版脚本与 shell 版的行为一致性,以及"扩展脚本不依赖 specify CLI"的独立性。
bash、PowerShell、Python 三个运行时的脚本(scripts/bash/update-agent-context.sh、scripts/powershell/update-agent-context.ps1、scripts/python/update_agent_context.py)在语义上互为孪生实现,配置解析、自播种、路径校验、plan 解析与 upsert 逻辑逐条对齐,跨平台行为以测试为准绳。
小结
agent-context 是 Spec Kit 扩展体系中一个边界清晰、职责单一的范本:它以 opt-in 的方式接管编码 agent 上下文文件,把"让 agent 知道最新 plan 在哪"这件容易被遗忘的小事变成 after_specify/after_plan 钩子驱动的自动行为。对使用者的实际收益是——在 Claude Code、Copilot、Cursor 等工具中始终有一份指向当前 specs/**/plan.md 的新鲜指引,而标记之外的文件内容(团队手写的规则、项目约定)永远不会被覆盖;若你更倾向自行维护该文件,不安装扩展即可,Spec Kit 的其余部分对此完全无感。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00