refactor: let Cobra handle error display

Amolith created

Remove redundant ui.Error calls outside cmd/init/. Errors are now
returned directly to Cobra for consistent display. ui.Success is still
used for explicit success confirmations.

Assisted-by: Claude Sonnet 4 via Crush

Change summary

cmd/area/list.go |  2 --
cmd/area/show.go |  4 ----
cmd/goal/list.go |  2 --
cmd/goal/show.go | 21 ++++++---------------
cmd/ping.go      |  9 ---------
cmd/task/add.go  | 12 ------------
cmd/task/list.go |  6 ------
cmd/task/show.go |  2 --
8 files changed, 6 insertions(+), 52 deletions(-)

Detailed changes

cmd/area/list.go 🔗

@@ -33,8 +33,6 @@ func init() {
 func runList(cmd *cobra.Command, _ []string) error {
 	cfg, err := config.Load()
 	if err != nil {
-		fmt.Fprintln(cmd.ErrOrStderr(), ui.Error.Render("Config not found; run 'lune init' to configure areas"))
-
 		return err
 	}
 

cmd/area/show.go 🔗

@@ -31,15 +31,11 @@ func runShow(cmd *cobra.Command, args []string) error {
 
 	cfg, err := config.Load()
 	if err != nil {
-		fmt.Fprintln(cmd.ErrOrStderr(), ui.Error.Render("Config not found; run 'lune init' to configure areas"))
-
 		return err
 	}
 
 	area := cfg.AreaByKey(areaKey)
 	if area == nil {
-		fmt.Fprintln(cmd.ErrOrStderr(), ui.Error.Render("Unknown area: "+areaKey))
-
 		return fmt.Errorf("%w: %s", ErrUnknownArea, areaKey)
 	}
 

cmd/goal/list.go 🔗

@@ -38,8 +38,6 @@ func init() {
 func runList(cmd *cobra.Command, _ []string) error {
 	cfg, err := config.Load()
 	if err != nil {
-		fmt.Fprintln(cmd.ErrOrStderr(), ui.Error.Render("Config not found; run 'lune init' to configure areas"))
-
 		return err
 	}
 

cmd/goal/show.go 🔗

@@ -44,12 +44,10 @@ func runShow(cmd *cobra.Command, args []string) error {
 
 	cfg, err := config.Load()
 	if err != nil {
-		fmt.Fprintln(cmd.ErrOrStderr(), ui.Error.Render("Config not found; run 'lune init' to configure areas"))
-
 		return err
 	}
 
-	match, err := resolveGoal(cmd, cfg, goalKey, areaKey)
+	match, err := resolveGoal(cfg, goalKey, areaKey)
 	if err != nil {
 		return err
 	}
@@ -64,19 +62,15 @@ func runShow(cmd *cobra.Command, args []string) error {
 	return printGoalDetails(cmd, match.Goal, match.Area, counter)
 }
 
-func resolveGoal(cmd *cobra.Command, cfg *config.Config, goalKey, areaKey string) (*config.GoalMatch, error) {
+func resolveGoal(cfg *config.Config, goalKey, areaKey string) (*config.GoalMatch, error) {
 	if areaKey != "" {
 		area := cfg.AreaByKey(areaKey)
 		if area == nil {
-			fmt.Fprintln(cmd.ErrOrStderr(), ui.Error.Render("Unknown area: "+areaKey))
-
 			return nil, fmt.Errorf("%w: %s", ErrUnknownArea, areaKey)
 		}
 
 		goal := area.GoalByKey(goalKey)
 		if goal == nil {
-			fmt.Fprintln(cmd.ErrOrStderr(), ui.Error.Render("Unknown goal: "+goalKey))
-
 			return nil, fmt.Errorf("%w: %s", ErrUnknownGoal, goalKey)
 		}
 
@@ -87,8 +81,6 @@ func resolveGoal(cmd *cobra.Command, cfg *config.Config, goalKey, areaKey string
 
 	switch len(matches) {
 	case 0:
-		fmt.Fprintln(cmd.ErrOrStderr(), ui.Error.Render("Unknown goal: "+goalKey))
-
 		return nil, fmt.Errorf("%w: %s", ErrUnknownGoal, goalKey)
 
 	case 1:
@@ -100,11 +92,10 @@ func resolveGoal(cmd *cobra.Command, cfg *config.Config, goalKey, areaKey string
 			areas[i] = m.Area.Key
 		}
 
-		fmt.Fprintf(cmd.ErrOrStderr(), "%s\n",
-			ui.Error.Render("Goal '"+goalKey+"' exists in multiple areas: "+strings.Join(areas, ", ")))
-		fmt.Fprintln(cmd.ErrOrStderr(), "Use --area to specify which one")
-
-		return nil, fmt.Errorf("%w: %s exists in %s", ErrAmbiguousGoal, goalKey, strings.Join(areas, ", "))
+		return nil, fmt.Errorf(
+			"%w: %s exists in %s; use --area to specify",
+			ErrAmbiguousGoal, goalKey, strings.Join(areas, ", "),
+		)
 	}
 }
 

cmd/ping.go 🔗

@@ -5,7 +5,6 @@
 package cmd
 
 import (
-	"errors"
 	"fmt"
 
 	"git.secluded.site/lune/internal/client"
@@ -19,19 +18,11 @@ var pingCmd = &cobra.Command{
 	RunE: func(cmd *cobra.Command, _ []string) error {
 		c, err := client.New()
 		if err != nil {
-			if errors.Is(err, client.ErrNoToken) {
-				fmt.Fprintln(cmd.ErrOrStderr(), ui.Error.Render("No access token configured; run 'lune init'"))
-
-				return err
-			}
-
 			return err
 		}
 
 		resp, err := c.Ping(cmd.Context())
 		if err != nil {
-			fmt.Fprintln(cmd.ErrOrStderr(), ui.Error.Render("Authentication failed"))
-
 			return err
 		}
 

cmd/task/add.go 🔗

@@ -82,8 +82,6 @@ func runAdd(cmd *cobra.Command, args []string) error {
 
 	task, err := builder.Create(cmd.Context())
 	if err != nil {
-		fmt.Fprintln(cmd.ErrOrStderr(), ui.Error.Render("Failed to create task"))
-
 		return err
 	}
 
@@ -125,17 +123,11 @@ func applyAreaAndGoal(cmd *cobra.Command, builder *lunatask.TaskBuilder) error {
 
 	cfg, err := config.Load()
 	if err != nil {
-		if errors.Is(err, config.ErrNotFound) {
-			fmt.Fprintln(cmd.ErrOrStderr(), ui.Error.Render("Config not found; run 'lune init' to configure areas"))
-		}
-
 		return err
 	}
 
 	area := cfg.AreaByKey(areaKey)
 	if area == nil {
-		fmt.Fprintln(cmd.ErrOrStderr(), ui.Error.Render("Unknown area: "+areaKey))
-
 		return fmt.Errorf("%w: %s", ErrUnknownArea, areaKey)
 	}
 
@@ -147,8 +139,6 @@ func applyAreaAndGoal(cmd *cobra.Command, builder *lunatask.TaskBuilder) error {
 
 	goal := area.GoalByKey(goalKey)
 	if goal == nil {
-		fmt.Fprintln(cmd.ErrOrStderr(), ui.Error.Render("Unknown goal: "+goalKey))
-
 		return fmt.Errorf("%w: %s", ErrUnknownGoal, goalKey)
 	}
 
@@ -210,8 +200,6 @@ func applySchedule(cmd *cobra.Command, builder *lunatask.TaskBuilder) error {
 
 	date, err := lunatask.ParseDate(schedule)
 	if err != nil {
-		fmt.Fprintln(cmd.ErrOrStderr(), ui.Error.Render("Invalid date format: "+schedule))
-
 		return fmt.Errorf("parsing schedule date: %w", err)
 	}
 

cmd/task/list.go 🔗

@@ -56,8 +56,6 @@ func runList(cmd *cobra.Command, _ []string) error {
 
 	tasks, err := apiClient.ListTasks(cmd.Context(), nil)
 	if err != nil {
-		fmt.Fprintln(cmd.ErrOrStderr(), ui.Error.Render("Failed to list tasks"))
-
 		return err
 	}
 
@@ -112,8 +110,6 @@ func resolveAreaFilter(cmd *cobra.Command) (string, error) {
 		// Config not required if no area flag and we just skip default
 		if errors.Is(err, config.ErrNotFound) {
 			if areaKey != "" {
-				fmt.Fprintln(cmd.ErrOrStderr(), ui.Error.Render("Config not found; run 'lune init' to configure areas"))
-
 				return "", err
 			}
 
@@ -134,8 +130,6 @@ func resolveAreaFilter(cmd *cobra.Command) (string, error) {
 
 	area := cfg.AreaByKey(areaKey)
 	if area == nil {
-		fmt.Fprintln(cmd.ErrOrStderr(), ui.Error.Render("Unknown area: "+areaKey))
-
 		return "", fmt.Errorf("%w: %s", ErrUnknownArea, areaKey)
 	}
 

cmd/task/show.go 🔗

@@ -48,8 +48,6 @@ func runShow(cmd *cobra.Command, args []string) error {
 
 	task, err := apiClient.GetTask(cmd.Context(), id)
 	if err != nil {
-		fmt.Fprintln(cmd.ErrOrStderr(), ui.Error.Render("Failed to get task"))
-
 		return err
 	}