diff --git a/setup/lib/browser.ts b/setup/lib/browser.ts index 9d801fa..fc6eb17 100644 --- a/setup/lib/browser.ts +++ b/setup/lib/browser.ts @@ -9,12 +9,18 @@ * `confirmThenOpen` pauses for the operator before triggering the open — * the browser tends to steal focus when it pops, and a split-second * "wait what just happened" moment is worse than letting the user hit - * Enter when they're ready. + * Enter when they're ready. On headless devices (no graphical session + * available) it skips both the prompt and the open: there's no browser + * to launch, the surrounding `note(...)` already shows the URL for + * copy-paste on another device, and the next prompt in the channel + * flow ("Got your bot token?" etc.) provides the natural completion + * confirmation. */ import { spawn } from 'child_process'; import * as p from '@clack/prompts'; +import { isHeadless } from '../platform.js'; import { ensureAnswer } from './runner.js'; /** Best-effort open of a URL in the user's default browser. Silent on failure. */ @@ -35,12 +41,15 @@ export function openUrl(url: string): void { /** * Gate a browser-open on a confirm so the user is ready for their browser * to take focus. Proceeds on cancel as well — the user can always copy the - * URL from the note that precedes the prompt. + * URL from the note that precedes the prompt. On headless devices both + * the prompt and the open are skipped — there's no browser to time + * focus for, and the URL is already visible in the surrounding note. */ export async function confirmThenOpen( url: string, message = 'Press Enter to open your browser', ): Promise { + if (isHeadless()) return; ensureAnswer( await p.confirm({ message,