Skip to content

fix(login): do not prompt for a default number without a TTY#42

Open
jflayhart wants to merge 1 commit into
bump-sdk-0.31from
login-headless-token
Open

fix(login): do not prompt for a default number without a TTY#42
jflayhart wants to merge 1 commit into
bump-sdk-0.31from
login-headless-token

Conversation

@jflayhart

Copy link
Copy Markdown
Collaborator

Branched off #40 (bump-sdk-0.31) to keep the diff readable; the change itself is independent of the SDK version. Retargets to main once #40 merges.

The problem

linq login --token <t> is the documented non-interactive path. On a paid account with more than one Linq Number it fell through to an interactive select() with no TTY guard:

login.ts:92   if (!process.stdin.isTTY) { ... }   // guards the TOKEN prompt
login.ts:160  fromPhone = await select({ ... })   // number picker — unguarded
login.ts:175  await saveProfile(...)              // never reached

With no TTY the prompt can never be answered, so the command blocks and exits before saveProfile(). No token is written, and every later command fails as unauthenticated with nothing explaining why. Reproduced from an agent shell: exits 0, writes nothing.

It also explains the Detected unsettled top-level await warning on Node 26 — bin/run.js awaits execute() at the top level, so a prompt that never resolves surfaces there rather than at the call site. Same root cause, not a separate Node compatibility issue.

The change

Prompt only when stdin is a TTY. Otherwise default to the first number, say which one was picked, and point at linq phonenumbers set:

Defaulted to +18005551111 of 2 Linq Numbers (no terminal for the picker).
Change it with linq phonenumbers set.

Shared and sandbox accounts already auto-picked, so only the paid multi-number path changes.

Note for review

The existing test paid user with multiple phones is prompted asserted behaviour that only holds with a terminal — it passed because the unguarded prompt ran regardless. It now stubs isTTY explicitly, which makes its assumption visible, and a new regression test covers the headless path end to end (token persisted, no prompt, first number chosen).

174 tests pass.

🤖 Generated with Claude Code

https://claude.ai/code/session_01L3QhRZE6nKoGLGNhzUkmmF

`linq login --token <t>` is the documented non-interactive path, but on a paid
account with more than one Linq Number it fell through to an interactive
select() with no TTY guard. The prompt could never be answered, so the command
blocked and exited before saveProfile() ran — no token was written, and every
later command failed as unauthenticated with nothing explaining why.

The token prompt earlier in the same command already guards on
process.stdin.isTTY; the number picker did not.

It now prompts only when stdin is a TTY, and otherwise defaults to the first
number, saying which one it picked and pointing at `linq phonenumbers set`.
Shared and sandbox accounts already auto-picked, so this only changes the paid
multi-number path.

This also clears the "Detected unsettled top-level await" warning on Node 26:
bin/run.js awaits execute() at the top level, so a prompt that never resolves
surfaces there rather than at the call site.

The existing prompt test asserted behaviour that only holds with a terminal, so
it now stubs isTTY explicitly, and a regression test covers the headless path.
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.

2 participants