openclaw源码解读(1) —— 启动流程:从命令行到 Gateway 跑起来

L36: 这部分是:Gateway 的auth.mode: “token” 配置 + device-auth.ts 处理的
L53-L134,先判断是不是main module,如果是,才会执行else里面的部分。避免启动两次导致程序crush。在else的逻辑里
L63-66: respawnWithoutOpenClawCompileCacheIfNeeded的意思是“如果当前 Node 进程没启用 OpenClaw 的编译缓存,就 spawn 一个新子进程(带缓存),然后父进程退出“
所以waitingForCompileCacheRespawn的返回值含义如下:
返回 true → 我是父进程,我在等子进程重启 → 什么都不做,等着退出
返回 false → 我是子进程(或本来就有缓存)→ 不需要等,正常往下走
L67, 意思是,如果不需要等编译就可以直接重启了,那么,做一些初始化的设置,比如process.title=’openclaw’, 确保openclaw的标记线程被执行(ensureOpenClawExecMarkerOnProcess),安装线程告警过滤器(installProcessWarningFilter),设置环境变量(normalizeEnv),
L75, 在enableOpenClawCompileCache这个方法里,安装Root(installRoot),
L78,这只是性能打点,记录从进程启动到”bootstrap完成”花了多少毫秒。Gateway 实际启动在很后面:runMainOrRootHelp → runCli(argv) → openclaw gateway run。
L80-82,这里判断的是”是否在执行secrets audit 命令”
L84-87,设置颜色;
L89-98看openclaw有没有重启计划,如果没有,就执行默认的重启计划。
L100,不是”设置 Windows 环境变量”,而是规范化命令行参数。比如在 WSL 里跑时,路径里的反斜杠 \ 要转成正斜杠 /,Windows 风格的 C:\xxx 要转成 /mnt/c/xxx。
L102-132,如果没有重启计划,解析容器参数,如失败退出;解析文件参数,如失败退出;解析容器target,如果成功,并且文件参数也解析成功,报异常:–container 参数不能和 –profile/–dev 一起使用;如文件参数解析成功,把文件参数赋值给线程参数;gateway启动线程标志argv,
L129,这个处理的是 –version(版本号快速通道),不是 –help。
–help 在 tryHandleRootHelpFastPath 里处理。
逻辑是:先判断是不是 –version,如果是就输出版本号退出;如果不是,才进入 runMainOrRootHelp(里面有 help 分支 + 正常启动分支)。
L136-184,异步执行tryHandleRootHelpFastPath,把help命令输出到客户端的逻辑和过程;
L186-200:异步执行tryHandlePrecomputedCommandHelpFastPath,预计算的逻辑和过程;
L202-226:异步执行runMainOrRootHelp,异步执行主函数启动程序;
不只是”启动程序”。这个函数有三层判断:–help 快速通道 → 子命令 help → 都不是才真正启动。
L212-214:
- L212
import(“./cli/run-main.js”) — 是动态加载run-main.js 模块到内存(还没执行) - L214
await runCli(argv) — 才是真正开始执行,启动 Gateway
修正后的正确流程
openclaw 进程启动
│
├─ isMainModule? ──No──→ 退出(被 import 了,不做任何事)
│
└─Yes
│
├─ 编译缓存检查 → 需要重启? → spawn 子进程,父进程退出
│
└─ 不需要重启
│
├─ process.title = “openclaw”
├─ 环境标准化(env, warning filter, runtime guard)
├─ 启用编译缓存
├─ 【打点】gatewayEntryStartupTrace.mark(“bootstrap”)
│
├─ secrets audit? → 设 auth store 只读
├─ –no-color? → 关颜色
│
├─ 有 CLI respawn plan? → 执行 plan,退出
│
└─ 没有 respawn plan
│
├─ 解析 –container, –profile 参数
├─ –container + –profile → 报错退出
├─ –version? → 输出版本,退出
│
└─ runMainOrRootHelp
├─ –help? → 输出 help,退出
├─ 子命令 help? → 输出,退出
└─ import runCli → 真正启动 Gateway
夜雨聆风