feat(setup): default into GitHub login when setup finishes logged-out on a TTY

Merged
TO
3mo ago
+128-4

Tony's ask: the one command should carry the whole journey, curl-installer style, and "default login if not logged in makes sense".

After the βœ“ checkmarks, when setup ran on an interactive human terminal with no stored session, it now flows straight into insta login --oauth github β€” Enter continues into the browser, n skips. shouldOfferLogin (pure, tested) gates it:

  • -y runs, piped stdin/stdout, agents, CI: never prompted (a browser OAuth flow can't work there; they keep the printed next: hint, and prompt.md walks agents through login as its own step, relaying the sign-in link to the human).
  • Already logged in: straight to the next: insta project create hint.
  • Declined prompt or failed browser flow: best-effort β€” setup already succeeded, prints the manual hint, never an error, exit code untouched (tested).

The flow is injected (LoginFlow) so tests never touch a real TTY or browser. Gate: typecheck clean, 410/410 tests (4 new).

Ships in 0.0.39 (0.0.38 = #116 alone, releasing now via #118 β€” kept separate so the staging fix isn't held by this review).

πŸ€– Generated with Claude Code


Summary by cubic

Defaults setup into GitHub OAuth login when it finishes on an interactive TTY without a session, instead of only printing a manual next step. This reduces first-run friction while keeping non-interactive and already-logged-in behavior unchanged.

  • Adds pure gate shouldOfferLogin(yes, loggedIn, stdinTty, stdoutTty); when true, prompts β€œlog in now with GitHub? (Y/n)” and runs insta login --oauth github on Enter.
  • Non-TTY and -y runs never prompt; logged-in users go straight to the project-create hint. EOF (Ctrl-D) counts as decline. Declined or failed browser login is best-effort: setup still succeeds, prints the manual hint, and points SSH users to insta login --device.
  • With --mcp-token, re-runs MCP token registration after a successful interactive login so the token mints with the new session; tests pin that registration happens exactly once and only after login.
  • Injects LoginFlow (ask/login/stdinTty/stdoutTty) with a readline-based default; adds tests for gating, TTY flow, decline/failure, non-TTY cases, and the --mcp-token contract.