@kaitranntt/ccs 2.4.4 → 2.4.6
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/README.md +21 -40
- package/README.vi.md +13 -32
- package/VERSION +1 -1
- package/bin/ccs.js +122 -131
- package/bin/claude-detector.js +5 -34
- package/bin/config-manager.js +8 -69
- package/bin/helpers.js +40 -33
- package/lib/ccs +131 -80
- package/lib/ccs.ps1 +219 -364
- package/package.json +1 -1
package/lib/ccs.ps1
CHANGED
|
@@ -3,9 +3,8 @@
|
|
|
3
3
|
# https://github.com/kaitranntt/ccs
|
|
4
4
|
|
|
5
5
|
param(
|
|
6
|
-
[
|
|
7
|
-
[
|
|
8
|
-
|
|
6
|
+
[switch]$Help,
|
|
7
|
+
[switch]$Version,
|
|
9
8
|
[Parameter(ValueFromRemainingArguments=$true)]
|
|
10
9
|
[string[]]$RemainingArgs
|
|
11
10
|
)
|
|
@@ -16,419 +15,295 @@ $ErrorActionPreference = "Stop"
|
|
|
16
15
|
function Write-ErrorMsg {
|
|
17
16
|
param([string]$Message)
|
|
18
17
|
Write-Host ""
|
|
19
|
-
Write-Host "
|
|
20
|
-
Write-Host "
|
|
21
|
-
Write-Host "
|
|
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
|
-
|
|
26
|
+
function Write-ColoredText {
|
|
27
|
+
param(
|
|
28
|
+
[string]$Text,
|
|
29
|
+
[string]$Color = "White",
|
|
30
|
+
[switch]$NoNewline
|
|
31
|
+
)
|
|
28
32
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
-
|
|
61
|
-
|
|
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
|
-
|
|
64
|
-
|
|
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
|
-
|
|
68
|
-
|
|
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
|
-
|
|
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-Host ""
|
|
108
|
+
Write-ColorLine "Configuration:" "Cyan"
|
|
109
|
+
Write-Host " Config File: ~/.ccs/config.json"
|
|
110
|
+
Write-Host " Settings: ~/.ccs/*.settings.json"
|
|
111
|
+
Write-Host " Environment: CCS_CONFIG (override config path)"
|
|
112
|
+
Write-Host ""
|
|
113
|
+
Write-ColorLine "Examples:" "Cyan"
|
|
114
|
+
Write-Host " # Use default Claude subscription"
|
|
115
|
+
Write-ColorLine " ccs 'Review this architecture'" "Yellow"
|
|
116
|
+
Write-Host ""
|
|
117
|
+
Write-Host " # Switch to GLM for cost-effective tasks"
|
|
118
|
+
Write-ColorLine " ccs glm 'Write unit tests'" "Yellow"
|
|
119
|
+
Write-Host ""
|
|
120
|
+
Write-Host " # Use GLM with verbose output"
|
|
121
|
+
Write-ColorLine " ccs glm --verbose 'Debug error'" "Yellow"
|
|
122
|
+
Write-Host ""
|
|
123
|
+
Write-ColorLine "Uninstall:" "Cyan"
|
|
124
|
+
Write-Host " macOS/Linux: curl -fsSL ccs.kaitran.ca/uninstall | bash"
|
|
125
|
+
Write-Host " Windows: irm ccs.kaitran.ca/uninstall | iex"
|
|
126
|
+
Write-Host " npm: npm uninstall -g @kaitranntt/ccs"
|
|
127
|
+
Write-Host ""
|
|
128
|
+
Write-ColorLine "Documentation:" "Cyan"
|
|
129
|
+
Write-Host " GitHub: https://github.com/kaitranntt/ccs"
|
|
130
|
+
Write-Host " Docs: https://github.com/kaitranntt/ccs/blob/main/README.md"
|
|
131
|
+
Write-Host " Issues: https://github.com/kaitranntt/ccs/issues"
|
|
132
|
+
Write-Host ""
|
|
133
|
+
Write-ColorLine "License: MIT" "Cyan"
|
|
72
134
|
}
|
|
73
135
|
|
|
74
136
|
# Version (updated by scripts/bump-version.sh)
|
|
75
|
-
$CcsVersion = "2.4.
|
|
137
|
+
$CcsVersion = "2.4.6"
|
|
76
138
|
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
139
|
+
$ConfigFile = if ($env:CCS_CONFIG) { $env:CCS_CONFIG } else { "$env:USERPROFILE\.ccs\config.json" }
|
|
77
140
|
|
|
78
|
-
|
|
79
|
-
|
|
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
|
-
)
|
|
141
|
+
function Show-Version {
|
|
142
|
+
$UseColors = $env:FORCE_COLOR -or ([Console]::IsOutputRedirected -eq $false -and -not $env:NO_COLOR)
|
|
86
143
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
|
144
|
+
# Title
|
|
145
|
+
if ($UseColors) {
|
|
146
|
+
Write-Host "CCS (Claude Code Switch) v$CcsVersion" -ForegroundColor White
|
|
147
|
+
} else {
|
|
148
|
+
Write-Host "CCS (Claude Code Switch) v$CcsVersion"
|
|
119
149
|
}
|
|
150
|
+
Write-Host ""
|
|
120
151
|
|
|
121
|
-
#
|
|
122
|
-
$
|
|
123
|
-
|
|
152
|
+
# Installation
|
|
153
|
+
if ($UseColors) { Write-Host "Installation:" -ForegroundColor Cyan }
|
|
154
|
+
else { Write-Host "Installation:" }
|
|
124
155
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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
|
-
}
|
|
156
|
+
# Location
|
|
157
|
+
$InstallLocation = (Get-Command ccs -ErrorAction SilentlyContinue).Source
|
|
158
|
+
if ($InstallLocation) {
|
|
159
|
+
if ($UseColors) {
|
|
160
|
+
Write-Host " Location: " -ForegroundColor Cyan -NoNewline
|
|
161
|
+
Write-Host $InstallLocation
|
|
162
|
+
} else {
|
|
163
|
+
Write-Host " Location: $InstallLocation"
|
|
156
164
|
}
|
|
157
165
|
} else {
|
|
158
|
-
|
|
166
|
+
if ($UseColors) {
|
|
167
|
+
Write-Host " Location: " -ForegroundColor Cyan -NoNewline
|
|
168
|
+
Write-Host "(not found - run from current directory)" -ForegroundColor Gray
|
|
169
|
+
} else {
|
|
170
|
+
Write-Host " Location: (not found - run from current directory)"
|
|
171
|
+
}
|
|
159
172
|
}
|
|
160
173
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
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
|
-
}
|
|
174
|
+
# Config
|
|
175
|
+
if ($UseColors) {
|
|
176
|
+
Write-Host " Config: " -ForegroundColor Cyan -NoNewline
|
|
177
|
+
Write-Host $ConfigFile
|
|
185
178
|
} else {
|
|
186
|
-
Write-Host "
|
|
179
|
+
Write-Host " Config: $ConfigFile"
|
|
187
180
|
}
|
|
188
181
|
|
|
189
|
-
Write-Host "[DONE]"
|
|
190
182
|
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
|
-
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
|
-
|
|
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
183
|
|
|
222
|
-
#
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
Write-Host "
|
|
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
|
-
}
|
|
184
|
+
# Documentation
|
|
185
|
+
if ($UseColors) {
|
|
186
|
+
Write-Host "Documentation: https://github.com/kaitranntt/ccs" -ForegroundColor Cyan
|
|
187
|
+
Write-Host "License: MIT" -ForegroundColor Cyan
|
|
240
188
|
} else {
|
|
241
|
-
Write-Host "
|
|
242
|
-
|
|
189
|
+
Write-Host "Documentation: https://github.com/kaitranntt/ccs"
|
|
190
|
+
Write-Host "License: MIT"
|
|
243
191
|
}
|
|
192
|
+
Write-Host ""
|
|
244
193
|
|
|
245
|
-
|
|
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
|
-
}
|
|
194
|
+
if ($UseColors) {
|
|
195
|
+
Write-Host "Run 'ccs --help' for usage information" -ForegroundColor Yellow
|
|
265
196
|
} else {
|
|
266
|
-
Write-Host "
|
|
267
|
-
$NotFoundCount++
|
|
197
|
+
Write-Host "Run 'ccs --help' for usage information"
|
|
268
198
|
}
|
|
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
199
|
}
|
|
279
200
|
|
|
280
201
|
# Special case: version command (check BEFORE profile detection)
|
|
281
|
-
#
|
|
282
|
-
|
|
283
|
-
|
|
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"
|
|
202
|
+
# Handle switch parameters and remaining arguments
|
|
203
|
+
if ($Version) {
|
|
204
|
+
Show-Version
|
|
293
205
|
exit 0
|
|
206
|
+
} elseif ($RemainingArgs.Count -gt 0) {
|
|
207
|
+
$FirstArg = $RemainingArgs[0]
|
|
208
|
+
if ($FirstArg -eq "version" -or $FirstArg -eq "--version" -or $FirstArg -eq "-v") {
|
|
209
|
+
Show-Version
|
|
210
|
+
exit 0
|
|
211
|
+
}
|
|
294
212
|
}
|
|
295
213
|
|
|
296
214
|
# Special case: help command (check BEFORE profile detection)
|
|
297
|
-
if ($
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
}
|
|
306
|
-
exit $LASTEXITCODE
|
|
307
|
-
} catch {
|
|
308
|
-
Show-ClaudeNotFoundError
|
|
309
|
-
exit 1
|
|
215
|
+
if ($Help) {
|
|
216
|
+
Show-Help
|
|
217
|
+
exit 0
|
|
218
|
+
} elseif ($RemainingArgs.Count -gt 0) {
|
|
219
|
+
$FirstArg = $RemainingArgs[0]
|
|
220
|
+
if ($FirstArg -eq "--help" -or $FirstArg -eq "-h" -or $FirstArg -eq "help") {
|
|
221
|
+
Show-Help
|
|
222
|
+
exit 0
|
|
310
223
|
}
|
|
311
224
|
}
|
|
312
225
|
|
|
313
226
|
# Special case: install command (check BEFORE profile detection)
|
|
314
227
|
if ($FirstArg -eq "--install") {
|
|
315
|
-
|
|
316
|
-
|
|
228
|
+
Write-Host ""
|
|
229
|
+
Write-Host "Feature not available" -ForegroundColor Yellow
|
|
230
|
+
Write-Host ""
|
|
231
|
+
Write-Host "The --install flag is currently under development."
|
|
232
|
+
Write-Host ".claude/ integration testing is not complete."
|
|
233
|
+
Write-Host ""
|
|
234
|
+
Write-Host "For updates: https://github.com/kaitranntt/ccs/issues"
|
|
235
|
+
Write-Host ""
|
|
236
|
+
exit 0
|
|
317
237
|
}
|
|
318
238
|
|
|
319
239
|
# Special case: uninstall command (check BEFORE profile detection)
|
|
320
240
|
if ($FirstArg -eq "--uninstall") {
|
|
321
|
-
|
|
322
|
-
|
|
241
|
+
Write-Host ""
|
|
242
|
+
Write-Host "Feature not available" -ForegroundColor Yellow
|
|
243
|
+
Write-Host ""
|
|
244
|
+
Write-Host "The --uninstall flag is currently under development."
|
|
245
|
+
Write-Host ".claude/ integration testing is not complete."
|
|
246
|
+
Write-Host ""
|
|
247
|
+
Write-Host "For updates: https://github.com/kaitranntt/ccs/issues"
|
|
248
|
+
Write-Host ""
|
|
249
|
+
exit 0
|
|
323
250
|
}
|
|
324
251
|
|
|
325
252
|
# Smart profile detection: if first arg starts with '-', it's a flag not a profile
|
|
326
|
-
if ($
|
|
327
|
-
#
|
|
253
|
+
if ($RemainingArgs.Count -eq 0 -or $RemainingArgs[0] -match '^-') {
|
|
254
|
+
# No args or first arg is a flag → use default profile
|
|
328
255
|
$Profile = "default"
|
|
329
|
-
#
|
|
330
|
-
if ($RemainingArgs) {
|
|
331
|
-
$RemainingArgs = @($ProfileOrFlag) + $RemainingArgs
|
|
332
|
-
} else {
|
|
333
|
-
$RemainingArgs = @($ProfileOrFlag)
|
|
334
|
-
}
|
|
256
|
+
# $RemainingArgs already contains the remaining args correctly
|
|
335
257
|
} else {
|
|
336
258
|
# First arg is a profile name
|
|
337
|
-
$Profile = $
|
|
338
|
-
|
|
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"
|
|
259
|
+
$Profile = $RemainingArgs[0]
|
|
260
|
+
$RemainingArgs = if ($RemainingArgs.Count -gt 1) { $RemainingArgs | Select-Object -Skip 1 } else { @() }
|
|
362
261
|
}
|
|
363
262
|
|
|
364
263
|
# Check config exists
|
|
365
264
|
if (-not (Test-Path $ConfigFile)) {
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
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
|
-
"@
|
|
265
|
+
$ErrorMessage = "Config file not found: $ConfigFile" + "`n`n" +
|
|
266
|
+
"Solutions:" + "`n" +
|
|
267
|
+
" 1. Reinstall CCS:" + "`n" +
|
|
268
|
+
" irm ccs.kaitran.ca/install | iex" + "`n`n" +
|
|
269
|
+
" 2. Or create config manually:" + "`n" +
|
|
270
|
+
" New-Item -ItemType Directory -Force -Path '$env:USERPROFILE\.ccs'" + "`n" +
|
|
271
|
+
" Set-Content -Path '$env:USERPROFILE\.ccs\config.json' -Value '{`"profiles`":{`"glm`":`"~/.ccs/glm.settings.json`",`"default`":`"~/.claude/settings.json`"}}'"
|
|
272
|
+
|
|
273
|
+
Write-ErrorMsg $ErrorMessage
|
|
382
274
|
exit 1
|
|
383
275
|
}
|
|
384
276
|
|
|
385
277
|
# Validate profile name (alphanumeric, dash, underscore only)
|
|
386
278
|
if ($Profile -notmatch '^[a-zA-Z0-9_-]+$') {
|
|
387
|
-
|
|
388
|
-
|
|
279
|
+
$ErrorMessage = "Invalid profile name: $Profile" + "`n`n" +
|
|
280
|
+
"Use only alphanumeric characters, dash, or underscore."
|
|
389
281
|
|
|
390
|
-
|
|
391
|
-
"@
|
|
282
|
+
Write-ErrorMsg $ErrorMessage
|
|
392
283
|
exit 1
|
|
393
284
|
}
|
|
394
285
|
|
|
395
|
-
# Read and parse JSON config
|
|
286
|
+
# Read and parse JSON config, get profile path in one step
|
|
396
287
|
try {
|
|
397
288
|
$ConfigContent = Get-Content $ConfigFile -Raw -ErrorAction Stop
|
|
398
289
|
$Config = $ConfigContent | ConvertFrom-Json -ErrorAction Stop
|
|
399
|
-
|
|
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
|
-
}
|
|
290
|
+
$SettingsPath = $Config.profiles.$Profile
|
|
408
291
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
292
|
+
if (-not $SettingsPath) {
|
|
293
|
+
$AvailableProfiles = ($Config.profiles.PSObject.Properties.Name | ForEach-Object { " - $_" }) -join "`n"
|
|
294
|
+
$ErrorMessage = "Profile '$Profile' not found in $ConfigFile" + "`n`n" +
|
|
295
|
+
"Available profiles:" + "`n" +
|
|
296
|
+
$AvailableProfiles
|
|
413
297
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
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
|
|
298
|
+
Write-ErrorMsg $ErrorMessage
|
|
299
|
+
exit 1
|
|
300
|
+
}
|
|
301
|
+
} catch {
|
|
302
|
+
$ErrorMessage = "Invalid JSON in $ConfigFile" + "`n`n" +
|
|
303
|
+
"Fix the JSON syntax or reinstall:" + "`n" +
|
|
304
|
+
" irm ccs.kaitran.ca/install | iex"
|
|
428
305
|
|
|
429
|
-
|
|
430
|
-
$AvailableProfiles
|
|
431
|
-
"@
|
|
306
|
+
Write-ErrorMsg $ErrorMessage
|
|
432
307
|
exit 1
|
|
433
308
|
}
|
|
434
309
|
|
|
@@ -446,33 +321,13 @@ $SettingsPath = $SettingsPath -replace '/', '\'
|
|
|
446
321
|
|
|
447
322
|
# Validate settings file exists
|
|
448
323
|
if (-not (Test-Path $SettingsPath)) {
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
2. Update the path in $ConfigFile
|
|
455
|
-
3. Or reinstall: irm ccs.kaitran.ca/install | iex
|
|
456
|
-
"@
|
|
457
|
-
exit 1
|
|
458
|
-
}
|
|
324
|
+
$ErrorMessage = "Settings file not found: $SettingsPath" + "`n`n" +
|
|
325
|
+
"Solutions:" + "`n" +
|
|
326
|
+
" 1. Create the settings file for profile '$Profile'" + "`n" +
|
|
327
|
+
" 2. Update the path in $ConfigFile" + "`n" +
|
|
328
|
+
" 3. Or reinstall: irm ccs.kaitran.ca/install | iex"
|
|
459
329
|
|
|
460
|
-
|
|
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: $_
|
|
469
|
-
|
|
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
|
-
"@
|
|
330
|
+
Write-ErrorMsg $ErrorMessage
|
|
476
331
|
exit 1
|
|
477
332
|
}
|
|
478
333
|
|
|
@@ -490,4 +345,4 @@ try {
|
|
|
490
345
|
} catch {
|
|
491
346
|
Show-ClaudeNotFoundError
|
|
492
347
|
exit 1
|
|
493
|
-
}
|
|
348
|
+
}
|