0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【#2】 OpenClaw を読み解く — openclaw と打ってから、起動まで

0
Last updated at Posted at 2026-06-27

【#2】 OpenClaw を読み解く — openclaw と打ってから、起動まで

本記事のコード参照は OpenClaw maincee2aca409(version 2026.6.10)時点。行番号は更新でズレ得ます。

openclaw とターミナルに打ち込んでから Gateway が応答するまで、何が起きているのか。今回は src/entry.ts(全 295 行)を起点に、CLI プロセスの起動の一本道を読み解きます。巨大アプリの起動コードは「いかに重い処理を遅延させ、地雷を踏まないか」の工夫が詰まった場所です。

二段構えの入口 — openclaw.mjs から entry.ts

package.jsonbin はこうです。

"bin": { "openclaw": "openclaw.mjs" }

ルートの openclaw.mjs が薄いラッパーで、実体は dist/.../entry.js(ソースは src/entry.ts)。この2段構えには理由があります。

地雷その一 — 自分が主役かを確かめる main-module ガード

entry.ts:57isMainModule ガードは、このファイルの最重要コメントが付いています。

// Guard: only run entry-point logic when this file is the main module.
// The bundler may import entry.js as a shared dependency when dist/index.js
// is the actual entry point; without this guard the top-level code below
// would call runCli a second time, starting a duplicate gateway that fails
// on the lock / port and crashes the process.
if (!isMainModule({ currentFile: fileURLToPath(import.meta.url),
                     wrapperEntryPairs: [...ENTRY_WRAPPER_PAIRS] })) {
  // Imported as a dependency — skip all entry-point side effects.
} else {
  // ... 起動処理本体 ...
}

dist/index.js(ライブラリ用エントリ)が entry.js を依存として読み込むことがあり、その際にトップレベルの起動処理がもう一度走ると、Gateway が二重起動してロック/ポート衝突でクラッシュします。ENTRY_WRAPPER_PAIRSentry.ts:28)で openclaw.mjs / openclaw.js というラッパー名を許容しつつ、本当に自分がプロセスの主役のときだけ副作用を実行する、という防御です。

このコメントは AGENTS.md の「lifecycle ordering / ownership boundary な非自明分岐にはインラインコメントを必須とする」という規約の好例でもあります。

地雷その二 — キャッシュのために、自らを起動し直す

main モジュールだと確定すると、まず実行ルートを解決し、必要なら**自分自身を再起動(respawn)**します。

const installRoot = resolveEntryInstallRoot(entryFile);
const waitingForCompileCacheRespawn = respawnWithoutOpenClawCompileCacheIfNeeded({
  currentFile: entryFile, installRoot,
});
if (!waitingForCompileCacheRespawn) {
  process.title = "openclaw";
  ensureOpenClawExecMarkerOnProcess();
  installProcessWarningFilter();
  normalizeEnv();
  enableOpenClawCompileCache({ installRoot });
  ...
}

Node の V8 コンパイルキャッシュを使うと起動が速くなりますが、状況によっては無効化して再起動したほうが安全です。respawnWithoutOpenClawCompileCacheIfNeeded がその判断を担い、再起動を選んだ場合は親プロセスはここで止まります(waitingForCompileCacheRespawn === true)。

その後の初期化も順序が意味を持ちます。

  • process.title = "openclaw"ps での見分けやすさ
  • ensureOpenClawExecMarkerOnProcess() — 自分が openclaw 実行であるマーカー(子プロセス判定用)
  • installProcessWarningFilter() — Node の警告ノイズを抑制
  • normalizeEnv() — 環境変数の正規化

地雷その三 — 引数を整え、形を変えて生まれ直す

process.argv = normalizeWindowsArgv(process.argv);

if (!ensureCliRespawnReady()) {
  const parsedContainer = parseCliContainerArgs(process.argv);  // --container
  const parsed = parseCliProfileArgs(parsedContainer.argv);     // --profile / --dev
  ...
}

ensureCliRespawnReady()entry.ts:90)は buildCliRespawnPlan() を呼び、必要なら runCliRespawnPlan(plan) で再実行して true を返します。true のときは「親はもう CLI を続行してはいけない」。Node のバージョンやフラグの都合で、適切な実行形態に自分を起動し直す仕組みです。

--container(コンテナターゲット指定)と --profile/--dev(プロファイル切替)は早い段階でパースされ、両者の同時指定はここで弾かれます。

if (containerTargetName && parsed.profile) {
  console.error("[openclaw] --container cannot be combined with --profile/--dev");
  process.exit(2);
}

