From 9e3b1408f332882d5a8633e2aa2c5890bee195a6 Mon Sep 17 00:00:00 2001 From: cursive <44798535+Cursivez@users.noreply.github.com> Date: Sat, 3 Jan 2026 16:43:25 +0800 Subject: [PATCH] Copy OAuth login URL to clipboard for mobile SSH users (#415) --- .../src/modes/interactive/interactive-mode.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/coding-agent/src/modes/interactive/interactive-mode.ts b/packages/coding-agent/src/modes/interactive/interactive-mode.ts index 238aaa5c..929b1fee 100644 --- a/packages/coding-agent/src/modes/interactive/interactive-mode.ts +++ b/packages/coding-agent/src/modes/interactive/interactive-mode.ts @@ -1994,15 +1994,26 @@ export class InteractiveMode { await this.session.modelRegistry.authStorage.login(providerId as OAuthProvider, { onAuth: (info: { url: string; instructions?: string }) => { this.chatContainer.addChild(new Spacer(1)); - // Use OSC 8 hyperlink escape sequence for clickable link + + // OSC 8 hyperlink for desktop terminals that support clicking const hyperlink = `\x1b]8;;${info.url}\x07Click here to login\x1b]8;;\x07`; this.chatContainer.addChild(new Text(theme.fg("accent", hyperlink), 1, 0)); + + // OSC 52 to copy URL to clipboard (works over SSH, e.g., Termux) + const urlBase64 = Buffer.from(info.url).toString("base64"); + process.stdout.write(`\x1b]52;c;${urlBase64}\x07`); + this.chatContainer.addChild( + new Text(theme.fg("dim", "(URL copied to clipboard - paste in browser)"), 1, 0), + ); + if (info.instructions) { this.chatContainer.addChild(new Spacer(1)); this.chatContainer.addChild(new Text(theme.fg("warning", info.instructions), 1, 0)); } + this.ui.requestRender(); + // Try to open browser on desktop const openCmd = process.platform === "darwin" ? "open"