@kaitranntt/ccs 2.4.3 → 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/README.md +29 -15
- package/README.vi.md +50 -7
- package/VERSION +1 -1
- package/bin/ccs.js +16 -109
- package/bin/claude-detector.js +5 -34
- package/bin/config-manager.js +8 -63
- package/bin/helpers.js +7 -23
- package/lib/ccs +107 -71
- package/lib/ccs.ps1 +210 -364
- package/package.json +13 -3
- package/scripts/bump-version.sh +136 -0
- package/scripts/check-executables.js +18 -0
- package/scripts/get-version.sh +16 -0
- package/scripts/postinstall.js +99 -0
- package/scripts/sync-version.js +15 -0
- package/scripts/worker.js +46 -0
- package/scripts/wrangler.toml +15 -0
package/lib/ccs
CHANGED
|
@@ -2,18 +2,23 @@
|
|
|
2
2
|
set -euo pipefail
|
|
3
3
|
|
|
4
4
|
# Version (updated by scripts/bump-version.sh)
|
|
5
|
-
CCS_VERSION="2.4.
|
|
5
|
+
CCS_VERSION="2.4.5"
|
|
6
6
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
7
|
+
readonly CONFIG_FILE="${CCS_CONFIG:-$HOME/.ccs/config.json}"
|
|
7
8
|
|
|
8
9
|
# --- Color/Format Functions ---
|
|
9
10
|
setup_colors() {
|
|
10
|
-
if
|
|
11
|
+
# Enable colors if: FORCE_COLOR set OR (TTY detected AND NO_COLOR not set) OR (TERM supports colors AND NO_COLOR not set)
|
|
12
|
+
if [[ -n "${FORCE_COLOR:-}" ]] || \
|
|
13
|
+
([[ -t 1 || -t 2 ]] && [[ -z "${NO_COLOR:-}" ]]) || \
|
|
14
|
+
([[ -n "${TERM:-}" && "${TERM}" != "dumb" ]] && [[ -z "${NO_COLOR:-}" ]]); then
|
|
11
15
|
RED='\033[0;31m'
|
|
12
16
|
YELLOW='\033[1;33m'
|
|
17
|
+
CYAN='\033[0;36m'
|
|
13
18
|
BOLD='\033[1m'
|
|
14
19
|
RESET='\033[0m'
|
|
15
20
|
else
|
|
16
|
-
RED='' YELLOW='' BOLD='' RESET=''
|
|
21
|
+
RED='' YELLOW='' CYAN='' BOLD='' RESET=''
|
|
17
22
|
fi
|
|
18
23
|
}
|
|
19
24
|
|
|
@@ -27,27 +32,72 @@ msg_error() {
|
|
|
27
32
|
echo "" >&2
|
|
28
33
|
}
|
|
29
34
|
|
|
35
|
+
show_help() {
|
|
36
|
+
echo -e "${BOLD}CCS (Claude Code Switch) - Instant profile switching for Claude CLI${RESET}"
|
|
37
|
+
echo ""
|
|
38
|
+
echo -e "${CYAN}Usage:${RESET}"
|
|
39
|
+
echo -e " ${YELLOW}ccs${RESET} [profile] [claude-args...]"
|
|
40
|
+
echo -e " ${YELLOW}ccs${RESET} [flags]"
|
|
41
|
+
echo ""
|
|
42
|
+
echo -e "${CYAN}Description:${RESET}"
|
|
43
|
+
echo -e " Switch between Claude models instantly. Stop hitting rate limits."
|
|
44
|
+
echo -e " Maps profile names to Claude settings files via ~/.ccs/config.json"
|
|
45
|
+
echo ""
|
|
46
|
+
echo -e "${CYAN}Profile Switching:${RESET}"
|
|
47
|
+
echo -e " ${YELLOW}ccs${RESET} Use default profile"
|
|
48
|
+
echo -e " ${YELLOW}ccs glm${RESET} Switch to GLM profile"
|
|
49
|
+
echo -e " ${YELLOW}ccs glm${RESET} \"debug this code\" Switch to GLM and run command"
|
|
50
|
+
echo -e " ${YELLOW}ccs glm${RESET} --verbose Switch to GLM with Claude flags"
|
|
51
|
+
echo ""
|
|
52
|
+
echo -e "${CYAN}Flags:${RESET}"
|
|
53
|
+
echo -e " ${YELLOW}-h, --help${RESET} Show this help message"
|
|
54
|
+
echo -e " ${YELLOW}-v, --version${RESET} Show version and installation info"
|
|
55
|
+
echo -e " ${YELLOW}--install${RESET} Install CCS commands to Claude CLI"
|
|
56
|
+
echo -e " ${YELLOW}--uninstall${RESET} Remove CCS commands from Claude CLI"
|
|
57
|
+
echo ""
|
|
58
|
+
echo -e "${CYAN}Configuration:${RESET}"
|
|
59
|
+
echo -e " Config File: ~/.ccs/config.json"
|
|
60
|
+
echo -e " Settings: ~/.ccs/*.settings.json"
|
|
61
|
+
echo -e " Environment: CCS_CONFIG (override config path)"
|
|
62
|
+
echo ""
|
|
63
|
+
echo -e "${CYAN}Examples:${RESET}"
|
|
64
|
+
echo -e " # Use default Claude subscription"
|
|
65
|
+
echo -e " ${YELLOW}ccs${RESET} \"Review this architecture\""
|
|
66
|
+
echo ""
|
|
67
|
+
echo -e " # Switch to GLM for cost-effective tasks"
|
|
68
|
+
echo -e " ${YELLOW}ccs glm${RESET} \"Write unit tests\""
|
|
69
|
+
echo ""
|
|
70
|
+
echo -e " # Use GLM with verbose output"
|
|
71
|
+
echo -e " ${YELLOW}ccs glm${RESET} --verbose \"Debug error\""
|
|
72
|
+
echo ""
|
|
73
|
+
echo -e " # Install CCS task delegation"
|
|
74
|
+
echo -e " ${YELLOW}ccs${RESET} --install"
|
|
75
|
+
echo ""
|
|
76
|
+
echo -e "${YELLOW}Uninstall:${RESET}"
|
|
77
|
+
echo -e " macOS/Linux: curl -fsSL ccs.kaitran.ca/uninstall | bash"
|
|
78
|
+
echo -e " Windows: irm ccs.kaitran.ca/uninstall | iex"
|
|
79
|
+
echo -e " npm: npm uninstall -g @kaitranntt/ccs"
|
|
80
|
+
echo ""
|
|
81
|
+
echo -e "${CYAN}Documentation:${RESET}"
|
|
82
|
+
echo -e " GitHub: ${CYAN}https://github.com/kaitranntt/ccs${RESET}"
|
|
83
|
+
echo -e " Docs: https://github.com/kaitranntt/ccs/blob/main/README.md"
|
|
84
|
+
echo -e " Issues: https://github.com/kaitranntt/ccs/issues"
|
|
85
|
+
echo ""
|
|
86
|
+
echo -e "${CYAN}License:${RESET} MIT"
|
|
87
|
+
}
|
|
88
|
+
|
|
30
89
|
setup_colors
|
|
31
90
|
|
|
91
|
+
# Check dependencies early
|
|
92
|
+
command -v jq &>/dev/null || {
|
|
93
|
+
msg_error "jq required but not installed. Install: brew install jq (macOS) or apt install jq (Ubuntu)"
|
|
94
|
+
exit 1
|
|
95
|
+
}
|
|
96
|
+
|
|
32
97
|
# --- Claude CLI Detection Logic ---
|
|
33
98
|
|
|
34
99
|
detect_claude_cli() {
|
|
35
|
-
|
|
36
|
-
if [[ -n "${CCS_CLAUDE_PATH:-}" ]]; then
|
|
37
|
-
# Basic validation: file exists
|
|
38
|
-
if [[ -f "$CCS_CLAUDE_PATH" ]]; then
|
|
39
|
-
echo "$CCS_CLAUDE_PATH"
|
|
40
|
-
return 0
|
|
41
|
-
fi
|
|
42
|
-
# Invalid CCS_CLAUDE_PATH - show warning and fall back to PATH
|
|
43
|
-
echo "[!] Warning: CCS_CLAUDE_PATH is set but file not found: $CCS_CLAUDE_PATH" >&2
|
|
44
|
-
echo " Falling back to system PATH lookup..." >&2
|
|
45
|
-
fi
|
|
46
|
-
|
|
47
|
-
# Priority 2: Use 'claude' from PATH (trust the system)
|
|
48
|
-
# This is the standard case - if user installed Claude CLI, it's in their PATH
|
|
49
|
-
echo "claude"
|
|
50
|
-
return 0
|
|
100
|
+
echo "${CCS_CLAUDE_PATH:-claude}"
|
|
51
101
|
}
|
|
52
102
|
|
|
53
103
|
show_claude_not_found_error() {
|
|
@@ -72,8 +122,6 @@ Solutions:
|
|
|
72
122
|
Restart your terminal after installation."
|
|
73
123
|
}
|
|
74
124
|
|
|
75
|
-
CONFIG_FILE="${CCS_CONFIG:-$HOME/.ccs/config.json}"
|
|
76
|
-
|
|
77
125
|
# Installation function for commands and skills
|
|
78
126
|
install_commands_and_skills() {
|
|
79
127
|
# Try both possible locations for .claude directory
|
|
@@ -261,35 +309,37 @@ uninstall_commands_and_skills() {
|
|
|
261
309
|
echo "To reinstall: ccs --install"
|
|
262
310
|
}
|
|
263
311
|
|
|
312
|
+
show_version() {
|
|
313
|
+
echo -e "${BOLD}CCS (Claude Code Switch) v${CCS_VERSION}${RESET}"
|
|
314
|
+
echo ""
|
|
315
|
+
echo -e "${CYAN}Installation:${RESET}"
|
|
316
|
+
|
|
317
|
+
# Simple location - just show what 'command -v' returns
|
|
318
|
+
local location=$(command -v ccs 2>/dev/null || echo "(not installed)")
|
|
319
|
+
echo -e " ${CYAN}Location:${RESET} ${location}"
|
|
320
|
+
|
|
321
|
+
# Simple config display
|
|
322
|
+
local config="${CCS_CONFIG:-$HOME/.ccs/config.json}"
|
|
323
|
+
echo -e " ${CYAN}Config:${RESET} ${config}"
|
|
324
|
+
echo ""
|
|
325
|
+
|
|
326
|
+
echo -e "${CYAN}Documentation:${RESET} https://github.com/kaitranntt/ccs"
|
|
327
|
+
echo -e "${CYAN}License:${RESET} MIT"
|
|
328
|
+
echo ""
|
|
329
|
+
echo -e "${YELLOW}Run 'ccs --help' for usage information${RESET}"
|
|
330
|
+
}
|
|
331
|
+
|
|
264
332
|
# Special case: version command (check BEFORE profile detection)
|
|
265
333
|
if [[ $# -gt 0 ]] && [[ "${1}" == "version" || "${1}" == "--version" || "${1}" == "-v" ]]; then
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
# Show install location if we can determine it
|
|
269
|
-
INSTALL_LOCATION=$(command -v ccs 2>/dev/null || echo "unknown")
|
|
270
|
-
if [[ "$INSTALL_LOCATION" != "unknown" ]]; then
|
|
271
|
-
# Resolve symlink to actual file
|
|
272
|
-
if [[ -L "$INSTALL_LOCATION" ]]; then
|
|
273
|
-
ACTUAL_LOCATION=$(readlink "$INSTALL_LOCATION" 2>/dev/null || echo "$INSTALL_LOCATION")
|
|
274
|
-
echo "Installed at: $INSTALL_LOCATION -> $ACTUAL_LOCATION"
|
|
275
|
-
else
|
|
276
|
-
echo "Installed at: $INSTALL_LOCATION"
|
|
277
|
-
fi
|
|
278
|
-
fi
|
|
279
|
-
|
|
280
|
-
echo "https://github.com/kaitranntt/ccs"
|
|
334
|
+
show_version
|
|
281
335
|
exit 0
|
|
282
336
|
fi
|
|
283
337
|
|
|
284
338
|
# Special case: help command (check BEFORE profile detection)
|
|
285
339
|
if [[ $# -gt 0 ]] && [[ "${1}" == "--help" || "${1}" == "-h" || "${1}" == "help" ]]; then
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
if ! exec "$CLAUDE_CLI" --help "$@"; then
|
|
290
|
-
show_claude_not_found_error
|
|
291
|
-
exit 1
|
|
292
|
-
fi
|
|
340
|
+
setup_colors
|
|
341
|
+
show_help
|
|
342
|
+
exit 0
|
|
293
343
|
fi
|
|
294
344
|
|
|
295
345
|
# Special case: install command (check BEFORE profile detection)
|
|
@@ -334,16 +384,6 @@ EOF"
|
|
|
334
384
|
exit 1
|
|
335
385
|
fi
|
|
336
386
|
|
|
337
|
-
# Check jq installed
|
|
338
|
-
if ! command -v jq &> /dev/null; then
|
|
339
|
-
msg_error "jq is required but not installed
|
|
340
|
-
|
|
341
|
-
Install jq:
|
|
342
|
-
macOS: brew install jq
|
|
343
|
-
Ubuntu: sudo apt install jq
|
|
344
|
-
Fedora: sudo dnf install jq"
|
|
345
|
-
exit 1
|
|
346
|
-
fi
|
|
347
387
|
|
|
348
388
|
# Validate profile name (alphanumeric, dash, underscore only)
|
|
349
389
|
if [[ "$PROFILE" =~ [^a-zA-Z0-9_-] ]]; then
|
|
@@ -353,34 +393,30 @@ Use only alphanumeric characters, dash, or underscore."
|
|
|
353
393
|
exit 1
|
|
354
394
|
fi
|
|
355
395
|
|
|
356
|
-
#
|
|
357
|
-
|
|
358
|
-
|
|
396
|
+
# Single check gets profile path, validates JSON + structure in one step
|
|
397
|
+
SETTINGS_PATH=$(jq -r --arg profile "$PROFILE" '.profiles[$profile] // empty' "$CONFIG_FILE" 2>/dev/null)
|
|
398
|
+
|
|
399
|
+
if [[ -z "$SETTINGS_PATH" ]]; then
|
|
400
|
+
# Could be: invalid JSON, no profiles object, or profile not found
|
|
401
|
+
# Show helpful error based on what we can detect
|
|
402
|
+
if ! jq -e . "$CONFIG_FILE" &>/dev/null; then
|
|
403
|
+
msg_error "Invalid JSON in $CONFIG_FILE
|
|
359
404
|
|
|
360
405
|
Fix the JSON syntax or reinstall:
|
|
361
406
|
curl -fsSL ccs.kaitran.ca/install | bash"
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
# Validate config has profiles object
|
|
366
|
-
if ! jq -e '.profiles' "$CONFIG_FILE" &>/dev/null; then
|
|
367
|
-
msg_error "Config must have 'profiles' object
|
|
407
|
+
elif ! jq -e '.profiles' "$CONFIG_FILE" &>/dev/null; then
|
|
408
|
+
msg_error "Config must have 'profiles' object
|
|
368
409
|
|
|
369
410
|
See config/config.example.json for correct format
|
|
370
411
|
Or reinstall:
|
|
371
412
|
curl -fsSL ccs.kaitran.ca/install | bash"
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
# Get settings path for profile (using --arg to prevent injection)
|
|
376
|
-
SETTINGS_PATH=$(jq -r --arg profile "$PROFILE" '.profiles[$profile] // empty' "$CONFIG_FILE")
|
|
377
|
-
|
|
378
|
-
if [[ -z "$SETTINGS_PATH" ]]; then
|
|
379
|
-
AVAILABLE_PROFILES=$(jq -r '.profiles | keys[]' "$CONFIG_FILE" 2>/dev/null | sed 's/^/ - /')
|
|
380
|
-
msg_error "Profile '$PROFILE' not found in $CONFIG_FILE
|
|
413
|
+
else
|
|
414
|
+
AVAILABLE_PROFILES=$(jq -r '.profiles | keys[]' "$CONFIG_FILE" 2>/dev/null | sed 's/^/ - /')
|
|
415
|
+
msg_error "Profile '$PROFILE' not found in $CONFIG_FILE
|
|
381
416
|
|
|
382
417
|
Available profiles:
|
|
383
418
|
$AVAILABLE_PROFILES"
|
|
419
|
+
fi
|
|
384
420
|
exit 1
|
|
385
421
|
fi
|
|
386
422
|
|