fix(cli): prevent plugin loading logs from polluting 'openclaw agent --json' stdout#51086
fix(cli): prevent plugin loading logs from polluting 'openclaw agent --json' stdout#51086tomi-claycosmos wants to merge 1 commit intoopenclaw:mainfrom
Conversation
…plugin loading pollution
Greptile SummaryThis PR attempts to fix stdout pollution from plugin loading logs when running
Confidence Score: 1/5
Prompt To Fix All With AIThis is a comment left during a code review.
Path: src/commands/agent-via-gateway.ts
Line: 184-186
Comment:
**JSON response redirected to stderr by same call**
Calling `routeLogsToStderr()` here patches `console.log` (via `enableConsoleCapture`, which runs before this point in `run-main.ts`) to write to `process.stderr` whenever `forceConsoleToStderr` is `true`. The problem is that the final JSON payload in `agentViaGatewayCommand` is emitted the same way:
```ts
// agentViaGatewayCommand (line ~160)
if (opts.json) {
runtime.log(JSON.stringify(response, null, 2)); // calls console.log → now goes to stderr!
return response;
}
```
`runtime.log` delegates to `console.log`, which is already patched. Once `routeLogsToStderr()` is called, *every* subsequent `console.log` call — including the one that outputs the JSON result — is redirected to `process.stderr`. This means `--json` stdout would be empty and the JSON would land on stderr instead.
Compare with `completion-cli.ts`, which writes its stdout output with `process.stdout.write(script + "\n")` directly, bypassing the console patch entirely.
The fix should write the JSON using `process.stdout.write` (or `rawConsole.log` / `loggingState.rawConsole`) so it is not subject to the `forceConsoleToStderr` redirect. For example, in `agentViaGatewayCommand`:
```ts
if (opts.json) {
process.stdout.write(JSON.stringify(response, null, 2) + "\n");
return response;
}
```
Without this change, `openclaw agent --json` will produce an empty stdout and the JSON on stderr — the opposite of the intended behaviour.
How can I resolve this? If you propose a fix, please make it concise.Last reviewed commit: "fix(cli): route logs..." |
| if (opts.json) { | ||
| routeLogsToStderr(); | ||
| } |
There was a problem hiding this comment.
JSON response redirected to stderr by same call
Calling routeLogsToStderr() here patches console.log (via enableConsoleCapture, which runs before this point in run-main.ts) to write to process.stderr whenever forceConsoleToStderr is true. The problem is that the final JSON payload in agentViaGatewayCommand is emitted the same way:
// agentViaGatewayCommand (line ~160)
if (opts.json) {
runtime.log(JSON.stringify(response, null, 2)); // calls console.log → now goes to stderr!
return response;
}runtime.log delegates to console.log, which is already patched. Once routeLogsToStderr() is called, every subsequent console.log call — including the one that outputs the JSON result — is redirected to process.stderr. This means --json stdout would be empty and the JSON would land on stderr instead.
Compare with completion-cli.ts, which writes its stdout output with process.stdout.write(script + "\n") directly, bypassing the console patch entirely.
The fix should write the JSON using process.stdout.write (or rawConsole.log / loggingState.rawConsole) so it is not subject to the forceConsoleToStderr redirect. For example, in agentViaGatewayCommand:
if (opts.json) {
process.stdout.write(JSON.stringify(response, null, 2) + "\n");
return response;
}Without this change, openclaw agent --json will produce an empty stdout and the JSON on stderr — the opposite of the intended behaviour.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/commands/agent-via-gateway.ts
Line: 184-186
Comment:
**JSON response redirected to stderr by same call**
Calling `routeLogsToStderr()` here patches `console.log` (via `enableConsoleCapture`, which runs before this point in `run-main.ts`) to write to `process.stderr` whenever `forceConsoleToStderr` is `true`. The problem is that the final JSON payload in `agentViaGatewayCommand` is emitted the same way:
```ts
// agentViaGatewayCommand (line ~160)
if (opts.json) {
runtime.log(JSON.stringify(response, null, 2)); // calls console.log → now goes to stderr!
return response;
}
```
`runtime.log` delegates to `console.log`, which is already patched. Once `routeLogsToStderr()` is called, *every* subsequent `console.log` call — including the one that outputs the JSON result — is redirected to `process.stderr`. This means `--json` stdout would be empty and the JSON would land on stderr instead.
Compare with `completion-cli.ts`, which writes its stdout output with `process.stdout.write(script + "\n")` directly, bypassing the console patch entirely.
The fix should write the JSON using `process.stdout.write` (or `rawConsole.log` / `loggingState.rawConsole`) so it is not subject to the `forceConsoleToStderr` redirect. For example, in `agentViaGatewayCommand`:
```ts
if (opts.json) {
process.stdout.write(JSON.stringify(response, null, 2) + "\n");
return response;
}
```
Without this change, `openclaw agent --json` will produce an empty stdout and the JSON on stderr — the opposite of the intended behaviour.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7caf1239ad
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if (opts.json) { | ||
| routeLogsToStderr(); |
There was a problem hiding this comment.
Keep
openclaw agent --json output on stdout
In the normal CLI entrypoint, src/cli/run-main.ts:113-115 enables console capture, and defaultRuntime.log is implemented with console.log (src/runtime.ts:21-29). routeLogsToStderr() flips all captured console.log output to stderr (src/logging/console.ts:115-117 and src/logging/console.ts:291-296), so this new call also redirects the later runtime.log(JSON.stringify(...)) in agentViaGatewayCommand (src/commands/agent-via-gateway.ts:159-161). That means openclaw agent --json now produces its JSON response on stderr instead of stdout, breaking the machine-readable contract for real CLI users even though the completion command pattern looked similar.
Useful? React with 👍 / 👎.
|
Noted. The concern about JSON output going to stderr via routeLogsToStderr() is valid — I will switch to process.stdout.write for structured JSON to preserve the --json contract. |
Summary
When running
openclaw agent --json, plugin loading logs were being printed to stdout, corrupting the JSON output.Root cause: The
agentCliCommandfunction did not redirect runtime logs to stderr when--jsonwas used. This is the same class of bug that was already fixed incompletion-cli.ts(see therouteLogsToStderr()call there).Fix: Call
routeLogsToStderr()at the start ofagentCliCommandwhenopts.jsonistrue. This redirects allconsole.log/defaultRuntime.logcalls to stderr, keeping stdout clean for the pure JSON response.Changes
src/commands/agent-via-gateway.ts: ImportrouteLogsToStderrand call it whenopts.jsonis trueTesting
Fixes #51076