プロファイル指定があれば applyCliProfileEnv で環境を切り替え、Commander とアドホックな argv チェックの両方が一貫するよう process.argv を書き戻します。

速さの肝 — 「必要になるまで読まない」fast-path

起動コードを読むと、tryHandle...FastPath という関数が複数あることに気づきます。

if (!tryHandleRootVersionFastPath(process.argv)) {
  await runMainOrRootHelp(process.argv);
}
  • tryHandleRootVersionFastPathentry.ts:22 import) — openclaw --version を、重いモジュールを一切読まずに即答する。
  • tryHandleRootHelpFastPathentry.ts:137) — openclaw --help のヘルプ表示。ここが秀逸で、まず 設定に敏感なプラグインがあるかloadRootHelpRenderOptionsForConfigSensitivePlugins で確認し、なければ事前計算済みのヘルプ文字列outputPrecomputedRootHelpText)をそのまま出します。プラグインの状態次第でヘルプ内容が変わるので、変わらないと分かるときだけ事前計算をショートカットする、という二段構えです。
  • tryHandlePrecomputedCommandHelpFastPathentry.ts:208) — browser / secrets / nodes の各サブコマンドの --help も同様に事前計算。

なぜここまでするのか。--version--help のためにプラグインローダーや設定読み込みまで走らせるのは無駄で、体感も遅くなるからです。「重い初期化は本当に必要になるまで遅延する」という設計が、起動コードのいたるところに見えます。OPENCLAW_GATEWAY_STARTUP_TRACE を立てると、entry.bootstrap / entry.argv などの計測トレースが出る仕掛けもあります(createGatewayStartupTrace, src/cli/startup-trace.ts)。

起動の全景 — 一本道を俯瞰する

openclaw.mjs
  └─ entry.ts (main module 判定)
       ├─ compile cache respawn 判定 ── 必要なら再起動して親終了
       ├─ process 初期化 (title / marker / warning filter / env)
       ├─ Windows argv 正規化
       ├─ CLI respawn 判定 ── 必要なら再実行して親終了
       ├─ --container / --profile パース
       ├─ fast-path: --version / --help は即応答
       └─ runMain (Commander 本体) ──→ 各サブコマンドへ

常駐するということ — OS の差異を吸う daemon 層

openclaw gateway で起動した Gateway を常駐サービスにするのが src/daemon/ です。README.md の推奨セットアップ openclaw onboard --install-daemon がここを使います。

ディレクトリを見ると、OS ごとのサービスマネージャを抽象化しているのがわかります。

  • launchd.ts / launchd-plist.ts — macOS(launchd user service)
  • systemd.ts / systemd-unit.ts / systemd-linger.ts — Linux(systemd user service)
  • schtasks.ts / schtasks-exec.ts — Windows(タスクスケジューラ)
  • service.ts / service-env.ts / service-layout.ts — 3 OS 共通のサービス抽象

つまり「OS ごとのサービス登録の差異」を daemon/ が吸収し、上位は openclaw gateway restart/status --deepAGENTS.md の Platform/Ops 節)という統一インターフェイスで扱える、という設計です。bootstrap/ は対照的に薄く、node-extra-ca-certs(追加 CA 証明書)と node-startup-env(起動時の環境)の調整だけを担います。

読みどころ — 起動コードが教える三つの定石

今回押さえたいのは次の3点です。

  1. 二重起動を防ぐ main-module ガード — バンドル時の共有依存に強い。
  2. respawn による自己再起動 — コンパイルキャッシュ/Node 実行形態を最適化するため、エントリは自分を起動し直すことを厭わない。
  3. fast-path による遅延初期化--version / --help は重い経路を踏まずに即応答。「必要になるまで読まない」が徹底されている。

これらはすべて「起動が速く、壊れにくい CLI」を作るための定石であり、巨大アプリほど効いてきます。

次回予告 — 制御プレーンの会話へ

#03 は、起動後に立ち上がる Gateway とその通信規約 Gateway プロトコルpackages/gateway-protocol)を読み解きます。チャネル・ツール・イベントを束ねる「制御プレーン」が、クライアント(CLI / Web UI / モバイルノード)とどう会話するのか。プロトコルのバージョニング規律(AGENTS.md: 「additive first」)にも踏み込みます。


参考: src/entry.ts(特に :28 / :49 / :57 / :90 / :130 / :137 / :208), src/cli/startup-trace.ts, src/daemon/, src/bootstrap/, README.md(daemon セットアップ)

図1.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?