Repository navigation
Description
Summary
hookdeck login opens a browser window and blocks indefinitely when there is no terminal, instead of failing fast with guidance.
Reproduce
With an empty config and no TTY:
hookdeck login --hookdeck-config <empty.toml> </dev/null # stdout+stderr redirectedOutput: Press Enter to open the browser (^C to quit)Waiting for confirmation...
It then opens a real browser window on the user's desktop and blocks. Killed at 60s with no sign of stopping on its own. This happened to a maintainer during testing.
Root cause
pkg/login/client_login.go:
Login()has the headless guard, but only insideif config.Profile.APIKey != ""(~line 62):needsStdin := !isSSH() && canOpenBrowser() if !stdinIsTerminal() && needsStdin { return ErrRejectedKeyNoTerminal }
- With an empty config that entire block is skipped, so execution reaches
waitForLoginSession()unguarded. - There (~line 120) the else-branch does
fmt.Printf("Press Enter to open the browser (^C to quit)"), thenfmt.Fscanln(input), thenopenBrowser(...). With stdin at/dev/null,Fscanlnreturns instantly on EOF and the browser opens anyway.
The comment above the existing guard reads "mirroring the branch in waitForLoginSession" — so the branch was known about, and only the rejected-key path was guarded.
The isSSH() || !canOpenBrowser() branch prints a URL and polls without reading stdin. That works headlessly and must keep working.
Why this matters
Any CI job, Dockerfile, nohup script or coding agent that runs hookdeck login hangs indefinitely and spawns browser processes.
It also means the v2.5.0 release-note claim for #337 — "Unauthenticated commands no longer hang for four minutes… Without a terminal it now exits immediately with instructions" — was never true for hookdeck login itself.
Two sub-issues on the same line
Press Enter to open the browser (^C to quit)has no trailing newline, so it runs straight intoWaiting for confirmation....- It advertises
^C to quitwhile holding no terminal that can deliver^C.
Suggested fix
Apply the same guard on the fresh-login path, with an error matching the quality of the existing rejected-key message — naming hookdeck ci --api-key, hookdeck login --cli-key, and HOOKDECK_API_KEY as the ways forward.
Testing
Unit: pkg/login/client_login_test.go already stubs stdinIsTerminal and canOpenBrowser. Cover no-key + no-terminal + browser-capable → fast error and no browser; no-key + no-terminal + SSH → still prints the URL and polls.
Related
- Unauthenticated commands hang for ~4 minutes instead of failing when there is no terminal #337 — the v2.5.0 headless work this case escaped
Filed by Claude on Phil's behalf, from release-candidate testing.
Activity
fix: stop hookdeck login opening a browser where nobody asked for one
fix: guard the guest-upgrade browser branch, and always print the sig…
!20268 merge bump-hookdeck-2.6.0 into main