首页
/ Spec Kit 升级指南:CLI 自升级与项目文件刷新的完整操作与源码解析

Spec Kit 升级指南:CLI 自升级与项目文件刷新的完整操作与源码解析

2026-09-05 22:26:58作者:冯爽妲Honey

Spec Kit 的升级分为两层:独立的 specify CLI 工具,以及已安装到项目中的命令/模板文件。本文围绕 升级指南 展开,完整覆盖 specify self upgrade 自升级机制、specify integration upgrade 清单感知的项目文件刷新、/constitution 行为变更与 opt-in 恢复方案,并结合 自升级实现源码constitution-sync preset 解释底层原理,帮助你安全地完成大版本升级而不丢失任何本地定制。

升级速查表

升级对象 命令 使用场景
CLI 工具(推荐) specify self upgrade 升级到最新稳定版,原地升级。自动检测你是通过 uv tool 还是 pipx 安装的
CLI 工具 — 固定版本 specify self upgrade --tag vX.Y.Z[suffix] 升级到指定 release tag 而非最新稳定版。后缀仅限 dev、alpha/beta/rc 和/或 build 元数据形式
CLI 工具 — 手动兜底 uv tool install specify-cli --force --from git+https://github.com/github/spec-kit.git@vX.Y.Z specify self upgrade 不可用(较老版本安装)或希望显式控制安装器命令时
CLI 工具 — 手动兜底(pipx) pipx install --force git+https://github.com/github/spec-kit.git@vX.Y.Z 同上,面向 pipx 安装
项目文件 specify integration upgrade <key>,随后 specify extension update 刷新项目中已安装的集成文件与扩展
两者都升 先升级 CLI,再更新项目 大版本更新时推荐

CLI 工具(specify)与项目文件是相互独立的:升级 CLI 获取新特性和缺陷修复,刷新项目文件让 AI 代理拿到新的斜杠命令与模板。

第一部分:升级 CLI 工具

推荐路径:specify self checkspecify self upgrade

CLI 内置两个自管理命令,自动处理常见场景:

# 检查是否有更新的发布版本(只读,不修改任何东西)
specify self check

# 预览将执行的升级动作,但不实际升级
specify self upgrade --dry-run

# 原地升级到最新稳定版(自动检测 uv tool 与 pipx 安装方式)
specify self upgrade

# 或固定到指定 release tag(将 vX.Y.Z[suffix] 替换为目标 tag)
specify self upgrade --tag vX.Y.Z[suffix]

裸调 specify self upgrade 会立即执行、不弹确认提示,行为与 pip install -Unpm update 一致。CLI 会把当前运行时归类为五种之一:uv toolpipxuvx (ephemeral)source checkoutunsupported;只有 uv toolpipx 会被自动升级——对 uv tool 安装,底层执行的是 uv tool install specify-cli --force --from <git ref>,因此固定 release tag 可以正常工作。其余路径打印各自的处理指引并以 0 退出,不触碰任何文件。

源码视角:安装方式检测是三级判定

_version.py 中的 _detect_install_method 实现了三级检测,按顺序短路:

  1. 一级:路径前缀匹配。比较 sys.argv[0] 的解析路径是否落在已知安装目录内,前缀表 _INSTALLER_PATH_PREFIXES 覆盖 Linux/macOS 与 Windows:
    • uv-tool~/.local/share/uv/tools/specify-cli/%LOCALAPPDATA%\uv\tools\specify-cli\
    • pipx~/.local/pipx/venvs/specify-cli/%LOCALAPPDATA%\pipx\venvs\specify-cli\
    • uvx-ephemeral~/.cache/uv/archive-v0/ 等缓存目录
  2. 二级:editable 安装标记。读取分发包元数据中的 direct_url.json,若记录了 editable 且根目录含 .git,判定为 source-checkout
  3. 三级:安装器注册表核对。运行 uv tool listpipx list --json(各带 5 秒超时)确认哪个管理器拥有 specify-cli。若两个注册表同时声称拥有该包,入口点归属存在歧义,会被判定为 unsupported 而不是猜测——避免升级错的那个安装。

对非可自动升级的路径,_emit_guidance 打印针对性指引:uvx (ephemeral) 提示"下一次 uvx 调用自动解析最新版,无需升级动作";source checkout 提示在检出目录执行 git pullpip install -e .unsupported 则给出 uv tool installpipx install --force 两条手动命令。

--tag 版本校验规则

固定 tag 必须形如 vMAJOR.MINOR.PATCH,可选后缀仅限 dev、alpha/beta/rc 以及/或 build 元数据,可组合。合法示例:

  • v1.0.0-rc1
  • v0.8.0.dev0
  • v0.8.0+build.42
  • v1.0.0-rc1+build.42

分支名、hash 引用、latest、不带 v 前缀的裸版本号一律被拒绝。对应实现见 _TAG_REGEX 与 _validate_tag:正则之外还叠加 packaging.version.Version 的 PEP 440 解析双重校验;一个细节是开头大写 V 会被折叠为小写 v,但其余大小写保持原样——因为校验后的 tag 会逐字用作 git 引用,而 GitHub 上的引用是大小写敏感的。

超时控制:SPECIFY_UPGRADE_TIMEOUT_SECS 与退出码 124

默认情况下安装器子进程不设超时(依赖解析、大 wheel 下载可能合法地耗时数分钟,需要时按 Ctrl+C 中断)。设置 SPECIFY_UPGRADE_TIMEOUT_SECS 为整数/浮点秒数可强制上限;取值无法解析、非正或非有限时,CLI 会打印告警并按"无超时"继续运行。超时处理见 _run_installer

  • 内部超时触发时,specify self upgrade124 退出,并报告"在安装器子进程上超时",附带的信息包含配置的超时值和可手动重试的完整命令;
  • 真实安装器进程退出码 124 会原样透传为 Upgrade failed. Installer exit code: 124.

因此脚本层面应把退出码 124 视为歧义值,需要区分两种情况时必须检查输出消息。完整的退出码语义在 self_upgrade 命令的 docstring 中有完整定义:

退出码 含义
0 成功或无操作成功(已是最新、--dry-run、非可升级路径已打印指引)
1 目标 tag 解析失败或 --tag 正则校验失败
2 安装器退出 0 但 specify --version 未解析到目标 tag(校验不一致);安装器本身退出 2 时原样透传
3 安装器二进制不在 PATH 上,或解析出的安装器路径不存在/不可执行
124 内部安装器超时,或真实安装器退出码 124 原样透传
其他 安装器退出码原样透传

此外,_scrubbed_env 会在派生安装器子进程前移除形如 GitHub 凭据的环境变量(GH_*/GITHUB_* 前缀,或含 _GITHUB_ 段且以 _TOKEN/_SECRET/_KEY/_PAT/_PASSWORD/_CREDENTIALS 结尾的键),避免凭据随安装器输出泄露。升级成功后 CLI 还会派生一个全新子进程运行 specify --version 做校验——因为当前进程内无法热替换已被安装器替换的模块,见 _verify_upgrade。失败时输出还会附带 _rollback_hint 生成的回退命令(例如用 pipx install --force git+...@v旧版本 钉回上一稳定版)。相关行为有专门测试覆盖,如安装器缺失时退出 3 的用例见 test_self_upgrade_execution.py

如果 self check 因限流失败(GitHub API 返回 403/429),输出会提示在 ~/.specify/auth.json 配置 GitHub token 缓解;该失败分类逻辑见 _fetch_latest_release_tag

手动兜底命令

若已安装的 CLI 早于引入 specify self upgrade 的版本,使用下面等价命令;这些命令也适合希望显式控制安装器的场景。

使用 uv tool install 安装时(目标 tag 以 GitHub Releases 页最新 tag 为准):

uv tool install specify-cli --force --from git+https://github.com/github/spec-kit.git@vX.Y.Z

使用一次性 uvx 命令时,直接指定目标 tag:

uvx --from git+https://github.com/github/spec-kit.git@vX.Y.Z specify init --here --integration copilot

