DEV Community

homesickjava
homesickjava

Posted on

OpenClaw Source Code Walkthrough (1) – Startup Flow: From Command Line to a Running Gateway

source file : entry.ts

L36: This part is handled by the Gateway's auth.mode: "token" configuration plus device-auth.ts.

L53-L134: It first checks whether it's the main module. Only if it is, the else block executes. This prevents the program from crashing due to double startup. The actual logic runs inside the else.

L63-66: respawnWithoutOpenClawCompileCacheIfNeeded means: "if the current Node process hasn't enabled OpenClaw's compile cache, spawn a new child process (with cache enabled) and let the parent exit."

So the return value of waitingForCompileCacheRespawn means:

true → I'm the parent process, waiting for the child to restart → do nothing, just exit.

false → I'm the child process (or cache is already enabled) → no need to wait, continue normally.

L67: If no restart is needed (i.e., we can proceed directly), perform some initialization: set process.title = 'openclaw', ensure the OpenClaw execution marker is set (ensureOpenClawExecMarkerOnProcess), install a process warning filter (installProcessWarningFilter), and normalize environment variables (normalizeEnv).

L75: Inside enableOpenClawCompileCache, it calls installRoot.

L78: This is just a performance marker – it records how many milliseconds elapsed from process start to "bootstrap complete". The actual Gateway startup happens much later in runMainOrRootHelp → runCli(argv) → openclaw gateway run.

L80-82: This checks whether the command being run is secrets audit.

L84-87: Sets up color output.

L89-98: Checks if OpenClaw has a restart plan; if not, applies the default restart plan.

L100: This is not "setting Windows environment variables" – it normalizes command-line arguments. For example, when running in WSL, backslashes () in paths are converted to forward slashes (/), and Windows-style C:\xxx paths are converted to /mnt/c/xxx.

L102-132: If there's no restart plan:

Parse container arguments (--container) – exit on failure.

Parse file arguments (--profile / --dev) – exit on failure.

If both container and file arguments are parsed successfully, throw an error: --container cannot be used together with --profile or --dev.

If file arguments are parsed successfully, assign them to the thread arguments and set the argv for Gateway startup.

L129: This handles the --version fast path, not --help. --help is handled inside tryHandleRootHelpFastPath. The logic: first check if it's --version – if so, print version and exit; otherwise, proceed to runMainOrRootHelp (which contains both the help branch and the normal startup branch).

L136-184: Asynchronously executes tryHandleRootHelpFastPath – this handles the logic and flow of outputting help messages to the client.

L186-200: Asynchronously executes tryHandlePrecomputedCommandHelpFastPath – this handles precomputed help logic.

L202-226: Asynchronously executes runMainOrRootHelp, which asynchronously starts the main program.

This is not just "starting the program". This function has a three-layer decision:

--help fast path

Subcommand help

If neither, then actually start.

L212-214:

L212: import("./cli/run-main.js") – dynamically loads the run-main.js module into memory (not yet executed).

L214: await runCli(argv) – this is where execution actually begins, starting the Gateway.

Corrected Boot Flow
text
openclaw process starts

├─ isMainModule? ──No──→ exit (was imported, do nothing)

└─ Yes

├─ Compile cache check → needs restart? → spawn child, parent exits

└─ No restart needed

├─ process.title = "openclaw"
├─ Normalize env (env, warning filter, runtime guard)
├─ Enable compile cache
├─ [Mark] gatewayEntryStartupTrace.mark("bootstrap")

├─ secrets audit? → set auth store read‑only
├─ --no-color? → disable colors

├─ Have a CLI respawn plan? → execute plan, exit

└─ No respawn plan

├─ Parse --container, --profile / --dev
├─ --container + --profile / --dev → error and exit
├─ --version? → print version, exit

└─ runMainOrRootHelp
├─ --help? → print help, exit
├─ Subcommand help? → print, exit
└─ import runCli → actually start Gateway

I'm continuously breaking down the OpenClaw source code – 4 posts published so far. Stay tuned!

Top comments (0)