package cmd import ( "fmt" "os" "github.com/jensbecker/homelab/knecht/config" "github.com/jensbecker/homelab/knecht/portainer" "github.com/jensbecker/homelab/knecht/stack" "github.com/jensbecker/homelab/knecht/tui" "github.com/spf13/cobra" ) var servicesPathFlag string var rootCmd = &cobra.Command{ Use: "knecht", Short: "Homelab stack manager", Long: "knecht manages Portainer stacks from your local services/ directory.", // No subcommand → launch TUI RunE: func(cmd *cobra.Command, args []string) error { cfg, client, svcPath, err := setup() if err != nil { return err } return tui.Run(client, svcPath, cfg) }, } func Execute() { if err := rootCmd.Execute(); err != nil { os.Exit(1) } } func init() { rootCmd.PersistentFlags().StringVar(&servicesPathFlag, "services", "", "path to services directory (default: auto-detected from git root)") } // setup loads config, builds the Portainer client, and resolves the services path. func setup() (*config.Config, *portainer.Client, string, error) { cfg, err := config.Load() if err != nil { return nil, nil, "", err } client, err := portainer.New(cfg.Portainer.URL, cfg.Portainer.Token, cfg.Portainer.Endpoint) if err != nil { return nil, nil, "", fmt.Errorf("connecting to Portainer: %w", err) } svcPath, err := stack.ServicesPath(servicesPathFlag) if svcPath == "" && err == nil { svcPath, err = stack.ServicesPath(cfg.ServicesPath) } if err != nil { return nil, nil, "", err } return cfg, client, svcPath, nil }