注意 uvx 只为该条命令运行一份临时副本,不会更新通过 uv tool installpipx 等持久安装的 specify。如果新特性在 uvx 下可用而本地 specify 仍报告旧版本,请用与安装方式匹配的命令升级持久 CLI。

使用 pipx 安装时

pipx install --force git+https://github.com/github/spec-kit.git@vX.Y.Z

验证升级

# 确认 CLI 可用并展示已安装工具
specify check

# 将已安装版本与 GitHub 最新 release 对比
specify self check

两者语义不同:specify check 是离线的环境/工具链扫描;specify self check 是只读的 CLI 版本查询,告诉你现在是否处于最新 release(Up to date: X.Y.Z)还是有新版本可用(Update available: X.Y.Z → vY.Z.W)。从源码看,已安装版本通过 importlib.metadata.version("specify-cli") 读取(_get_installed_version),反映的是 pip/uv/pipx 实际安装的发行版元数据,而非源码树中的 pyproject.toml 值。

第二部分:更新项目文件

当 Spec Kit 发布新特性(新斜杠命令、模板更新、扩展变更)时,需要刷新安装进项目的 Spec Kit 文件。已有项目应优先走**清单感知(manifest-aware)**升级路径。

会被更新什么?

  • 集成命令/技能文件.claude/skills/.github/prompts/.agents/skills/ 等)
  • 受管的共享脚本与模板.specify/scripts/.specify/templates/)——前提是它们相对上一份受管副本未被修改
  • 已安装扩展——运行 specify extension update

集成升级命令利用安装清单检测本地编辑:某个受管集成文件在安装后被改过,命令会停止并提示你检查改动,或加 --force 重跑。

什么绝对安全?

清单感知的集成/扩展升级路径从不触碰以下内容:

  • ✅ 你的规格文档(specs/001-my-feature/spec.md 等)
  • ✅ 你的实现计划(specs/001-my-feature/plan.mdtasks.md 等)
  • ✅ 你的宪法(.specify/memory/constitution.md),使用 specify integration upgrade
  • ✅ 你的源码
  • ✅ 你的 git 历史

specs/ 目录被模板打包完全排除,升级期间绝不会修改。

清单机制的底层原语在 integrations/base.py:安装时每个写入的文件都会哈希并记录进 IntegrationManifest;升级时,旧清单中有、新清单中没有的文件被视为"陈旧文件"清理,而 stale_cleanup_exclusions 允许集成声明"永远不得被陈旧清理删除"的路径(例如合并进既有文件后即停止跟踪的 settings 文件),避免误删仍受管理的文件。

步骤 1:查看已安装集成

在项目目录内运行:

specify integration status

它会报告默认集成、全部已安装集成,以及被修改或缺失的受管文件。也可直接查看 .specify/integration.json,已安装集成列在 installed_integrations 字段下。

步骤 2:逐个升级已安装集成

specify integration upgrade <key>

<key> 替换为已安装集成键,如 copilotclaudecodex;安装了多个集成时,每个键各跑一次:

specify integration upgrade claude
specify integration upgrade codex

选项如 --script--integration-options--force 详见集成参考文档的升级小节

步骤 3:更新已安装扩展

specify extension update

不带参数时更新全部已安装扩展;specify extension update <extension-id-or-name> 只更新单个扩展。实现入口是 extensions/_commands.py 中的 extension_update:它会核对注册表中每个扩展的已安装版本是否可解析(PEP 440),跳过损坏或缺失版本号的注册项,再与目录(catalog)信息对比确定可用更新。扩展参考文档见扩展升级小节

兜底:重跑 init

若项目早于清单机制、集成元数据缺失或需要更大范围恢复,可以重跑 init:

specify init --here --force --integration <your-agent>

这是逃生舱而非默认项目文件升级路径:它会刷新选定集成与共享项目脚手架,但不走逐集成清单检查就直接覆盖文件。

三个升级风险点

1. 宪法文件与记忆定制

