From 7288acae20fb614d70d0fb657e7bb80383b295c8 Mon Sep 17 00:00:00 2001 From: Nate Meyer <672246+notnmeyer@users.noreply.github.com> Date: Mon, 27 Apr 2026 11:23:36 -0700 Subject: [PATCH 1/3] auth: positional name --- cmd/auth_login.go | 19 ++++++++----------- cmd/auth_logout.go | 17 ++++++++--------- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/cmd/auth_login.go b/cmd/auth_login.go index 355c5c3..b68e675 100644 --- a/cmd/auth_login.go +++ b/cmd/auth_login.go @@ -12,16 +12,14 @@ import ( "golang.org/x/term" ) -var loginName string var loginSkipVerify bool var loginCmd = &cobra.Command{ - Use: "login", + Use: "login ", Short: "Authenticate with your Loops API key", + Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - if loginName == "" { - return errors.New("use --name to give this key a name (e.g. loops auth login --name my-team)") - } + name := args[0] fmt.Fprint(os.Stderr, "Enter your API key: ") raw, err := term.ReadPassword(int(os.Stdin.Fd())) @@ -35,22 +33,22 @@ var loginCmd = &cobra.Command{ return fmt.Errorf("API key cannot be empty") } - result, err := runAuthLogin(apiKey, loginName, loginSkipVerify) + result, err := runAuthLogin(apiKey, name, loginSkipVerify) if err != nil { return err } if isJSONOutput() { - msg := fmt.Sprintf("API key saved as %q", loginName) + msg := fmt.Sprintf("API key saved as %q", name) if result != nil { msg = fmt.Sprintf("Authenticated as team: %s", result.TeamName) } return printJSON(cmd.OutOrStdout(), Result{Success: true, Message: msg}) } if result != nil { - fmt.Fprintf(cmd.OutOrStdout(), "API key saved as %q. Authenticated as team: %s\n", loginName, result.TeamName) + fmt.Fprintf(cmd.OutOrStdout(), "API key saved as %q. Authenticated as team: %s\n", name, result.TeamName) } else { - fmt.Fprintf(cmd.OutOrStdout(), "API key saved as %q.\n", loginName) + fmt.Fprintf(cmd.OutOrStdout(), "API key saved as %q.\n", name) } return nil }, @@ -58,7 +56,7 @@ var loginCmd = &cobra.Command{ func runAuthLogin(apiKey, name string, skipVerify bool) (*api.APIKeyResponse, error) { if name == "" { - return nil, errors.New("use --name to give this key a name") + return nil, errors.New("a key name is required") } if skipVerify { if err := config.Save(apiKey, name); err != nil { @@ -77,7 +75,6 @@ func runAuthLogin(apiKey, name string, skipVerify bool) (*api.APIKeyResponse, er } func init() { - loginCmd.Flags().StringVarP(&loginName, "name", "n", "", "Name for this API key (e.g. my-team)") loginCmd.Flags().BoolVar(&loginSkipVerify, "skip-verify", false, "Save the API key without verifying it") authCmd.AddCommand(loginCmd) } diff --git a/cmd/auth_logout.go b/cmd/auth_logout.go index b9cbbdd..622f272 100644 --- a/cmd/auth_logout.go +++ b/cmd/auth_logout.go @@ -8,31 +8,30 @@ import ( "github.com/spf13/cobra" ) -var logoutName string - var logoutCmd = &cobra.Command{ - Use: "logout", + Use: "logout ", Short: "Remove stored Loops credentials", + Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - if logoutName == "" { - return errors.New("use --name to specify which key to remove (e.g. loops auth logout --name loops-prod)") - } - if err := runAuthLogout(logoutName); err != nil { + name := args[0] + if err := runAuthLogout(name); err != nil { return err } if isJSONOutput() { return printJSON(cmd.OutOrStdout(), Result{Success: true}) } - fmt.Fprintf(cmd.OutOrStdout(), "Logged out of %q.\n", logoutName) + fmt.Fprintf(cmd.OutOrStdout(), "Logged out of %q.\n", name) return nil }, } func runAuthLogout(name string) error { + if name == "" { + return errors.New("a key name is required") + } return config.Delete(name) } func init() { - logoutCmd.Flags().StringVarP(&logoutName, "name", "n", "", "Name of the API key to remove") authCmd.AddCommand(logoutCmd) } From a2c6f511979022a06c0c92d5f2089e4e41f8f5fb Mon Sep 17 00:00:00 2001 From: Nate Meyer <672246+notnmeyer@users.noreply.github.com> Date: Mon, 27 Apr 2026 11:24:08 -0700 Subject: [PATCH 2/3] transactional: positional id --- cmd/send.go | 3 ++- cmd/transactional.go | 7 +++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/send.go b/cmd/send.go index df33a14..2a0debe 100644 --- a/cmd/send.go +++ b/cmd/send.go @@ -3,8 +3,9 @@ package cmd import "github.com/spf13/cobra" var sendCmd = &cobra.Command{ - Use: "send", + Use: "send ", Short: "Send a transactional email", + Args: cobra.ExactArgs(1), RunE: transactionalSendRunE, } diff --git a/cmd/transactional.go b/cmd/transactional.go index 354514d..435d193 100644 --- a/cmd/transactional.go +++ b/cmd/transactional.go @@ -117,8 +117,8 @@ func transactionalSendRunE(cmd *cobra.Command, args []string) error { return err } + id := args[0] email, _ := cmd.Flags().GetString("email") - id, _ := cmd.Flags().GetString("id") idempotencyKey, _ := cmd.Flags().GetString("idempotency-key") req := api.SendTransactionalRequest{ @@ -164,19 +164,18 @@ func transactionalSendRunE(cmd *cobra.Command, args []string) error { func addTransactionalSendFlags(cmd *cobra.Command) { cmd.Flags().String("email", "", "Recipient email address") - cmd.Flags().String("id", "", "Transactional email ID") cmd.Flags().BoolP("add-to-audience", "a", false, "Create a contact if one doesn't exist") cmd.Flags().StringArrayP("var", "v", nil, "Data variable as KEY=value (repeatable)") cmd.Flags().StringP("json-vars", "j", "", "Path to a JSON file of data variables") cmd.Flags().StringArrayP("attachment", "A", nil, "Path to a file to attach (repeatable)") cmd.Flags().String("idempotency-key", "", "Idempotency key to prevent duplicate sends") cmd.MarkFlagRequired("email") - cmd.MarkFlagRequired("id") } var transactionalSendCmd = &cobra.Command{ - Use: "send", + Use: "send ", Short: "Send a transactional email", + Args: cobra.ExactArgs(1), RunE: transactionalSendRunE, } From 47d2e0e1c890ede18de2059fa023bff67c99d298 Mon Sep 17 00:00:00 2001 From: Nate Meyer <672246+notnmeyer@users.noreply.github.com> Date: Mon, 27 Apr 2026 11:25:05 -0700 Subject: [PATCH 3/3] events send: positional event id --- cmd/events.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cmd/events.go b/cmd/events.go index ea1e7a0..9c83176 100644 --- a/cmd/events.go +++ b/cmd/events.go @@ -44,8 +44,9 @@ var eventsCmd = &cobra.Command{ } var eventsSendCmd = &cobra.Command{ - Use: "send", + Use: "send ", Short: "Send an event", + Args: cobra.ExactArgs(1), RunE: eventsSendRunE, } @@ -61,7 +62,7 @@ func eventsSendRunE(cmd *cobra.Command, args []string) error { return fmt.Errorf("at least one of --email or --user-id is required") } - eventName, _ := cmd.Flags().GetString("event") + eventName := args[0] idempotencyKey, _ := cmd.Flags().GetString("idempotency-key") req := api.SendEventRequest{ @@ -112,14 +113,12 @@ func eventsSendRunE(cmd *cobra.Command, args []string) error { } func addEventsSendFlags(cmd *cobra.Command) { - cmd.Flags().String("event", "", "Event name") cmd.Flags().String("email", "", "Contact email address") cmd.Flags().String("user-id", "", "Contact user ID") cmd.Flags().String("props", "", "Path to a JSON file of event properties") cmd.Flags().String("contact-props", "", "Path to a JSON file of contact properties") cmd.Flags().StringArray("list", nil, "Mailing list subscription as id=true|false (repeatable)") cmd.Flags().String("idempotency-key", "", "Idempotency key to prevent duplicate sends") - cmd.MarkFlagRequired("event") } func init() {