#22488: fix(cli): redirect plugin logs to stderr during completion
cli
size: XS
Cluster:
CLI Enhancements and Fixes
Closes #22449
## Problem
When running `source <(openclaw completion zsh)`, any logs generated during CLI initialization would pollute stdout and corrupt the generated completion script. This broke process substitution because the shell would try to source invalid syntax.
The root cause was a timing issue: `enableConsoleCapture()` was called early in `run-main.ts`, but `routeLogsToStderr()` wasn't called until the completion command action ran. Any logs from config loading, plugin discovery, or other initialization would escape to stdout in between.
## Solution
Detect the completion command early (right after `enableConsoleCapture()`) and immediately route all logs to stderr before any other initialization happens. This keeps stdout clean for the generated completion script while still capturing all logs to the log files.
The fix is minimal and focused: just a simple check for the completion command that calls `routeLogsToStderr()` before program building or command registration.
## Testing
Verified that `source <(openclaw completion zsh)` now works without any log pollution corrupting the output.
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
This PR fixes stdout pollution during shell completion generation by detecting the `completion` command early and routing logs to stderr before any initialization occurs. The fix prevents plugin discovery and config loading logs from corrupting the completion script output when using process substitution patterns like `source <(openclaw completion zsh)`.
The change adds a simple check immediately after `enableConsoleCapture()` that detects when the primary command is "completion" and calls `routeLogsToStderr()` before `buildProgram()` or any plugin/config loading happens. This ensures all subsequent logs go to stderr, keeping stdout clean for the completion script.
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with minimal risk
- The change is minimal, well-scoped, and directly addresses the stated problem. It adds a simple guard that routes logs to stderr for the completion command only, maintaining existing behavior for all other commands. The implementation correctly uses existing utility functions (`getCommandPath`, `routeLogsToStderr`) and is placed at the optimal location in the execution flow.
- No files require special attention
<sub>Last reviewed commit: f270369</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#12308: fix(cli): redirect log output to stderr during completion script ge...
by mcaxtr · 2026-02-09
90.6%
#13840: perf(cli): skip plugin loading during completion generation
by lailoo · 2026-02-11
80.9%
#17680: perf(cli): skip plugin loading during completion generation
by mcrolly · 2026-02-16
79.7%
#9148: Fix: Speed up shell completion generation from ~4.6s to <200ms
by vishaltandale00 · 2026-02-04
79.3%
#6382: fix(cli): silence Powerlevel10k Zsh warning from completion script
by dungngo4520 · 2026-02-01
78.6%
#16908: fix(cli): clean stale shell completion profile entries on uninstall...
by lorstyang · 2026-02-15
78.5%
#17962: fix(cli): speed up completion plugin loading
by forketyfork · 2026-02-16
77.7%
#20553: fix(completion): guard zsh compdef call for environments without co...
by mr-sk · 2026-02-19
77.5%
#17325: fix(completion): avoid zsh compdef error when compinit is not initi...
by ephelia-ai · 2026-02-15
77.3%
#18938: fix(completion): avoid compdef error in zsh by guarding completion ...
by gcsenyan · 2026-02-17
77.1%