Conversation
Replace term.ReadPassword (which shows no visual feedback) with a charmbracelet/huh masked input that displays asterisks during typing. This fixes the Windows issue where the password prompt appeared to accept no input, and improves UX on all platforms. Also adds pipe detection: when stdin is not a terminal, the password is read from the pipe, enabling scripted usage like: echo "password" | msgvault add-imap --host ... --username ... Closes #209 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
roborev: Combined Review (
|
Address two review findings: 1. Use go-isatty (IsTerminal + IsCygwinTerminal) instead of x/term for TTY detection, matching the pattern used elsewhere in the codebase. This fixes Cygwin/MSYS pseudo-terminals falling through to the pipe path. 2. Only use the huh TUI prompt when both stdin and stdout are terminals. When stdout is redirected (but stdin is a terminal), fall back to term.ReadPassword to avoid leaking TUI escape sequences into the redirected output. The prompt is written to stderr in this case. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
roborev: Combined Review (
|
…rHash Address review finding: term.ReadPassword doesn't work on Cygwin/mintty PTYs because it uses Windows console APIs. Split TTY detection into native vs Cygwin: - Native terminal + stdout redirected: term.ReadPassword (works fine) - Cygwin terminal + stdout redirected: huh with output on stderr (avoids both the Cygwin PTY issue and TUI escape sequence leakage) Also refactor readPasswordInteractive to accept an io.Writer so the Form can direct TUI output to either stdout or stderr. Update nix flake vendorHash for new huh dependency. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
roborev: Combined Review (
|
Address two review findings: 1. Check stderr (not stdout) TTY status for the huh prompt, since the prompt is UI chrome and should never go to stdout. This means stdout redirection never triggers the fallback path at all. 2. Handle Cygwin PTY with stderr redirected: fail with a clear error message since neither term.ReadPassword (Cygwin-incompatible) nor huh (needs TTY for output) can work in that configuration. The decision matrix is now: - stdin TTY + stderr TTY → huh on stderr (asterisk masking) - native stdin TTY + stderr redirected → term.ReadPassword - Cygwin stdin TTY + stderr redirected → clear error - stdin not TTY → pipe read Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
roborev: Combined Review (
|
Prefer stderr for the huh prompt (keeps stdout clean), but fall back to stdout when stderr is redirected (e.g. 2>errors.log). This avoids the prompt disappearing into a log file while the terminal appears to hang. The term.ReadPassword and Cygwin error paths only trigger when neither output stream is a TTY. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
roborev: Combined Review (
|
Address two review findings: 1. Extract choosePasswordStrategy() with table-driven tests covering all stdin/stdout/stderr TTY combinations (native, Cygwin, piped). This prevents the regressions that occurred across prior commits. 2. When both stdout and stderr are redirected, fail with a clear error instead of prompting invisibly. This replaces the term.ReadPassword path, which allowed the golang.org/x/term direct dependency to be removed. The strategy is now a pure function of four booleans, fully tested: - stdin TTY + stderr TTY → huh on stderr - stdin TTY + stdout TTY (stderr redirected) → huh on stdout - stdin TTY + no output TTY → clear error - stdin not TTY → pipe read Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
roborev: Combined Review (
|
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
roborev: Combined Review (
|
Usage: powershell -File scripts/build.ps1 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
roborev: Combined Review (
|
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
roborev: Combined Review (
|
The help text showed `echo "password" | msgvault add-imap ...` which exposes the password in shell history and process listings. Replace with `read -s` example that avoids this. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
roborev: Combined Review (
|
Summary
term.ReadPassword(no visual feedback) withcharmbracelet/huhmasked input that shows*per keystroke during IMAP password entryecho "pass" | msgvault add-imap ...)go-isattyfor TTY detection (including Cygwin/MSYS), matching existing codebase patternschoosePasswordStrategy()with table-driven tests covering all stdin/stdout/stderr TTY combinationsgolang.org/x/termdirect dependency (no longer needed)The strategy selection is a pure function of four booleans, tested across 10 cases:
Test plan
choosePasswordStrategy: 10 cases covering native/Cygwin/piped stdin × stderr/stdout TTY combinationsreadPasswordFromPipe: newline trimming, CRLF, empty input, whitespace-only, EOF, multi-linemsgvault add-imap --host ... --username ...shows asterisks during password entryecho "pass" | msgvault add-imap --host ... --username ...reads from pipeCloses #209
🤖 Generated with Claude Code