massu login hung forever in non-interactive shells (CI / scripts / agents) with MASSU_API_KEY set (plan-2026-07-06-login-noninteractive-env-hang). runLogin() never read the MASSU_API_KEY environment variable and then read a non-TTY stdin unbounded (for await … process.stdin, blocking on an EOF that never arrives on an idle non-TTY stdin), so the documented, non-exposing scripted path (MASSU_API_KEY=<key> massu login) blocked indefinitely — the only working non-interactive path was --key, which leaks the key to shell history. Patch per semver: a bug fix with no API change, scoped entirely to the login command. Incident #1.
Fixed
massu loginno longer hangs without a TTY. Key resolution is now a pure, dependency-injectedresolveLoginKey()with explicit precedence:--key>MASSU_API_KEYenv > TTY prompt > bounded non-TTY stdin. The env var is read before any stdin touch (the reported hang case), and the non-TTY read is bounded byMASSU_LOGIN_STDIN_TIMEOUT_MS(default 2000ms) and capped at 64KB, so an idle or oversized stdin fails fast (fail-closed) with an actionable message instead of hanging;echo "$KEY" | massu loginstill works. A structural regression guard makes the interactive prompt / blocking stdin read unreachable when a key is available and stdin is not a TTY, and a help↔code contract test assertsloginhonors the advertisedMASSU_API_KEY.
Added
--keynow prints a shell-history exposure warning to stderr when a key is passed via the flag, steering scripted/CI usage towardMASSU_API_KEYor a piped key.