一切从一个 .mjs 文件开始
打开 OpenClaw 的项目根目录,你会看到一个叫 openclaw.mjs 的文件。它只有短短几行,内容大概是:加载 src/index.ts,设置好模块路径,然后把控制权交出去。
这个文件是整个 OpenClaw 的物理入口。当你在终端敲下 openclaw gateway start,操作系统找到的就是这个文件,随后 Node.js 开始执行。它通过 package.json 里的 bin 字段注册为系统命令,安装时 npm 会在全局 bin 目录里创建一个指向它的软链接。
但真正有趣的故事,从 src/index.ts 开始。
启动时做了什么:src/index.ts
src/index.ts 是程序的初始化层,它在把控制权移交给 CLI 之前,要先完成三件事。
第一件是环境准备。读取环境变量、确定配置文件路径、设置 Node.js 的运行模式。这一步看起来简单,但它决定了后续所有模块能不能正确找到自己依赖的文件路径。
第二件是全局错误处理。注册 process.on('uncaughtException') 和 process.on('unhandledRejection') 两个监听器。一个常驻运行的 AI 助手进程,必须对意外的异常有兜底处理,不能因为某个通道突然报了一个未预期的错误就整个崩掉。
第三件才是构建 CLI 程序。调用 src/cli/program.ts 里的构建函数,把所有命令注册好,然后调用 Commander.js 的 parse(process.argv) 开始解析用户输入。
整个初始化过程非常克制,没有任何不必要的提前加载。
快速路由:一个被低估的性能设计
在把控制权交给 Commander.js 之前,OpenClaw 还做了一件事,很多人注意不到,但它直接影响你每次运行 CLI 命令的响应速度。
那就是 src/cli/route.ts 里的 tryRouteCli() 函数。
Commander.js 构建一棵完整的命令树是有成本的——注册 30 多条子命令、加载插件系统、初始化各种模块,这些加在一起会让 CLI 的启动出现可感知的延迟。对于 openclaw gateway status 这种你每天可能要运行几十次的快捷命令,这个延迟会很烦。
tryRouteCli() 的解法是在进入 Commander 之前先拦截一下。它用最轻量的方式解析 argv(靠 src/cli/argv.ts 里自己写的简单解析器,完全不依赖 Commander),判断当前命令是不是在"高频快捷命令"名单里。如果是,就直接执行,完全绕过整棵命令树的构建。
用源码里的注释来说:"load as little as possible for the command being run"——为当前命令加载尽可能少的东西。这是整个 CLI 设计里最大的单项性能优化。被纳入快速路由的都是最常见的命令:检查 Gateway 是否存活、列出当前 Session、查看状态。
CLI 的命令树
绕过快速路由之后,就进入了 Commander.js 的世界。src/cli/program.ts 负责把所有命令组织成一棵树,src/commands/ 目录下的各个文件分别实现具体的命令逻辑。
命令树大致分为以下几组,每组都很有代表性。
setup 组包含 onboard、configure、doctor 等面向初次使用和运维的命令,是用户与 OpenClaw 建立关系的起点。
gateway 组负责控制 Gateway 进程的生命周期:start、stop、restart、status、logs。这组命令的实现本质上是通过 WebSocket 连上正在运行的 Gateway 发 RPC 请求,或者直接操作系统服务(launchd/systemd)。
channels 组管理消息平台的账号配置:add、remove、login、logout、status、logs。你用这组命令完成所有平台的接入和认证。
config 组提供配置文件的读写接口:get、set、unset、validate。这组命令在内部调用 Zod schema 验证,写进去的值都经过类型检查。
agent 组管理 Agent 的配置和会话,包括 agents list、sessions、health。
models 组管理模型账号、别名、降级策略,以及各模型的认证配置。
memory 和 skills 组分别管理记忆索引和技能的安装卸载。
nodes 组管理连接到 Gateway 的设备节点(手机、树莓派等)。
cron 组管理定时任务的配置和运行记录。
还有两个特殊命令值得单独说:security audit 扫描配置和本地状态里常见的安全隐患,可以加 --fix 自动修复;openclaw update --channel stable|beta|dev 切换更新频道,类似于在 stable、beta、dev 三条发布轨道之间切换。
另外,插件可以向命令树里注入额外的顶层命令。比如安装了语音通话插件后,会出现 openclaw voicecall 命令。这套机制让 CLI 的能力边界是开放的,而不是固定写死的。
Onboarding Wizard:第一次运行的魔法
第一次安装完 OpenClaw,官方推荐的下一步是运行这个命令:
openclaw onboard这是整个项目里最用心打磨的用户体验之一,源码在 src/wizard/onboarding.ts 里,逻辑长达数百行。
Wizard 把初次配置拆成五个阶段,按顺序引导用户完成:
第一阶段是模式选择。用户在 QuickStart(应用默认值、减少提问)和 Advanced(逐项配置)之间选一个。多数人选 QuickStart,五分钟内就能跑起来一个可用的助手;想精细控制的用户选 Advanced,每一个关键决策都会有说明。
第二阶段是模型 API 认证。向导会问你用哪家模型,然后引导你填入 API Key,并用 SecretRef 格式写进配置文件——不是明文存储。
第三阶段是Workspace 初始化。在 ~/.openclaw/workspace/ 目录下生成初始的 SOUL.md、USER.md、AGENTS.md 等文件,Agent 的人格和行为规则都从这里来。
第四阶段是通道配置。引导用户添加第一个消息平台账号,比如扫码连接 WhatsApp,或者输入 Telegram Bot Token。
第五阶段是收尾与启动。这一步做的事最多:在 Linux 上检查 systemd linger 是否启用(这决定用户级服务能否在退出登录后继续运行)、安装 Gateway daemon、运行一次健康检查、构建 Control UI 静态资源。最后向导会问你:用 TUI(终端交互界面)、Web UI 还是稍后手动启动?如果选 TUI,终端里会出现一行令人愉快的文字:"Wake up, my friend!"
Wizard 最终把所有答案写进 ~/.openclaw/openclaw.json。如果你在向导结束之后想修改某项配置,可以直接编辑这个文件,也可以用 openclaw config set 命令修改,两种方式等价。
Daemon 安装:让 Gateway 永不下线
Wizard 在第五阶段安装的 daemon,是 OpenClaw 能实现"永远在线"的关键。一个 AI 助手如果只在你打开终端的时候才能回复消息,价值会大打折扣——你希望它在你合上笔记本睡觉时仍然在工作,早上醒来手机上有它主动发来的汇报。
实现这一点的机制在三个平台上不同,但命令接口是统一的。
在 macOS 上,openclaw gateway install 在 ~/Library/LaunchAgents/ 目录下生成一个 .plist 文件,向 launchd 注册一个用户级 Agent。这意味着 Gateway 会在你登录时自动启动,即便你关闭了终端,它也继续在后台运行。
在 Linux 上,对应的是 ~/.config/systemd/user/openclaw-gateway.service,一个 systemd 用户单元。通过 systemctl --user enable openclaw-gateway 设置为开机自启。对于服务器场景,还需要确保 systemd linger 已启用(loginctl enable-linger),否则用户注销后服务会被终止。
在 Windows 上,使用 Windows Task Scheduler(schtasks)注册为系统任务,功能与 launchd/systemd 类似。
安装之后,openclaw gateway status 命令默认会向 Gateway 的 RPC 接口发一次探针请求,确认服务不只是"进程存在",而且"能响应请求"。加上 --deep 参数时,还会扫描系统里有没有遗留的旧版 Gateway 进程,防止多个版本并行运行导致端口冲突。
颜色是一种立场:Lobster Palette
CLI 的视觉风格也值得一提,虽然不影响功能,但体现了项目的个性。
所有终端输出的颜色都来自 src/terminal/palette.ts 里的 LOBSTER_PALETTE 对象,主题色是一个叫做 #FF5A2D 的颜色——这是一种接近熟龙虾壳的橙红色,项目内部称之为 accent。整个配色方案在几处文档里被称为 "lobster seam"(龙虾接缝),可以理解为整个品牌视觉语言的源头。
调色板同时遵守 NO_COLOR 和 FORCE_COLOR 两个环境变量的约定——前者让所有输出退回纯文本,后者强制启用颜色(即便终端检测不到颜色支持)。这是对 Unix 传统惯例的尊重。
与此同时,src/terminal/table.ts 实现了一套完整的表格渲染器,支持 Unicode 和 ASCII 两种边框风格,列对齐、ANSI 转义序列感知的文字折行一应俱全——因为 OpenClaw 大量使用表格来展示通道状态、Session 列表、模型列表。
小结
openclaw 这个命令看起来平常,但背后的工程细节相当讲究:快速路由绕过不必要的加载开销,Onboarding Wizard 把复杂的初次配置变成一个有温度的引导流程,跨平台 daemon 安装抹平了 launchd / systemd / schtasks 的差异,颜色系统甚至是有品牌立场的设计决策。
这些东西加在一起,共同构成了"用户第一次遇见 OpenClaw"的体验。一个开源工具能不能留住用户,往往不取决于它的核心功能有多强,而取决于它在第一个五分钟里给人什么感觉。
下一篇,我们往里走一层,进入配置系统——JSON5 格式、Zod 校验、SecretRef,以及配置的热更新是如何做到的。
源码参考:src/index.ts · src/cli/program.ts · src/cli/route.ts · src/wizard/onboarding.ts · src/terminal/palette.ts基于 commit bf6ec64f 版本
夜雨聆风