首页
/ spec-kit 本地开发实战指南:specify CLI 从直接运行到 Wheel 构建的完整迭代闭环

spec-kit 本地开发实战指南:specify CLI 从直接运行到 Wheel 构建的完整迭代闭环

2026-09-05 13:23:31作者:侯霆垣

本文基于 spec-kit 仓库的 docs/local-development.md 指南展开,覆盖在不发布版本、不先合入 main 分支的前提下迭代 specify CLI 的完整流程:直跑源码模块、可编辑安装、uvx 本地/Git 分支运行、脚本权限验证、内置集成脚手架、Lint 检查与 Wheel 构建。读完后你可以独立搭建一条针对 spec-kit 的快速编辑-验证-构建闭环,并能定位常见运行问题。

前置条件与仓库结构

当前仓库的 pyproject.toml 声明了 CLI 的运行前提:

  • 包名为 specify-cli,要求 Python >=3.11
  • 核心依赖包括 typer>=0.24.0click>=8.2.1richplatformdirsreadcharpyyaml>=6.0packaging>=23.0pathspecjson5
  • 入口点 specify = "specify_cli:main",即安装后可直接执行 specify 命令;
  • 构建系统为 hatchling

DEVELOPMENT.md 概括了与本地开发直接相关的目录职责,快速定位改动落点:

目录 角色
templates/ 定义核心工作流行为与生成产物的提示词资产与模板
scripts/ 工作流、setup 与仓库工具使用的支持脚本(Bash/PowerShell/Python 三套变体)
src/specify_cli/ specify CLI 的 Python 源码,含各 agent 集成资产
extensions/ 扩展相关的文档、目录(catalog)与支撑资产
presets/ 预设相关的文档、目录与支撑资产

另外注意一个重要背景:所有脚本都以 Bash(.sh)、PowerShell(.ps1)、Python(.py)三种变体提供;交互式 specify init 会提示你选择其中一种,非交互运行(无 TTY 或加 --non-interactive)会按操作系统默认选择对应的 shell 变体,也可以显式传 --script sh|ps|py 指定。

第一步:克隆仓库并切换分支

# 从 gitcode 镜像克隆仓库(GitHub 源地址见官方 README)
git clone https://gitcode.com/GitHub_Trending/sp/spec-kit.git
cd spec-kit
# 在功能分支上工作
git checkout -b your-feature-branch

第二步:直接运行 CLI(反馈最快)

无需安装任何依赖,直接用模块入口运行:

# 仓库根目录下
python -m src.specify_cli --help
python -m src.specify_cli init demo-project --integration claude --ignore-agent-tools --script sh

如果你更习惯脚本文件式调用(走 shebang):

python src/specify_cli/__init__.py init demo-project --script ps

从源码结构看,这两种写法能成立有两个原因:

  1. src/specify_cli/init.py 顶部带有 PEP 723 内联脚本头(requires-python = ">=3.11"typerrich 等依赖声明),这既支持 uv run/uvx 之类的工具按头部声明自动解析依赖,也让文件可直接用解释器执行;
  2. 文件末尾有 if __name__ == "__main__": main() 守卫,main() 负责启动 Typer 应用,并且在 Windows 上会把 stdout/stderr 重配置为 UTF-8 编码(带 errors="replace" 降级),避免 Rich banner 的制表符在默认代码页下触发 UnicodeEncodeError

由于 src/ 目录本身没有 __init__.pypython -m src.specify_cli 依赖 PEP 420 命名空间包机制在仓库根目录解析模块——这也是为什么命令必须“从仓库根目录”执行的原因。

第三步:可编辑安装(隔离环境)

uv 创建隔离虚拟环境,使依赖解析方式与最终用户拿到的一致:

# 创建并激活虚拟环境(uv 自动管理 .venv)
uv venv
source .venv/bin/activate  # Windows PowerShell 则用:.venv\Scripts\Activate.ps1

# 以可编辑模式安装项目
uv pip install -e .

