首页
/ Cline SDK 开发工作流实战:从 bun 命令体系、调试构建到 SDK 与 CLI 发布全流程

Cline SDK 开发工作流实战:从 bun 命令体系、调试构建到 SDK 与 CLI 发布全流程

2026-09-06 15:40:34作者:俞予舒Fleming

本文基于 Cline 仓库的 sdk/CONTRIBUTING.md 展开,系统讲解 Cline SDK 工作区的包结构、bun 命令体系、调试构建、测试策略以及 SDK 与 CLI 的两套发布流程。读完本文,你可以独立完成从拉取代码、本地开发、跨包验证到打包发布 npm 包的完整闭环,并理解每个发布步骤背后的源码机制。

需要说明文档分工:sdk/CONTRIBUTING.md 覆盖入职、开发工作流与发布;包边界与变更路由见 sdk/AGENTS.md;架构与运行时流程见 sdk/ARCHITECTURE.md。该仓库被定位为「构建与编排 AI Agent 的 WIP 框架」,文档明确说明:当重构能改进架构且所有调用点都已更新时,大规模重构是被接受的。

工作区结构:四个发布包与宿主应用

发布的 SDK 包

CONTRIBUTING 文档用一张职责表划定了发布面,这也是理解整个仓库的关键入口:

负责内容
@cline/shared 契约、schema、路径辅助、hook 引擎、扩展注册表
@cline/llms Provider 配置、模型目录、manifest、handler 创建
@cline/agents 无状态 Agent 循环、工具编排、hook/扩展运行时
@cline/core 有状态编排、会话生命周期、存储、配置、遥测、hub 运行时服务、hub 发现、分离式守护进程,以及 hub 客户端适配器(@cline/core/hub@cline/core/hub/daemon-entry

sdk/AGENTS.md 的依赖方向看,层次是单向的:shared 保持底层可复用,llms 隔离 provider 行为,agents 保持无状态(不碰会话/存储/配置),core 拥有全部有状态编排与 hub 运行时,宿主应用(CLI / VS Code / Desktop App)依赖 core。做变更时应把改动路由到「拥有该关注点」的包:模型/provider schema 进 llms,无状态循环与流式进 agents,会话、存储、配置监听、遥测、hub 守护进程进 core,宿主专属 UX 进应用包。

宿主应用(Apps)

  • apps/cli:CLI 宿主与本地 hub 管理
  • apps/examples/desktop-app:Tauri + Next.js 桌面应用示例
  • apps/examples/vscode:VS Code 扩展示例
  • apps/examples/menubar:hub 通知菜单栏示例
  • examples:插件、hook 与 cron 自动化示例(对 Cline SDK 的定制)

开发工作流:bun 命令体系

必备命令

CONTRIBUTING 文档给出的核心命令表:

命令 用途
bun install 安装依赖
bun run build 构建 SDK 与 CLI
bun run build:sdk 只构建 SDK 包
bun run dev 开发模式构建
bun run cli 交互式运行 CLI
bun run test 运行 Vitest 测试套件
bun run types 全量类型检查
bun run lint / format / fix 代码质量与格式化

包级命令则通过 bun 的 workspace flag 定向执行:

bun -F @cline/core build|test|typecheck
bun -F @cline/agents build|test|typecheck

这些命令在根 package.json 中都有对应实现,且能看出一些文档未展开的细节:

  • 运行环境锁定为 engines: { "bun": "1.3.13", "node": ">=22" }packageManager 也是 bun@1.3.13
  • build 脚本实际是一条完整流水线:bun run clean && bun install && bun run build:sdk && bun -F @cline/cli build
  • build:sdk 以生产条件构建 SDK 工作区:bun --production -F './sdk/packages/*' build
  • typesbun --parallel -F '*' typecheck 并行检查所有包;
  • 代码质量由 Biome 承担:lintformatfix 三个脚本均作用于 sdk/apps/cli/apps/cline-hub/apps/examples/ 四个目录;
  • 仓库通过 husky + lint-staged 在提交前对 sdk/**apps/{cli,cline-hub,examples}/** 自动执行 bun run types 和 Biome 检查。

重新构建:一个容易踩的坑

文档特别强调了构建顺序问题:

  1. 修改了发布型 SDK 包后,必须跑 bun run build:sdk;直接运行 CLI 会立即拾取重建后的包。开发期自动重建可用 dev:* 脚本。
  2. CLI 构建从编译后的 dist/ 打包,而非 TypeScript 源码bun -F @cline/cli build 不会感知包源码的变更——如果你改了某个包却没有先重建它,CLI 二进制会静默打进旧代码。做端到端验证时,务必先 bun run build:sdk(或对应的 bun -F @cline/<pkg> build)再构建 CLI。
  3. 另一个相关陷阱在 sdk/AGENTS.md 中:SDK 包的 export 通过编译产物 dist/ 解析兄弟包,dist/ 缺失时包测试会报缺失导出。文档建议把它当作工作区设置问题处理——先 bun run build:sdk 再重跑同一测试命令,而不是当成源码 bug。SDK 命令应从 sdk/ 工作区根目录运行,避免绕过 workspace 设置导致 workspace:* 解析失败。
  4. 如果触碰了 hub bootstrap 流程,文档要求保留启动锁(startup lock)与 owner-scoped 发现行为,使多个构建可以安全共存。

调试构建:断点注入与确定性端口

CONTRIBUTING 文档对调试构建的说明非常完整,适合直接作为调试手册使用:

  • 设置 CLINE_BUILD_ENV=development 即可产出 debug 构建。被派生的 Node/Bun 子进程会获得 inspector 端点并附加 --enable-source-maps
  • 默认情况下子进程 inspector 端口是临时的(--inspect=127.0.0.1:0),以避免并行开发时端口冲突;
  • 需要确定性端口时,设置 CLINE_DEBUG_HOSTCLINE_DEBUG_PORT_BASE 启用基于角色的固定端口。以 CLINE_DEBUG_PORT_BASE=9230 为例,各角色映射为:hub 9230、hook worker 9231、plugin sandbox 9232、connector child 9233、fallback sandbox 9234
  • 环境判断的回落链是:CLINE_BUILD_ENVNODE_ENV → Bun --conditions=development
  • 调试 CLI 进程本身的完整命令:
cd apps/cli && CLINE_BUILD_ENV=development bun --conditions=development --inspect-brk=6499 ./src/index.ts "hey"
  • 工作区还自带 VS Code launch 配置(Launch CLI Debugger),其 "type": "bun" 依赖 oven.bun-vscode 扩展。

测试策略:跨包信心与 hub 流程的双保险

根级命令用于建立跨包信心:

bun run test        # 所有测试
bun run types       # 全量类型检查
bun run check       # lint + build + typecheck + check-publish

对照根 package.jsoncheck 的实际链条比文档描述更长:Biome check(error 级)→ build:sdk@cline/cli build@cline/cline-hub build:webview → 全工作区并行 typecheck → bun sdk/scripts/check-publish.ts。也就是说 check 已经把「发布前可打包性验证」纳入了日常检查。

文档还给出两条实践建议:

  • 若改动了 hub/bootstrap/session 流程,应同时准备单元测试覆盖和一次端到端 sanity check;
  • 聚焦验证时优先用工作区包脚本(如 bun -F @cline/core test:unit),若失败信息是缺失 @cline/* 导出或缺 dist/ 文件,先按 sdk/AGENTS.md 的指引重建依赖包再复测。

SDK 发布:bun release sdk 自动化流程

命令与参数

bun release sdk 脚本(入口为根 package.json 中的 release 脚本,实现位于 sdk/scripts/release.ts)自动化了版本化、lockfile 再生成、校验与发布:

bun release sdk              # 自动递增 patch 版本
bun release sdk 0.1.0        # 指定版本
bun release sdk --tag next   # 使用自定义 npm dist-tag
bun release sdk --dry-run    # 无副作用预览

附加 flag:--skip-tests--skip-git-tags

源码印证:五步流程与前置条件

阅读 sdk/scripts/release.ts 可以看到文档描述的流程在代码中的对应:

  1. 前置条件ensureMainBranch() 会检查当前分支,若不是 main,先要求工作树干净(git status --porcelain 非空即中止),然后 git checkout maingit pull --ff-only——这正是文档所说「脚本启动前会检出 main 并拉取最新,脏工作树直接中止」的实现。
  2. Step 1/5 测试:运行 bun run test,可被 --skip-tests 跳过。
  3. Step 2/5 版本更新:调用 sdk/scripts/version.ts 完成版本递增、lockfile 再生成、models 生成、格式化与构建。
  4. Step 3/5 打包校验:运行 sdk/scripts/check-publish.ts。该脚本会把每个「非 internal 标记」的包 bun pm pack 成 tarball、读取打包后的 manifest、检查 exports 中是否混入 development 条件,并在隔离目录做安装与模块解析测试。
  5. Step 4/5 按依赖顺序发布:代码中 SDK_PUBLISH_ORDER = ["shared", "llms", "agents", "core", "sdk"]——即文档所述 shared → llms → agents → core 的顺序,外加 @cline/sdk 包(发布前会把 sdk/README.md 暂存复制为其 README,发布后清理)。
  6. Step 5/5 Git tag:仅当 dist-tag 为 latest 且未指定 --skip-git-tags 时,创建 sdk-v{VERSION} 标签,并交互式询问是否推送到远端。

此外,未显式指定版本时,脚本会读取 sdk/packages/ 下第一个版本非 0.0.0 的包并自动递增 patch 位。

手动发布 SDK

需要精细控制每一步时,文档给出的手动流程为:

  1. bun run test
  2. bun version <version> —— 更新所有 workspace 包版本、重新生成 models、格式化并构建(对应根 package.jsonversion 脚本:bun run types && bun sdk/scripts/version.ts
  3. rm bun.lock && bun install --lockfile-only —— 重新生成 lockfile,使 bun pm packworkspace:* 解析为新版本
  4. bun scripts/check-publish.ts —— 打包 tarball、验证依赖对齐、隔离安装与模块解析测试
  5. npm login —— 确认 npm 注册表认证
  6. 按依赖顺序发布:
cd packages/shared && bun publish && cd ../llms && bun publish && cd ../agents && bun publish && cd ../core && bun publish && cd ../../
  1. 标签化正式发布时创建并推送 tag:git tag -a sdk-v{VERSION} -m "SDK v{VERSION}" && git push origin sdk-v{VERSION}

工作区依赖规则

  • 源码 manifest 使用 workspace:*,保证 bun install 与本地构建正确解析;
  • 发布时的运行时 workspace 包保留在 dependencies;被打包进产物内部的依赖放 devDependencies,避免泄漏进打包后的 manifest;
  • bun publish 在打包时会把 workspace:* 解析为具体版本号。

验证单个包

查看最终会被发布的 manifest:

cd ./packages/core
tmpdir=$(mktemp -d)
bun pm pack --destination "$tmpdir" >/dev/null
tar -xOf "$tmpdir"/*.tgz package/package.json | jq '.version, .dependencies'

在消费方项目中检查实际安装版本:

bun pm ls @cline/core @cline/agents @cline/llms

CI 发布

CI 发布工作流 .github/workflows/sdk-publish.yml 遵循相同顺序:build → version → check-publish → publish(shared → llms → agents → core)。从该工作流定义看,它支持 nightlylatest 两个 channel,由手动 dispatch 或每日 cron(UTC 02:00)触发;latest 通道要求显式输入确认字符串,且带有「近 24 小时无提交则跳过」的保护开关(force_publish 可强制)。

CLI 发布:先准备发布提交,再选发布路径

CLI 通过 npm 发布。文档建议从 apps/cli 出发、使用 publish-cli skill 启动发布——该 skill 文件位于仓库根的 .cline/skills/publish-cli/SKILL.md。skill 引导完成发布准备后,提供 GitHub Actions 发布路径与本地发布路径两个选项。据 apps/cli/DEVELOPMENT.md,CLI 以 npm 上的 cline 包装包 + @cline/cli-* 平台二进制包形式发布。

准备发布提交

无论走哪条路径,每次发布都从同一份发布提交开始:

  1. 基于自上一个 cli-vX.Y.Z tag 以来的提交,起草面向用户的 release notes;
  2. 选定发布版本;
  3. 更新 apps/cli/package.json
  4. 将批准的 notes 追加到 apps/cli/CHANGELOG.md
  5. 运行要求的检查;
  6. 提交版本与 changelog 变更。

路径 A:GitHub Actions 发布

常规发布走这条路:将发布提交合入 main,创建并推送对应 tag,然后触发工作流:

git tag -a cli-vX.Y.Z -m "CLI vX.Y.Z"
git push origin refs/tags/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

该工作流(.github/workflows/cli-publish.yml)会检出指定的 cli-vX.Y.Z tag、校验其与 apps/cli/package.json 一致、构建平台包、以 latest dist-tag 发布到 npm、创建 GitHub Release 并发送 Slack 通知。

路径 B:本地发布

在已认证的本地机器上发布时,从发布提交的干净检出开始:

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
gh release create cli-vX.Y.Z --verify-tag --title "CLI vX.Y.Z" --notes "Paste the approved release notes here."

本地助手在 sdk/scripts/release.ts 中的 releaseCLI 路径实现,源码可以确认其校验强度:ensureCleanWorkingTree() 要求工作树干净;ensureCliReleaseTag() 会通过 git tag --points-at HEADgit ls-remote 分别验证 cli-vX.Y.Z 在本地与 origin 上均指向 HEAD,tag 指向错误提交时会给出精确的错误提示。随后依次执行:Step 1 测试(bun run test)→ Step 2 交叉编译全部平台(bun script/build.ts --install-native-variants)→ Step 3 发布到 npm(bun script/publish-npm.ts --tag <tag>,dry-run 时透传 --dry-run)。

Nightly 发布

gh workflow run cli-publish.yml -f publish_target=nightly

Nightly 也会按调度自动运行:以 X.Y.Z-nightly.TIMESTAMP 版本和 nightly dist-tag 发布到 npm;除非强制触发,近 24 小时无提交则跳过。

根自动化边界:内部包不要混入发布

文档最后强调了一个架构约束(与 sdk/ARCHITECTURE.md 的「Publishability Constraint」相互印证):

  • 根级 SDK 的 build/test/version/publish 流程只针对可发布的 SDK 包;
  • 内部包仍然可以直接构建/测试,但不应被意外卷入发布自动化;
  • 新增内部包时,除非明确打算发布它,否则保持其处于根级 publish/version/build 扫描范围之外。

sdk/scripts/check-publish.tssdk/scripts/release.ts 的源码看,这一边界的实现机制是:两个脚本都通过遍历 sdk/packages/过滤掉 manifest 中标记为 internal 的目录来确定发布清单,因此新增内部包只要带 internal: true 标记即可自动排除在发布流程之外。

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