生成模型:Claude Opus 4.6 (anthropic/claude-opus-4-6) Token 消耗:输入 ~140,000 tokens,输出 ~10,000 tokens(本章合计)
高效的开发循环是贡献开源项目的基础。OpenClaw 提供了多种工具来加速"修改 → 验证"的反馈循环。
2.4.1 pnpm gateway:watch — 文件监听与热重载
对于 Gateway 开发,最常用的命令是:
这个命令的实现在 scripts/watch-node.mjs 中,它做了两件事:
// scripts/watch-node.mjs(简化)
// 1. 先执行一次完整构建
const initialBuild = spawnSync("pnpm", ["exec", "tsdown"], { stdio: "inherit" });
// 2. 同时启动两个进程:
// (a) tsdown --watch:监听 TypeScript 源码变更,增量重新编译
const compilerProcess = spawn("pnpm", ["exec", "tsdown", "--watch"], { stdio: "inherit" });
// (b) node --watch:监听 dist/ 中的 JS 变更,自动重启 Gateway
const nodeProcess = spawn(
process.execPath,
["--watch", "openclaw.mjs", ...args],
{ stdio: "inherit" }
);
工作流程如下:
注意 --watch 是 Node.js 22 内置的文件监听重启功能,不需要额外的 nodemon 等工具。
还有一个跳过通道连接的开发模式,适合只开发 Gateway 核心逻辑时使用:
这两个命令设置了环境变量 OPENCLAW_SKIP_CHANNELS=1,让 Gateway 启动时不连接任何通道(WhatsApp、Telegram 等),大幅缩短启动时间。
scripts/run-node.mjs 实现了一个智能增量构建机制:
它通过比较 .buildstamp 文件与 src/ 目录下最新文件的修改时间来判断是否需要重新构建。这样在运行 pnpm openclaw gateway 时,如果你没有修改任何源文件,就会跳过构建直接启动——节省了几秒钟的启动时间。
OpenClaw 拥有一套完善的分层测试体系:
单元测试使用 vitest,配置在 vitest.config.ts 中。测试文件与源码放在同一目录下,以 .test.ts 后缀命名:
vitest 的关键配置:
进程隔离(pool: "forks"):每个测试文件在独立进程中运行。这对于 OpenClaw 很重要,因为 Gateway 测试可能涉及全局状态(端口绑定、文件锁等)。
排除 live 和 e2e 测试:这些需要真实 API Key 或完整环境,单独运行。
E2E 测试(*.e2e.test.ts)验证完整的用户流程——启动 Gateway、发送消息、验证回复。它们使用 vitest.e2e.config.ts 配置。
Live 测试(*.live.test.ts)需要真实的 API Key(如 Anthropic API Key、OpenAI API Key),测试与真实模型的交互。通过环境变量 OPENCLAW_LIVE_TEST=1 启用。
Docker 测试在容器中运行,验证打包、安装、网络等场景:
test:docker:gateway-network
test:docker:doctor-switch
OpenClaw 有一个自定义的并行测试运行器 scripts/test-parallel.mjs,被 pnpm test 调用。它将测试文件分成多个批次并行运行,充分利用多核 CPU。
Web UI 有自己的测试配置(ui/vitest.config.ts),使用 @vitest/browser-playwright 在真实浏览器中运行。
2.4.3 代码质量:oxlint 类型感知 Lint + oxfmt 格式化
OpenClaw 使用 oxlint(Rust 编写的 Linter)而非 ESLint。oxlint 的优势在于速度——对于 OpenClaw 数十万行的代码库,oxlint 的 lint 时间只有 ESLint 的几十分之一。
--type-aware 标志启用类型感知规则,这意味着 oxlint 会读取 TypeScript 的类型信息来进行更精确的检查(例如检测未使用的类型导入、类型不安全的比较等)。
oxfmt 处理代码格式化。配置在 .oxfmtrc.jsonc 中。
原生应用的 Swift 代码有独立的 Lint 和格式化工具:
配置文件 .swiftlint.yml 和 .swiftformat 分别定义了规则。
check:loc 通过 scripts/check-ts-max-loc.ts 确保没有单个 TypeScript 文件超过 500 行——这是一个代码组织的硬性约束。如果一个文件增长到接近 500 行,就应该考虑拆分。
OpenClaw 通过 git-hooks/ 目录配置了 Git 钩子,在 prepare 脚本中设置:
这确保了每次 commit 之前自动运行 lint 和格式化检查。
总结一下 OpenClaw 的开发工作流:
到这里,你已经具备了参与 OpenClaw 开发所需的全部环境知识。从下一章开始,我们将深入 Gateway 控制平面的源码实现。