spec-kit 本地开发实战指南:specify CLI 从直接运行到 Wheel 构建的完整迭代闭环
本文基于 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.0、click>=8.2.1、rich、platformdirs、readchar、pyyaml>=6.0、packaging>=23.0、pathspec、json5; - 入口点
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
从源码结构看,这两种写法能成立有两个原因:
- src/specify_cli/init.py 顶部带有 PEP 723 内联脚本头(
requires-python = ">=3.11"及typer、rich等依赖声明),这既支持uv run/uvx之类的工具按头部声明自动解析依赖,也让文件可直接用解释器执行; - 文件末尾有
if __name__ == "__main__": main()守卫,main() 负责启动 Typer 应用,并且在 Windows 上会把 stdout/stderr 重配置为 UTF-8 编码(带errors="replace"降级),避免 Rich banner 的制表符在默认代码页下触发UnicodeEncodeError。
由于 src/ 目录本身没有 __init__.py,python -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 中定义为可选字符串(sh、ps、py 三选一),交互模式下会回退为带方向键选择的提示;最终选定的脚本类型会写入项目的 .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_url、requires_cli、multi_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)、S604、S605 三条安全规则,意图是把 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/ 三套脚本变体、内置扩展(git、agent-context、assess、bug)、workflows/speckit、presets/lean 与 presets/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.md 与 CONTRIBUTING.md,后者定义了测试与开发实践要求,是本地闭环之后的 PR 门槛。
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