specify integration upgrade <key> 不更新 .specify/memory/constitution.md。兜底路径 specify init --here --force --integration <your-agent> 也会保留已存在的宪法文件;文件缺失时才从当前宪法模板创建。清单感知升级路径无需宪法备份/恢复步骤。但任何大范围兜底刷新之前,都建议先提交或备份本地定制,便于事后审查 diff。

2. 自定义集成、脚本或模板

受清单跟踪的集成文件被本地修改时,specify integration upgrade <key>阻塞,除非传 --force。共享脚本与模板只有在仍与先前记录的受管副本匹配时才会刷新;本地定制在显式 force/refresh 前会被保留。若你定制过 .specify/scripts/.specify/templates/,先提交或备份:

# 备份自定义模板和脚本
cp -r .specify/templates .specify/templates-backup
cp -r .specify/scripts .specify/scripts-backup

# 升级后手动把你的改动合并回来

3. 斜杠命令重复(IDE 系代理)

部分 IDE 系代理(如 Kilo Code、Cline)升级后可能显示重复斜杠命令——新旧两版同时出现。

解决:手动删除代理目录中的旧命令文件。以 Kilo Code 为例:

# 列出当前与旧版 Kilo 命令目录
ls -la .kilo/commands/
ls -la .kilocode/workflows/

# 删除旧版本(示例文件名,你的可能不同)
rm .kilocode/workflows/speckit.specify-old.md
rm .kilocode/workflows/speckit.plan-v1.md

然后重启 IDE 刷新命令列表。

行为变更:/constitution 不再向模板传播

/constitution 命令的作用域现在限定在它自己的产物上:更新 .specify/memory/constitution.md 并写入 Sync Impact Report,不再编辑 plan-template.mdspec-template.mdtasks-template.md、已安装命令文件或指引文档。

为什么

Spec Kit 采用运行时解析(runtime resolution)plantasksanalyze 每次运行时都实时读取 .specify/memory/constitution.mdanalyze 是专职的漂移检查器。受治理模板携带的是指针而非副本——plan-template.md 出厂带 [Gates determined based on constitution file]/plan 每次运行时用实时宪法填充该段。传播做法复制了单一事实源,并与 preset/override 组合系统相冲突(replace 策略的 preset 会遮蔽被编辑过的核心模板)。

更广义地,preset 与扩展——而非就地文件编辑——才是 Spec Kit 治理共享资产的现行方式。通过解析栈组合策略,让策略保持集中拥有、可版本化、跨仓库可审计,而不是冻结成核心团队看不到的逐仓库副本。

对现有项目是否破坏性变更

不是——工作流继续可用。 只有当你依赖 /constitution 就地编辑那些文件时才会察觉差异。模板是脚手架而非权威:/plan 运行时会把模板复制进逐功能的 plan.md,并从实时宪法重新推导 Constitution Check;/analyze 对照它做校验。即使先前某次 /constitution 运行把具体 gate 文本物化进了 .specify/templates/plan-template.md,运行时事实源仍是实时宪法。

非强制升级下,已物化的模板会被保留(其哈希与记录的受管副本分叉,刷新逻辑视其为定制,不会覆盖)。不会有任何功能回退。

可选清理——回到运行时指针

冻结的预填 Constitution Check 是略显误导的脚手架,可能让第一轮 /plan 锚定在冻结文本上。若要彻底回到运行时解析,把 .specify/templates/plan-template.md 中该小节正文重置为指针:

## Constitution Check

*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*

[Gates determined based on constitution file]

文件其余部分保持不变。这是清理动作,不是必须的迁移。

保留旧行为(opt-in)

如果你的团队把物化模板当作已评审、已提交的产物,希望 /constitution 继续传播,安装内置的 constitution-sync preset:

specify preset add constitution-sync

它以 wrap 策略包装核心 /constitution 命令并重新加入传播环节(对齐 .specify/templates/ 下的 plan/spec/tasks-template.md、更新项目本地命令文件与指引文档、扩展 Sync Impact Report)。它不会编辑带版本号的 preset/扩展提供的模板或命令文件(那些由所属包拥有,会在协调时重新组合)。从 constitution-sync 的 README 可以确认其边界:它只写项目本地、未被 preset/扩展管理的文件,且不会替代运行时解析——plan/tasks/analyze 每次运行仍读实时宪法。需要权衡的是:物化副本会漂移、对组合文件的传播在栈重新协调时会被覆盖、预填 Constitution Check 可能偏向第一轮 /plan,详见该 README 的 "Caveats you take on" 与 "Interaction with the resolution stack" 讨论。