# 此时 'specify' 入口点可用
specify --help

得益于 editable 模式,代码修改后直接重跑 specify 即可,无需重新安装。对应到 pyproject.toml[project.scripts] 的声明,specify 命令最终指向 specify_cli:main

第四步:用 uvx 从本地路径或 Git 分支直接运行

uvx 支持从本地路径(或 Git ref)运行,适合模拟真实用户流程:

uvx --from . specify init demo-uvx --integration copilot --ignore-agent-tools --script sh

也可以把 uvx 指向某个具体分支而无需合并:

# 先推送工作分支
git push origin your-feature-branch
uvx --from git+https://gitcode.com/GitHub_Trending/sp/spec-kit.git@your-feature-branch specify init demo-branch-test --script ps

绝对路径 uvx(随处运行)

如果你身处其他目录,把 . 换成绝对路径即可:

uvx --from /mnt/c/GitHub/spec-kit specify --help
uvx --from /mnt/c/GitHub/spec-kit specify init demo-anywhere --integration copilot --ignore-agent-tools --script sh

用环境变量提升便捷性:

export SPEC_KIT_SRC=/mnt/c/GitHub/spec-kit
uvx --from "$SPEC_KIT_SRC" specify init demo-env --integration copilot --ignore-agent-tools --script ps

(可选)定义一个 shell 函数:

specify-dev() { uvx --from /mnt/c/GitHub/spec-kit specify "$@"; }
# 然后
specify-dev --help

--script 参数在 src/specify_cli/commands/init.py 中定义为可选字符串(shpspy 三选一),交互模式下会回退为带方向键选择的提示;最终选定的脚本类型会写入项目的 .specify/init-options.json,供后续集成切换、事件分发等复用(见 events.py 中的 _script_variant 读取逻辑)。

第五步:验证脚本权限逻辑

在 POSIX 系统上执行一次 init 后,检查生成的 shell 脚本是否具有可执行位:

ls -l scripts | grep .sh
# 期望看到属主可执行位(如 -rwxr-xr-x)

Windows 上则直接使用 .ps1 脚本(无需 chmod)。

这一行为的源码实现是 src/specify_cli/init.py 中的 ensure_executable_scripts():它在非 Windows 平台(os.name != "nt")递归扫描 .specify/scripts.specify/extensions 下所有 *.sh 文件,跳过符号链接,仅对以 #! shebang 开头的文件,按原有读位镜像追加对应的执行位(owner/group/other),并汇总更新与失败数量输出到步骤追踪器。理解这段实现可以解释“为什么有时需要重跑 init 或手动 chmod +x”——只有文件缺少可执行位且具备 shebang 时才会被修正。

第六步:脚手架化一个内置集成

使用 specify integration scaffold 为新内置集成生成初始 Python 包与测试骨架:

specify integration scaffold my-agent --type markdown
specify integration scaffold my-agent --type toml
specify integration scaffold my-agent --type yaml
specify integration scaffold my-agent --type skills

带连字符的 key 会被转换为 Python 安全的包名,例如 my-agent 会生成 src/specify_cli/integrations/my_agent/tests/integrations/test_integration_my_agent.py

脚手架不会自动注册集成。从源码看(integration_scaffold.py),scaffold_integration() 的行为有几个硬性约束:

  • 必须在 Spec Kit 仓库根目录执行(会校验 pyproject.toml 存在),否则抛 ValueError
  • 四种类型(markdown/toml/yaml/skills)各对应一套模板,分别决定配置元数据的序列化格式;
  • 目标文件已存在时会直接报 FileExistsError 拒绝覆盖,写文件中途失败还会做补偿性回滚(删除已写入的文件与新建的目录)。

生成后按 next steps 操作:审查元数据(install_urlrequires_climulti_install_safe 等字段),然后在 src/specify_cli/integrations/init.py 中添加对应的 from .<package> import ... 导入与 _register() 调用——该文件集中列出了仓库现有全部内置集成(claude、copilot、gemini、codex 等 40 余个)的导入与注册,是新增集成唯一需要手动编辑的注册点。最后运行:

