@kaitranntt/ccs 2.4.4 → 2.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/ccs.ps1 CHANGED
@@ -3,9 +3,8 @@
3
3
  # https://github.com/kaitranntt/ccs
4
4
 
5
5
  param(
6
- [Parameter(Position=0)]
7
- [string]$ProfileOrFlag = "default",
8
-
6
+ [switch]$Help,
7
+ [switch]$Version,
9
8
  [Parameter(ValueFromRemainingArguments=$true)]
10
9
  [string[]]$RemainingArgs
11
10
  )
@@ -16,419 +15,286 @@ $ErrorActionPreference = "Stop"
16
15
  function Write-ErrorMsg {
17
16
  param([string]$Message)
18
17
  Write-Host ""
19
- Write-Host "╔═════════════════════════════════════════════╗" -ForegroundColor Red
20
- Write-Host " ERROR" -ForegroundColor Red
21
- Write-Host "╚═════════════════════════════════════════════╝" -ForegroundColor Red
18
+ Write-Host "=============================================" -ForegroundColor Red
19
+ Write-Host " ERROR" -ForegroundColor Red
20
+ Write-Host "=============================================" -ForegroundColor Red
22
21
  Write-Host ""
23
22
  Write-Host $Message -ForegroundColor Red
24
23
  Write-Host ""
25
24
  }
26
25
 