常见场景

场景 1:"我只想要新的斜杠命令"

# 升级 CLI(自动检测 uv tool 与 pipx 安装方式)
specify self upgrade

# 查看已安装集成
specify integration status

# 更新项目文件以获取新命令
specify integration upgrade <key>
specify extension update

场景 2:"我定制了模板和宪法"

# 1. 提交或备份定制
git status
cp -r .specify/templates /tmp/templates-backup

# 2. 升级 CLI
specify self upgrade

# 3. 优先使用清单感知的项目更新
specify integration upgrade <key>
specify extension update

# 4. 若升级报告受管文件被修改,先检查 diff 再考虑 --force

场景 3:"IDE 里出现重复斜杠命令"

发生在 IDE 系代理(Kilo Code、Cline 等)上:

# Kilo Code:检查当前与旧版命令目录
ls -la .kilo/commands/
ls -la .kilocode/workflows/

# 删除旧命令文件
rm .kilocode/workflows/speckit.old-command-name.md

# 重启 IDE

场景 4:"我不要 git 扩展"

git 扩展现在是 opt-in,升级不会安装它,除非显式添加:

# 升级 CLI
specify self upgrade

# 刷新集成文件与已安装扩展
specify integration upgrade <key>
specify extension update

# 除非运行 `specify extension add git`,git 扩展不会被添加

之后想要它的命令与 hooks 时显式安装即可:

specify extension add git

不使用 Git 的项目也能配合 Spec Kit 工作:在计划类命令前设置 SPECIFY_FEATURE_DIRECTORY 指向功能目录:

# Bash/Zsh
export SPECIFY_FEATURE_DIRECTORY="specs/001-my-feature"

# PowerShell
$env:SPECIFY_FEATURE_DIRECTORY = "specs/001-my-feature"

或者运行 /speckit.specify 命令,它会自动创建 .specify/feature.json

故障排查

"升级后斜杠命令没有出现"

原因:代理没有重新加载命令文件。

处理

  1. 完整重启 IDE/编辑器(不是只 reload window)

  2. CLI 系代理确认文件存在:

    ls -la .claude/skills/        # Claude Code
    ls -la .gemini/commands/      # Gemini
    ls -la .cursor/skills/        # Cursor
    ls -la .pi/prompts/           # Pi Coding Agent
    ls -la .omp/commands/         # Oh My Pi
    
  3. 检查代理专属设置:Codex 需要 CODEX_HOME 环境变量;部分代理需要重启工作区或清缓存。

"init 会覆盖我的宪法定制吗?"

当前 specify init --here --force 会保留已存在的 .specify/memory/constitution.md,只在文件缺失时从模板创建。如果此前通过旧流程或手动替换丢了宪法改动,从 git 或备份恢复:

# 若定制过的宪法已提交
git restore .specify/memory/constitution.md

# 若手动备份过
cp /tmp/constitution-backup.md .specify/memory/constitution.md

预防:例行项目文件更新使用 specify integration upgrade <key>;确需兜底 specify init --here --force 时先提交,便于事后审查完整 diff。

"Warning: Current directory is not empty"

完整警告信息:

Warning: Current directory is not empty (25 items)
Template files will be merged with existing content and may overwrite existing files
Do you want to continue? [y/N]

在已有文件的目录中运行 specify init --here(或 specify init .)时出现,含义是:目录已有内容;新模板文件会与现有文件合并;既有 Spec Kit 文件(.claude/.specify/ 等)会被新版本替换。

会被覆盖的:只有 Spec Kit 基础设施文件——代理命令/技能文件(.claude/skills/.github/prompts/ 等)、.specify/scripts/ 中的脚本、.specify/templates/ 中的模板;缺失的记忆文件(如 .specify/memory/constitution.md)可能从模板创建,已存在的宪法会被保留。

