diff --git a/src/commands/agents.commands.add.ts b/src/commands/agents.commands.add.ts index ec96d12cdf9..7b5eac50db6 100644 --- a/src/commands/agents.commands.add.ts +++ b/src/commands/agents.commands.add.ts @@ -11,6 +11,7 @@ import { } from "../agents/auth-profiles.js"; import { resolveAuthStorePath } from "../agents/auth-profiles/paths.js"; import { loadPersistedAuthProfileStore } from "../agents/auth-profiles/persisted.js"; +import { formatCliCommand } from "../cli/command-format.js"; import { commitConfigWithPendingPluginInstalls } from "../cli/plugins-install-record-commit.js"; import { logConfigUpdated } from "../config/logging.js"; import { pathExists } from "../infra/fs-safe.js"; @@ -97,7 +98,7 @@ export async function agentsAddCommand( if (nonInteractive && !workspaceFlag) { runtime.error( - "Non-interactive mode requires --workspace. Re-run without flags to use the wizard.", + `Non-interactive agent creation requires --workspace. Re-run ${formatCliCommand("openclaw agents add --workspace ")} or omit flags to use the wizard.`, ); runtime.exit(1); return; @@ -105,20 +106,24 @@ export async function agentsAddCommand( if (nonInteractive) { if (!nameInput) { - runtime.error("Agent name is required in non-interactive mode."); + runtime.error( + `Agent name is required in non-interactive mode. Run ${formatCliCommand("openclaw agents add --workspace ")}.`, + ); runtime.exit(1); return; } if (!workspaceFlag) { runtime.error( - "Non-interactive mode requires --workspace. Re-run without flags to use the wizard.", + `Non-interactive agent creation requires --workspace. Re-run ${formatCliCommand("openclaw agents add --workspace ")} or omit flags to use the wizard.`, ); runtime.exit(1); return; } const agentId = normalizeAgentId(nameInput); if (agentId === DEFAULT_AGENT_ID) { - runtime.error(`"${DEFAULT_AGENT_ID}" is reserved. Choose another name.`); + runtime.error( + `"${DEFAULT_AGENT_ID}" is reserved. Choose another name, or run ${formatCliCommand("openclaw agents list")} to inspect the default agent.`, + ); runtime.exit(1); return; } @@ -126,7 +131,9 @@ export async function agentsAddCommand( runtime.log(`Normalized agent id to "${agentId}".`); } if (findAgentEntryIndex(listAgentEntries(cfg), agentId) >= 0) { - runtime.error(`Agent "${agentId}" already exists.`); + runtime.error( + `Agent "${agentId}" already exists. Run ${formatCliCommand("openclaw agents list")} to inspect configured agents.`, + ); runtime.exit(1); return; } diff --git a/src/commands/auth-choice.apply.ts b/src/commands/auth-choice.apply.ts index 47138083005..f31d1acddaf 100644 --- a/src/commands/auth-choice.apply.ts +++ b/src/commands/auth-choice.apply.ts @@ -1,3 +1,4 @@ +import { formatCliCommand } from "../cli/command-format.js"; import { applyAuthChoiceLoadedPluginProvider } from "../plugins/provider-auth-choice.js"; import type { ApplyAuthChoiceParams, ApplyAuthChoiceResult } from "./auth-choice.apply.types.js"; import type { AuthChoice } from "./onboard-types.js"; @@ -56,7 +57,7 @@ async function formatDeprecatedProviderChoiceError( if (!deprecatedChoice) { return undefined; } - return `Auth choice ${JSON.stringify(authChoice)} is no longer supported. Use ${JSON.stringify(deprecatedChoice.choiceId)} instead.`; + return `Auth choice ${JSON.stringify(authChoice)} is no longer supported. Use ${JSON.stringify(deprecatedChoice.choiceId)} instead, or run ${formatCliCommand("openclaw onboard")} to choose interactively.`; } export async function applyAuthChoice( @@ -95,14 +96,14 @@ export async function applyAuthChoice( throw new Error( [ `Auth choice "${normalizedParams.authChoice}" was not matched to a provider setup flow.`, - 'For Anthropic legacy token auth, use "setup-token" with tokenProvider="anthropic" or choose the Anthropic setup-token entry explicitly.', + `Run ${formatCliCommand("openclaw models auth login --provider ")} for provider auth, or rerun ${formatCliCommand("openclaw onboard")} to choose interactively.`, ].join("\n"), ); } if (normalizedParams.authChoice === "oauth") { throw new Error( - 'Auth choice "oauth" is no longer supported directly. Use "setup-token" for Anthropic legacy token auth or a provider-specific OAuth entry.', + `Auth choice "oauth" is no longer supported directly. Use a provider-specific auth entry, or run ${formatCliCommand("openclaw models auth login --provider ")}.`, ); } diff --git a/src/commands/channels/resolve.ts b/src/commands/channels/resolve.ts index 9642c99ed63..f3adc357d87 100644 --- a/src/commands/channels/resolve.ts +++ b/src/commands/channels/resolve.ts @@ -4,6 +4,7 @@ import type { ChannelResolveResult, } from "../../channels/plugins/types.adapters.js"; import { resolveCommandConfigWithSecrets } from "../../cli/command-config-resolution.js"; +import { formatCliCommand } from "../../cli/command-format.js"; import { getChannelsCommandSecretTargetIds } from "../../cli/command-secret-targets.js"; import { commitConfigWithPendingPluginInstalls } from "../../cli/plugins-install-record-commit.js"; import { refreshPluginRegistryAfterConfigMutation } from "../../cli/plugins-registry-refresh.js"; @@ -130,7 +131,9 @@ export async function channelsResolveCommand(opts: ChannelsResolveOptions, runti }); const entries = (opts.entries ?? []).map((entry) => entry.trim()).filter(Boolean); if (entries.length === 0) { - throw new Error("At least one entry is required."); + throw new Error( + `At least one entry is required. Example: ${formatCliCommand("openclaw channels resolve --channel discord ")}.`, + ); } const explicitChannel = opts.channel?.trim(); @@ -145,7 +148,7 @@ export async function channelsResolveCommand(opts: ChannelsResolveOptions, runti : null; if (explicitChannel && resolvedExplicit?.catalogEntry && !resolvedExplicit.plugin) { throw new Error( - `Channel plugin "${resolvedExplicit.catalogEntry.id}" is not installed. Run "openclaw channels add --channel ${resolvedExplicit.catalogEntry.id}" first.`, + `Channel plugin "${resolvedExplicit.catalogEntry.id}" is not installed. Run ${formatCliCommand(`openclaw channels add --channel ${resolvedExplicit.catalogEntry.id}`)} first.`, ); } if (resolvedExplicit?.configChanged) { @@ -193,7 +196,9 @@ export async function channelsResolveCommand(opts: ChannelsResolveOptions, runti (selection.channel ? getChannelPlugin(selection.channel) : undefined); if (!plugin?.resolver?.resolveTargets) { const channelText = selection.channel ?? explicitChannel ?? ""; - throw new Error(`Channel ${channelText} does not support resolve.`); + throw new Error( + `Channel ${channelText} does not support resolve. Run ${formatCliCommand("openclaw channels capabilities --channel " + channelText)} to inspect supported actions.`, + ); } const preferredKind = resolvePreferredKind(opts.kind); diff --git a/src/commands/migrate.ts b/src/commands/migrate.ts index e48a8810e76..49a988b9f14 100644 --- a/src/commands/migrate.ts +++ b/src/commands/migrate.ts @@ -1,4 +1,5 @@ import { cancel, isCancel } from "@clack/prompts"; +import { formatCliCommand } from "../cli/command-format.js"; import { promptYesNo } from "../cli/prompt.js"; import { getRuntimeConfig } from "../config/config.js"; import { redactMigrationPlan } from "../plugin-sdk/migration.js"; @@ -119,7 +120,9 @@ export async function migrateListCommand(runtime: RuntimeEnv, opts: { json?: boo return; } if (providers.length === 0) { - runtime.log("No migration providers found."); + runtime.log( + `No migration providers found. Run ${formatCliCommand("openclaw plugins list")} to verify provider plugins are installed and enabled.`, + ); return; } runtime.log( @@ -139,7 +142,9 @@ export async function migratePlanCommand( ): Promise { const providerId = opts.provider?.trim(); if (!providerId) { - throw new Error("Migration provider is required."); + throw new Error( + `Migration provider is required. Run ${formatCliCommand("openclaw migrate list")} to choose one.`, + ); } const plan = selectMigrationItems( await createMigrationPlan(runtime, { ...opts, provider: providerId }), @@ -167,13 +172,17 @@ export async function migrateApplyCommand( ): Promise { const providerId = opts.provider?.trim(); if (!providerId) { - throw new Error("Migration provider is required."); + throw new Error( + `Migration provider is required. Run ${formatCliCommand("openclaw migrate list")} to choose one.`, + ); } if (opts.noBackup && !opts.force) { - throw new Error("--no-backup requires --force."); + throw new Error("--no-backup requires --force because it skips the automatic rollback copy."); } if (!opts.yes && !process.stdin.isTTY) { - throw new Error("openclaw migrate apply requires --yes in non-interactive mode."); + throw new Error( + `openclaw migrate apply requires --yes in non-interactive mode. Preview first with ${formatCliCommand("openclaw migrate plan --provider ")}.`, + ); } const provider = resolveMigrationProvider(providerId); if (!opts.yes) {