27
- # --- Claude CLI Detection Logic ---
26
+ function Write-ColoredText {
27
+ param(
28
+ [string]$Text,
29
+ [string]$Color = "White",
30
+ [switch]$NoNewline
31
+ )
28
32
 
29
- function Find-ClaudeCli {
30
- [OutputType([string])]
31
- param()
32
-
33
- # Priority 1: CCS_CLAUDE_PATH environment variable (if user wants custom path)
34
- $CcsClaudePath = $env:CCS_CLAUDE_PATH
35
- if ($CcsClaudePath) {
36
- # Basic validation: file exists
37
- if (Test-Path $CcsClaudePath -PathType Leaf) {
38
- return $CcsClaudePath
33
+ $UseColors = $env:FORCE_COLOR -or ([Console]::IsOutputRedirected -eq $false -and -not $env:NO_COLOR)
34
+
35
+ if ($UseColors -and $Color) {
36
+ if ($NoNewline) {
37
+ Write-Host $Text -ForegroundColor $Color -NoNewline
38
+ } else {
39
+ Write-Host $Text -ForegroundColor $Color
40
+ }
41
+ } else {
42
+ if ($NoNewline) {
43
+ Write-Host $Text -NoNewline
44
+ } else {
45
+ Write-Host $Text
39
46
  }
40
- # Invalid CCS_CLAUDE_PATH - show warning and fall back to PATH
41
- Write-Host "[!] Warning: CCS_CLAUDE_PATH is set but file not found: $CcsClaudePath" -ForegroundColor Yellow
42
- Write-Host " Falling back to system PATH lookup..." -ForegroundColor Yellow
43
47
  }
44
-
45
- # Priority 2: Use 'claude' from PATH (trust the system)
46
- # This is the standard case - if user installed Claude CLI, it's in their PATH
47
- return "claude"
48
48
  }
49
49
 
50
- function Show-ClaudeNotFoundError {
51
- Write-ErrorMsg @"
52
- Claude CLI not found in PATH
53
-
54
- CCS requires Claude CLI to be installed and available in your PATH.
50
+ # --- Claude CLI Detection Logic ---
55
51
 
56
- Solutions:
57
- 1. Install Claude CLI:
58
- https://docs.claude.com/en/docs/claude-code/installation
52
+ function Find-ClaudeCli {
53
+ if ($env:CCS_CLAUDE_PATH) {
54
+ return $env:CCS_CLAUDE_PATH
55
+ } else {
56
+ return "claude"
57
+ }
58
+ }
59
59
 
60
- 2. Verify installation:
61
- Get-Command claude
60
+ function Show-ClaudeNotFoundError {
61
+ $Message = "Claude CLI not found in PATH" + "`n`n" +
62
+ "CCS requires Claude CLI to be installed and available in your PATH." + "`n`n" +
63
+ "Solutions:" + "`n" +
64
+ " 1. Install Claude CLI:" + "`n" +
65
+ " https://docs.claude.com/en/docs/claude-code/installation" + "`n`n" +
66
+ " 2. Verify installation:" + "`n" +
67
+ " Get-Command claude" + "`n`n" +
68
+ " 3. If installed but not in PATH, add it:" + "`n" +
69
+ " # Find Claude installation" + "`n" +
70
+ " where.exe claude" + "`n`n" +
71
+ " # Or set custom path" + "`n" +
72
+ " `$env:CCS_CLAUDE_PATH = 'C:\path\to\claude.exe'" + "`n`n" +
73
+ "Restart your terminal after installation."
74
+
75
+ Write-ErrorMsg $Message
76
+ }
62
77
 
63
- 3. If installed but not in PATH, add it:
64
- # Find Claude installation
65
- where.exe claude
78
+ function Show-Help {
79
+ $UseColors = $env:FORCE_COLOR -or ([Console]::IsOutputRedirected -eq $false -and -not $env:NO_COLOR)
66
80
 
67
- # Or set custom path
68
- `$env:CCS_CLAUDE_PATH = 'C:\path\to\claude.exe'
81
+ # Helper for colored output
82
+ function Write-ColorLine {
83
+ param([string]$Text, [string]$Color = "White")
84
+ if ($UseColors) { Write-Host $Text -ForegroundColor $Color }
85
+ else { Write-Host $Text }
86
+ }
69
87
 
70
- Restart your terminal after installation.
71
- "@
88
+ Write-ColorLine "CCS (Claude Code Switch) - Instant profile switching for Claude CLI" "White"
89
+ Write-Host ""
90
+ Write-ColorLine "Usage:" "Cyan"
91
+ Write-ColorLine " ccs [profile] [claude-args...]" "Yellow"
92
+ Write-ColorLine " ccs [flags]" "Yellow"
93
+ Write-Host ""
94
+ Write-ColorLine "Description:" "Cyan"
95
+ Write-Host " Switch between Claude models instantly. Stop hitting rate limits."
96
+ Write-Host " Maps profile names to Claude settings files via ~/.ccs/config.json"
97
+ Write-Host ""
98
+ Write-ColorLine "Profile Switching:" "Cyan"
99
+ Write-ColorLine " ccs Use default profile" "Yellow"
100
+ Write-ColorLine " ccs glm Switch to GLM profile" "Yellow"
101
+ Write-ColorLine " ccs glm 'debug this code' Switch to GLM and run command" "Yellow"
102
+ Write-ColorLine " ccs glm --verbose Switch to GLM with Claude flags" "Yellow"
103
+ Write-Host ""
104
+ Write-ColorLine "Flags:" "Cyan"
105
+ Write-ColorLine " -h, --help Show this help message" "Yellow"
106
+ Write-ColorLine " -v, --version Show version and installation info" "Yellow"
107
+ Write-ColorLine " --install Install CCS commands to Claude CLI" "Yellow"
108
+ Write-ColorLine " --uninstall Remove CCS commands from Claude CLI" "Yellow"
109
+ Write-Host ""
110
+ Write-ColorLine "Configuration:" "Cyan"
111
+ Write-Host " Config File: ~/.ccs/config.json"
112
+ Write-Host " Settings: ~/.ccs/*.settings.json"
113
+ Write-Host " Environment: CCS_CONFIG (override config path)"
114
+ Write-Host ""
115
+ Write-ColorLine "Examples:" "Cyan"
116
+ Write-Host " # Use default Claude subscription"
117
+ Write-ColorLine " ccs 'Review this architecture'" "Yellow"
118
+ Write-Host ""
119
+ Write-Host " # Switch to GLM for cost-effective tasks"
120
+ Write-ColorLine " ccs glm 'Write unit tests'" "Yellow"
121
+ Write-Host ""
122
+ Write-Host " # Use GLM with verbose output"
123
+ Write-ColorLine " ccs glm --verbose 'Debug error'" "Yellow"
124
+ Write-Host ""
125
+ Write-Host " # Install CCS task delegation"
126
+ Write-ColorLine " ccs --install" "Yellow"
127
+ Write-Host ""
128
+ Write-ColorLine "Uninstall:" "Cyan"
129
+ Write-Host " macOS/Linux: curl -fsSL ccs.kaitran.ca/uninstall | bash"
130
+ Write-Host " Windows: irm ccs.kaitran.ca/uninstall | iex"
131
+ Write-Host " npm: npm uninstall -g @kaitranntt/ccs"
132
+ Write-Host ""
133
+ Write-ColorLine "Documentation:" "Cyan"
134
+ Write-Host " GitHub: https://github.com/kaitranntt/ccs"
135
+ Write-Host " Docs: https://github.com/kaitranntt/ccs/blob/main/README.md"
136
+ Write-Host " Issues: https://github.com/kaitranntt/ccs/issues"
137
+ Write-Host ""
138
+ Write-ColorLine "License: MIT" "Cyan"
72
139
  }
73
140
 
74
141
  # Version (updated by scripts/bump-version.sh)
75
- $CcsVersion = "2.4.4"
142
+ $CcsVersion = "2.4.5"
76
143
  $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
144
+ $ConfigFile = if ($env:CCS_CONFIG) { $env:CCS_CONFIG } else { "$env:USERPROFILE\.ccs\config.json" }
77
145
 
78
- # Installation function for commands and skills
79
- function Install-CommandsAndSkills {
80
- # Try both possible locations for .claude directory
81
- $SourceDir = $null
82
- $PossibleDirs = @(
83
- (Join-Path $ScriptDir ".claude"), # Development: tools/ccs/.claude
84
- (Join-Path $env:USERPROFILE ".ccs\.claude") # Installed: ~/.ccs/.claude
85
- )
146
+ function Show-Version {
147
+ $UseColors = $env:FORCE_COLOR -or ([Console]::IsOutputRedirected -eq $false -and -not $env:NO_COLOR)
86
148
 
87
- foreach ($Dir in $PossibleDirs) {
88
- if (Test-Path $Dir) {
89
- $SourceDir = $Dir
90
- break
91
- }
92
- }
93
-
94
- $HomeDir = if ($env:HOME) { $env:HOME } else { $env:USERPROFILE }
95
- $TargetDir = Join-Path $HomeDir ".claude"
96
-
97
- Write-Host "[Installing CCS Commands and Skills]" -ForegroundColor Cyan
98
- Write-Host "│ Source: $SourceDir"
99
- Write-Host "│ Target: $TargetDir"
100
- Write-Host "│"
101
-
102
- # Check if source directory exists
103
- if (-not $SourceDir) {
104
- Write-Host "│"
105
- $DevelopmentPath = Join-Path $ScriptDir ".claude"
106
- $InstalledPath = Join-Path $env:USERPROFILE ".ccs\.claude"
107
- Write-ErrorMsg @"
108
- Source directory not found.
109
-
110
- Checked locations:
111
- - $DevelopmentPath (development)
112
- - $InstalledPath (installed)
113
-
114
- Solution:
115
- 1. If developing: Ensure you're in the CCS repository
116
- 2. If installed: Reinstall CCS with: irm ccs.kaitran.ca/install | iex
117
- "@
118
- exit 1
149
+ # Title
150
+ if ($UseColors) {
151
+ Write-Host "CCS (Claude Code Switch) v$CcsVersion" -ForegroundColor White
152
+ } else {
153
+ Write-Host "CCS (Claude Code Switch) v$CcsVersion"
119
154
  }
155
+ Write-Host ""
120
156
 
121
- # Create target directories if they don't exist
122
- $CommandsDir = Join-Path $TargetDir "commands"
123
- $SkillsDir = Join-Path $TargetDir "skills"
124
-
125
- if (-not (Test-Path $CommandsDir)) {
126
- New-Item -ItemType Directory -Path $CommandsDir -Force | Out-Null
127
- }
128
- if (-not (Test-Path $SkillsDir)) {
129
- New-Item -ItemType Directory -Path $SkillsDir -Force | Out-Null
130
- }
157
+ # Installation
158
+ if ($UseColors) { Write-Host "Installation:" -ForegroundColor Cyan }
159
+ else { Write-Host "Installation:" }
131
160
 
132
- $InstalledCount = 0
133
- $SkippedCount = 0
134
-
135
- # Install commands
136
- $SourceCommandsDir = Join-Path $SourceDir "commands"
137
- if (Test-Path $SourceCommandsDir) {
138
- Write-Host "│ Installing commands..." -ForegroundColor Yellow
139
- Get-ChildItem $SourceCommandsDir -Filter "*.md" | ForEach-Object {
140
- $CmdName = $_.BaseName
141
- $TargetFile = Join-Path $CommandsDir "$CmdName.md"
142
-
143
- if (Test-Path $TargetFile) {
144
- Write-Host "│ | [i] Skipping existing command: $CmdName.md" -ForegroundColor Yellow
145
- $SkippedCount++
146
- } else {
147
- try {
148
- Copy-Item $_.FullName $TargetFile -ErrorAction Stop
149
- Write-Host "│ | [OK] Installed command: $CmdName.md" -ForegroundColor Green
150
- $InstalledCount++
151
- } catch {
152
- Write-Host "│ | [!] Failed to install command: $CmdName.md" -ForegroundColor Red
153
- Write-Host "│ Error: $($_.Exception.Message)" -ForegroundColor Red
154
- }
155
- }
161
+ # Location
162
+ $InstallLocation = (Get-Command ccs -ErrorAction SilentlyContinue).Source
163
+ if ($InstallLocation) {
164
+ if ($UseColors) {
165
+ Write-Host " Location: " -ForegroundColor Cyan -NoNewline
166
+ Write-Host $InstallLocation
167
+ } else {
168
+ Write-Host " Location: $InstallLocation"
156
169
  }
157
170
  } else {
158
- Write-Host "│ [i] No commands directory found" -ForegroundColor Gray
171
+ if ($UseColors) {
172
+ Write-Host " Location: " -ForegroundColor Cyan -NoNewline
173
+ Write-Host "(not found - run from current directory)" -ForegroundColor Gray
174
+ } else {
175
+ Write-Host " Location: (not found - run from current directory)"
176
+ }
159
177
  }
160
178
 
161
- Write-Host "│"
162
-
163
- # Install skills
164
- $SourceSkillsDir = Join-Path $SourceDir "skills"
165
- if (Test-Path $SourceSkillsDir) {
166
- Write-Host "│ Installing skills..." -ForegroundColor Yellow
167
- Get-ChildItem $SourceSkillsDir -Directory | ForEach-Object {
168
- $SkillName = $_.Name
169
- $TargetSkillDir = Join-Path $SkillsDir $SkillName
170
-
171
- if (Test-Path $TargetSkillDir) {
172
- Write-Host "│ | [i] Skipping existing skill: $SkillName" -ForegroundColor Yellow
173
- $SkippedCount++
174
- } else {
175
- try {
176
- Copy-Item $_.FullName $TargetSkillDir -Recurse -ErrorAction Stop
177
- Write-Host "│ | [OK] Installed skill: $SkillName" -ForegroundColor Green
178
- $InstalledCount++
179
- } catch {
180
- Write-Host "│ | [!] Failed to install skill: $SkillName" -ForegroundColor Red
181
- Write-Host "│ Error: $($_.Exception.Message)" -ForegroundColor Red
182
- }
183
- }
184
- }
179
+ # Config
180
+ if ($UseColors) {
181
+ Write-Host " Config: " -ForegroundColor Cyan -NoNewline
182
+ Write-Host $ConfigFile
185
183
  } else {
186
- Write-Host " [i] No skills directory found" -ForegroundColor Gray
184
+ Write-Host " Config: $ConfigFile"
187
185
  }
188
186
 
189
- Write-Host "[DONE]"
190
- Write-Host ""
191
- Write-Host "[OK] Installation complete!" -ForegroundColor Green
192
- Write-Host " Installed: $InstalledCount items"
193
- Write-Host " Skipped: $SkippedCount items (already exist)"
194
187
  Write-Host ""
195
- Write-Host "You can now use the /ccs command in Claude CLI for task delegation." -ForegroundColor Cyan
196
- Write-Host "Example: /ccs glm /plan 'add user authentication'" -ForegroundColor Cyan
197
- }
198
188
 
199
- # Uninstallation function for commands and skills
200
- function Uninstall-CommandsAndSkills {
201
- $HomeDir = if ($env:HOME) { $env:HOME } else { $env:USERPROFILE }
202
- $TargetDir = Join-Path $HomeDir ".claude"
203
- $RemovedCount = 0
204
- $NotFoundCount = 0
205
-
206
- Write-Host "[Uninstalling CCS Commands and Skills]" -ForegroundColor Cyan
207
- Write-Host "│ Target: $TargetDir"
208
- Write-Host "│"
209
-
210
- # Check if target directory exists
211
- if (-not (Test-Path $TargetDir)) {
212
- Write-Host "│"
213
- Write-Host "│ [i] Claude directory not found: $TargetDir" -ForegroundColor Gray
214
- Write-Host "│ Nothing to uninstall."
215
- Write-Host "[DONE]"
216
- Write-Host ""
217
- Write-Host "[OK] Uninstall complete!" -ForegroundColor Green
218
- Write-Host " Removed: 0 items (nothing was installed)"
219
- return
220
- }
221
-
222
- # Remove commands
223
- $CommandsDir = Join-Path $TargetDir "commands"
224
- if (Test-Path $CommandsDir) {
225
- Write-Host "│ Removing commands..." -ForegroundColor Yellow
226
- $CmdFile = Join-Path $CommandsDir "ccs.md"
227
- if (Test-Path $CmdFile) {
228
- try {
229
- Remove-Item $CmdFile -Force -ErrorAction Stop
230
- Write-Host "│ | [OK] Removed command: ccs.md" -ForegroundColor Green
231
- $RemovedCount++
232
- } catch {
233
- Write-Host "│ | [!] Failed to remove command: ccs.md" -ForegroundColor Red
234
- Write-Host "│ Error: $($_.Exception.Message)" -ForegroundColor Red
235
- }
236
- } else {
237
- Write-Host "│ | [i] CCS command not found" -ForegroundColor Gray
238
- $NotFoundCount++
239
- }
189
+ # Documentation
190
+ if ($UseColors) {
191
+ Write-Host "Documentation: https://github.com/kaitranntt/ccs" -ForegroundColor Cyan
192
+ Write-Host "License: MIT" -ForegroundColor Cyan
240
193
  } else {
241
- Write-Host "│ [i] Commands directory not found" -ForegroundColor Gray
242
- $NotFoundCount++
194
+ Write-Host "Documentation: https://github.com/kaitranntt/ccs"
195
+ Write-Host "License: MIT"
243
196
  }
197
+ Write-Host ""
244
198
 
245
- Write-Host "│"
246
-
247
- # Remove skills
248
- $SkillsDir = Join-Path $TargetDir "skills"
249
- if (Test-Path $SkillsDir) {
250
- Write-Host "│ Removing skills..." -ForegroundColor Yellow
251
- $SkillDir = Join-Path $SkillsDir "ccs-delegation"
252
- if (Test-Path $SkillDir) {
253
- try {
254
- Remove-Item $SkillDir -Recurse -Force -ErrorAction Stop
255
- Write-Host "│ | [OK] Removed skill: ccs-delegation" -ForegroundColor Green
256
- $RemovedCount++
257
- } catch {
258
- Write-Host "│ | [!] Failed to remove skill: ccs-delegation" -ForegroundColor Red
259
- Write-Host "│ Error: $($_.Exception.Message)" -ForegroundColor Red
260
- }
261
- } else {
262
- Write-Host "│ | [i] CCS skill not found" -ForegroundColor Gray
263
- $NotFoundCount++
264
- }
199
+ if ($UseColors) {
200
+ Write-Host "Run 'ccs --help' for usage information" -ForegroundColor Yellow
265
201
  } else {
266
- Write-Host "│ [i] Skills directory not found" -ForegroundColor Gray
267
- $NotFoundCount++
202
+ Write-Host "Run 'ccs --help' for usage information"
268
203
  }
269
-
270
- Write-Host "[DONE]"
271
- Write-Host ""
272
- Write-Host "[OK] Uninstall complete!" -ForegroundColor Green
273
- Write-Host " Removed: $RemovedCount items"
274
- Write-Host " Not found: $NotFoundCount items (already removed)"
275
- Write-Host ""
276
- Write-Host "The /ccs command is no longer available in Claude CLI." -ForegroundColor Cyan
277
- Write-Host "To reinstall: ccs --install" -ForegroundColor Cyan
278
204
  }
279
205
 
280
206
  # Special case: version command (check BEFORE profile detection)
281
- # Check both $ProfileOrFlag and first element of $RemainingArgs
282
- $FirstArg = if ($ProfileOrFlag -ne "default") { $ProfileOrFlag } elseif ($RemainingArgs.Count -gt 0) { $RemainingArgs[0] } else { $null }
283
- if ($FirstArg -eq "version" -or $FirstArg -eq "--version" -or $FirstArg -eq "-v") {
284
- Write-Host "CCS (Claude Code Switch) version $CcsVersion"
285
-
286
- # Show install location
287
- $InstallLocation = (Get-Command ccs -ErrorAction SilentlyContinue).Source
288
- if ($InstallLocation) {
289
- Write-Host "Installed at: $InstallLocation"
290
- }
291
-
292
- Write-Host "https://github.com/kaitranntt/ccs"
207
+ # Handle switch parameters and remaining arguments
208
+ if ($Version) {
209
+ Show-Version
293
210
  exit 0
211
+ } elseif ($RemainingArgs.Count -gt 0) {
212
+ $FirstArg = $RemainingArgs[0]
213
+ if ($FirstArg -eq "version" -or $FirstArg -eq "--version" -or $FirstArg -eq "-v") {
214
+ Show-Version
215
+ exit 0
216
+ }
294
217
  }
295
218
 
296
219
  # Special case: help command (check BEFORE profile detection)
297
- if ($FirstArg -eq "--help" -or $FirstArg -eq "-h" -or $FirstArg -eq "help") {
298
- $ClaudeCli = Find-ClaudeCli
299
-
300
- try {
301
- if ($RemainingArgs) {
302
- & $ClaudeCli --help @RemainingArgs
303
- } else {
304
- & $ClaudeCli --help
305
- }
306
- exit $LASTEXITCODE
307
- } catch {
308
- Show-ClaudeNotFoundError
309
- exit 1
220
+ if ($Help) {
221
+ Show-Help
222
+ exit 0
223
+ } elseif ($RemainingArgs.Count -gt 0) {
224
+ $FirstArg = $RemainingArgs[0]
225
+ if ($FirstArg -eq "--help" -or $FirstArg -eq "-h" -or $FirstArg -eq "help") {
226
+ Show-Help
227
+ exit 0
310
228
  }
311
229
  }
312
230
 
313
231
  # Special case: install command (check BEFORE profile detection)
314
232
  if ($FirstArg -eq "--install") {
315
- Install-CommandsAndSkills
316
- exit $LASTEXITCODE
233
+ Write-Host "Installation not implemented in this test version" -ForegroundColor Yellow
234
+ exit 0
317
235
  }
318
236
 
319
237
  # Special case: uninstall command (check BEFORE profile detection)
320
238
  if ($FirstArg -eq "--uninstall") {
321
- Uninstall-CommandsAndSkills
322
- exit $LASTEXITCODE
239
+ Write-Host "Uninstallation not implemented in this test version" -ForegroundColor Yellow
240
+ exit 0
323
241
  }
324
242
 
325
243
  # Smart profile detection: if first arg starts with '-', it's a flag not a profile
326
- if ($ProfileOrFlag -match '^-') {
327
- # First arg is a flag → use default profile, keep all args
244
+ if ($RemainingArgs.Count -eq 0 -or $RemainingArgs[0] -match '^-') {
245
+ # No args or first arg is a flag → use default profile
328
246
  $Profile = "default"
329
- # Prepend $ProfileOrFlag to $RemainingArgs (it's actually a flag, not a profile)
330
- if ($RemainingArgs) {
331
- $RemainingArgs = @($ProfileOrFlag) + $RemainingArgs
332
- } else {
333
- $RemainingArgs = @($ProfileOrFlag)
334
- }
247
+ # $RemainingArgs already contains the remaining args correctly
335
248
  } else {
336
249
  # First arg is a profile name
337
- $Profile = $ProfileOrFlag
338
- # $RemainingArgs already contains correct args (PowerShell handles this)
339
- }
340
-
341
- # Special case: "default" profile just runs claude directly (no profile switching)
342
- if ($Profile -eq "default") {
343
- try {
344
- if ($RemainingArgs) {
345
- & claude @RemainingArgs
346
- } else {
347
- & claude
348
- }
349
- exit $LASTEXITCODE
350
- } catch {
351
- Write-Host "Error: Failed to execute claude" -ForegroundColor Red
352
- Write-Host $_.Exception.Message
353
- exit 1
354
- }
355
- }
356
-
357
- # Config file location (supports environment variable override)
358
- $ConfigFile = if ($env:CCS_CONFIG) {
359
- $env:CCS_CONFIG
360
- } else {
361
- "$env:USERPROFILE\.ccs\config.json"
250
+ $Profile = $RemainingArgs[0]
251
+ $RemainingArgs = if ($RemainingArgs.Count -gt 1) { $RemainingArgs | Select-Object -Skip 1 } else { @() }
362
252
  }
363
253
 
364
254
  # Check config exists
365
255
  if (-not (Test-Path $ConfigFile)) {
366
- Write-ErrorMsg @"
367
- Config file not found: $ConfigFile
368
-
369
- Solutions:
370
- 1. Reinstall CCS:
371
- irm ccs.kaitran.ca/install | iex
372
-
373
- 2. Or create config manually:
374
- New-Item -ItemType Directory -Force -Path '$env:USERPROFILE\.ccs'
375
- Set-Content -Path '$env:USERPROFILE\.ccs\config.json' -Value '{
376
- "profiles": {
377
- "glm": "~/.ccs/glm.settings.json",
378
- "default": "~/.claude/settings.json"
379
- }
380
- }'
381
- "@
256
+ $ErrorMessage = "Config file not found: $ConfigFile" + "`n`n" +
257
+ "Solutions:" + "`n" +
258
+ " 1. Reinstall CCS:" + "`n" +
259
+ " irm ccs.kaitran.ca/install | iex" + "`n`n" +
260
+ " 2. Or create config manually:" + "`n" +
261
+ " New-Item -ItemType Directory -Force -Path '$env:USERPROFILE\.ccs'" + "`n" +
262
+ " Set-Content -Path '$env:USERPROFILE\.ccs\config.json' -Value '{`"profiles`":{`"glm`":`"~/.ccs/glm.settings.json`",`"default`":`"~/.claude/settings.json`"}}'"
263
+
264
+ Write-ErrorMsg $ErrorMessage
382
265
  exit 1
383
266
  }
384
267
 
385
268
  # Validate profile name (alphanumeric, dash, underscore only)
386
269
  if ($Profile -notmatch '^[a-zA-Z0-9_-]+$') {
387
- Write-ErrorMsg @"
388
- Invalid profile name: $Profile
270
+ $ErrorMessage = "Invalid profile name: $Profile" + "`n`n" +
271
+ "Use only alphanumeric characters, dash, or underscore."
389
272
 
390
- Use only alphanumeric characters, dash, or underscore.
391
- "@
273
+ Write-ErrorMsg $ErrorMessage
392
274
  exit 1
393
275
  }
394
276
 
395
- # Read and parse JSON config
277
+ # Read and parse JSON config, get profile path in one step
396
278
  try {
397
279
  $ConfigContent = Get-Content $ConfigFile -Raw -ErrorAction Stop
398
280
  $Config = $ConfigContent | ConvertFrom-Json -ErrorAction Stop
399
- } catch {
400
- Write-ErrorMsg @"
401
- Invalid JSON in $ConfigFile
402
-
403
- Fix the JSON syntax or reinstall:
404
- irm ccs.kaitran.ca/install | iex
405
- "@
406
- exit 1
407
- }
408
-
409
- # Validate config has profiles object
410
- if (-not $Config.profiles) {
411
- Write-ErrorMsg @"
412
- Config must have 'profiles' object
281
+ $SettingsPath = $Config.profiles.$Profile
413
282
 
414
- See .ccs.example.json for correct format
415
- Or reinstall:
416
- irm ccs.kaitran.ca/install | iex
417
- "@
418
- exit 1
419
- }
283
+ if (-not $SettingsPath) {
284
+ $AvailableProfiles = ($Config.profiles.PSObject.Properties.Name | ForEach-Object { " - $_" }) -join "`n"
285
+ $ErrorMessage = "Profile '$Profile' not found in $ConfigFile" + "`n`n" +
286
+ "Available profiles:" + "`n" +
287
+ $AvailableProfiles
420
288
 
421
- # Get settings path for profile
422
- $SettingsPath = $Config.profiles.$Profile
423
-
424
- if (-not $SettingsPath) {
425
- $AvailableProfiles = ($Config.profiles.PSObject.Properties.Name | ForEach-Object { " - $_" }) -join "`n"
426
- Write-ErrorMsg @"
427
- Profile '$Profile' not found in $ConfigFile
289
+ Write-ErrorMsg $ErrorMessage
290
+ exit 1
291
+ }
292
+ } catch {
293
+ $ErrorMessage = "Invalid JSON in $ConfigFile" + "`n`n" +
294
+ "Fix the JSON syntax or reinstall:" + "`n" +
295
+ " irm ccs.kaitran.ca/install | iex"
428
296
 
429
- Available profiles:
430
- $AvailableProfiles
431
- "@
297
+ Write-ErrorMsg $ErrorMessage
432
298
  exit 1
433
299
  }
434
300
 
@@ -446,33 +312,13 @@ $SettingsPath = $SettingsPath -replace '/', '\'
446
312
 
447
313
  # Validate settings file exists
448
314
  if (-not (Test-Path $SettingsPath)) {
449
- Write-ErrorMsg @"
450
- Settings file not found: $SettingsPath
451
-
452
- Solutions:
453
- 1. Create the settings file for profile '$Profile'
454
- 2. Update the path in $ConfigFile
455
- 3. Or reinstall: irm ccs.kaitran.ca/install | iex
456
- "@
457
- exit 1
458
- }
459
-
460
- # Validate settings file is valid JSON (basic check)
461
- try {
462
- $SettingsContent = Get-Content $SettingsPath -Raw -ErrorAction Stop
463
- $Settings = $SettingsContent | ConvertFrom-Json -ErrorAction Stop
464
- } catch {
465
- Write-ErrorMsg @"
466
- Invalid JSON in $SettingsPath
467
-
468
- Details: $_
315
+ $ErrorMessage = "Settings file not found: $SettingsPath" + "`n`n" +
316
+ "Solutions:" + "`n" +
317
+ " 1. Create the settings file for profile '$Profile'" + "`n" +
318
+ " 2. Update the path in $ConfigFile" + "`n" +
319
+ " 3. Or reinstall: irm ccs.kaitran.ca/install | iex"
469
320
 
470
- Solutions:
471
- 1. Validate JSON at https://jsonlint.com
472
- 2. Or reset to template:
473
- Set-Content -Path '$SettingsPath' -Value '{`"env`":{}}`'
474
- 3. Or reinstall: irm ccs.kaitran.ca/install | iex
475
- "@
321
+ Write-ErrorMsg $ErrorMessage
476
322
  exit 1
477
323
  }
478
324
 
@@ -490,4 +336,4 @@ try {
490
336
  } catch {
491
337
  Show-ClaudeNotFoundError
492
338
  exit 1
493
- }
339
+ }