Cline CLI 发布实战指南:publish-cli 技能、cli-vX.Y.Z 标签与 GitHub Actions 双通道 npm 发布
Cline 的 CLI(npm 包名 cline)以"编译好的跨平台二进制 + npm 分发"的方式交付,其发布流程由仓库内 .cline/skills/publish-cli/SKILL.md 这份技能文档完整定义:先判断 SDK 是否需要先行发版,再走"收集提交 → 起草发布说明 → 定版本号 → 更新版本与 CHANGELOG → 验证 → 打标签 → 选择发布通道"的标准流程。读完本文,你可以独立执行一次 Cline CLI 版本发布:理解 cli-vX.Y.Z git 标签与 npm dist-tag 的区别、掌握 cli-publish.yml 工作流的触发参数与校验逻辑、并会用 bun release cli 从本机完成可信发布。
1. 发布契约:版本来源、标签与发布通道
SKILL 文档在 "Release contract" 一节中定义了本次发布的硬约束,所有后续操作都围绕它展开:
| 契约项 | 约定 |
|---|---|
| 版本来源 | apps/cli/package.json(当前仓库中为 3.0.61) |
| 主发布 git 标签 | cli-vX.Y.Z,其中 X.Y.Z 必须与 apps/cli/package.json 中的 version 完全一致 |
| 夜间版本 | X.Y.Z-nightly.TIMESTAMP(时间戳由工作流运行时生成) |
| 发布准备 | 包含三部分:已审批的发布说明、版本号 bump、apps/cli/CHANGELOG.md 更新 |
| 发布通道 | GitHub 工作流 .github/workflows/cli-publish.yml;本机发布助手 bun release cli |
| 依赖前提 | CLI 通过 workspace:* 依赖 SDK(@cline/core、@cline/shared 等),SDK 若有未发布变更,必须先发 SDK |
有三点约定容易被忽略,值得单独强调:
- npm dist-tag 与 git 标签是两套体系。
--tag latest/--tag nightly是 npm 注册表的发布通道(决定npm i -g cline或npm i -g cline@nightly装到哪个版本);而cli-vX.Y.Z是 git 标签,用于源码历史与 GitHub Release 锚点。二者同名但职责不同。 - GitHub 主发布从
main触发,但发布的是标签指向的提交。工作流要求cli-vX.Y.Z标签已存在,会 checkout 该标签并从此提交发布(详见第 4.2 节的校验代码)。 - 本地发布要求干净工作区,且标签必须同时指向本地与远端的
HEAD。这一约束在 sdk/scripts/release.ts 的ensureCliReleaseTag中有完整实现(见 第 4.4 节)。
另外,Cline CLI 是 npm-only 分发,不增加其他分发通道。Windows 二进制会在发布工作流中通过 Azure Trusted Signing 自动完成 Authenticode 签名(复合 action .github/actions/sign-windows-cli;若签名 secrets 未配置,工作流会告警并以未签名二进制发布)。因此 SKILL 文档建议:面向 Windows 用户的正式版本优先走 GitHub Actions 发布路径,本地 bun release cli 不做签名。完整的分发机制(7 个 npm 包、optionalDependencies 平台过滤、postinstall 硬链接缓存等)在 apps/cli/DISTRIBUTION.md 中有详细说明,本文只在第 5 节简要回顾。
所有命令均从仓库根目录执行,路径均相对根目录书写。
2. Step 0:SDK 有变更时先发 SDK
SKILL 文档要求在任何 CLI 发布操作之前先执行这一步,原因是 CLI 以 monorepo 内的 SDK 源码构建(workspace:* 依赖),无论 SDK 是否发布过,CLI 都会携带最新 SDK 代码。但在 SDK 代码有变更而未 bump 版本时,有两个实际问题:
- Hub 新鲜度问题(核心动机)。Hub 守护进程位于
@cline/core,其buildId默认取自@cline/core包版本(见 sdk/packages/core/src/hub/discovery/index.ts 中的resolveHubBuildId)。正在运行的 hub 只在该buildId变化时才会被检测为不兼容并重建(isCompatibleHubRecord/retireIncompatibleHub,见 sdk/packages/core/src/hub/daemon/index.ts)。也就是说:如果 SDK 代码变了但版本没变,升级 CLI 的用户会继续与"仍运行旧 SDK 代码"的 hub 进程通信。bump SDK 版本后,新 CLI 的buildId发生变化,旧 hub 会被判定为不兼容并用新代码重建。 - 发布卫生。保持"每次发 CLI 都顺手发一次 SDK"的节奏,让已发布的 SDK 与 CLI 实际携带的代码保持同步。
注意:CLI 对 SDK 的依赖始终保持 workspace:*——在 apps/cli/package.json 中可以看到 @cline/cline-hub 位于 dependencies(第 79 行),@cline/core 与 @cline/shared 位于 devDependencies(第 100–101 行),三者均为 workspace:*。修正是"发布 SDK",而不是"给 CLI 钉死 SDK 版本"。
2.1 检查是否有未发布的 SDK 变更
git fetch origin --tags
git tag --list 'sdk/sdk/v*' 'sdk-v*' --sort=-v:refname | head -1
git log <last-sdk-tag>..origin/main --oneline --no-merges -- sdk/packages
sdk/<pkg>/v* 标签由 sdk-publish.yml 工作流创建;sdk-v* 标签由本地 bun release sdk 助手创建。取较新者作为基线。若 git log 无输出,说明 SDK 已最新,跳过 Step 0 其余部分;有输出则人工核对 diff(可忽略仅包含上次 bump 提交的 lockfile 或生成文件的条目)。
2.2 决定 SDK 版本号
所有 SDK 包共享一个版本号,从 sdk/packages/llms/package.json 读取。patch / minor / major / 显式版本,patch 为默认;用户未明确时不要猜测。
2.3 起草 SDK 发布说明并更新 CHANGELOG
将第 2.1 步收集到的 SDK 提交转写为用户视角的发布说明,在 sdk/CHANGELOG.md 顶部插入新的 ## <version> 小节(不带日期,与 apps/cli/CHANGELOG.md 相同的"扁平、最新在上"格式)。该 SDK changelog 由人工维护,sdk-publish.yml 工作流不会读取它。
2.4 版本号 bump 与再生成:bun run version <version>
根 package.json 中该脚本的定义是:
"version": "bun run types && bun sdk/scripts/version.ts",
即先对全仓库并行跑 typecheck,再执行 sdk/scripts/version.ts。后者会:把 sdk/packages/ 下所有非 internal 包的 version 写入新版本号;删除旧的 bun.lock 并用 bun install --lockfile-only 重新生成;运行 bun -F @cline/llms generate:models 重新生成模型目录;执行 bun format --write 与 bun run build(见 sdk/scripts/version.ts)。执行后需人工 review 结果。
2.5 提交、推送并触发 SDK 发布工作流
sdk-publish.yml 发布的是提交到 main 上的版本并为其打标签,所以 bump 必须先落到 main:
git add -A
git commit -m "chore(sdk): release v<version>"
# 推送前需征询用户
git push origin HEAD
然后以 latest 通道触发工作流:
gh workflow run sdk-publish.yml -f channel=latest -f confirm_publish=publish
gh run list --workflow=sdk-publish.yml --limit=1 --json databaseId,url,status,createdAt --jq '.[0]'
该工作流会运行 SDK 测试,按依赖顺序将 @cline/shared、@cline/llms、@cline/agents、@cline/core、@cline/sdk 以 latest dist-tag 发布到 npm,并推送 sdk/<pkg>/v<version> git 标签。
2.6 等待 SDK 工作流成功,再开始 CLI 发布
gh run watch <run-id> --exit-status
SDK run 未成功前不要开始 CLI 发布。CLI 虽然不从 npm 安装 SDK,但让 CLI 发布提交恰好落在 @cline/core 版本 bump 之上,能同时满足两件事:发布的 CLI 携带新版本号从而强制运行中的 hub 重建;且不会在一个半途失败的 SDK 发布之上构建 CLI 发布。SDK 发布成功后:
git checkout main && git pull --ff-only
之后再进入下面第 3 节的 Workflow。若只想从已认证本机直接发 SDK,bun release sdk <version> 也可用,但常规发布仍建议走 sdk-publish.yml,这样 CLI 发布可以"门控"在单个 GitHub Actions run 上。
3. CLI 发布主流程(Workflow)
完成 Step 0 后再开始本节。SKILL 文档的 Workflow 共 9 步:收集上下文 → 收集发布提交 → 起草说明 → 定版本 → 更新发布文件 → 验证 → 提交 → 选择发布通道 → 汇报。
3.1 收集上下文,确定基线
git status --short --branch
git fetch origin --tags
git tag --list 'cli-v*' --sort=-v:refname | head -10
node -p "require('./apps/cli/package.json').version"
找到最新的 cli-v* 标签;若尚无任何 cli-v* 标签,则以首个相关 CLI 发布提交作为基线,并明确告知用户基线是推断得到的。
3.2 收集发布提交
git log <last-cli-tag>..HEAD --oneline --no-merges -- apps/cli sdk/packages sdk/scripts .github/workflows/cli-publish.yml
注意 sdk/packages 的提交即使已在 Step 0 单独发过 SDK,也必须纳入本次 CLI 发布说明:CLI 打包携带了 SDK,SDK 变更也会随这个 CLI 版本一起交付。逐条阅读这些提交,把对用户可见的部分(provider/模型更新、行为变化、CLI 继承的修复)并入发布说明;纯内部、对 CLI 无可见影响的 SDK 变更可以跳过。
3.3 起草面向用户的发布说明
只写用户可见的内容:功能、修复、行为变化、兼容性变化、值得注意的安装/发布变化;排除纯重构、测试、样式、杂务与内部文件移动(除非对用户有实际影响)。格式要求:
- 扁平的 bullet 列表;
- 把提交信息翻译成用户语言;
- 提交信息不清晰时,先读完整提交再总结;
- 把草稿呈现给用户,等待批准后才允许改文件。
3.4 决定版本 bump
询问用户:patch / minor / major / 显式版本。用户未明确时不要猜测。
3.5 更新发布文件
- 将 apps/cli/package.json 的
version更新为批准后的版本; - 在 apps/cli/CHANGELOG.md 顶部插入批准版本的小节,使用已批准的发布说明,标题格式为
## X.Y.Z(不带日期)。
为什么"不带日期、## X.Y.Z"是硬格式?因为发布工作流用 awk 精确匹配 changelog 的第一个数字开头的 ## 标题来提取顶部小节,并逐字粘贴进 GitHub Release 正文与 Slack 公告。对应实现在 cli-publish.yml:
CONTENT=$(awk '/^## [0-9]/{if(found) exit; found=1; next} found{print}' apps/cli/CHANGELOG.md)
所以 changelog 顶部小节的内容就是最终"发货"的发布说明,格式不合规会导致提取为空。
3.6 提交前验证:三档检查
按可信度从低到高三档,SKILL 文档要求按需选择:
| 档位 | 命令 | 适用场景 |
|---|---|---|
| 聚焦检查 | bun -F @cline/cli typecheck 与 bun -F @cline/cli test:unit |
快速提交前验证 |
| 更高可信度 | bun run types 与 bun --cwd apps/cli run build:platforms:single |
常规发布前 |
| 完整发布可信度 | bun run test 与 bun --cwd apps/cli run build:platforms |
打标签前用户要求全量确认时 |
(对照 package.json:根 test 会并行跑 sdk/packages/**、@cline/cli、@cline/cline-hub、@cline/vscode 的测试;types 是 -F '*' 全仓库 typecheck。)
已知的本地环境专属测试失败:src/commands/distribution-package.test.ts > rejects direct source package packing by default(对应测试文件 apps/cli/src/commands/distribution-package.test.ts)在 ~/.npmrc 中设置了 ignore-scripts=true(npm 供应链加固指南会设置它)的机器上会失败。机制是:Bun 会读取 npm 的 ignore-scripts 配置,导致 bun pm pack --dry-run 跳过"源码发布"的 prepack 守卫并以 0 退出,测试便将其判为失败。CI 不设 ignore-scripts,所以测试在 CI 通过。
这个 prepack 守卫就是 apps/cli/script/guard-direct-publish.ts,它在 prepack / prepublishOnly 两个钩子中执行(见 apps/cli/package.json),默认直接拒绝从 apps/cli 打源码包,仅当环境变量 CLINE_ALLOW_DIRECT_PUBLISH=1 时才放行(见 guard-direct-publish.ts)。可以本地验证:直接运行 bun pm pack --dry-run——~/.npmrc 存在时退出码 0 且无守卫输出;把 ~/.npmrc 移开后再跑,退出码 1 并打印守卫信息。这本身不是发布阻断项,但意味着在同一台机器上本地发布路径 bun release cli 也会绕过该守卫;SKILL 文档给出的对策是:在全局设置了 ignore-scripts=true 的机器上优先走 GitHub Actions 发布路径,或临时取消该配置(npm config delete ignore-scripts 或 mv ~/.npmrc ~/.npmrc.bak)仅在本次本地发布期间生效。
3.7 提交发布变更
仅在用户批准说明与版本之后:
git add apps/cli/package.json apps/cli/CHANGELOG.md
git commit -m "chore(cli): release vX.Y.Z"
# 推送前征询用户
git push origin HEAD
走 GitHub 主发布路径时,创建并推送发布标签前也要征询:
git tag -a cli-vX.Y.Z -m "CLI vX.Y.Z"
git push origin refs/tags/cli-vX.Y.Z
SKILL 文档还强调两条行为准则:任何提交/标签推送之前必须先问;除非用户明确要求,不要 amend 提交。
4. 四条发布出口
SKILL 文档要求让用户在以下路径中做出选择(也可"只到版本提交就停下"):
4.1 GitHub 主发布(推荐常规路径)
前提:发布提交已在 main 上、对应 cli-vX.Y.Z 标签已推送。
gh workflow run cli-publish.yml -f publish_target=main -f git_tag=cli-vX.Y.Z -f confirm_publish=publish
gh run list --workflow=cli-publish.yml --limit=1 --json url,status,conclusion,createdAt --jq '.[0]'
从 cli-publish.yml 的源码可以看到这条路径的完整门控与执行细节:
- 触发条件(L44-L50):仓库为
cline/cline、ref 为refs/heads/main、事件为workflow_dispatch、publish_target=main、confirm_publish必须精确等于字符串publish、且触发者不是 bot。confirm_publish这一"打字确认"参数是第一道防误触。 - 标签五重校验(L89-L131):
git_tag必填且须匹配^cli-v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$;去掉cli-v前缀后的版本必须与apps/cli/package.json的version相等且本身是合法 semver;标签指向的 commit 必须等于 checkout 出的 HEAD;且该 commit 必须可从origin/main可达。任何一条不满足都直接失败。 - 工具链校验:npm 必须 ≥ 11.5.1,因为 npm 可信发布(trusted publishing,OIDC 换取 npm 令牌)依赖该版本能力;工作流以
NPM_CONFIG_PROVENANCE=true发布,因此 npm 侧必须已为cline及全部平台包配置可信发布者。 - 构建与测试:
bun run build:sdk→bun run test→ 在apps/cli下运行bun script/build.ts --install-native-variants --skip-sdk-build交叉编译全部 6 个平台二进制,并逐一校验dist/下各平台包的package.json名称与版本。 - Windows 签名:调用复合 action
.github/actions/sign-windows-cli,对cli-windows-x64/bin/cline.exe与cli-windows-arm64/bin/cline.exe做 Authenticode 签名;全部AZURE_*secrets 缺失时仅告警、以未签名发布,部分缺失则硬失败(机制详见 apps/cli/DISTRIBUTION.md 的 "Windows code signing" 一节)。 - 发布与公告:
bun script/publish-npm.ts --tag latest发布 6 个平台包 + 生成的cline包装包(编排逻辑见 apps/cli/script/publish-npm.ts);随后用 awk 提取 changelog 顶部小节创建 GitHub Release(附带与上一标签的 compare 链接),并向 Slack 频道发送公告。这里有个值得注意的实现细节:Slack section block 拒绝超过 3000 字符的文本,且被拒时 action 只记日志不失败——历史上就发生过公告静默丢失而流水线保持绿色的事故。因此工作流会另生成一份 3000 字符预算内的截断副本发 Slack 并附完整说明链接,而 GitHub Release 正文保持完整(L231-L255)。
4.2 GitHub 夜间发布
# 手动触发
gh workflow run cli-publish.yml -f publish_target=nightly
# 强制夜间发布(即使 24 小时内无提交)
gh workflow run cli-publish.yml -f publish_target=nightly -f force_nightly_publish=true
nightly 任务(publish-nightly job)由 cron: "0 12 * * *" 每日定时触发,也可手动 dispatch。它的行为特征:
- 无新提交则跳过:
git rev-list --count HEAD --since='24 hours ago'为 0 时直接跳过(除非force_nightly_publish=true),避免空发布; - 版本号临时改写:读取
apps/cli/package.json的基础版本,拼出X.Y.Z-nightly.<unix-timestamp>(L389-L400),再把它写回 checkout 出的package.json(该改动只存在于 CI 工作区,不产生提交); - 不创建 git 标签,直接以
--tag nightly发布到 npm——这正是"npm dist-tag 与 git 标签是两回事"的活例。
4.3 本地发布(bun release cli)
适用于希望从本机发布的场景,要求本机已认证 npm 与 GitHub:
gh auth status
npm whoami
git tag -a cli-vX.Y.Z -m "CLI vX.Y.Z"
git push origin refs/tags/cli-vX.Y.Z
bun release cli
bun release cli 背后是 sdk/scripts/release.ts(根 package.json 中 "release": "bun sdk/scripts/release.ts")。从源码看它做三层防护,比口头约定更严格:
- 版本解析(
resolveCliVersion,L203-L226):只信apps/cli/package.json的version,且必须匹配 semver;若命令行带了显式版本且与package.json不一致,直接报错——版本以文件为准。 - 前置检查:
ensureCleanWorkingTree要求工作区干净;ensureCliReleaseTag(L269-L357)要求cli-vX.Y.Z存在且指向本地HEAD,再经git ls-remote核对远端标签(含 peeled 标签对象)也指向同一 commit——这实现了契约中"标签须在本地与origin都指向HEAD"的要求。 - 三步发布(
releaseCLI,L480-L530):bun run test→ 在apps/cli下bun script/build.ts --install-native-variants交叉编译全部平台 →bun script/publish-npm.ts --tag <dist-tag>发布。--tag默认latest,--dry-run、--skip-tests、--skip-git-tags均可用;交互式确认(y/N)默认必须通过。
本地发布成功后,SKILL 文档建议先征询再创建 GitHub Release:
gh release create cli-vX.Y.Z --verify-tag --title "CLI vX.Y.Z" --notes "Paste the approved release notes here."
--verify-tag 会校验标签指向的 commit 与当前 checkout 一致。如需发布到其他 npm dist-tag:
bun release cli --tag next
4.4 最终汇报
发布完成后,SKILL 文档要求向用户报告:版本号、标签、更新的 changelog 文件、commit hash、是否有推送发生、所选发布通道、工作流 URL 或本地发布结果、以及运行过的测试与构建。
5. 附:一次 CLI 发布实际交付什么
结合 apps/cli/DISTRIBUTION.md 与 apps/cli/script/build.ts 的构建逻辑,理解发布产物有助于验收发布结果。每次发布会把 7 个包推上 npm:6 个平台包(@cline/cli-darwin-arm64 / darwin-x64 / linux-arm64 / linux-x64 / windows-x64 / windows-arm64,各含一个 bun build --compile 产物和带 os/cpu 字段的 package.json,npm 据此只安装匹配平台)加上 1 个 cline 包装包(无二进制,仅 resolver 脚本、postinstall 脚本与指向全部平台包的 optionalDependencies)。构建脚本在 --install-native-variants 下先用 bun install --os="*" --cpu="*" 预装全部 @opentui/core 平台变体以支持交叉编译(OpenTUI 通过 bun:ffi 调用原生 Zig 渲染库,这是 CLI 必须以编译二进制而非 JS bundle 分发的根本原因);发布脚本则保证"平台包先于包装包发布",因为 npm 会校验 optionalDependencies 的存在。所有 7 个包必须同版本,版本均取自 apps/cli/package.json——这也解释了为什么 SKILL 契约把"版本来源"唯一锁定在该文件上。
6. 小结
- 发布契约:版本唯一来源是
apps/cli/package.json;cli-vX.Y.Z标签必须与其一致;npm dist-tag(latest/nightly/next…)与 git 标签互不替代。 - 顺序不可颠倒:SDK 有变更就先按 Step 0 发 SDK 并等
sdk-publish.yml成功,CLI 发布提交落在 SDK bump 之上,workspace:*保持不动。 - changelog 顶部
## X.Y.Z(无日期)小节就是将被逐字粘贴进 GitHub Release 与 Slack 的正文,格式必须与工作流的 awk 提取逻辑兼容。 - 常规发布走
gh workflow run cli-publish.yml -f publish_target=main -f git_tag=cli-vX.Y.Z -f confirm_publish=publish(可信发布 + Windows 签名 + Release + Slack 一条龙);从本机发布则依赖bun release cli的三重校验(版本一致、工作区干净、标签本地远端均指向 HEAD)。 - 全程守则:推送前必问、不擅自 amend、验证按三档选做、
ignore-scripts=true机器慎用本地发布路径。
关键文件索引:技能文档 .cline/skills/publish-cli/SKILL.md、发布工作流 .github/workflows/cli-publish.yml、SDK 发布工作流 .github/workflows/sdk-publish.yml、发布助手 sdk/scripts/release.ts、版本脚本 sdk/scripts/version.ts、分发说明 apps/cli/DISTRIBUTION.md、构建与发布脚本 apps/cli/script/build.ts / apps/cli/script/publish-npm.ts / apps/cli/script/guard-direct-publish.ts、CHANGELOG apps/cli/CHANGELOG.md 与 sdk/CHANGELOG.md。
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 StartedRust0622
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