package cli import ( "fmt" "os" "github.com/spf13/cobra" ) // RootFlags holds global flags that apply to all commands. // These flags are defined on the root command and inherited by all subcommands. type RootFlags struct { ConfigPath string Verbose bool Debug bool } var rootFlags RootFlags // NewRootCommand creates the root cobra command for the vaultik CLI. // It sets up the command structure, global flags, and adds all subcommands. // This is the main entry point for the CLI command hierarchy. func NewRootCommand() *cobra.Command { cmd := &cobra.Command{ Use: "vaultik", Short: "Secure incremental backup tool with asymmetric encryption", Long: `vaultik is a secure incremental backup daemon that encrypts data using age public keys and uploads to S3-compatible storage. No private keys are needed on the source system.`, SilenceUsage: true, } // Add global flags cmd.PersistentFlags().StringVar(&rootFlags.ConfigPath, "config", "", "Path to config file (default: $VAULTIK_CONFIG or /etc/vaultik/config.yml)") cmd.PersistentFlags().BoolVarP(&rootFlags.Verbose, "verbose", "v", false, "Enable verbose output") cmd.PersistentFlags().BoolVar(&rootFlags.Debug, "debug", false, "Enable debug output") // Add subcommands cmd.AddCommand( NewRestoreCommand(), NewPruneCommand(), NewVerifyCommand(), NewFetchCommand(), NewStoreCommand(), NewSnapshotCommand(), NewInfoCommand(), ) return cmd } // GetRootFlags returns the global flags that were parsed from the command line. // This allows subcommands to access global flag values like verbosity and config path. func GetRootFlags() RootFlags { return rootFlags } // ResolveConfigPath resolves the config file path from flags, environment, or default. // It checks in order: 1) --config flag, 2) VAULTIK_CONFIG environment variable, // 3) default location /etc/vaultik/config.yml. Returns an error if no valid // config file can be found through any of these methods. func ResolveConfigPath() (string, error) { // First check global flag if rootFlags.ConfigPath != "" { return rootFlags.ConfigPath, nil } // Then check environment variable if envPath := os.Getenv("VAULTIK_CONFIG"); envPath != "" { return envPath, nil } // Finally check default location defaultPath := "/etc/vaultik/config.yml" if _, err := os.Stat(defaultPath); err == nil { return defaultPath, nil } return "", fmt.Errorf("no config file specified, VAULTIK_CONFIG not set, and %s not found", defaultPath) }