Skip to content

fix(cli): auth login --device works without a terminal - #7045

Merged
miguel-heygen merged 1 commit into
mainfrom
fix/device-login-no-tty
Nov 3, 2026
Merged

miguel-heygen merged 1 commit into
mainfrom
fix/device-login-no-tty

Conversation

@miguel-heygen

@miguel-heygen miguel-heygen commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

What

hyperframes auth login --device now runs when there is no terminal (a coding agent's shell, an SSH command with no TTY). It still refuses in CI.

Why

Device login only prints a URL and a code and then polls, so it needs no terminal on this side; the person approves in any browser. assertAttendedDeviceFlow in packages/cli/src/commands/auth/login.ts refused unless stdin and stdout were both TTYs, so on a remote box or from an agent's ! command the plain login said "use --device" and --device said "requires an attended terminal". The signed-out path could not finish. The one check is now "not CI", the only place the flow has nobody to approve it.

Testing

fails without the fix: packages/cli/src/commands/auth/login.test.ts > "runs device authorization without a terminal, where only a URL and code are printed"

login.test.ts: the old "refuses device authorization when either terminal stream is not a TTY" test becomes "runs device authorization without a terminal". It fails on main (1 failed | 29 passed) and passes with the change, 3 runs in a row (30 passed). The CI refusal test is unchanged and still passes.

Size

A small root fix to one check and its test; it has no other carrier.

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes at caf6b70 because of the PR body. The code is fine.

Blocker: this is a fix(...) PR, and the body has no fails without the fix: line. The Testing section describes the right test, but it has to be on that line. Add something like:

fails without the fix: packages/cli/src/commands/auth/login.test.ts > "runs device authorization without a terminal, where only a URL and code are printed"

Once that line is in, I'll approve this head with no code changes.

Code (no changes needed):

  • The device flow only prints a URL and code, then polls. So isCI() is the right single gate, and the old TTY check was what stranded agent and SSH users after the plain-login path told them to use --device.
  • isAttendedTerminal is still used by isUnattended and by telemetry, so dropping the import here is self-contained.
  • The CI refusal test is unchanged. The new test sets both streams to non-TTY, which covers the old behaviour.

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving at caf6b70 (same head I reviewed before). The body now has the required line: fails without the fix: packages/cli/src/commands/auth/login.test.ts > "runs device authorization without a terminal, where only a URL and code are printed". That was my only blocker. The code is unchanged and my earlier assessment still holds: isCI() is the single gate for device login, and the CI refusal test is kept. CI on this head has a completed green run.

@miguel-heygen
miguel-heygen added this pull request to the merge queue Nov 2, 2026
Merged via the queue into main with commit de2603e Nov 3, 2026
117 checks passed
@miguel-heygen
miguel-heygen deleted the fix/device-login-no-tty branch November 3, 2026 00:01
@jrusso1020 jrusso1020 mentioned this pull request Nov 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant