@kaitranntt/ccs 4.1.3 → 4.1.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
@@ -12,7 +12,7 @@ param(
12
12
  $ErrorActionPreference = "Stop"
13
13
 
14
14
  # Version (updated by scripts/bump-version.sh)
15
- $CcsVersion = "4.1.3"
15
+ $CcsVersion = "4.1.5"
16
16
  $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
17
17
  $ConfigFile = if ($env:CCS_CONFIG) { $env:CCS_CONFIG } else { "$env:USERPROFILE\.ccs\config.json" }
18
18
  $ProfilesJson = "$env:USERPROFILE\.ccs\profiles.json"
@@ -212,70 +212,105 @@ function Show-Help {
212
212
 
213
213
  Write-ColorLine "CCS (Claude Code Switch) - Instant profile switching for Claude CLI" "White"
214
214
  Write-Host ""
215
+
215
216
  Write-ColorLine "Usage:" "Cyan"
216
217
  Write-ColorLine " ccs [profile] [claude-args...]" "Yellow"
217
- Write-ColorLine " ccs auth <command> [options]" "Yellow"
218
218
  Write-ColorLine " ccs [flags]" "Yellow"
219
219
  Write-Host ""
220
+
220
221
  Write-ColorLine "Description:" "Cyan"
221
- Write-Host " Switch between multiple Claude accounts (work, personal, team) and"
222
- Write-Host " alternative models (GLM, Kimi) instantly. Concurrent sessions with"
223
- Write-Host " auto-recovery. Zero downtime."
222
+ Write-Host " Switch between multiple Claude accounts and alternative models"
223
+ Write-Host " (GLM, Kimi) instantly. Run different Claude CLI sessions concurrently"
224
+ Write-Host " with auto-recovery. Zero downtime."
224
225
  Write-Host ""
226
+
225
227
  Write-ColorLine "Model Switching:" "Cyan"
226
228
  Write-ColorLine " ccs Use default Claude account" "Yellow"
227
229
  Write-ColorLine " ccs glm Switch to GLM 4.6 model" "Yellow"
228
230
  Write-ColorLine " ccs glmt Switch to GLM with thinking mode" "Yellow"
231
+ Write-ColorLine " ccs glmt --verbose Enable debug logging" "Yellow"
229
232
  Write-ColorLine " ccs kimi Switch to Kimi for Coding" "Yellow"
230
233
  Write-ColorLine " ccs glm 'debug this code' Use GLM and run command" "Yellow"
231
234
  Write-Host ""
232
- Write-ColorLine "Examples:" "Cyan"
233
- Write-Host " Quick start:"
234
- Write-ColorLine " `$ ccs" "Yellow" -NoNewline
235
- Write-Host " # Use default account"
236
- Write-ColorLine " `$ ccs glm `"implement API`"" "Yellow" -NoNewline
237
- Write-Host " # Cost-optimized model"
238
- Write-Host ""
239
- Write-Host " Profile usage:"
240
- Write-ColorLine " `$ ccs work `"debug code`"" "Yellow" -NoNewline
241
- Write-Host " # Switch to work profile"
242
- Write-ColorLine " `$ ccs personal" "Yellow" -NoNewline
243
- Write-Host " # Open personal account"
244
- Write-Host ""
235
+
245
236
  Write-ColorLine "Account Management:" "Cyan"
246
- Write-ColorLine " ccs auth --help Manage multiple Claude accounts" "Yellow"
247
- Write-ColorLine " ccs work Switch to work account" "Yellow"
248
- Write-ColorLine " ccs personal Switch to personal account" "Yellow"
237
+ Write-ColorLine " ccs auth --help Run multiple Claude accounts concurrently" "Yellow"
238
+ Write-Host ""
239
+
240
+ Write-ColorLine "Delegation (inside Claude Code CLI):" "Cyan"
241
+ Write-ColorLine " /ccs:glm `"task`" Delegate to GLM-4.6 for simple tasks" "Yellow"
242
+ Write-ColorLine " /ccs:kimi `"task`" Delegate to Kimi for long context" "Yellow"
243
+ Write-Host " Save tokens by delegating simple tasks to cost-optimized models"
249
244
  Write-Host ""
245
+
250
246
  Write-ColorLine "Diagnostics:" "Cyan"
251
247
  Write-ColorLine " ccs doctor Run health check and diagnostics" "Yellow"
248
+ Write-ColorLine " ccs sync Sync delegation commands and skills" "Yellow"
252
249
  Write-Host ""
250
+
253
251
  Write-ColorLine "Flags:" "Cyan"
254
252
  Write-ColorLine " -h, --help Show this help message" "Yellow"
255
253
  Write-ColorLine " -v, --version Show version and installation info" "Yellow"
256
- Write-ColorLine " --shell-completion Install shell auto-completion" "Yellow"
254
+ Write-ColorLine " -sc, --shell-completion Install shell auto-completion" "Yellow"
257
255
  Write-Host ""
256
+
258
257
  Write-ColorLine "Configuration:" "Cyan"
259
- Write-Host " Config: ~/.ccs/config.json"
260
- Write-Host " Profiles: ~/.ccs/profiles.json"
261
- Write-Host " Instances: ~/.ccs/instances/"
262
- Write-Host " Settings: ~/.ccs/*.settings.json"
258
+ Write-Host " Config File: ~/.ccs/config.json"
259
+ Write-Host " Profiles: ~/.ccs/profiles.json"
260
+ Write-Host " Instances: ~/.ccs/instances/"
261
+ Write-Host " Settings: ~/.ccs/*.settings.json"
262
+ Write-Host " Environment: CCS_CONFIG (override config path)"
263
263
  Write-Host ""
264
+
264
265
  Write-ColorLine "Shared Data:" "Cyan"
265
- Write-Host " Commands: ~/.ccs/shared/commands/"
266
- Write-Host " Skills: ~/.ccs/shared/skills/"
266
+ Write-Host " Commands: ~/.ccs/shared/commands/"
267
+ Write-Host " Skills: ~/.ccs/shared/skills/"
268
+ Write-Host " Agents: ~/.ccs/shared/agents/"
267
269
  Write-Host " Note: Commands, skills, and agents are symlinked across all profiles"
268
270
  Write-Host ""
271
+
272
+ Write-ColorLine "Examples:" "Cyan"
273
+ Write-ColorLine " `$ ccs # Use default account" "Yellow"
274
+ Write-ColorLine " `$ ccs glm `"implement API`" # Cost-optimized model" "Yellow"
275
+ Write-Host ""
276
+ Write-ColorLine " For more: https://github.com/kaitranntt/ccs/blob/main/README.md" "Cyan"
277
+ Write-Host ""
278
+
279
+ Write-ColorLine "Uninstall:" "Yellow"
280
+ Write-Host " npm: npm uninstall -g @kaitranntt/ccs"
281
+ Write-Host " macOS/Linux: curl -fsSL ccs.kaitran.ca/uninstall | bash"
282
+ Write-Host " Windows: irm ccs.kaitran.ca/uninstall | iex"
283
+ Write-Host ""
284
+
269
285
  Write-ColorLine "Documentation:" "Cyan"
270
286
  Write-Host " GitHub: https://github.com/kaitranntt/ccs"
271
287
  Write-Host " Docs: https://github.com/kaitranntt/ccs/blob/main/README.md"
288
+ Write-Host " Issues: https://github.com/kaitranntt/ccs/issues"
272
289
  Write-Host ""
290
+
273
291
  Write-ColorLine "License: MIT" "Cyan"
274
292
  }
275
293
 
276
294
  function Show-Version {
277
295
  $UseColors = $env:FORCE_COLOR -or ([Console]::IsOutputRedirected -eq $false -and -not $env:NO_COLOR)
278
296
 
297
+ # Helper for aligned output
298
+ function Write-TableLine {
299
+ param(
300
+ [string]$Label,
301
+ [string]$Value,
302
+ [string]$Color = "Cyan"
303
+ )
304
+ if ($UseColors) {
305
+ $PaddedLabel = $Label.PadRight(17)
306
+ Write-Host " $PaddedLabel " -ForegroundColor $Color -NoNewline
307
+ Write-Host $Value
308
+ } else {
309
+ $PaddedLabel = $Label.PadRight(17)
310
+ Write-Host " $PaddedLabel $Value"
311
+ }
312
+ }
313
+
279
314
  # Title
280
315
  if ($UseColors) {
281
316
  Write-Host "CCS (Claude Code Switch) v$CcsVersion" -ForegroundColor White
@@ -284,38 +319,91 @@ function Show-Version {
284
319
  }
285
320
  Write-Host ""
286
321
 
287
- # Installation
322
+ # Installation section with table-like formatting
288
323
  if ($UseColors) { Write-Host "Installation:" -ForegroundColor Cyan }
289
324
  else { Write-Host "Installation:" }
290
325
 
291
- # Location
326
+ # Location - prioritize script location over command location
327
+ $ScriptLocation = $MyInvocation.MyCommand.Path
292
328
  $InstallLocation = (Get-Command ccs -ErrorAction SilentlyContinue).Source
293
- if ($InstallLocation) {
294
- if ($UseColors) {
295
- Write-Host " Location: " -ForegroundColor Cyan -NoNewline
296
- Write-Host $InstallLocation
297
- } else {
298
- Write-Host " Location: $InstallLocation"
299
- }
329
+
330
+ # Show script location if running from source
331
+ if ($ScriptLocation -and (Test-Path $ScriptLocation)) {
332
+ Write-TableLine "Location:" $ScriptLocation
333
+ } elseif ($InstallLocation) {
334
+ Write-TableLine "Location:" $InstallLocation
300
335
  } else {
301
- if ($UseColors) {
302
- Write-Host " Location: " -ForegroundColor Cyan -NoNewline
303
- Write-Host "(not found - run from current directory)" -ForegroundColor Gray
304
- } else {
305
- Write-Host " Location: (not found - run from current directory)"
336
+ Write-TableLine "Location:" "(not found - run from current directory)"
337
+ }
338
+
339
+ # .ccs/ directory location
340
+ Write-TableLine "CCS Directory:" "$env:USERPROFILE\.ccs\"
341
+
342
+ # Config path
343
+ Write-TableLine "Config:" $ConfigFile
344
+
345
+ # Profiles.json location
346
+ Write-TableLine "Profiles:" $ProfilesJson
347
+
348
+ # Delegation status - check multiple indicators
349
+ $DelegationConfigured = $false
350
+ $ReadyProfiles = @()
351
+
352
+ # Check for delegation-sessions.json (primary indicator)
353
+ $DelegationSessions = "$env:USERPROFILE\.ccs\delegation-sessions.json"
354
+ if (Test-Path $DelegationSessions) {
355
+ $DelegationConfigured = $true
356
+ }
357
+
358
+ # Check for profiles with valid API keys (secondary indicator)
359
+ foreach ($profile in @("glm", "kimi")) {
360
+ $SettingsFile = "$env:USERPROFILE\.ccs\$profile.settings.json"
361
+ if (Test-Path $SettingsFile) {
362
+ try {
363
+ $Settings = Get-Content $SettingsFile -Raw | ConvertFrom-Json
364
+ $ApiKey = $Settings.env.ANTHROPIC_AUTH_TOKEN
365
+ if ($ApiKey -and $ApiKey -notmatch "YOUR_.*_API_KEY_HERE" -and $ApiKey -notmatch "sk-test.*") {
366
+ $ReadyProfiles += $profile
367
+ $DelegationConfigured = $true
368
+ }
369
+ } catch { }
306
370
  }
307
371
  }
308
372
 
309
- # Config
310
- if ($UseColors) {
311
- Write-Host " Config: " -ForegroundColor Cyan -NoNewline
312
- Write-Host $ConfigFile
373
+ if ($DelegationConfigured) {
374
+ Write-TableLine "Delegation:" "Enabled"
313
375
  } else {
314
- Write-Host " Config: $ConfigFile"
376
+ Write-TableLine "Delegation:" "Not configured"
315
377
  }
316
378
 
317
379
  Write-Host ""
318
380
 
381
+ # Ready Profiles section - make it more prominent
382
+ if ($ReadyProfiles.Count -gt 0) {
383
+ if ($UseColors) { Write-Host "Delegation Ready:" -ForegroundColor Cyan }
384
+ else { Write-Host "Delegation Ready:" }
385
+
386
+ $ReadyProfilesStr = $ReadyProfiles -join ", "
387
+ if ($UseColors) {
388
+ Write-Host " ✓ " -ForegroundColor Yellow -NoNewline
389
+ Write-Host "$ReadyProfilesStr profiles are ready for delegation"
390
+ } else {
391
+ Write-Host " ! $ReadyProfilesStr profiles are ready for delegation"
392
+ }
393
+ Write-Host ""
394
+ } elseif ($DelegationConfigured) {
395
+ if ($UseColors) { Write-Host "Delegation Ready:" -ForegroundColor Cyan }
396
+ else { Write-Host "Delegation Ready:" }
397
+
398
+ if ($UseColors) {
399
+ Write-Host " ! " -ForegroundColor Yellow -NoNewline
400
+ Write-Host "Delegation configured but no valid API keys found"
401
+ } else {
402
+ Write-Host " ! Delegation configured but no valid API keys found"
403
+ }
404
+ Write-Host ""
405
+ }
406
+
319
407
  # Documentation
320
408
  if ($UseColors) {
321
409
  Write-Host "Documentation: https://github.com/kaitranntt/ccs" -ForegroundColor Cyan
@@ -849,11 +937,105 @@ function Get-ProfileType {
849
937
  }
850
938
  }
851
939
 
940
+ # --- Sync Command ---
941
+
942
+ function Sync-Run {
943
+ $CcsClaudeDir = "$env:USERPROFILE\.ccs\.claude"
944
+ $UserClaudeDir = "$env:USERPROFILE\.claude"
945
+
946
+ Write-Host "Syncing delegation commands and skills to ~/.claude/..." -ForegroundColor Cyan
947
+ Write-Host ""
948
+
949
+ # Check if source directory exists
950
+ if (-not (Test-Path $CcsClaudeDir)) {
951
+ Write-Host "[X] CCS .claude/ directory not found at $CcsClaudeDir" -ForegroundColor Red
952
+ Write-Host "Reinstall CCS: npm install -g @kaitranntt/ccs --force"
953
+ exit 1
954
+ }
955
+
956
+ # Create ~/.claude/ if missing
957
+ if (-not (Test-Path $UserClaudeDir)) {
958
+ Write-Host "[i] Creating ~/.claude/ directory" -ForegroundColor Cyan
959
+ New-Item -ItemType Directory -Path $UserClaudeDir -Force | Out-Null
960
+ }
961
+
962
+ # Items to symlink
963
+ $Items = @(
964
+ @{ Source = "commands\ccs"; Target = "commands\ccs"; Type = "Directory" }
965
+ @{ Source = "skills\ccs-delegation"; Target = "skills\ccs-delegation"; Type = "Directory" }
966
+ @{ Source = "agents\ccs-delegator.md"; Target = "agents\ccs-delegator.md"; Type = "File" }
967
+ )
968
+
969
+ $Installed = 0
970
+ $Skipped = 0
971
+
972
+ foreach ($Item in $Items) {
973
+ $SourcePath = Join-Path $CcsClaudeDir $Item.Source
974
+ $TargetPath = Join-Path $UserClaudeDir $Item.Target
975
+ $TargetDir = Split-Path -Parent $TargetPath
976
+
977
+ # Check source exists
978
+ if (-not (Test-Path $SourcePath)) {
979
+ Write-Host "[!] Source not found: $($Item.Source), skipping" -ForegroundColor Yellow
980
+ continue
981
+ }
982
+
983
+ # Create parent directory if needed
984
+ if (-not (Test-Path $TargetDir)) {
985
+ New-Item -ItemType Directory -Path $TargetDir -Force | Out-Null
986
+ }
987
+
988
+ # Check if already correct symlink
989
+ if (Test-Path $TargetPath) {
990
+ $ItemInfo = Get-Item $TargetPath -Force
991
+ if ($ItemInfo.LinkType -eq "SymbolicLink") {
992
+ $LinkTarget = $ItemInfo.Target
993
+ if ($LinkTarget -eq $SourcePath) {
994
+ $Skipped++
995
+ continue
996
+ }
997
+ }
998
+
999
+ # Backup existing file/directory
1000
+ $Timestamp = Get-Date -Format "yyyy-MM-dd"
1001
+ $BackupPath = "$TargetPath.backup-$Timestamp"
1002
+ $Counter = 1
1003
+
1004
+ while (Test-Path $BackupPath) {
1005
+ $BackupPath = "$TargetPath.backup-$Timestamp-$Counter"
1006
+ $Counter++
1007
+ }
1008
+
1009
+ Move-Item -Path $TargetPath -Destination $BackupPath -Force
1010
+ Write-Host "[i] Backed up existing to $(Split-Path -Leaf $BackupPath)" -ForegroundColor Cyan
1011
+ }
1012
+
1013
+ # Create symlink
1014
+ try {
1015
+ $SymlinkType = if ($Item.Type -eq "Directory") { "Junction" } else { "SymbolicLink" }
1016
+ New-Item -ItemType $SymlinkType -Path $TargetPath -Target $SourcePath -Force -ErrorAction Stop | Out-Null
1017
+ Write-Host "[OK] Installed $($Item.Target)" -ForegroundColor Green
1018
+ $Installed++
1019
+ } catch {
1020
+ Write-Host "[X] Failed to install $($Item.Target): $($_.Exception.Message)" -ForegroundColor Red
1021
+ if ($_.Exception.Message -match "privilege") {
1022
+ Write-Host "[i] Run PowerShell as Administrator or enable Developer Mode" -ForegroundColor Yellow
1023
+ }
1024
+ }
1025
+ }
1026
+
1027
+ Write-Host ""
1028
+ Write-Host "✓ Update complete" -ForegroundColor Green
1029
+ Write-Host " Installed: $Installed"
1030
+ Write-Host " Already up-to-date: $Skipped"
1031
+ Write-Host ""
1032
+ }
1033
+
852
1034
  # --- Auth Commands (Phase 3) ---
853
1035
 
854
1036
  function Show-AuthHelp {
855
1037
  Write-Host ""
856
- Write-Host "CCS Account Management" -ForegroundColor White
1038
+ Write-Host "CCS Concurrent Account Management" -ForegroundColor White
857
1039
  Write-Host ""
858
1040
  Write-Host "Usage:" -ForegroundColor Cyan
859
1041
  Write-Host " ccs auth <command> [options]" -ForegroundColor Yellow
@@ -1318,7 +1500,7 @@ if ($Help) {
1318
1500
  }
1319
1501
 
1320
1502
  # Special case: shell completion installer
1321
- if ($RemainingArgs.Count -gt 0 -and $RemainingArgs[0] -eq "--shell-completion") {
1503
+ if ($RemainingArgs.Count -gt 0 -and ($RemainingArgs[0] -eq "--shell-completion" -or $RemainingArgs[0] -eq "-sc")) {
1322
1504
  $CompletionArgs = if ($RemainingArgs.Count -gt 1) { $RemainingArgs[1..($RemainingArgs.Count-1)] } else { @() }
1323
1505
  $Result = Install-ShellCompletion $CompletionArgs
1324
1506
  exit $Result
@@ -1331,6 +1513,12 @@ if ($RemainingArgs.Count -gt 0 -and $RemainingArgs[0] -eq "auth") {
1331
1513
  exit $LASTEXITCODE
1332
1514
  }
1333
1515
 
1516
+ # Special case: sync command
1517
+ if ($RemainingArgs.Count -gt 0 -and ($RemainingArgs[0] -eq "sync" -or $RemainingArgs[0] -eq "--sync")) {
1518
+ Sync-Run
1519
+ exit 0
1520
+ }
1521
+
1334
1522
  # Run auto-recovery before main logic
1335
1523
  if (-not (Invoke-AutoRecovery)) {
1336
1524
  Write-ErrorMsg "Auto-recovery failed. Check permissions."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaitranntt/ccs",
3
- "version": "4.1.3",
3
+ "version": "4.1.5",
4
4
  "description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6",
5
5
  "keywords": [
6
6
  "cli",
@@ -18,8 +18,8 @@ _ccs_completion() {
18
18
 
19
19
  # Top-level completion (first argument)
20
20
  if [[ ${COMP_CWORD} -eq 1 ]]; then
21
- local commands="auth doctor"
22
- local flags="--help --version -h -v"
21
+ local commands="auth doctor sync"
22
+ local flags="--help --version --shell-completion -h -v -sc"
23
23
  local profiles=""
24
24
 
25
25
  # Add profiles from config.json (settings-based profiles)
@@ -74,6 +74,12 @@ _ccs_completion() {
74
74
  return 0
75
75
  fi
76
76
 
77
+ # Flags for shell-completion command
78
+ if [[ ${prev} == "--shell-completion" ]]; then
79
+ COMPREPLY=( $(compgen -W "--bash --zsh --fish --powershell" -- ${cur}) )
80
+ return 0
81
+ fi
82
+
77
83
  return 0
78
84
  }
79
85
 
@@ -9,22 +9,41 @@
9
9
  # Fish will automatically load completions from this directory.
10
10
  # No need to source or reload - completions are loaded on demand.
11
11
 
12
- # Helper function to get profiles
13
- function __fish_ccs_get_profiles
12
+ # Helper function to get settings profiles
13
+ function __fish_ccs_get_settings_profiles
14
14
  set -l config_path ~/.ccs/config.json
15
- set -l profiles_path ~/.ccs/profiles.json
16
15
 
17
16
  # Get settings-based profiles from config.json
18
17
  if test -f $config_path
19
18
  jq -r '.profiles | keys[]' $config_path 2>/dev/null
20
19
  end
20
+ end
21
21
 
22
- # Get account-based profiles from profiles.json
23
- if test -f $profiles_path
24
- jq -r '.profiles | keys[]' $profiles_path 2>/dev/null
22
+ # Helper function to get custom/unknown settings profiles
23
+ # (profiles not in the hardcoded known list)
24
+ function __fish_ccs_get_custom_settings_profiles
25
+ set -l config_path ~/.ccs/config.json
26
+ set -l known_profiles default glm glmt kimi
27
+
28
+ # Get all settings profiles
29
+ if test -f $config_path
30
+ set -l all_profiles (jq -r '.profiles | keys[]' $config_path 2>/dev/null)
31
+
32
+ # Filter out known profiles
33
+ for profile in $all_profiles
34
+ if not contains $profile $known_profiles
35
+ echo $profile
36
+ end
37
+ end
25
38
  end
26
39
  end
27
40
 
41
+ # Helper function to get profiles with all types
42
+ function __fish_ccs_get_profiles
43
+ __fish_ccs_get_settings_profiles
44
+ __fish_ccs_get_account_profiles
45
+ end
46
+
28
47
  # Helper function to get account profiles only
29
48
  function __fish_ccs_get_account_profiles
30
49
  set -l profiles_path ~/.ccs/profiles.json
@@ -51,13 +70,30 @@ complete -c ccs -f
51
70
  # Top-level flags
52
71
  complete -c ccs -s h -l help -d 'Show help message'
53
72
  complete -c ccs -s v -l version -d 'Show version information'
54
-
55
- # Top-level commands
56
- complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor' -a 'auth' -d 'Manage multiple Claude accounts'
57
- complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor' -a 'doctor' -d 'Run health check and diagnostics'
58
-
59
- # Top-level profile completion (all profiles)
60
- complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor' -a '(__fish_ccs_get_profiles)' -d 'Switch to profile'
73
+ complete -c ccs -s sc -l shell-completion -d 'Install shell completion'
74
+
75
+ # Top-level commands (blue color for commands)
76
+ complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor sync' -a 'auth' -d (set_color blue)'Manage multiple Claude accounts'(set_color normal)
77
+ complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor sync' -a 'doctor' -d (set_color blue)'Run health check and diagnostics'(set_color normal)
78
+ complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor sync' -a 'sync' -d (set_color blue)'Sync delegation commands and skills'(set_color normal)
79
+
80
+ # Top-level known settings profiles (green color for model profiles)
81
+ complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor sync' -a 'default' -d (set_color green)'Default Claude Sonnet 4.5'(set_color normal)
82
+ complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor sync' -a 'glm' -d (set_color green)'GLM-4.6 (cost-optimized)'(set_color normal)
83
+ complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor sync' -a 'glmt' -d (set_color green)'GLM-4.6 with thinking mode'(set_color normal)
84
+ complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor sync' -a 'kimi' -d (set_color green)'Kimi for Coding (long-context)'(set_color normal)
85
+
86
+ # Top-level custom settings profiles (dynamic, with generic description in green)
87
+ complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor sync' -a '(__fish_ccs_get_custom_settings_profiles)' -d (set_color green)'Settings-based profile'(set_color normal)
88
+
89
+ # Top-level account profiles (dynamic, yellow color for account profiles)
90
+ complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor sync' -a '(__fish_ccs_get_account_profiles)' -d (set_color yellow)'Account profile'(set_color normal)
91
+
92
+ # shell-completion subflags
93
+ complete -c ccs -n '__fish_seen_argument -l shell-completion; or __fish_seen_argument -s sc' -l bash -d 'Install for bash'
94
+ complete -c ccs -n '__fish_seen_argument -l shell-completion; or __fish_seen_argument -s sc' -l zsh -d 'Install for zsh'
95
+ complete -c ccs -n '__fish_seen_argument -l shell-completion; or __fish_seen_argument -s sc' -l fish -d 'Install for fish'
96
+ complete -c ccs -n '__fish_seen_argument -l shell-completion; or __fish_seen_argument -s sc' -l powershell -d 'Install for PowerShell'
61
97
 
62
98
  # auth subcommands
63
99
  complete -c ccs -n '__fish_ccs_using_auth; and not __fish_seen_subcommand_from create list show remove default' -a 'create' -d 'Create new profile and login'
@@ -12,8 +12,9 @@
12
12
  Register-ArgumentCompleter -CommandName ccs -ScriptBlock {
13
13
  param($commandName, $wordToComplete, $commandAst, $fakeBoundParameters)
14
14
 
15
- $commands = @('auth', 'doctor', '--help', '--version', '-h', '-v')
15
+ $commands = @('auth', 'doctor', 'sync', '--help', '--version', '--shell-completion', '-h', '-v', '-sc')
16
16
  $authCommands = @('create', 'list', 'show', 'remove', 'default', '--help', '-h')
17
+ $shellCompletionFlags = @('--bash', '--zsh', '--fish', '--powershell')
17
18
  $listFlags = @('--verbose', '--json')
18
19
  $removeFlags = @('--yes', '-y')
19
20
  $showFlags = @('--json')
@@ -67,6 +68,21 @@ Register-ArgumentCompleter -CommandName ccs -ScriptBlock {
67
68
  return
68
69
  }
69
70
 
71
+ # shell-completion flag completion
72
+ if ($words[1] -eq '--shell-completion' -or $words[1] -eq '-sc') {
73
+ if ($position -eq 3) {
74
+ $shellCompletionFlags | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
75
+ [System.Management.Automation.CompletionResult]::new(
76
+ $_,
77
+ $_,
78
+ 'ParameterValue',
79
+ $_
80
+ )
81
+ }
82
+ }
83
+ return
84
+ }
85
+
70
86
  # auth subcommand completion
71
87
  if ($words[1] -eq 'auth') {
72
88
  if ($position -eq 3) {
@@ -12,41 +12,76 @@
12
12
  # Or install system-wide:
13
13
  # sudo cp scripts/completion/ccs.zsh /usr/local/share/zsh/site-functions/_ccs
14
14
 
15
+ # Set up completion styles for better formatting and colors
16
+ # Color codes: 0;34=blue, 0;32=green, 0;33=yellow, 2;37=dim white
17
+ # Pattern format: =(#b)(group1)(group2)==color_for_group1=color_for_group2
18
+ # The leading '=' means no color for whole match, then each '=' assigns to each group
19
+ zstyle ':completion:*:*:ccs:*:commands' list-colors '=(#b)(auth|doctor|sync)([[:space:]]#--[[:space:]]#*)==0\;34=2\;37'
20
+ zstyle ':completion:*:*:ccs:*:model-profiles' list-colors '=(#b)(default|glm|glmt|kimi|[^[:space:]]##)([[:space:]]#--[[:space:]]#*)==0\;32=2\;37'
21
+ zstyle ':completion:*:*:ccs:*:account-profiles' list-colors '=(#b)([^[:space:]]##)([[:space:]]#--[[:space:]]#*)==0\;33=2\;37'
22
+ zstyle ':completion:*:*:ccs:*' group-name ''
23
+ zstyle ':completion:*:*:ccs:*:descriptions' format $'\n%B%F{yellow}── %d ──%f%b'
24
+ zstyle ':completion:*:*:ccs:*' list-separator ' -- '
25
+ zstyle ':completion:*:*:ccs:*' list-rows-first true
26
+ zstyle ':completion:*:*:ccs:*' menu select
27
+
15
28
  _ccs() {
16
- local -a commands profiles settings_profiles account_profiles
29
+ local -a commands settings_profiles_described account_profiles_described
17
30
  local curcontext="$curcontext" state line
18
31
  typeset -A opt_args
19
32
 
20
- # Define top-level commands
33
+ # Define top-level commands (padded for alignment)
21
34
  commands=(
22
35
  'auth:Manage multiple Claude accounts'
23
36
  'doctor:Run health check and diagnostics'
37
+ 'sync:Sync delegation commands and skills'
38
+ )
39
+
40
+ # Define known settings profiles with descriptions (consistent padding)
41
+ local -A profile_descriptions
42
+ profile_descriptions=(
43
+ 'default' 'Default Claude Sonnet 4.5'
44
+ 'glm' 'GLM-4.6 (cost-optimized)'
45
+ 'glmt' 'GLM-4.6 with thinking mode'
46
+ 'kimi' 'Kimi for Coding (long-context)'
24
47
  )
25
48
 
26
49
  # Load settings-based profiles from config.json
27
50
  if [[ -f ~/.ccs/config.json ]]; then
28
- settings_profiles=(${(f)"$(jq -r '.profiles | keys[]' ~/.ccs/config.json 2>/dev/null)"})
51
+ local -a raw_settings_profiles
52
+ raw_settings_profiles=(${(f)"$(jq -r '.profiles | keys[]' ~/.ccs/config.json 2>/dev/null)"})
53
+
54
+ # Add descriptions to settings profiles
55
+ for profile in $raw_settings_profiles; do
56
+ local desc="${profile_descriptions[$profile]:-Settings-based profile}"
57
+ settings_profiles_described+=("${profile}:${desc}")
58
+ done
29
59
  fi
30
60
 
31
61
  # Load account-based profiles from profiles.json
32
62
  if [[ -f ~/.ccs/profiles.json ]]; then
33
- account_profiles=(${(f)"$(jq -r '.profiles | keys[]' ~/.ccs/profiles.json 2>/dev/null)"})
34
- fi
63
+ local -a raw_account_profiles
64
+ raw_account_profiles=(${(f)"$(jq -r '.profiles | keys[]' ~/.ccs/profiles.json 2>/dev/null)"})
35
65
 
36
- # Combine all profiles
37
- profiles=($settings_profiles $account_profiles)
66
+ # Add descriptions to account profiles
67
+ for profile in $raw_account_profiles; do
68
+ account_profiles_described+=("${profile}:Account-based profile")
69
+ done
70
+ fi
38
71
 
39
72
  _arguments -C \
40
73
  '(- *)'{-h,--help}'[Show help message]' \
41
74
  '(- *)'{-v,--version}'[Show version information]' \
75
+ '(- *)'{-sc,--shell-completion}'[Install shell completion]' \
42
76
  '1: :->command' \
43
77
  '*:: :->args'
44
78
 
45
79
  case $state in
46
80
  command)
47
- local -a all_options
48
- all_options=($commands $profiles)
49
- _describe -t commands 'ccs commands' all_options
81
+ # Describe commands and profiles with proper tagging for colors
82
+ _describe -t commands 'commands' commands
83
+ _describe -t model-profiles 'model profiles' settings_profiles_described
84
+ _describe -t account-profiles 'account profiles' account_profiles_described
50
85
  ;;
51
86
 
52
87
  args)
@@ -58,6 +93,13 @@ _ccs() {
58
93
  _arguments \
59
94
  '(- *)'{-h,--help}'[Show help for doctor command]'
60
95
  ;;
96
+ --shell-completion)
97
+ _arguments \
98
+ '--bash[Install for bash]' \
99
+ '--zsh[Install for zsh]' \
100
+ '--fish[Install for fish]' \
101
+ '--powershell[Install for PowerShell]'
102
+ ;;
61
103
  *)
62
104
  # For profile names, complete with Claude CLI arguments
63
105
  _message 'Claude CLI arguments'