feat(01-05): add CLI root command, config package, output table, and settings helpers
- cmd/root.go: Cobra root with all 11 subcommands, viper config loading - cmd/stubs.go: 8 stub commands for future phases (verify, import, recon, keys, serve, dorks, hook, schedule) - cmd/scan.go: scan command wiring engine + storage + output with per-installation salt - cmd/providers.go: providers list/info/stats subcommands - cmd/config.go: config init/set/get subcommands - pkg/config/config.go: Config struct with Load() and defaults - pkg/output/table.go: lipgloss terminal table for PrintFindings - pkg/storage/settings.go: GetSetting/SetSetting for settings table CRUD
This commit is contained in:
76
cmd/root.go
76
cmd/root.go
@@ -1,8 +1,76 @@
|
||||
package cmd
|
||||
|
||||
import "os"
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
// Execute is a stub. The real command tree is built in Plan 05.
|
||||
func Execute() {
|
||||
_ = os.Args
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var cfgFile string
|
||||
|
||||
// rootCmd is the base command when called without any subcommands.
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "keyhunter",
|
||||
Short: "KeyHunter -- detect leaked LLM API keys across 108+ providers",
|
||||
Long: `KeyHunter scans files, git history, and internet sources for leaked LLM API keys.
|
||||
Supports 108+ providers with Aho-Corasick pre-filtering and regex + entropy detection.`,
|
||||
SilenceUsage: true,
|
||||
}
|
||||
|
||||
// Execute is the entry point called by main.go.
|
||||
func Execute() {
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
cobra.OnInitialize(initConfig)
|
||||
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default: ~/.keyhunter.yaml)")
|
||||
rootCmd.AddCommand(scanCmd)
|
||||
rootCmd.AddCommand(providersCmd)
|
||||
rootCmd.AddCommand(configCmd)
|
||||
// Stub commands for future phases (per CLI-01 requirement of 11 commands)
|
||||
rootCmd.AddCommand(verifyCmd)
|
||||
rootCmd.AddCommand(importCmd)
|
||||
rootCmd.AddCommand(reconCmd)
|
||||
rootCmd.AddCommand(keysCmd)
|
||||
rootCmd.AddCommand(serveCmd)
|
||||
rootCmd.AddCommand(dorksCmd)
|
||||
rootCmd.AddCommand(hookCmd)
|
||||
rootCmd.AddCommand(scheduleCmd)
|
||||
}
|
||||
|
||||
func initConfig() {
|
||||
if cfgFile != "" {
|
||||
viper.SetConfigFile(cfgFile)
|
||||
} else {
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "warning: cannot determine home directory:", err)
|
||||
return
|
||||
}
|
||||
viper.SetConfigName(".keyhunter")
|
||||
viper.SetConfigType("yaml")
|
||||
viper.AddConfigPath(home)
|
||||
viper.AddConfigPath(".")
|
||||
}
|
||||
|
||||
viper.SetEnvPrefix("KEYHUNTER")
|
||||
viper.AutomaticEnv()
|
||||
|
||||
// Defaults
|
||||
viper.SetDefault("scan.workers", 0) // 0 = auto (CPU*8)
|
||||
viper.SetDefault("database.path", filepath.Join(mustHomeDir(), ".keyhunter", "keyhunter.db"))
|
||||
|
||||
// Config file is optional -- ignore if not found
|
||||
_ = viper.ReadInConfig()
|
||||
}
|
||||
|
||||
func mustHomeDir() string {
|
||||
h, _ := os.UserHomeDir()
|
||||
return h
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user