From 5c4f830fea55addf398c5c5e2c5bdd71a29cf962 Mon Sep 17 00:00:00 2001 From: A <258483684+la14-1@users.noreply.github.com> Date: Wed, 11 Feb 2026 03:42:55 -0800 Subject: [PATCH] fix: improve credential guidance in error messages and quick-start hints (#427) - Show cloud provider URL alongside credential env vars in quick-start sections (both `spawn ` and `spawn ` info views) - Restructure script failure errors: separate credential issues from other causes, inline the `spawn ` hint next to cloud credentials - Replace "Check cloud-specific READMEs" with actionable `spawn ` in help troubleshooting section - Show concise 4-line guidance instead of full help dump when spawn is run without a TTY (e.g. piped or in CI) - Add `spawn ` as primary action in `spawn list` footer Agent: ux-engineer Co-authored-by: A <6723574+louisgv@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) --- cli/package.json | 2 +- cli/src/commands.ts | 24 +++++++++++++----------- cli/src/index.ts | 9 +++++++-- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/cli/package.json b/cli/package.json index be250adb..37ddb28a 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,6 +1,6 @@ { "name": "@openrouter/spawn", - "version": "0.2.34", + "version": "0.2.35", "type": "module", "bin": { "spawn": "cli.js" diff --git a/cli/src/commands.ts b/cli/src/commands.ts index e597988d..c2ccd348 100644 --- a/cli/src/commands.ts +++ b/cli/src/commands.ts @@ -434,12 +434,12 @@ async function execScript(cloud: string, agent: string, prompt?: string): Promis } p.log.error("Spawn script failed"); console.error("\nError:", errMsg); - console.error("\nCommon causes:"); - console.error(" - Missing OPENROUTER_API_KEY (get one at https://openrouter.ai/settings/keys)"); - console.error(" - Missing cloud provider credentials (API key, token, etc.)"); + console.error("\nCheck your credentials:"); + console.error(` - OPENROUTER_API_KEY ${pc.dim("https://openrouter.ai/settings/keys")}`); + console.error(` - Cloud credentials ${pc.dim(`run ${pc.cyan(`spawn ${cloud}`)} for setup instructions`)}`); + console.error("\nOther causes:"); console.error(" - Cloud provider API rate limit or quota exceeded"); console.error(" - Missing local dependencies (SSH, curl, etc.)"); - console.error(`\nRun ${pc.cyan(`spawn ${cloud}`)} to see setup instructions for this provider.`); process.exit(1); } } @@ -594,7 +594,7 @@ export async function cmdList(): Promise { console.log(`${pc.green("+")} implemented ${pc.dim("-")} not yet available`); } console.log(pc.green(`${impl}/${total} combinations implemented`)); - console.log(pc.dim(`Run ${pc.cyan("spawn ")} or ${pc.cyan("spawn ")} for details.`)); + console.log(pc.dim(`Launch: ${pc.cyan("spawn ")} | Details: ${pc.cyan("spawn ")} or ${pc.cyan("spawn ")}`)); console.log(); } @@ -707,13 +707,14 @@ export async function cmdAgentInfo(agent: string): Promise { // Show quick-start with first available cloud if (implClouds.length > 0) { const exampleCloud = implClouds[0]; - const authVars = parseAuthEnvVars(manifest.clouds[exampleCloud].auth); - const cloudName = manifest.clouds[exampleCloud].name; + const cloudDef = manifest.clouds[exampleCloud]; + const authVars = parseAuthEnvVars(cloudDef.auth); console.log(); console.log(pc.bold("Quick start:")); console.log(` ${pc.cyan("export OPENROUTER_API_KEY=sk-or-v1-...")} ${pc.dim("# https://openrouter.ai/settings/keys")}`); if (authVars.length > 0) { - console.log(` ${pc.cyan(`export ${authVars[0]}=...`)} ${pc.dim(`# ${cloudName} credential`)}`); + const hint = cloudDef.url ? ` ${pc.dim(`# ${cloudDef.url}`)}` : ` ${pc.dim(`# ${cloudDef.name} credential`)}`; + console.log(` ${pc.cyan(`export ${authVars[0]}=...`)}${hint}`); } console.log(` ${pc.cyan(`spawn ${agentKey} ${exampleCloud}`)}`); } @@ -757,7 +758,7 @@ async function validateAndGetCloud(cloud: string): Promise<[manifest: Manifest, /** Print quick-start auth instructions for a cloud provider */ function printCloudQuickStart( - cloud: { auth: string }, + cloud: { auth: string; url?: string }, authVars: string[], exampleAgent: string | undefined, cloudKey: string @@ -766,8 +767,9 @@ function printCloudQuickStart( console.log(pc.bold("Quick start:")); console.log(` ${pc.cyan("export OPENROUTER_API_KEY=sk-or-v1-...")} ${pc.dim("# https://openrouter.ai/settings/keys")}`); if (authVars.length > 0) { + const hint = cloud.url ? ` ${pc.dim(`# ${cloud.url}`)}` : ""; for (const v of authVars) { - console.log(` ${pc.cyan(`export ${v}=your-${v.toLowerCase().replace(/_/g, "-")}-here`)}`); + console.log(` ${pc.cyan(`export ${v}=...`)}${hint}`); } } else if (cloud.auth.toLowerCase() !== "none") { console.log(` ${pc.dim(`Auth: ${cloud.auth}`)}`); @@ -921,7 +923,7 @@ ${pc.bold("INSTALL")} ${pc.bold("TROUBLESHOOTING")} ${pc.dim("*")} Script not found: Run ${pc.cyan("spawn list")} to verify the combination exists - ${pc.dim("*")} Missing credentials: Check cloud-specific READMEs in the repo + ${pc.dim("*")} Missing credentials: Run ${pc.cyan("spawn ")} to see setup instructions ${pc.dim("*")} Update issues: Try ${pc.cyan("spawn update")} or reinstall manually ${pc.dim("*")} Garbled unicode: Set ${pc.cyan("SPAWN_NO_UNICODE=1")} for ASCII-only output ${pc.dim("*")} Slow startup: Set ${pc.cyan("SPAWN_NO_UPDATE_CHECK=1")} to skip auto-update diff --git a/cli/src/index.ts b/cli/src/index.ts index abb42f11..eac8e2e7 100644 --- a/cli/src/index.ts +++ b/cli/src/index.ts @@ -237,8 +237,13 @@ async function handleNoCommand(prompt: string | undefined): Promise { await cmdInteractive(); } else { console.error(pc.yellow("No interactive terminal detected.")); - console.error(pc.dim(`To launch directly: ${pc.cyan("spawn ")}\n`)); - cmdHelp(); + console.error(); + console.error(` Launch directly: ${pc.cyan("spawn ")}`); + console.error(` Browse agents: ${pc.cyan("spawn agents")}`); + console.error(` Browse clouds: ${pc.cyan("spawn clouds")}`); + console.error(` Full help: ${pc.cyan("spawn help")}`); + console.error(); + process.exit(1); } }