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:
- The CLI prints a "Press Enter to open the browser…" style prompt to stdout, then calls
read() on stdin.
- 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.
- 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)
-
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.
-
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.
-
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.
Summary
gws auth loginblocks indefinitely with no visible output when stdout is not attached to a TTY — for example, when theCLI 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:
read()on stdin.exits — so nothing appears while the process waits on stdin.
Reproduction
In any non-TTY context — easiest to repro with a redirect:
The process is sitting on
read()waiting for an Enter that the user doesn't know to give, because the prompt text nevermade it to stdout.
Proposed fixes (any one helps; all three would be ideal)
Flush stdout (or write the prompt to stderr) before
read().process.stdoutis block-buffered when not a TTY; anexplicit 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.
Add a non-interactive flag. Something like
--yes,--no-prompt, or--non-interactivethat skips the "PressEnter" confirmation and either opens the browser immediately or just prints the URL for the caller to handle. This is the
right primitive for automation.
Auto-skip the prompt when stdin is not a TTY (
process.stdin.isTTY === false). In that environment there's no humanto 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
script -q /dev/null gws auth login(macOS).printf '\n' | gws auth login— works only if you don't actually need to see the prompt.gwscan detectisatty(0) === falseand pre-feed\non stdin to satisfy the read.Environment
@googleworkspace/cli0.18.1