diff --git a/CHANGELOG.md b/CHANGELOG.md index ea6970ba7c..c04ed7651c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Docs: https://docs.openclaw.ai ### Fixes +- CLI/Completion: route plugin-load logs to stderr and write generated completion scripts directly to stdout to avoid `source <(openclaw completion ...)` corruption. (#15481) Thanks @arosstale. - Gateway/Agents: stop injecting a phantom `main` agent into gateway agent listings when `agents.list` explicitly excludes it. (#11450) Thanks @arosstale. - Agents/Heartbeat: stop auto-creating `HEARTBEAT.md` during workspace bootstrap so missing files continue to run heartbeat as documented. (#11766) Thanks @shadril238. - Telegram: cap bot menu registration to Telegram's 100-command limit with an overflow warning while keeping typed hidden commands available. (#15844) Thanks @battman21. diff --git a/src/cli/completion-cli.ts b/src/cli/completion-cli.ts index 1a65595a76..6874611f89 100644 --- a/src/cli/completion-cli.ts +++ b/src/cli/completion-cli.ts @@ -3,6 +3,7 @@ import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; import { resolveStateDir } from "../config/paths.js"; +import { routeLogsToStderr } from "../logging/console.js"; import { pathExists } from "../utils.js"; import { getSubCliEntries, registerSubCliByName } from "./program/register.subclis.js"; @@ -235,6 +236,9 @@ export function registerCompletionCli(program: Command) { ) .option("-y, --yes", "Skip confirmation (non-interactive)", false) .action(async (options) => { + // Route logs to stderr so plugin loading messages do not corrupt + // the completion script written to stdout. + routeLogsToStderr(); const shell = options.shell ?? "zsh"; // Eagerly register all subcommands to build the full tree const entries = getSubCliEntries(); @@ -269,7 +273,7 @@ export function registerCompletionCli(program: Command) { throw new Error(`Unsupported shell: ${shell}`); } const script = getCompletionScript(shell, program); - console.log(script); + process.stdout.write(script + "\n"); }); }