|
| 1 | +--- |
| 2 | +review_comment_synced_at: 2026-04-29T14:05:47.137Z |
| 3 | +number: 74378 |
| 4 | +repository: openclaw/openclaw |
| 5 | +type: issue |
| 6 | +title: "[Bug]: OpenClaw CLI commands remain alive as node.exe processes after execution on Windows" |
| 7 | +url: https://github.com/openclaw/openclaw/issues/74378 |
| 8 | +state_at_review: open |
| 9 | +item_created_at: 2026-04-29T14:00:18Z |
| 10 | +item_updated_at: 2026-04-29T14:00:36Z |
| 11 | +author: 2ndNuts |
| 12 | +author_association: NONE |
| 13 | +labels: ["bug","regression"] |
| 14 | +reviewed_at: 2026-04-29T14:04:41.274Z |
| 15 | +main_sha: 0544c6d493ff89887b3480aaf9fa7e326d9357fc |
| 16 | +pull_head_sha: unknown |
| 17 | +latest_release: v2026.4.26 |
| 18 | +latest_release_sha: be8c24633aaa7ef0425ae1178f096ee8dd6226c0 |
| 19 | +fixed_release: unknown |
| 20 | +fixed_sha: unknown |
| 21 | +fixed_at: unknown |
| 22 | +review_policy: bdf05b6f0cc69e54 |
| 23 | +review_model: gpt-5.5 |
| 24 | +review_reasoning_effort: high |
| 25 | +review_sandbox: danger-full-access |
| 26 | +review_service_tier: fast |
| 27 | +review_mode: propose |
| 28 | +review_status: complete |
| 29 | +local_checkout_access: verified |
| 30 | +item_snapshot_hash: cfbcb52336c7364105ca967c7a4cc18dfa591d1cacf05f459581582e63f5c8ed |
| 31 | +close_comment_sha256: none |
| 32 | +review_comment_sha256: aa6db1288582d1f726552db7f15d6662f4022bbe390eb1ddf1d8e0ce895973b1 |
| 33 | +review_comment_id: 4344473502 |
| 34 | +review_comment_url: https://github.com/openclaw/openclaw/issues/74378#issuecomment-4344473502 |
| 35 | +decision: keep_open |
| 36 | +close_reason: none |
| 37 | +confidence: high |
| 38 | +action_taken: kept_open |
| 39 | +work_candidate: queue_fix_pr |
| 40 | +work_confidence: medium |
| 41 | +work_priority: high |
| 42 | +work_status: candidate |
| 43 | +work_reason_sha256: dabe84245b8106dc04d3fa298cb8fab8bfa5178ced181861cc65d5b133d2f24f |
| 44 | +work_prompt_sha256: db960cd1c582ab013ec6d03f329b00d4efa7ea469f3725ba04ab624015ec088d |
| 45 | +work_cluster_refs: ["openclaw/openclaw#74378"] |
| 46 | +work_validation: ["pnpm test src/cli/run-main.exit.test.ts src/infra/net/undici-global-dispatcher.test.ts src/cli/program/routes.test.ts","pnpm exec oxfmt --check --threads=1 src/cli/run-main.ts src/infra/net/undici-global-dispatcher.ts src/cli/run-main.exit.test.ts src/infra/net/undici-global-dispatcher.test.ts","Windows npm smoke: run `node <npm-global-openclaw>/openclaw.mjs status` and `node <npm-global-openclaw>/openclaw.mjs --version`; both should exit within a few seconds and leave no `node.exe ... openclaw.mjs <command>` process.","pnpm check:changed"] |
| 47 | +work_likely_files: ["src/cli/run-main.ts","src/infra/net/undici-global-dispatcher.ts","src/cli/run-main.exit.test.ts","src/infra/net/undici-global-dispatcher.test.ts","src/entry.version-fast-path.ts","CHANGELOG.md"] |
| 48 | +--- |
| 49 | + |
| 50 | +# [#74378: [Bug]: OpenClaw CLI commands remain alive as node.exe processes after execution on Windows](https://github.com/openclaw/openclaw/issues/74378) |
| 51 | + |
| 52 | +Type: issue |
| 53 | + |
| 54 | +URL: [https://github.com/openclaw/openclaw/issues/74378](https://github.com/openclaw/openclaw/issues/74378) |
| 55 | + |
| 56 | +Author: 2ndNuts |
| 57 | + |
| 58 | +Author association: NONE |
| 59 | + |
| 60 | +Labels: bug, regression |
| 61 | + |
| 62 | +Created at: Apr 29, 2026, 14:00 UTC |
| 63 | + |
| 64 | +Updated at: Apr 29, 2026, 14:00 UTC |
| 65 | + |
| 66 | +Reviewed against: [0544c6d493ff](https://github.com/openclaw/openclaw/commit/0544c6d493ff89887b3480aaf9fa7e326d9357fc) |
| 67 | + |
| 68 | +Codex review: model gpt-5.5, reasoning high |
| 69 | + |
| 70 | +Latest release at review time: [v2026.4.26](https://github.com/openclaw/openclaw/releases/tag/v2026.4.26) ([be8c24633aaa](https://github.com/openclaw/openclaw/commit/be8c24633aaa7ef0425ae1178f096ee8dd6226c0)) |
| 71 | + |
| 72 | +Fixed in: not determined |
| 73 | + |
| 74 | +## Decision |
| 75 | + |
| 76 | +Keep open: kept open |
| 77 | + |
| 78 | +Confidence: high |
| 79 | + |
| 80 | +Action taken: kept_open |
| 81 | + |
| 82 | +## Summary |
| 83 | + |
| 84 | +Keep open. Current main still lacks an evident fix for the Windows process-lifetime regression: `status` is routed as a short-lived read-only CLI command, but the route path still bootstraps process-wide proxy/Undici state and then returns without a general active-handle teardown. The documented `--version` fast path exits directly, but the documented `status` reproduction is enough to keep this actionable. |
| 85 | + |
| 86 | +## What This Changes |
| 87 | + |
| 88 | +The report asks for Windows npm-installed OpenClaw CLI commands such as `version` and `status` to terminate after completing instead of leaving `node.exe openclaw.mjs <command>` processes alive. |
| 89 | + |
| 90 | +## Best Possible Solution |
| 91 | + |
| 92 | +Add a focused CLI lifecycle fix so short-lived non-daemon commands clean up process-wide proxy/Undici/debug-capture resources and exit naturally on Windows, while preserving long-running gateway/agent behavior and existing proxy routing semantics. |
| 93 | + |
| 94 | +## Work Candidate |
| 95 | + |
| 96 | +Candidate: queue_fix_pr |
| 97 | + |
| 98 | +Confidence: medium |
| 99 | + |
| 100 | +Priority: high |
| 101 | + |
| 102 | +Status: candidate |
| 103 | + |
| 104 | +Reason: This is a fresh regression with a narrow CLI lifecycle surface and clear likely files, but the repair should first identify the Windows active handle and avoid changing proxy/security semantics beyond teardown for short-lived commands. |
| 105 | + |
| 106 | +Cluster refs: |
| 107 | + |
| 108 | +- openclaw/openclaw#74378 |
| 109 | + |
| 110 | +Likely files: |
| 111 | + |
| 112 | +- src/cli/run-main.ts |
| 113 | +- src/infra/net/undici-global-dispatcher.ts |
| 114 | +- src/cli/run-main.exit.test.ts |
| 115 | +- src/infra/net/undici-global-dispatcher.test.ts |
| 116 | +- src/entry.version-fast-path.ts |
| 117 | +- CHANGELOG.md |
| 118 | + |
| 119 | +Validation: |
| 120 | + |
| 121 | +- pnpm test src/cli/run-main.exit.test.ts src/infra/net/undici-global-dispatcher.test.ts src/cli/program/routes.test.ts |
| 122 | +- pnpm exec oxfmt --check --threads=1 src/cli/run-main.ts src/infra/net/undici-global-dispatcher.ts src/cli/run-main.exit.test.ts src/infra/net/undici-global-dispatcher.test.ts |
| 123 | +- Windows npm smoke: run `node <npm-global-openclaw>/openclaw.mjs status` and `node <npm-global-openclaw>/openclaw.mjs --version`; both should exit within a few seconds and leave no `node.exe ... openclaw.mjs <command>` process. |
| 124 | +- pnpm check:changed |
| 125 | + |
| 126 | +## Repair Work Prompt |
| 127 | + |
| 128 | +Fix openclaw/openclaw#74378. Investigate why short-lived Windows npm CLI invocations such as `node .../openclaw.mjs status` remain alive after output. Focus on CLI lifecycle cleanup for routed/non-daemon commands: `src/cli/run-main.ts`, env proxy/bootstrap handling, and `src/infra/net/undici-global-dispatcher.ts`. Preserve existing proxy routing semantics and long-running commands (`gateway`, `node run`, live provider/plugin commands); do not paper over the bug by forcing `process.exit` for every successful command unless tests prove it is the least risky boundary. Add focused regression coverage for routed `status` with env proxy/global dispatcher cleanup, and cover the version/unknown-command distinction as appropriate. Add a changelog fix entry if runtime behavior changes, crediting `Thanks @2ndNuts`. Do not change dependency versions or bundled plugin behavior. |
| 129 | + |
| 130 | +## Evidence |
| 131 | + |
| 132 | +- **Fresh user report:** The issue reports OpenClaw 2026.4.26 on Windows 11 via npm leaving `node.exe ... openclaw.mjs version` and `node.exe ... openclaw.mjs status` alive after 3 and 13 seconds, while the gateway process remained separate and healthy. |
| 133 | +- **Status is a routed short-lived CLI command:** Current main maps `status` to a routed command with plugins disabled and network proxy bypass, so it should complete without becoming a long-running runtime process. |
| 134 | + - file: [src/cli/command-catalog.ts:94](https://github.com/openclaw/openclaw/blob/0544c6d493ff89887b3480aaf9fa7e326d9357fc/src/cli/command-catalog.ts#L94) |
| 135 | + - command: `nl -ba src/cli/command-catalog.ts | sed -n '1,260p'` |
| 136 | + - sha: [0544c6d493ff](https://github.com/openclaw/openclaw/commit/0544c6d493ff89887b3480aaf9fa7e326d9357fc) |
| 137 | +- **Routed status executes and returns:** The routed status definition loads `statusCommand` or `statusJsonCommand`, awaits it, and returns; there is no command-specific process termination or active-handle cleanup here. |
| 138 | + - file: [src/cli/program/routed-command-definitions.ts:68](https://github.com/openclaw/openclaw/blob/0544c6d493ff89887b3480aaf9fa7e326d9357fc/src/cli/program/routed-command-definitions.ts#L68) |
| 139 | + - command: `nl -ba src/cli/program/routed-command-definitions.ts | sed -n '1,320p'` |
| 140 | + - sha: [0544c6d493ff](https://github.com/openclaw/openclaw/commit/0544c6d493ff89887b3480aaf9fa7e326d9357fc) |
| 141 | +- **CLI route path still bootstraps env proxy dispatcher:** Before routed commands, `runCli` calls proxy capture/bootstrap, which can install a global Undici env proxy dispatcher when proxy environment variables are present. |
| 142 | + - file: [src/cli/run-main.ts:239](https://github.com/openclaw/openclaw/blob/0544c6d493ff89887b3480aaf9fa7e326d9357fc/src/cli/run-main.ts#L239) |
| 143 | + - command: `nl -ba src/cli/run-main.ts | sed -n '260,640p'` |
| 144 | + - sha: [0544c6d493ff](https://github.com/openclaw/openclaw/commit/0544c6d493ff89887b3480aaf9fa7e326d9357fc) |
| 145 | +- **No general dispatcher teardown after routed commands:** The `finally` block removes managed-proxy signal handlers, stops the managed proxy if one was started, and closes memory managers, but it does not restore or close an env-installed global Undici dispatcher for short-lived route commands. |
| 146 | + - file: [src/cli/run-main.ts:603](https://github.com/openclaw/openclaw/blob/0544c6d493ff89887b3480aaf9fa7e326d9357fc/src/cli/run-main.ts#L603) |
| 147 | + - command: `nl -ba src/cli/run-main.ts | sed -n '260,640p'` |
| 148 | + - sha: [0544c6d493ff](https://github.com/openclaw/openclaw/commit/0544c6d493ff89887b3480aaf9fa7e326d9357fc) |
| 149 | +- **Global Undici dispatcher is replaced but not closed:** `ensureGlobalUndiciEnvProxyDispatcher` sets a new `EnvHttpProxyAgent` as the process global dispatcher; the helper tracks applied state but has no close/destroy/reset hook for command teardown. |
| 150 | + - file: [src/infra/net/undici-global-dispatcher.ts:91](https://github.com/openclaw/openclaw/blob/0544c6d493ff89887b3480aaf9fa7e326d9357fc/src/infra/net/undici-global-dispatcher.ts#L91) |
| 151 | + - command: `nl -ba src/infra/net/undici-global-dispatcher.ts | sed -n '1,240p'` |
| 152 | + - sha: [0544c6d493ff](https://github.com/openclaw/openclaw/commit/0544c6d493ff89887b3480aaf9fa7e326d9357fc) |
| 153 | +- **Existing test asserts no forced exit for routed commands:** The current regression test suite explicitly verifies that a successful routed `status` command does not call `process.exit`, so current coverage would not catch a Windows active-handle leak that prevents natural process exit. |
| 154 | + - file: [src/cli/run-main.exit.test.ts:225](https://github.com/openclaw/openclaw/blob/0544c6d493ff89887b3480aaf9fa7e326d9357fc/src/cli/run-main.exit.test.ts#L225) |
| 155 | + - command: `nl -ba src/cli/run-main.exit.test.ts | sed -n '225,239p'` |
| 156 | + - sha: [0544c6d493ff](https://github.com/openclaw/openclaw/commit/0544c6d493ff89887b3480aaf9fa7e326d9357fc) |
| 157 | +- **Relevant local related reports are not canonical duplicates:** The provided title-search overlaps cover Feishu command routing and older Anthropic initialization failures; none tracks this Windows `node.exe` process-lifetime leak. |
| 158 | + |
| 159 | +## Likely Related People |
| 160 | + |
| 161 | +- **masatohoshino:** introduced current CLI route/proxy lifecycle surface |
| 162 | + - reason: Blame on `src/cli/run-main.ts`, `src/infra/net/undici-global-dispatcher.ts`, `src/cli/command-catalog.ts`, and `src/cli/program/routed-command-definitions.ts` points to commit `016f5ae8`, which introduced the current routed CLI/proxy dispatcher code paths involved in this report. |
| 163 | + - confidence: high |
| 164 | + - commits: 016f5ae862e1704b522808c6e79409da83425d63 |
| 165 | + - files: src/cli/run-main.ts, src/infra/net/undici-global-dispatcher.ts, src/cli/command-catalog.ts, src/cli/program/routed-command-definitions.ts |
| 166 | +- **steipete:** recent adjacent maintainer |
| 167 | + - reason: Recent command-catalog policy maintenance touched the same CLI routing/proxy policy area, though not the central process-lifetime code. |
| 168 | + - confidence: medium |
| 169 | + - commits: 390a7598c952bda5db6a423e02db66c9db351f30 |
| 170 | + - files: src/cli/command-catalog.ts |
| 171 | + |
| 172 | +## Risks / Open Questions |
| 173 | + |
| 174 | +- Windows/npm reproduction was not performed in this read-only Linux review, so the exact active handle still needs confirmation on Windows. |
| 175 | +- The positional `version` command is not the documented version path; the fix should distinguish documented `openclaw --version` behavior from unknown-command handling while still addressing `status`. |
| 176 | + |
| 177 | +## Close Comment |
| 178 | + |
| 179 | +_No close comment posted._ |
| 180 | + |
| 181 | +## GitHub Snapshot |
| 182 | + |
| 183 | +- comments: 0 |
| 184 | +- timeline events: 2 |
| 185 | +- related items: 5 |
| 186 | +- PR files: 0 |
| 187 | +- PR commits: 0 |
| 188 | + |
0 commit comments