Skip to content

Commit e395060

Browse files
committed
feat: add environment config import support in init
Closes #1 - Detect ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN from environment - Offer to import existing configuration during init - Test imported configuration before saving - Add min helper function for safe string truncation - Show masked auth token in detection output This allows users who already have Claude Code configured via environment variables to easily import their configuration into the codes CLI management system.
1 parent 8c82261 commit e395060

File tree

1 file changed

+92
-3
lines changed

1 file changed

+92
-3
lines changed

internal/commands/commands.go

Lines changed: 92 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ import (
1515
"codes/internal/ui"
1616
)
1717

18+
// min returns the minimum of two integers
19+
func min(a, b int) int {
20+
if a < b {
21+
return a
22+
}
23+
return b
24+
}
25+
1826
func RunVersion() {
1927
fmt.Printf("codes version dev (built unknown)\n")
2028
}
@@ -411,9 +419,90 @@ func RunInit() {
411419
}
412420
fmt.Println()
413421

414-
// 2. Check if config file exists
422+
// 2. Check for existing environment variables
423+
ui.ShowInfo("Checking for existing Claude configuration...")
424+
baseURL := os.Getenv("ANTHROPIC_BASE_URL")
425+
authToken := os.Getenv("ANTHROPIC_AUTH_TOKEN")
426+
427+
hasEnvConfig := false
428+
if baseURL != "" && authToken != "" {
429+
ui.ShowSuccess("✓ Found existing configuration in environment variables")
430+
ui.ShowInfo(" ANTHROPIC_BASE_URL: %s", baseURL)
431+
ui.ShowInfo(" ANTHROPIC_AUTH_TOKEN: %s...", authToken[:min(10, len(authToken))])
432+
hasEnvConfig = true
433+
} else if baseURL != "" || authToken != "" {
434+
ui.ShowWarning("⚠ Incomplete environment configuration detected")
435+
if baseURL != "" {
436+
ui.ShowInfo(" ANTHROPIC_BASE_URL: %s", baseURL)
437+
}
438+
if authToken != "" {
439+
ui.ShowInfo(" ANTHROPIC_AUTH_TOKEN: configured")
440+
}
441+
}
442+
fmt.Println()
443+
444+
// 3. Check if config file exists
415445
ui.ShowInfo("Checking configuration file...")
416-
if _, err := os.Stat(config.ConfigPath); err != nil {
446+
configExists := false
447+
if _, err := os.Stat(config.ConfigPath); err == nil {
448+
configExists = true
449+
}
450+
451+
// If env config exists but no codes config, offer to import
452+
if hasEnvConfig && !configExists {
453+
fmt.Println()
454+
ui.ShowInfo("Would you like to import this configuration? (y/n): ")
455+
reader := bufio.NewReader(os.Stdin)
456+
response, _ := reader.ReadString('\n')
457+
response = strings.TrimSpace(strings.ToLower(response))
458+
459+
if response == "y" || response == "yes" {
460+
// Prompt for configuration name
461+
fmt.Print("Enter a name for this configuration (default: imported): ")
462+
name, _ := reader.ReadString('\n')
463+
name = strings.TrimSpace(name)
464+
if name == "" {
465+
name = "imported"
466+
}
467+
468+
// Create and test configuration
469+
ui.ShowLoading("Testing API connection...")
470+
testConfig := config.APIConfig{
471+
Name: name,
472+
AnthropicBaseURL: baseURL,
473+
AnthropicAuthToken: authToken,
474+
}
475+
476+
var cfg config.Config
477+
cfg.Configs = []config.APIConfig{testConfig}
478+
cfg.Default = name
479+
480+
if config.TestAPIConfig(testConfig) {
481+
ui.ShowSuccess("✓ API connection successful!")
482+
testConfig.Status = "active"
483+
} else {
484+
ui.ShowWarning("⚠ API connection failed, but configuration will be saved")
485+
testConfig.Status = "inactive"
486+
}
487+
488+
cfg.Configs[0] = testConfig
489+
490+
// Save configuration
491+
if err := config.SaveConfig(&cfg); err != nil {
492+
ui.ShowError("Failed to save configuration", err)
493+
allGood = false
494+
} else {
495+
ui.ShowSuccess("✓ Configuration imported successfully!")
496+
ui.ShowInfo(" Name: %s", name)
497+
ui.ShowInfo(" Status: %s", testConfig.Status)
498+
configExists = true
499+
}
500+
fmt.Println()
501+
}
502+
}
503+
504+
// Continue with normal config check
505+
if !configExists {
417506
ui.ShowError("✗ Configuration file not found", nil)
418507
ui.ShowInfo(" Expected location: %s", config.ConfigPath)
419508
ui.ShowWarning(" Run 'codes add' to create your first configuration")
@@ -422,7 +511,7 @@ func RunInit() {
422511
ui.ShowSuccess("✓ Configuration file exists")
423512
ui.ShowInfo(" Location: %s", config.ConfigPath)
424513

425-
// 3. Validate configuration
514+
// 4. Validate configuration
426515
cfg, err := config.LoadConfig()
427516
if err != nil {
428517
ui.ShowError("✗ Failed to load configuration", err)

0 commit comments

Comments
 (0)