From 1d17630dc654a0f27aeba65484e6769434bf38fa Mon Sep 17 00:00:00 2001 From: Shakker Date: Wed, 4 Feb 2026 13:49:54 +0000 Subject: [PATCH] feat: add shell completion installation prompt to CLI update command --- src/cli/update-cli.ts | 44 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/cli/update-cli.ts b/src/cli/update-cli.ts index 805d45984a..e898aec861 100644 --- a/src/cli/update-cli.ts +++ b/src/cli/update-cli.ts @@ -51,6 +51,7 @@ import { renderTable } from "../terminal/table.js"; import { theme } from "../terminal/theme.js"; import { replaceCliName, resolveCliName } from "./cli-name.js"; import { formatCliCommand } from "./command-format.js"; +import { installCompletion, isCompletionInstalled, resolveShellFromEnv } from "./completion-cli.js"; import { formatHelpExamples } from "./help-format.js"; export type UpdateCommandOptions = { @@ -224,6 +225,43 @@ async function tryWriteCompletionCache(root: string, jsonMode: boolean): Promise } } +/** Check if shell completion is installed and prompt user to install if not. */ +async function tryInstallShellCompletion(opts: { + jsonMode: boolean; + skipPrompt: boolean; +}): Promise { + if (opts.jsonMode || !process.stdin.isTTY) { + return; + } + + const shell = resolveShellFromEnv(); + const installed = await isCompletionInstalled(shell, CLI_NAME); + if (installed) { + return; + } + + defaultRuntime.log(""); + defaultRuntime.log(theme.heading("Shell completion")); + + const shouldInstall = await confirm({ + message: stylePromptMessage(`Enable ${shell} shell completion for ${CLI_NAME}?`), + initialValue: true, + }); + + if (isCancel(shouldInstall) || !shouldInstall) { + if (!opts.skipPrompt) { + defaultRuntime.log( + theme.muted( + `Skipped. Run \`${replaceCliName(formatCliCommand("openclaw completion --install"), CLI_NAME)}\` later to enable.`, + ), + ); + } + return; + } + + await installCompletion(shell, opts.skipPrompt, CLI_NAME); +} + async function isEmptyDir(targetPath: string): Promise { try { const entries = await fs.readdir(targetPath); @@ -985,6 +1023,12 @@ export async function updateCommand(opts: UpdateCommandOptions): Promise { await tryWriteCompletionCache(root, Boolean(opts.json)); + // Offer to install shell completion if not already installed + await tryInstallShellCompletion({ + jsonMode: Boolean(opts.json), + skipPrompt: Boolean(opts.yes), + }); + // Restart service if requested if (shouldRestart) { if (!opts.json) {