diff --git a/cmd/root.go b/cmd/root.go index 368c025..a659689 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -5,8 +5,23 @@ import ( "os" "github.com/spf13/cobra" + + "github.com/supermodeltools/cli/internal/config" ) +// noConfigCommands are subcommands that work without a config file. +// Includes Cobra's internal shell-completion helpers to avoid crashing them. +var noConfigCommands = map[string]bool{ + "setup": true, + "login": true, + "logout": true, + "version": true, + "help": true, + "completion": true, + "__complete": true, + "__completeNoDesc": true, +} + var rootCmd = &cobra.Command{ Use: "supermodel", Short: "Give your AI coding agent a map of your codebase", @@ -15,6 +30,24 @@ providing call graphs, dead code detection, and blast radius analysis. See https://supermodeltools.com for documentation.`, SilenceUsage: true, + PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + // Walk up to the root command name to get the subcommand. + name := cmd.Name() + if noConfigCommands[name] { + return nil + } + + cfg, err := config.Load() + if err != nil { + fmt.Fprintf(os.Stderr, "Error loading config: %v\n", err) + os.Exit(1) + } + if cfg.APIKey == "" { + fmt.Fprintln(os.Stderr, "Run 'supermodel setup' to get started.") + os.Exit(1) + } + return nil + }, } // Execute is the entry point called by main. diff --git a/install.sh b/install.sh index 54c2429..a67b15d 100644 --- a/install.sh +++ b/install.sh @@ -72,3 +72,11 @@ install -m755 "$TMP/$BINARY" "$INSTALL_DIR/$BINARY" echo "Installed: $INSTALL_DIR/$BINARY" "$INSTALL_DIR/$BINARY" version + +# Run the setup wizard when a controlling terminal is available. +# Use /dev/tty as stdin so interactive prompts work even in piped installs +# (e.g. curl … | sh), where stdin is the pipe rather than the terminal. +if [ -r /dev/tty ]; then + echo "" + "$INSTALL_DIR/$BINARY" setup