Files
goclaw/cmd/config_cmd.go
T
Viet TranandClaude Opus 4.6 f3f4c67b36 Initial commit: GoClaw AI agent gateway
Multi-agent AI gateway with WebSocket RPC, HTTP API, and messaging channel integrations.
Go port of OpenClaw with multi-tenant PostgreSQL, per-user isolation, security hardening,
and production observability.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 14:58:07 +07:00

97 lines
2.2 KiB
Go

package cmd
import (
"encoding/json"
"fmt"
"os"
"github.com/spf13/cobra"
"github.com/nextlevelbuilder/goclaw/internal/config"
)
func configCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "config",
Short: "View and manage configuration",
}
cmd.AddCommand(configShowCmd())
cmd.AddCommand(configPathCmd())
cmd.AddCommand(configValidateCmd())
return cmd
}
func configShowCmd() *cobra.Command {
return &cobra.Command{
Use: "show",
Short: "Display current configuration (secrets redacted)",
Run: func(cmd *cobra.Command, args []string) {
cfgPath := resolveConfigPath()
cfg, err := config.Load(cfgPath)
if err != nil {
fmt.Fprintf(os.Stderr, "Error loading config: %s\n", err)
os.Exit(1)
}
// Redact secrets before display
redacted := redactConfig(cfg)
data, _ := json.MarshalIndent(redacted, "", " ")
fmt.Println(string(data))
},
}
}
func configPathCmd() *cobra.Command {
return &cobra.Command{
Use: "path",
Short: "Print the config file path",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println(resolveConfigPath())
},
}
}
func configValidateCmd() *cobra.Command {
return &cobra.Command{
Use: "validate",
Short: "Validate configuration file",
Run: func(cmd *cobra.Command, args []string) {
cfgPath := resolveConfigPath()
_, err := config.Load(cfgPath)
if err != nil {
fmt.Fprintf(os.Stderr, "Invalid config: %s\n", err)
os.Exit(1)
}
fmt.Printf("Config at %s is valid.\n", cfgPath)
},
}
}
// redactConfig returns a JSON-safe copy with secrets masked.
func redactConfig(cfg *config.Config) interface{} {
data, _ := json.Marshal(cfg)
var raw map[string]interface{}
json.Unmarshal(data, &raw)
redactMap(raw)
return raw
}
func redactMap(m map[string]interface{}) {
secretKeys := map[string]bool{
"apiKey": true, "api_key": true, "token": true,
"botToken": true, "bot_token": true, "secret": true,
"appSecret": true, "encryptKey": true, "verificationToken": true,
}
for k, v := range m {
if secretKeys[k] {
if s, ok := v.(string); ok && len(s) > 8 {
m[k] = s[:4] + "****" + s[len(s)-4:]
} else if s, ok := v.(string); ok && s != "" {
m[k] = "****"
}
} else if sub, ok := v.(map[string]interface{}); ok {
redactMap(sub)
}
}
}