Skip to content

Commit 60e238c

Browse files
committed
refactor: split commands.go into per-command files (closes #18)
Split the 2354-line monolithic commands.go into 11 focused files: - version.go: Version vars, RunVersion, RunClaudeUpdate, RunSelfUpdate, checkForUpdates - select.go: RunSelect, RunClaudeWithConfig, runClaudeInDirectory - install.go: InstallClaude, installBinary, installShellCompletion, appendCompletionLine - add.go: RunAdd - init_cmd.go: RunInit - start.go: RunStart - project_cmd.go: RunProject* functions - profile.go: RunTest, testSingleConfiguration, testAllConfigurations, RunProfileList/Remove - config_cmd.go: RunConfig*, RunDefaultBehavior*, RunSkipPermissions*, RunTerminal* - remote_cmd.go: parseSSHAddress, RunRemote* functions - serve.go: RunServe, RunHTTPServer No behavior changes. Build and all tests pass.
1 parent fc86427 commit 60e238c

12 files changed

Lines changed: 2368 additions & 2354 deletions

File tree

internal/commands/add.go

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
package commands
2+
3+
import (
4+
"bufio"
5+
"fmt"
6+
"os"
7+
"strings"
8+
9+
"codes/internal/config"
10+
"codes/internal/ui"
11+
)
12+
13+
func RunAdd() {
14+
ui.ShowHeader("Add New Claude Configuration")
15+
16+
var configData config.Config
17+
if _, err := os.Stat(config.ConfigPath); err == nil {
18+
cfg, err := config.LoadConfig()
19+
if err != nil {
20+
ui.ShowError("Error loading existing config", err)
21+
return
22+
}
23+
configData = *cfg
24+
} else {
25+
configData.Profiles = []config.APIConfig{}
26+
}
27+
28+
reader := bufio.NewReader(os.Stdin)
29+
30+
fmt.Print("Enter configuration name: ")
31+
name, _ := reader.ReadString('\n')
32+
name = strings.TrimSpace(name)
33+
if name == "" {
34+
ui.ShowError("Configuration name cannot be empty", nil)
35+
return
36+
}
37+
38+
for _, c := range configData.Profiles {
39+
if c.Name == name {
40+
ui.ShowError("Configuration '%s' already exists", fmt.Errorf("name '%s' already exists", name))
41+
return
42+
}
43+
}
44+
45+
newConfig := config.APIConfig{
46+
Name: name,
47+
Env: make(map[string]string),
48+
}
49+
50+
defaultVars := config.GetDefaultEnvironmentVars()
51+
52+
fmt.Println("\nBasic Configuration:")
53+
ui.ShowInfo("Enter values for required environment variables.")
54+
55+
fmt.Print("Enter ANTHROPIC_BASE_URL (required): ")
56+
baseURL, _ := reader.ReadString('\n')
57+
baseURL = strings.TrimSpace(baseURL)
58+
if baseURL == "" {
59+
ui.ShowError("Base URL cannot be empty", nil)
60+
return
61+
}
62+
newConfig.Env["ANTHROPIC_BASE_URL"] = baseURL
63+
64+
fmt.Print("Enter ANTHROPIC_AUTH_TOKEN (required): ")
65+
authToken, _ := reader.ReadString('\n')
66+
authToken = strings.TrimSpace(authToken)
67+
if authToken == "" {
68+
ui.ShowError("Authentication token cannot be empty", nil)
69+
return
70+
}
71+
newConfig.Env["ANTHROPIC_AUTH_TOKEN"] = authToken
72+
73+
fmt.Println("\nOptional Configuration:")
74+
ui.ShowInfo("The following environment variables are optional. Press Enter to skip.")
75+
76+
modelVars := []string{
77+
"ANTHROPIC_MODEL",
78+
"ANTHROPIC_DEFAULT_HAIKU_MODEL",
79+
"ANTHROPIC_DEFAULT_OPUS_MODEL",
80+
"ANTHROPIC_DEFAULT_SONNET_MODEL",
81+
}
82+
83+
otherVars := make(map[string]string)
84+
for envVar, description := range defaultVars {
85+
if _, exists := newConfig.Env[envVar]; exists {
86+
continue
87+
}
88+
isModelVar := false
89+
for _, mv := range modelVars {
90+
if envVar == mv {
91+
isModelVar = true
92+
break
93+
}
94+
}
95+
if !isModelVar {
96+
otherVars[envVar] = description
97+
}
98+
}
99+
100+
fmt.Println("\nModel Configuration:")
101+
ui.ShowInfo("These are model-specific variables. You can enter values or type 'skip' to use defaults.")
102+
103+
for _, envVar := range modelVars {
104+
if _, exists := newConfig.Env[envVar]; exists {
105+
continue
106+
}
107+
108+
description := defaultVars[envVar]
109+
fmt.Printf("Enter %s (%s) [skip]: ", envVar, description)
110+
value, _ := reader.ReadString('\n')
111+
value = strings.TrimSpace(value)
112+
113+
if value == "skip" {
114+
ui.ShowInfo("Skipping %s", envVar)
115+
} else if value != "" {
116+
newConfig.Env[envVar] = value
117+
}
118+
}
119+
120+
fmt.Println("\nOther Optional Configuration:")
121+
ui.ShowInfo("The following environment variables are optional. Press Enter to skip.")
122+
123+
for envVar, description := range otherVars {
124+
fmt.Printf("Enter %s (%s): ", envVar, description)
125+
value, _ := reader.ReadString('\n')
126+
value = strings.TrimSpace(value)
127+
if value != "" {
128+
newConfig.Env[envVar] = value
129+
}
130+
}
131+
132+
fmt.Print("\nWould you like to add any additional environment variables? (y/n): ")
133+
response, _ := reader.ReadString('\n')
134+
response = strings.TrimSpace(strings.ToLower(response))
135+
136+
if response == "y" || response == "yes" {
137+
fmt.Println("Enter environment variables in the format: VARIABLE_NAME=value")
138+
fmt.Println("Enter an empty line to finish")
139+
140+
for {
141+
fmt.Print("> ")
142+
line, _ := reader.ReadString('\n')
143+
line = strings.TrimSpace(line)
144+
145+
if line == "" {
146+
break
147+
}
148+
149+
parts := strings.SplitN(line, "=", 2)
150+
if len(parts) == 2 {
151+
varName := strings.TrimSpace(parts[0])
152+
varValue := strings.TrimSpace(parts[1])
153+
if varName != "" {
154+
newConfig.Env[varName] = varValue
155+
}
156+
} else {
157+
ui.ShowWarning("Invalid format. Use VARIABLE_NAME=value")
158+
}
159+
}
160+
}
161+
162+
fmt.Print("Use --dangerously-skip-permissions? (y/n) [default: n]: ")
163+
skipResp, _ := reader.ReadString('\n')
164+
skipResp = strings.TrimSpace(strings.ToLower(skipResp))
165+
if skipResp == "y" {
166+
skipPermissions := true
167+
newConfig.SkipPermissions = &skipPermissions
168+
}
169+
170+
ui.ShowLoading("Testing API connection")
171+
if config.TestAPIConfig(newConfig) {
172+
ui.ShowSuccess("API connection successful!")
173+
newConfig.Status = "active"
174+
} else {
175+
ui.ShowWarning("API connection failed. Configuration added but marked as inactive")
176+
newConfig.Status = "inactive"
177+
}
178+
179+
configData.Profiles = append(configData.Profiles, newConfig)
180+
181+
if len(configData.Profiles) == 1 {
182+
configData.Default = name
183+
ui.ShowInfo("Set '%s' as default configuration", name)
184+
}
185+
186+
if err := config.SaveConfig(&configData); err != nil {
187+
ui.ShowError("Failed to save config", err)
188+
return
189+
}
190+
191+
ui.ShowSuccess("Configuration '%s' added successfully!", name)
192+
ui.ShowInfo("API: %s", baseURL)
193+
ui.ShowInfo("Environment variables: %d", len(newConfig.Env))
194+
195+
if newConfig.Status == "active" {
196+
ui.ShowInfo("Status: Active")
197+
} else {
198+
ui.ShowWarning("Status: Inactive (API test failed)")
199+
}
200+
201+
if newConfig.SkipPermissions != nil {
202+
if *newConfig.SkipPermissions {
203+
ui.ShowInfo("Permissions: Skip --dangerously-skip-permissions")
204+
} else {
205+
ui.ShowInfo("Permissions: Use default (no --dangerously-skip-permissions)")
206+
}
207+
}
208+
}

0 commit comments

Comments
 (0)