pytest tests/integrations/test_integration_my_agent.py -v

第七步:Lint 与基本检查

CI 在 .github/workflows/test.yml 中强制 ruff check(CI 固定版本为 uvx ruff@0.15.0 check src tests),所以推送前本地先跑:

uvx ruff check src tests

pyproject.toml[tool.ruff.lint] 段还额外启用了 S602(subprocess shell=True)、S604S605 三条安全规则,意图是把 subprocess 安全姿态“锁死”:任何重新引入 shell=True 的改动都必须显式加 # noqa 注释在 review 中暴露。

快速 sanity check 导入可用性:

python -c "import specify_cli; print('Import OK')"

第八步:本地构建 Wheel(可选)

发布前验证打包是否完好:

uv build
ls dist/

必要时把构建产物安装到一个全新的一次性环境里验证。从 pyproject.toml[tool.hatch.build.targets.wheel.force-include] 可以看出 wheel 的内容构成:除 specify_cli 包本身外,还把 templates/scripts/ 三套脚本变体、内置扩展(gitagent-contextassessbug)、workflows/speckitpresets/leanpresets/constitution-sync 以及社区 bundle 目录快照全部打包进 specify_cli/core_pack/——注释说明目的是让 specify init 在无网络(air-gapped/企业)环境下也能工作。因此本地 uv build 后验证的核心就是这些资产是否完整进入 wheel。

第九步:使用临时工作区

在“脏目录”中测试 init --here 时,建议先建一个干净工作区:

mkdir /tmp/spec-test && cd /tmp/spec-test
python -m src.specify_cli init --here --integration claude --ignore-agent-tools --script sh  # 前提是仓库已复制到此

或者只复制改动过的 CLI 部分做更轻量的沙箱测试。

第十步:排查网络/TLS 问题

已废弃: --skip-tls 参数是 no-op,没有任何效果。它此前用于在本地测试时跳过 TLS 校验。如果你遇到 TLS 错误(例如在企业网络中),应改为配置环境的证书库或代理,例如设置 SSL_CERT_FILE 或配置 HTTPS_PROXY / HTTP_PROXY

源码中该参数确实保留为隐藏选项:src/specify_cli/commands/init.py--skip-tls 被声明为 hidden=True、默认 False,帮助文本明确标注 "Deprecated (no-op)"。这意味着老脚本里残留的这个 flag 不会报错但也不会起作用,遇到 TLS 问题只能走证书/代理的正路。

快速编辑循环总结

操作 命令
直接运行 CLI python -m src.specify_cli --help
可编辑安装 uv pip install -e . 然后 specify ...
本地 uvx(仓库根目录) uvx --from . specify ...
本地 uvx(绝对路径) uvx --from /mnt/c/GitHub/spec-kit specify ...
Git 分支 uvx uvx --from git+URL@branch specify ...
构建 wheel uv build

清理

快速删除构建产物与虚拟环境:

rm -rf .venv dist build *.egg-info

常见问题速查

症状 处理
ModuleNotFoundError: typer 运行 uv pip install -e .
脚本不可执行(Linux) 重跑 init 或 chmod +x scripts/*.sh
Git 命令不可用 specify extension add git 安装 git 扩展
下载了错误的脚本类型 显式传 --script sh--script ps--script py
企业网络 TLS 错误 配置环境的证书库或代理;--skip-tls 已废弃且无效

下一步

  • 更新文档,并用你修改过的 CLI 走一遍 Quick Start 流程;
  • 满意后提交 PR;
  • (可选)改动合入 main 后打发布 tag。

更多开发背景可参阅 DEVELOPMENT.mdCONTRIBUTING.md,后者定义了测试与开发实践要求,是本地闭环之后的 PR 门槛。

登录后查看全文
热门项目推荐
相关项目推荐