保持不动的specs/ 目录(规格、计划、任务)、源码文件、.git/ 与 git 历史、模板包之外的任何文件。

如何响应:输入 y 回车继续合并(兜底 init 路径下);输入 n 取消;或用 --force 完全跳过确认:

specify init --here --force --integration copilot

何时会出现:在既有 Spec Kit 项目中使用兜底 init 路径时预期出现;给既有代码库添加 Spec Kit 时预期出现;若你以为自己在空目录创建新项目,则是意外预防:使用兜底 init 前提交当前工作,刷新出的文件便易审查与还原。

"CLI 升级似乎没生效"

若命令行为仍像旧版本,先问 CLI 本身:

# 只读——打印 "Up to date: X.Y.Z" 或 "Update available: X.Y.Z → vY.Z.W"
specify self check

# 预览升级将使用的安装方式、当前版本与目标 tag
specify self upgrade --dry-run

specify check 是离线环境扫描,specify self check 才是 CLI 版本查询。若 self check 显示的版本不对,验证安装:

# 查看已安装工具
uv tool list

# 应能看到 specify-cli

# 验证路径
which specify

# 应指向 uv tool 安装目录

找不到时重新安装:

uv tool uninstall specify-cli
uv tool install specify-cli --from git+https://github.com/github/spec-kit.git

"每次打开项目都要运行 specify 吗?"

不需要specify init 每个项目只运行一次,或之后作为兜底恢复路径使用。

specify CLI 的用途是:初始设置specify init)、例行项目文件升级specify integration upgrade <key>specify extension update)、兜底恢复(集成元数据缺失或清单感知路径不可用时的 specify init --here --force)、诊断specify check)。

一旦运行过 specify init,斜杠命令(/speckit.specify/speckit.plan 等)就永久安装在项目的代理目录中(.claude/.github/prompts/.pi/prompts/.omp/commands/ 等),AI 编码代理直接读取这些命令文件,无需再运行 specify

代理不识别斜杠命令时

  1. 验证命令文件存在:

    # GitHub Copilot
    ls -la .github/prompts/
    
    # Claude
    ls -la .claude/skills/
    
    # Pi
    ls -la .pi/prompts/
    
    # Oh My Pi
    ls -la .omp/commands/
    
  2. 完整重启 IDE/编辑器(不是只 reload window)

  3. 确认你在运行过 specify init正确目录

  4. 部分代理可能需要重新加载工作区或清缓存

相关问题:若 Copilot 打不开本地文件或意外使用 PowerShell 命令,通常是 IDE 上下文问题,与 specify 无关——尝试重启 VS Code、检查文件权限、确认工作区文件夹正确打开。

版本兼容性与升级后检查清单

Spec Kit 对大版本遵循语义化版本,CLI 与项目文件设计为在同一主版本内相互兼容。最佳实践:主版本变更时两者同步升级,保持一致。

升级完成后:

  • 测试新斜杠命令:运行 /speckit.constitution 或其他命令验证一切正常
  • 查看 release notes:到 GitHub Releases 页确认新特性与破坏性变更
  • 更新工作流:若新增了命令,更新团队的开发流程
  • 核对文档:参考仓库 docs/ 下的更新指南,例如参考总览

关键参考路径

资源 路径
升级指南(本文依据) docs/upgrade.md
自检查/自升级实现(检测、tag 校验、超时、退出码、回退提示) src/specify_cli/_version.py
自升级执行路径测试(安装器缺失、超时、校验等) tests/test_self_upgrade_execution.py
集成清单记录与陈旧清理排除 src/specify_cli/integrations/base.py
扩展更新命令实现 src/specify_cli/extensions/_commands.py
集成升级选项参考 docs/reference/integrations.md
扩展更新参考 docs/reference/extensions.md
constitution-sync preset(恢复传播行为的 opt-in 方案) presets/constitution-sync/README.md
登录后查看全文
热门项目推荐
相关项目推荐