Skip to content

auth login blocks indefinitely when stdout/stdin is not a TTY (prompt invisible, no way to skip) #781

@lgameplayer

Description

@lgameplayer

Summary

gws auth login blocks indefinitely with no visible output when stdout is not attached to a TTY — for example, when the
CLI is invoked from a script with redirected stdout, from a CI runner, from cron, from a non-PTY ssh session, or from any
harness that gives the child a pipe instead of a real terminal for stdout.

The user-visible symptom is "the command appears frozen." Two things combine to produce it:

  1. The CLI prints a "Press Enter to open the browser…" style prompt to stdout, then calls read() on stdin.
  2. When stdout is not a TTY, Node block-buffers it. The prompt text doesn't flush until the buffer fills or the process
    exits — so nothing appears while the process waits on stdin.
  3. There is no flag to skip the prompt non-interactively.

Reproduction

In any non-TTY context — easiest to repro with a redirect:

gws auth login >/tmp/out 2>&1 &
sleep 5                                                                                                                    
ps -ef | grep gws   # still running
cat /tmp/out        # empty (or only the URL, no prompt)                                                                   

The process is sitting on read() waiting for an Enter that the user doesn't know to give, because the prompt text never
made it to stdout.

Proposed fixes (any one helps; all three would be ideal)

  1. Flush stdout (or write the prompt to stderr) before read(). process.stdout is block-buffered when not a TTY; an
    explicit flush — or routing prompts to process.stderr, which is line-buffered — makes the prompt visible immediately.
    This alone removes the "appears frozen" symptom for redirected-output users.

  2. Add a non-interactive flag. Something like --yes, --no-prompt, or --non-interactive that skips the "Press
    Enter" confirmation and either opens the browser immediately or just prints the URL for the caller to handle. This is the
    right primitive for automation.

  3. Auto-skip the prompt when stdin is not a TTY (process.stdin.isTTY === false). In that environment there's no human
    to press Enter; the prompt cannot succeed, only block. Defaulting to "skip" when stdin is non-interactive is consistent
    with how most modern CLIs behave (gh, npm, docker login, etc.).

Workarounds

  • Run from a real PTY: script -q /dev/null gws auth login (macOS).
  • Pre-feed a newline: printf '\n' | gws auth login — works only if you don't actually need to see the prompt.
  • A wrapper around gws can detect isatty(0) === false and pre-feed \n on stdin to satisfy the read.

Environment

  • @googleworkspace/cli 0.18.1
  • macOS 26.4.1 (Darwin 25.4.0), Node 24.14.0
  • Reproduced via redirected stdout in bash and via Claude Code's pseudo-TTY harness.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions