- 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
77 lines
1.9 KiB
Go
77 lines
1.9 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"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
|
|
}
|