Skip to content

Commit 090342c

Browse files
improvement(setup): drop the paste-a-key fallback, simplify consent copy
The browser handoff is now the only path — the wizard waits on a spinner instead of racing a paste prompt. Consent card leads with "Connect your terminal" and moves the match-the-code disclaimer into the description.
1 parent 9a9132e commit 090342c

4 files changed

Lines changed: 18 additions & 58 deletions

File tree

apps/sim/app/cli/auth/cli-auth-view.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ export function CliAuthView() {
4040
return (
4141
<div className='space-y-6'>
4242
<AuthHeader
43-
title='Does this match your terminal?'
44-
description='Approve only if your terminal is showing this same code.'
43+
title='Connect your terminal'
44+
description='Approve only if the code below matches the one in your terminal.'
4545
/>
4646
<div className='space-y-4'>
4747
<div className='flex items-center justify-center rounded-[10px] border border-[var(--border-1)] py-5'>
@@ -65,7 +65,7 @@ export function CliAuthView() {
6565
)
6666
}
6767
>
68-
Codes match — connect terminal
68+
Connect
6969
</AuthSubmitButton>
7070
{approve.isError && (
7171
<AuthFormMessage type='error' align='center'>

apps/sim/app/cli/auth/loading.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,16 @@ import { AuthShell } from '@/app/(auth)/components'
44
/**
55
* Consent-card skeleton, shared by the route fallback and `page.tsx`'s Suspense.
66
*
7-
* Bars mirror the card's boxes so hydration doesn't shift the layout: the
8-
* heading and description each wrap to two lines in the 400px column, then the
9-
* 70px pairing panel (28px type + `py-5` + 1px border) and the `h-9` button.
7+
* Bars mirror the card's boxes so hydration doesn't shift the layout: a
8+
* one-line heading, a description that wraps to two in the 400px column, then
9+
* the 70px pairing panel (28px type + `py-5` + 1px border) and the `h-9` button.
1010
*/
1111
export function CliAuthLoading() {
1212
return (
1313
<div className='flex w-full flex-col items-center'>
14-
<Skeleton className='h-[38px] w-[300px] rounded-[4px]' />
15-
<Skeleton className='h-[38px] w-[220px] rounded-[4px]' />
16-
<Skeleton className='mt-1 h-[23px] w-[340px] rounded-[4px]' />
17-
<Skeleton className='h-[23px] w-[260px] rounded-[4px]' />
14+
<Skeleton className='h-[38px] w-[280px] rounded-[4px]' />
15+
<Skeleton className='mt-1 h-[23px] w-[360px] rounded-[4px]' />
16+
<Skeleton className='h-[23px] w-[240px] rounded-[4px]' />
1817
<Skeleton className='mt-6 h-[70px] w-full rounded-[10px]' />
1918
<Skeleton className='mt-4 h-9 w-full rounded-[10px]' />
2019
</div>

scripts/setup/cli-auth.ts

Lines changed: 9 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,8 @@ async function exchangeCode(
136136
}
137137

138138
/**
139-
* Races the browser handoff against a live paste prompt — whichever produces
140-
* a key first wins. Returns null when the handoff times out with nothing
141-
* pasted; ctrl-c cancels setup as everywhere else.
139+
* Waits for the browser handoff and redeems the code it returns. Null on
140+
* timeout or a failed exchange; ctrl-c exits setup via the SIGINT handler.
142141
*/
143142
export async function browserKeyFlow(origin: string): Promise<string | null> {
144143
const listener = await startCodeListener(origin)
@@ -151,35 +150,12 @@ export async function browserKeyFlow(origin: string): Promise<string | null> {
151150
)
152151
openBrowser(listener.authUrl)
153152

154-
const controller = new AbortController()
155-
let browserDone = false
156-
listener.code.then(() => {
157-
browserDone = true
158-
controller.abort()
159-
})
153+
const spin = p.spinner()
154+
spin.start('Waiting for approval in your browser')
155+
const code = await listener.code
156+
spin.stop(code ? 'Approved' : 'Browser handoff timed out')
160157

161-
for (;;) {
162-
const input = await p.passwordCancellable({
163-
message: 'Waiting for the browser… (or paste a key here)',
164-
signal: controller.signal,
165-
})
166-
if (p.isCancel(input)) {
167-
if (browserDone) {
168-
const code = await listener.code
169-
if (!code) {
170-
p.log.warn('Browser handoff timed out with no key.')
171-
return null
172-
}
173-
const key = await exchangeCode(origin, code, listener.verifier)
174-
if (key) p.log.step('Key received from browser')
175-
return key
176-
}
177-
listener.close()
178-
p.cancelAndExit()
179-
}
180-
if (input) {
181-
listener.close()
182-
return input
183-
}
184-
}
158+
if (!code) return null
159+
160+
return exchangeCode(origin, code, listener.verifier)
185161
}

scripts/setup/prompter.ts

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -113,18 +113,3 @@ export function cancelAndExit(): never {
113113
clack.cancel('Setup cancelled.')
114114
exitWith(130)
115115
}
116-
117-
/**
118-
* Password prompt that surfaces cancellation (abort or ctrl-c) as a symbol
119-
* instead of exiting — for flows that race a prompt against a background
120-
* event and must tell the two apart.
121-
*/
122-
export async function passwordCancellable(params: {
123-
message: string
124-
signal: AbortSignal
125-
}): Promise<string | symbol> {
126-
return clack.password({
127-
message: isRich() ? theme.accent(params.message) : params.message,
128-
signal: params.signal,
129-
})
130-
}

0 commit comments

Comments
 (0)