package cli import ( "os" "strings" "time" "sneak.berlin/go/vaultik/internal/globals" "sneak.berlin/go/vaultik/internal/ui" ) // CLIEntry is the main entry point for the CLI application. // It prints the startup banner (unless a quiet flag is present in os.Args), // executes the root cobra command, and routes any returned error through // the ui.Writer so the user sees a properly formatted "🛑 ERROR:" line. func CLIEntry() { if !bannerSuppressedInArgs(os.Args[1:]) { short := globals.Commit if len(short) > 12 { short = short[:12] } writeStartupBanner(ui.New(os.Stdout), time.Now().UTC(), short) } rootCmd := NewRootCommand() rootCmd.SilenceErrors = true if err := rootCmd.Execute(); err != nil { ReportError("%s", err.Error()) os.Exit(1) } } // ReportError emits a user-facing error to stderr in the standard // 🛑 ERROR: format. Use it from goroutine error paths (where returning // an error to cobra isn't an option) and anywhere else a CLI command // must surface a failure outside the normal RunE return path. func ReportError(format string, args ...any) { ui.New(os.Stderr).Error(format, args...) } // bannerSuppressedInArgs reports whether any of args is a flag that // should suppress the startup banner (--quiet/-q/--cron). Stops at the // "--" argument terminator. Recognizes both long forms and short -q, // including combined short flags like "-qv". func bannerSuppressedInArgs(args []string) bool { for _, a := range args { if a == "--" { return false } switch a { case "--quiet", "-q", "--cron": return true } if strings.HasPrefix(a, "--quiet=") || strings.HasPrefix(a, "--cron=") { return true } // Combined short flags like -qv or -vq. if len(a) > 1 && a[0] == '-' && a[1] != '-' { for _, c := range a[1:] { if c == 'q' { return true } } } } return false }