From 375956c14eb737147d3858dc015000f684477b1b Mon Sep 17 00:00:00 2001 From: ndenny Date: Thu, 11 Jun 2026 16:46:02 -0700 Subject: [PATCH 1/4] Add welcome message --- oauth/authcode.go | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/oauth/authcode.go b/oauth/authcode.go index bde8881..4259a3a 100644 --- a/oauth/authcode.go +++ b/oauth/authcode.go @@ -16,8 +16,8 @@ import ( "context" - "github.com/mattn/go-isatty" "apicontext.com/apimetrics/cli" + "github.com/mattn/go-isatty" "golang.org/x/oauth2" ) @@ -285,10 +285,30 @@ func (ac *AuthorizationCodeTokenSource) Token() (*oauth2.Token, error) { } }() - // Open auth URL in browser, print for manual use in case open fails. - fmt.Fprintln(os.Stderr, "Open your browser to log in using the URL:") - fmt.Fprintln(os.Stderr, authorizeURL.String()) - open(authorizeURL.String()) + // Print welcome banner, show login URL, and ask before opening browser. + fmt.Fprintln(os.Stderr, ` + _ ___ ___ _ _ + /_\ | _ \_ _|_ __ ___| |_ _ _(_)__ ___ + / _ \| _/| || ' \/ -_| _| '_| / _(_-< + /_/ \_\_| |___|_|_|_\___|\__|_| |_\__/__/ +`) + fmt.Fprintln(os.Stderr, "Welcome to APImetrics CLI!") + fmt.Fprintln(os.Stderr, "") + fmt.Fprintln(os.Stderr, "To log in, open the following URL in your browser:") + fmt.Fprintln(os.Stderr, "") + fmt.Fprintln(os.Stderr, " "+authorizeURL.String()) + fmt.Fprintln(os.Stderr, "") + if isatty.IsTerminal(os.Stderr.Fd()) || isatty.IsCygwinTerminal(os.Stderr.Fd()) { + fmt.Fprint(os.Stderr, "Open your browser now? [Y/n]: ") + reader := bufio.NewReader(os.Stdin) + answer, _ := reader.ReadString('\n') + answer = strings.TrimSpace(strings.ToLower(answer)) + if answer == "" || answer == "y" || answer == "yes" { + open(authorizeURL.String()) + } + } else { + open(authorizeURL.String()) + } // Provide a way to manually enter the code, e.g. for remote SSH sessions. // Only read from stdin if it is a live terminal, if a file or command has From b6ef104b5084a33253dc1d15194e512f378a45af Mon Sep 17 00:00:00 2001 From: ndenny Date: Fri, 12 Jun 2026 13:32:34 -0700 Subject: [PATCH 2/4] Formatting --- bench_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bench_test.go b/bench_test.go index a4ed1a0..2bf729a 100644 --- a/bench_test.go +++ b/bench_test.go @@ -6,10 +6,10 @@ import ( "net/http" "testing" - "github.com/amzn/ion-go/ion" - "github.com/fxamacker/cbor/v2" "apicontext.com/apimetrics/cli" "apicontext.com/apimetrics/openapi" + "github.com/amzn/ion-go/ion" + "github.com/fxamacker/cbor/v2" "github.com/shamaton/msgpack/v2" "github.com/spf13/cobra" ) From 393849aa1e22dd552167e4709e24ac9c75b9b667 Mon Sep 17 00:00:00 2001 From: ndenny Date: Fri, 12 Jun 2026 15:00:49 -0700 Subject: [PATCH 3/4] Fix go vet: redundant newline in Fprintln banner The welcome banner string already ends with a newline, so Fprintln appended a redundant one. Switch to Fprint to satisfy go vet. Co-Authored-By: Claude Opus 4.8 (1M context) --- oauth/authcode.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oauth/authcode.go b/oauth/authcode.go index 4259a3a..55f1533 100644 --- a/oauth/authcode.go +++ b/oauth/authcode.go @@ -286,7 +286,7 @@ func (ac *AuthorizationCodeTokenSource) Token() (*oauth2.Token, error) { }() // Print welcome banner, show login URL, and ask before opening browser. - fmt.Fprintln(os.Stderr, ` + fmt.Fprint(os.Stderr, ` _ ___ ___ _ _ /_\ | _ \_ _|_ __ ___| |_ _ _(_)__ ___ / _ \| _/| || ' \/ -_| _| '_| / _(_-< From 33b322d3886db8dc2ab9608b2ab3cf2a371ff174 Mon Sep 17 00:00:00 2001 From: ndenny Date: Fri, 12 Jun 2026 15:34:07 -0700 Subject: [PATCH 4/4] Gate browser prompt on stdin being a TTY The [Y/n] prompt read from stdin but only checked that stderr was a terminal. If a request body was piped into stdin while stderr was a TTY, the prompt would consume its first line. Check stdin instead, matching the manual-code path that protects piped input. Co-Authored-By: Claude Opus 4.8 (1M context) --- oauth/authcode.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/oauth/authcode.go b/oauth/authcode.go index 55f1533..6ee1127 100644 --- a/oauth/authcode.go +++ b/oauth/authcode.go @@ -298,7 +298,10 @@ func (ac *AuthorizationCodeTokenSource) Token() (*oauth2.Token, error) { fmt.Fprintln(os.Stderr, "") fmt.Fprintln(os.Stderr, " "+authorizeURL.String()) fmt.Fprintln(os.Stderr, "") - if isatty.IsTerminal(os.Stderr.Fd()) || isatty.IsCygwinTerminal(os.Stderr.Fd()) { + // Only prompt interactively if stdin is a live terminal. If a file or + // command has been piped in it is likely the request body to use after + // auth, so we must not consume it here (see the manual-code path below). + if isatty.IsTerminal(os.Stdin.Fd()) || isatty.IsCygwinTerminal(os.Stdin.Fd()) { fmt.Fprint(os.Stderr, "Open your browser now? [Y/n]: ") reader := bufio.NewReader(os.Stdin) answer, _ := reader.ReadString('\n')