首页
/ Cline CLI 发布实战指南:publish-cli 技能、cli-vX.Y.Z 标签与 GitHub Actions 双通道 npm 发布

Cline CLI 发布实战指南:publish-cli 技能、cli-vX.Y.Z 标签与 GitHub Actions 双通道 npm 发布

2026-09-04 16:41:33作者:江焘钦

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

有三点约定容易被忽略,值得单独强调:

  1. npm dist-tag 与 git 标签是两套体系--tag latest / --tag nightly 是 npm 注册表的发布通道(决定 npm i -g clinenpm i -g cline@nightly 装到哪个版本);而 cli-vX.Y.Z 是 git 标签,用于源码历史与 GitHub Release 锚点。二者同名但职责不同。
  2. GitHub 主发布从 main 触发,但发布的是标签指向的提交。工作流要求 cli-vX.Y.Z 标签已存在,会 checkout 该标签并从此提交发布(详见第 4.2 节的校验代码)。
  3. 本地发布要求干净工作区,且标签必须同时指向本地与远端的 HEAD。这一约束在 sdk/scripts/release.tsensureCliReleaseTag 中有完整实现(见 第 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 版本时,有两个实际问题:

  1. 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 会被判定为不兼容并用新代码重建。
  2. 发布卫生。保持"每次发 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 --writebun 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/sdklatest 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 更新发布文件

  1. apps/cli/package.jsonversion 更新为批准后的版本;
  2. 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 typecheckbun -F @cline/cli test:unit 快速提交前验证
更高可信度 bun run typesbun --cwd apps/cli run build:platforms:single 常规发布前
完整发布可信度 bun run testbun --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-scriptsmv ~/.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_dispatchpublish_target=mainconfirm_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.jsonversion 相等且本身是合法 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:sdkbun 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.execli-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")。从源码看它做三层防护,比口头约定更严格:

  1. 版本解析resolveCliVersionL203-L226):只信 apps/cli/package.jsonversion,且必须匹配 semver;若命令行带了显式版本且与 package.json 不一致,直接报错——版本以文件为准。
  2. 前置检查ensureCleanWorkingTree 要求工作区干净;ensureCliReleaseTagL269-L357)要求 cli-vX.Y.Z 存在且指向本地 HEAD,再经 git ls-remote 核对远端标签(含 peeled 标签对象)也指向同一 commit——这实现了契约中"标签须在本地与 origin 都指向 HEAD"的要求。
  3. 三步发布releaseCLIL480-L530):bun run test → 在 apps/clibun 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.mdapps/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.jsoncli-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.mdsdk/CHANGELOG.md

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

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
docsdocs
暂无描述
Markdown
889
5.78 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384
flutter_flutterflutter_flutter
本仓库是 Flutter SDK 与 Flutter Engine 的 OpenHarmony 适配版本,由 CPF-Flutter 团队维护。开发者可使用熟悉的 Flutter 技术栈开发 OpenHarmony 应用,3.35.7 及以后的适配版本可基于本仓库源码构建支持 OpenHarmony 的 Flutter Engine。
Dart
1.17 K
341