mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-15 04:18:19 +00:00
feat(cli): enhance version and help display formatting (#11)
* feat: add -sc short flag for --shell-completion Add -sc as a short flag alias for --shell-completion, matching the pattern of -h for --help and -v for --version. Changes: - bin/ccs.js: Add -sc support in help text and flag detection - lib/ccs: Add -sc support in help text and flag detection - lib/ccs.ps1: Add -sc support in help text and flag detection * chore: bump version to 4.1.4 * chore: bump version to 4.1.5 * feat: emphasize concurrent account usage in auth help text Update all auth-related help messages to emphasize the ability to run multiple Claude accounts concurrently. Changes: - bin/ccs.js: "Run multiple Claude accounts concurrently" - bin/auth/auth-commands.js: "CCS Concurrent Account Management" - lib/ccs: Updated both main help and auth_help function - lib/ccs.ps1: Updated both main help and Show-AuthHelp function * feat: implement ccs update command across all platforms Add cross-platform ccs update command to sync delegation commands and skills from ~/.ccs/.claude/ to ~/.claude/. Replaces vague "CCS items" wording with specific "delegation commands and skills". Changes: - bin/ccs.js: Add update command handler and update help text - bin/utils/claude-symlink-manager.js: Update user-facing messages - lib/ccs: Implement update_run() function with symlink logic - lib/ccs.ps1: Implement Update-Run function with Junction/SymbolicLink support Features: - Automatically backs up existing files before symlinking - Skips items that are already correctly symlinked - Reports installed vs up-to-date counts - Handles Windows permissions gracefully (suggests Admin/Developer Mode) Cross-platform parity: bash, PowerShell, and Node.js now all support ccs update * refactor: rename ccs update to ccs sync for clarity Rename the update command to sync across all platforms to avoid confusion with updating the CCS tool itself. The sync command clearly communicates syncing delegation features from the CCS package to ~/.claude/. Changes: - bin/ccs.js: Rename handleUpdateCommand → handleSyncCommand - bin/utils/claude-symlink-manager.js: Rename update() → sync() - lib/ccs: Rename update_run() → sync_run() - lib/ccs.ps1: Rename Update-Run → Sync-Run - All: Update help text "update" → "sync" - All: Update messages "Updating" → "Syncing" Command usage: ccs sync or ccs --sync * fix: update GitHub documentation links to stable permalink Update broken #usage anchor links to stable /blob/main/README.md permalink format. This matches the format already used in PowerShell version and ensures links always work. Changes: - bin/ccs.js: Update link from #usage to /blob/main/README.md - lib/ccs: Update link from #usage to /blob/main/README.md - Now consistent with lib/ccs.ps1 which already used this format Old: https://github.com/kaitranntt/ccs#usage New: https://github.com/kaitranntt/ccs/blob/main/README.md * feat: add sync command and -sc flag to shell completions Update all shell completion scripts to include the newly added sync command and -sc short flag for --shell-completion. Changes across all completion scripts (bash, zsh, fish, PowerShell): - Add 'sync' command to completion suggestions - Add '-sc' as short flag for '--shell-completion' - Update fish to handle both -sc and --shell-completion for subflags - Update PowerShell to recognize -sc for shell completion flags - Add sync command description: "Sync delegation commands and skills" This ensures tab completion discovers the sync command and users can use both -sc and --shell-completion interchangeably. * fix: standardize help text across all implementations Fix inconsistencies in help text that appeared after merge from main. Ensures all three implementations (bash, PowerShell, Node.js) display identical help messages. Changes: - lib/ccs: Update "Delegation (Token Optimization)" → "Delegation (inside Claude Code CLI)" - lib/ccs: Remove redundant /ccs:create line, simplify description - lib/ccs.ps1: Add missing Delegation section - All: Now use consistent messaging about delegation features This ensures users see the same information regardless of which platform they're using (Linux/macOS bash, Windows PowerShell, or npm). * fix: update description text to emphasize concurrent sessions Update outdated description in lib/ccs and lib/ccs.ps1 to match the improved wording already in bin/ccs.js. The new description better emphasizes running concurrent Claude CLI sessions. Changes: - lib/ccs: Update description to emphasize "Run different Claude CLI sessions concurrently" - lib/ccs.ps1: Update description to match bash and Node.js versions - Remove "(work, personal, team)" examples to keep description cleaner - Emphasize "Run different Claude CLI sessions concurrently" over vague "Concurrent sessions" Old: "Switch between multiple Claude accounts (work, personal, team) and alternative models (GLM, Kimi) instantly. Concurrent sessions with auto-recovery. Zero downtime." New: "Switch between multiple Claude accounts and alternative models (GLM, Kimi) instantly. Run different Claude CLI sessions concurrently with auto-recovery. Zero downtime." All three implementations now show identical, clearer description text. * feat(cli): enhance version display formatting and delegation status ---------
This commit is contained in:
1 parent
2671b97039
commit
fe4ff882b0
13 files changed
+516
-149
No files matched your search
@@ -2,7 +2,7 @@
|
||||
set -euo pipefail
|
||||
|
||||
# Version (updated by scripts/bump-version.sh)
|
||||
CCS_VERSION="4.1.4"
|
||||
CCS_VERSION="4.1.5"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
readonly CONFIG_FILE="${CCS_CONFIG:-$HOME/.ccs/config.json}"
|
||||
readonly PROFILES_JSON="$HOME/.ccs/profiles.json"
|
||||
@@ -165,65 +165,82 @@ find_similar_strings() {
|
||||
show_help() {
|
||||
echo -e "${BOLD}CCS (Claude Code Switch) - Instant profile switching for Claude CLI${RESET}"
|
||||
echo ""
|
||||
|
||||
echo -e "${CYAN}Usage:${RESET}"
|
||||
echo -e " ${YELLOW}ccs${RESET} [profile] [claude-args...]"
|
||||
echo -e " ${YELLOW}ccs auth${RESET} <command> [options]"
|
||||
echo -e " ${YELLOW}ccs${RESET} [flags]"
|
||||
echo ""
|
||||
|
||||
echo -e "${CYAN}Description:${RESET}"
|
||||
echo -e " Switch between multiple Claude accounts and alternative models"
|
||||
echo -e " (GLM, Kimi) instantly. Run different Claude CLI sessions concurrently"
|
||||
echo -e " with auto-recovery. Zero downtime."
|
||||
echo ""
|
||||
|
||||
echo -e "${CYAN}Model Switching:${RESET}"
|
||||
echo -e " ${YELLOW}ccs${RESET} Use default Claude account"
|
||||
echo -e " ${YELLOW}ccs glm${RESET} Switch to GLM 4.6 model"
|
||||
echo -e " ${YELLOW}ccs glmt${RESET} Switch to GLM with thinking mode"
|
||||
echo -e " ${YELLOW}ccs glmt --verbose${RESET} Enable debug logging"
|
||||
echo -e " ${YELLOW}ccs kimi${RESET} Switch to Kimi for Coding"
|
||||
echo -e " ${YELLOW}ccs glm${RESET} \"debug this code\" Use GLM and run command"
|
||||
echo ""
|
||||
|
||||
echo -e "${CYAN}Account Management:${RESET}"
|
||||
echo -e " ${YELLOW}ccs auth --help${RESET} Manage multiple Claude accounts"
|
||||
echo -e " ${YELLOW}ccs auth --help${RESET} Run multiple Claude accounts concurrently"
|
||||
echo ""
|
||||
|
||||
echo -e "${CYAN}Delegation (inside Claude Code CLI):${RESET}"
|
||||
echo -e " ${YELLOW}/ccs:glm \"task\"${RESET} Delegate to GLM-4.6 for simple tasks"
|
||||
echo -e " ${YELLOW}/ccs:kimi \"task\"${RESET} Delegate to Kimi for long context"
|
||||
echo -e " Save tokens by delegating simple tasks to cost-optimized models"
|
||||
echo ""
|
||||
|
||||
echo -e "${CYAN}Diagnostics:${RESET}"
|
||||
echo -e " ${YELLOW}ccs doctor${RESET} Run health check and diagnostics"
|
||||
echo -e " ${YELLOW}ccs sync${RESET} Sync delegation commands and skills"
|
||||
echo ""
|
||||
|
||||
echo -e "${CYAN}Flags:${RESET}"
|
||||
echo -e " ${YELLOW}-h, --help${RESET} Show this help message"
|
||||
echo -e " ${YELLOW}-v, --version${RESET} Show version and installation info"
|
||||
echo -e " ${YELLOW}--shell-completion${RESET} Install shell auto-completion"
|
||||
echo -e " ${YELLOW}-sc, --shell-completion${RESET} Install shell auto-completion"
|
||||
echo ""
|
||||
|
||||
echo -e "${CYAN}Configuration:${RESET}"
|
||||
echo -e " Config: ~/.ccs/config.json"
|
||||
echo -e " Profiles: ~/.ccs/profiles.json"
|
||||
echo -e " Instances: ~/.ccs/instances/"
|
||||
echo -e " Settings: ~/.ccs/*.settings.json"
|
||||
echo -e " Config File: ~/.ccs/config.json"
|
||||
echo -e " Profiles: ~/.ccs/profiles.json"
|
||||
echo -e " Instances: ~/.ccs/instances/"
|
||||
echo -e " Settings: ~/.ccs/*.settings.json"
|
||||
echo -e " Environment: CCS_CONFIG (override config path)"
|
||||
echo ""
|
||||
|
||||
echo -e "${CYAN}Shared Data:${RESET}"
|
||||
echo -e " Commands: ~/.ccs/shared/commands/"
|
||||
echo -e " Skills: ~/.ccs/shared/skills/"
|
||||
echo -e " Commands: ~/.ccs/shared/commands/"
|
||||
echo -e " Skills: ~/.ccs/shared/skills/"
|
||||
echo -e " Agents: ~/.ccs/shared/agents/"
|
||||
echo -e " Note: Commands, skills, and agents are symlinked across all profiles"
|
||||
echo ""
|
||||
|
||||
echo -e "${CYAN}Examples:${RESET}"
|
||||
echo -e " ${YELLOW}\$ ccs${RESET} # Use default account"
|
||||
echo -e " ${YELLOW}\$ ccs glm \"implement API\"${RESET} # Cost-optimized model"
|
||||
echo ""
|
||||
echo -e " For more: ${CYAN}https://github.com/kaitranntt/ccs#usage${RESET}"
|
||||
echo -e " For more: ${CYAN}https://github.com/kaitranntt/ccs/blob/main/README.md${RESET}"
|
||||
echo ""
|
||||
|
||||
echo -e "${YELLOW}Uninstall:${RESET}"
|
||||
echo " npm: npm uninstall -g @kaitranntt/ccs"
|
||||
echo " macOS/Linux: curl -fsSL ccs.kaitran.ca/uninstall | bash"
|
||||
echo " Windows: irm ccs.kaitran.ca/uninstall | iex"
|
||||
echo -e " npm: npm uninstall -g @kaitranntt/ccs"
|
||||
echo -e " macOS/Linux: curl -fsSL ccs.kaitran.ca/uninstall | bash"
|
||||
echo -e " Windows: irm ccs.kaitran.ca/uninstall | iex"
|
||||
echo ""
|
||||
|
||||
echo -e "${CYAN}Documentation:${RESET}"
|
||||
echo -e " GitHub: ${CYAN}https://github.com/kaitranntt/ccs${RESET}"
|
||||
echo -e " Docs: https://github.com/kaitranntt/ccs/blob/main/README.md"
|
||||
echo -e " Issues: https://github.com/kaitranntt/ccs/issues"
|
||||
echo ""
|
||||
|
||||
echo -e "${CYAN}License:${RESET} MIT"
|
||||
}
|
||||
|
||||
@@ -480,6 +497,100 @@ doctor_run() {
|
||||
$has_errors && exit 1 || exit 0
|
||||
}
|
||||
|
||||
# --- Sync Command ---
|
||||
|
||||
sync_run() {
|
||||
local ccs_claude_dir="$HOME/.ccs/.claude"
|
||||
local user_claude_dir="$HOME/.claude"
|
||||
|
||||
echo -e "${CYAN}Syncing delegation commands and skills to ~/.claude/...${RESET}"
|
||||
echo ""
|
||||
|
||||
# Check if source directory exists
|
||||
if [[ ! -d "$ccs_claude_dir" ]]; then
|
||||
msg_error "CCS .claude/ directory not found at $ccs_claude_dir"
|
||||
echo "Reinstall CCS: npm install -g @kaitranntt/ccs --force"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create ~/.claude/ if missing
|
||||
if [[ ! -d "$user_claude_dir" ]]; then
|
||||
echo -e "${CYAN}[i]${RESET} Creating ~/.claude/ directory"
|
||||
mkdir -p "$user_claude_dir"
|
||||
chmod 700 "$user_claude_dir"
|
||||
fi
|
||||
|
||||
# Items to symlink (source:target:type)
|
||||
local items=(
|
||||
"commands/ccs:commands/ccs:dir"
|
||||
"skills/ccs-delegation:skills/ccs-delegation:dir"
|
||||
"agents/ccs-delegator.md:agents/ccs-delegator.md:file"
|
||||
)
|
||||
|
||||
local installed=0
|
||||
local skipped=0
|
||||
|
||||
for item in "${items[@]}"; do
|
||||
IFS=':' read -r source target type <<< "$item"
|
||||
local source_path="$ccs_claude_dir/$source"
|
||||
local target_path="$user_claude_dir/$target"
|
||||
local target_dir="$(dirname "$target_path")"
|
||||
|
||||
# Check source exists
|
||||
if [[ ! -e "$source_path" ]]; then
|
||||
echo -e "${YELLOW}[!]${RESET} Source not found: $source, skipping"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Create parent directory if needed
|
||||
if [[ ! -d "$target_dir" ]]; then
|
||||
mkdir -p "$target_dir"
|
||||
chmod 700 "$target_dir"
|
||||
fi
|
||||
|
||||
# Check if already correct symlink
|
||||
if [[ -L "$target_path" ]]; then
|
||||
local link_target="$(readlink "$target_path")"
|
||||
local resolved_target="$(cd "$(dirname "$target_path")" && cd "$(dirname "$link_target")" && pwd)/$(basename "$link_target")"
|
||||
|
||||
if [[ "$resolved_target" == "$source_path" ]]; then
|
||||
((skipped++))
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
# Backup existing file/directory
|
||||
if [[ -e "$target_path" ]]; then
|
||||
local timestamp="$(date +%Y-%m-%d)"
|
||||
local backup_path="${target_path}.backup-${timestamp}"
|
||||
local counter=1
|
||||
|
||||
while [[ -e "$backup_path" ]]; do
|
||||
backup_path="${target_path}.backup-${timestamp}-${counter}"
|
||||
((counter++))
|
||||
done
|
||||
|
||||
mv "$target_path" "$backup_path"
|
||||
echo -e "${CYAN}[i]${RESET} Backed up existing to $(basename "$backup_path")"
|
||||
fi
|
||||
|
||||
# Create symlink
|
||||
ln -s "$source_path" "$target_path" 2>/dev/null
|
||||
if [[ $? -eq 0 ]]; then
|
||||
echo -e "${GREEN}[OK]${RESET} Installed $target"
|
||||
((installed++))
|
||||
else
|
||||
echo -e "${RED}[X]${RESET} Failed to install $target"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}✓ Update complete${RESET}"
|
||||
echo " Installed: $installed"
|
||||
echo " Already up-to-date: $skipped"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# --- Claude CLI Detection Logic ---
|
||||
|
||||
detect_claude_cli() {
|
||||
@@ -509,49 +620,81 @@ Restart your terminal after installation."
|
||||
}
|
||||
|
||||
show_version() {
|
||||
# Title
|
||||
echo -e "${BOLD}CCS (Claude Code Switch) v${CCS_VERSION}${RESET}"
|
||||
echo ""
|
||||
|
||||
# Installation section with table-like formatting
|
||||
echo -e "${CYAN}Installation:${RESET}"
|
||||
|
||||
# Simple location - just show what 'command -v' returns
|
||||
local location=$(command -v ccs 2>/dev/null || echo "(not installed)")
|
||||
echo -e " ${CYAN}Location:${RESET} ${location}"
|
||||
# Location - prioritize script location over command location
|
||||
local script_location="$(readlink -f "${BASH_SOURCE[0]}")"
|
||||
local command_location=$(command -v ccs 2>/dev/null || echo "(not found)")
|
||||
|
||||
# Simple config display
|
||||
local config="${CCS_CONFIG:-$HOME/.ccs/config.json}"
|
||||
echo -e " ${CYAN}Config:${RESET} ${config}"
|
||||
|
||||
# Delegation status
|
||||
local delegation_rules="$HOME/.ccs/delegation-rules.json"
|
||||
if [[ -f "$delegation_rules" ]]; then
|
||||
echo -e " ${CYAN}Delegation:${RESET} Enabled"
|
||||
|
||||
# Check which profiles are delegation-ready
|
||||
local ready_profiles=()
|
||||
for profile in glm kimi; do
|
||||
local settings_file="$HOME/.ccs/profiles/$profile/settings.json"
|
||||
if [[ -f "$settings_file" ]]; then
|
||||
# Check if API key is configured (not a placeholder)
|
||||
local api_key=$(jq -r '.env.ANTHROPIC_AUTH_TOKEN // empty' "$settings_file" 2>/dev/null)
|
||||
if [[ -n "$api_key" ]] && [[ ! "$api_key" =~ YOUR_.*_API_KEY_HERE ]]; then
|
||||
ready_profiles+=("$profile")
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#ready_profiles[@]} -gt 0 ]]; then
|
||||
echo -e " ${CYAN}Ready:${RESET} ${ready_profiles[*]}"
|
||||
else
|
||||
echo -e " ${CYAN}Ready:${RESET} None (configure profiles first)"
|
||||
fi
|
||||
# Show script location if running from source
|
||||
if [[ "$script_location" == *"ccs"* ]]; then
|
||||
printf " ${CYAN}%-16s${RESET} %s\n" "Location:" "${script_location}"
|
||||
else
|
||||
echo -e " ${CYAN}Delegation:${RESET} Not configured"
|
||||
printf " ${CYAN}%-16s${RESET} %s\n" "Location:" "${command_location}"
|
||||
fi
|
||||
|
||||
# .ccs/ directory location
|
||||
printf " ${CYAN}%-16s${RESET} %s\n" "CCS Directory:" "$HOME/.ccs/"
|
||||
|
||||
# Config path
|
||||
printf " ${CYAN}%-16s${RESET} %s\n" "Config:" "${CONFIG_FILE}"
|
||||
|
||||
# Profiles.json location
|
||||
printf " ${CYAN}%-16s${RESET} %s\n" "Profiles:" "${PROFILES_JSON}"
|
||||
|
||||
# Delegation status - check multiple indicators
|
||||
local delegation_configured=false
|
||||
local ready_profiles=()
|
||||
|
||||
# Check for delegation-sessions.json (primary indicator)
|
||||
local delegation_sessions="$HOME/.ccs/delegation-sessions.json"
|
||||
if [[ -f "$delegation_sessions" ]]; then
|
||||
delegation_configured=true
|
||||
fi
|
||||
|
||||
# Check for profiles with valid API keys (secondary indicator)
|
||||
for profile in glm kimi; do
|
||||
local settings_file="$HOME/.ccs/$profile.settings.json"
|
||||
if [[ -f "$settings_file" ]]; then
|
||||
# Check if API key is configured (not a placeholder)
|
||||
local api_key=$(jq -r '.env.ANTHROPIC_AUTH_TOKEN // empty' "$settings_file" 2>/dev/null)
|
||||
if [[ -n "$api_key" ]] && [[ ! "$api_key" =~ YOUR_.*_API_KEY_HERE ]] && [[ ! "$api_key" =~ sk-test.* ]]; then
|
||||
ready_profiles+=("$profile")
|
||||
delegation_configured=true
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if $delegation_configured; then
|
||||
printf " ${CYAN}%-16s${RESET} %s\n" "Delegation:" "Enabled"
|
||||
else
|
||||
printf " ${CYAN}%-16s${RESET} %s\n" "Delegation:" "Not configured"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Ready Profiles section - make it more prominent
|
||||
if [[ ${#ready_profiles[@]} -gt 0 ]]; then
|
||||
echo -e "${CYAN}Delegation Ready:${RESET}"
|
||||
echo " ${YELLOW}✓${RESET} ${ready_profiles[*]} profiles are ready for delegation"
|
||||
echo ""
|
||||
elif $delegation_configured; then
|
||||
echo -e "${CYAN}Delegation Ready:${RESET}"
|
||||
echo " ${YELLOW}!${RESET} Delegation configured but no valid API keys found"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Documentation
|
||||
echo -e "${CYAN}Documentation:${RESET} https://github.com/kaitranntt/ccs"
|
||||
echo -e "${CYAN}License:${RESET} MIT"
|
||||
echo ""
|
||||
|
||||
# Help hint
|
||||
echo -e "${YELLOW}Run 'ccs --help' for usage information${RESET}"
|
||||
}
|
||||
|
||||
@@ -957,7 +1100,7 @@ detect_profile_type() {
|
||||
# --- Auth Commands (Phase 3) ---
|
||||
|
||||
auth_help() {
|
||||
echo -e "${BOLD}CCS Account Management${RESET}"
|
||||
echo -e "${BOLD}CCS Concurrent Account Management${RESET}"
|
||||
echo ""
|
||||
echo -e "${CYAN}Usage:${RESET}"
|
||||
echo -e " ${YELLOW}ccs auth${RESET} <command> [options]"
|
||||
@@ -1509,7 +1652,7 @@ if [[ $# -gt 0 ]] && [[ "${1}" == "auth" ]]; then
|
||||
fi
|
||||
|
||||
# Special case: shell completion installer
|
||||
if [[ $# -gt 0 ]] && [[ "${1}" == "--shell-completion" ]]; then
|
||||
if [[ $# -gt 0 ]] && [[ "${1}" == "--shell-completion" || "${1}" == "-sc" ]]; then
|
||||
install_shell_completion "$@"
|
||||
exit $?
|
||||
fi
|
||||
@@ -1520,6 +1663,12 @@ if [[ $# -gt 0 ]] && [[ "${1}" == "doctor" || "${1}" == "--doctor" ]]; then
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Special case: sync command
|
||||
if [[ $# -gt 0 ]] && [[ "${1}" == "sync" || "${1}" == "--sync" ]]; then
|
||||
sync_run
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Run auto-recovery before main logic
|
||||
auto_recover || {
|
||||
msg_error "Auto-recovery failed. Check permissions."
|
||||
|
||||
+229
-37
@@ -12,7 +12,7 @@ param(
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# Version (updated by scripts/bump-version.sh)
|
||||
$CcsVersion = "4.1.4"
|
||||
$CcsVersion = "4.1.5"
|
||||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$ConfigFile = if ($env:CCS_CONFIG) { $env:CCS_CONFIG } else { "$env:USERPROFILE\.ccs\config.json" }
|
||||
$ProfilesJson = "$env:USERPROFILE\.ccs\profiles.json"
|
||||
@@ -212,66 +212,105 @@ function Show-Help {
|
||||
|
||||
Write-ColorLine "CCS (Claude Code Switch) - Instant profile switching for Claude CLI" "White"
|
||||
Write-Host ""
|
||||
|
||||
Write-ColorLine "Usage:" "Cyan"
|
||||
Write-ColorLine " ccs [profile] [claude-args...]" "Yellow"
|
||||
Write-ColorLine " ccs auth <command> [options]" "Yellow"
|
||||
Write-ColorLine " ccs [flags]" "Yellow"
|
||||
Write-Host ""
|
||||
|
||||
Write-ColorLine "Description:" "Cyan"
|
||||
Write-Host " Switch between multiple Claude accounts and alternative models"
|
||||
Write-Host " (GLM, Kimi) instantly. Run different Claude CLI sessions concurrently"
|
||||
Write-Host " with auto-recovery. Zero downtime."
|
||||
Write-Host ""
|
||||
|
||||
Write-ColorLine "Model Switching:" "Cyan"
|
||||
Write-ColorLine " ccs Use default Claude account" "Yellow"
|
||||
Write-ColorLine " ccs glm Switch to GLM 4.6 model" "Yellow"
|
||||
Write-ColorLine " ccs glmt Switch to GLM with thinking mode" "Yellow"
|
||||
Write-ColorLine " ccs glmt --verbose Enable debug logging" "Yellow"
|
||||
Write-ColorLine " ccs kimi Switch to Kimi for Coding" "Yellow"
|
||||
Write-ColorLine " ccs glm 'debug this code' Use GLM and run command" "Yellow"
|
||||
Write-Host ""
|
||||
Write-ColorLine "Examples:" "Cyan"
|
||||
Write-ColorLine " `$ ccs" "Yellow" -NoNewline
|
||||
Write-Host " # Use default account"
|
||||
Write-ColorLine " `$ ccs glm `"implement API`"" "Yellow" -NoNewline
|
||||
Write-Host " # Cost-optimized model"
|
||||
Write-Host ""
|
||||
|
||||
Write-ColorLine "Account Management:" "Cyan"
|
||||
Write-ColorLine " ccs auth --help Manage multiple Claude accounts" "Yellow"
|
||||
Write-ColorLine " ccs auth --help Run multiple Claude accounts concurrently" "Yellow"
|
||||
Write-Host ""
|
||||
|
||||
Write-ColorLine "Delegation (inside Claude Code CLI):" "Cyan"
|
||||
Write-ColorLine " /ccs:glm `"task`" Delegate to GLM-4.6 for simple tasks" "Yellow"
|
||||
Write-ColorLine " /ccs:kimi `"task`" Delegate to Kimi for long context" "Yellow"
|
||||
Write-Host " Save tokens by delegating simple tasks to cost-optimized models"
|
||||
Write-Host ""
|
||||
|
||||
Write-ColorLine "Diagnostics:" "Cyan"
|
||||
Write-ColorLine " ccs doctor Run health check and diagnostics" "Yellow"
|
||||
Write-ColorLine " ccs sync Sync delegation commands and skills" "Yellow"
|
||||
Write-Host ""
|
||||
|
||||
Write-ColorLine "Flags:" "Cyan"
|
||||
Write-ColorLine " -h, --help Show this help message" "Yellow"
|
||||
Write-ColorLine " -v, --version Show version and installation info" "Yellow"
|
||||
Write-ColorLine " --shell-completion Install shell auto-completion" "Yellow"
|
||||
Write-ColorLine " -sc, --shell-completion Install shell auto-completion" "Yellow"
|
||||
Write-Host ""
|
||||
|
||||
Write-ColorLine "Configuration:" "Cyan"
|
||||
Write-Host " Config: ~/.ccs/config.json"
|
||||
Write-Host " Profiles: ~/.ccs/profiles.json"
|
||||
Write-Host " Instances: ~/.ccs/instances/"
|
||||
Write-Host " Settings: ~/.ccs/*.settings.json"
|
||||
Write-Host " Config File: ~/.ccs/config.json"
|
||||
Write-Host " Profiles: ~/.ccs/profiles.json"
|
||||
Write-Host " Instances: ~/.ccs/instances/"
|
||||
Write-Host " Settings: ~/.ccs/*.settings.json"
|
||||
Write-Host " Environment: CCS_CONFIG (override config path)"
|
||||
Write-Host ""
|
||||
|
||||
Write-ColorLine "Shared Data:" "Cyan"
|
||||
Write-Host " Commands: ~/.ccs/shared/commands/"
|
||||
Write-Host " Skills: ~/.ccs/shared/skills/"
|
||||
Write-Host " Commands: ~/.ccs/shared/commands/"
|
||||
Write-Host " Skills: ~/.ccs/shared/skills/"
|
||||
Write-Host " Agents: ~/.ccs/shared/agents/"
|
||||
Write-Host " Note: Commands, skills, and agents are symlinked across all profiles"
|
||||
Write-Host ""
|
||||
|
||||
Write-ColorLine "Examples:" "Cyan"
|
||||
Write-ColorLine " `$ ccs # Use default account" "Yellow"
|
||||
Write-ColorLine " `$ ccs glm `"implement API`" # Cost-optimized model" "Yellow"
|
||||
Write-Host ""
|
||||
Write-ColorLine " For more: https://github.com/kaitranntt/ccs/blob/main/README.md" "Cyan"
|
||||
Write-Host ""
|
||||
|
||||
Write-ColorLine "Uninstall:" "Yellow"
|
||||
Write-Host " npm: npm uninstall -g @kaitranntt/ccs"
|
||||
Write-Host " macOS/Linux: curl -fsSL ccs.kaitran.ca/uninstall | bash"
|
||||
Write-Host " Windows: irm ccs.kaitran.ca/uninstall | iex"
|
||||
Write-Host ""
|
||||
|
||||
Write-ColorLine "Documentation:" "Cyan"
|
||||
Write-Host " GitHub: https://github.com/kaitranntt/ccs"
|
||||
Write-Host " Docs: https://github.com/kaitranntt/ccs/blob/main/README.md"
|
||||
Write-Host " Issues: https://github.com/kaitranntt/ccs/issues"
|
||||
Write-Host ""
|
||||
|
||||
Write-ColorLine "License: MIT" "Cyan"
|
||||
}
|
||||
|
||||
function Show-Version {
|
||||
$UseColors = $env:FORCE_COLOR -or ([Console]::IsOutputRedirected -eq $false -and -not $env:NO_COLOR)
|
||||
|
||||
# Helper for aligned output
|
||||
function Write-TableLine {
|
||||
param(
|
||||
[string]$Label,
|
||||
[string]$Value,
|
||||
[string]$Color = "Cyan"
|
||||
)
|
||||
if ($UseColors) {
|
||||
$PaddedLabel = $Label.PadRight(17)
|
||||
Write-Host " $PaddedLabel " -ForegroundColor $Color -NoNewline
|
||||
Write-Host $Value
|
||||
} else {
|
||||
$PaddedLabel = $Label.PadRight(17)
|
||||
Write-Host " $PaddedLabel $Value"
|
||||
}
|
||||
}
|
||||
|
||||
# Title
|
||||
if ($UseColors) {
|
||||
Write-Host "CCS (Claude Code Switch) v$CcsVersion" -ForegroundColor White
|
||||
@@ -280,38 +319,91 @@ function Show-Version {
|
||||
}
|
||||
Write-Host ""
|
||||
|
||||
# Installation
|
||||
# Installation section with table-like formatting
|
||||
if ($UseColors) { Write-Host "Installation:" -ForegroundColor Cyan }
|
||||
else { Write-Host "Installation:" }
|
||||
|
||||
# Location
|
||||
# Location - prioritize script location over command location
|
||||
$ScriptLocation = $MyInvocation.MyCommand.Path
|
||||
$InstallLocation = (Get-Command ccs -ErrorAction SilentlyContinue).Source
|
||||
if ($InstallLocation) {
|
||||
if ($UseColors) {
|
||||
Write-Host " Location: " -ForegroundColor Cyan -NoNewline
|
||||
Write-Host $InstallLocation
|
||||
} else {
|
||||
Write-Host " Location: $InstallLocation"
|
||||
}
|
||||
|
||||
# Show script location if running from source
|
||||
if ($ScriptLocation -and (Test-Path $ScriptLocation)) {
|
||||
Write-TableLine "Location:" $ScriptLocation
|
||||
} elseif ($InstallLocation) {
|
||||
Write-TableLine "Location:" $InstallLocation
|
||||
} else {
|
||||
if ($UseColors) {
|
||||
Write-Host " Location: " -ForegroundColor Cyan -NoNewline
|
||||
Write-Host "(not found - run from current directory)" -ForegroundColor Gray
|
||||
} else {
|
||||
Write-Host " Location: (not found - run from current directory)"
|
||||
Write-TableLine "Location:" "(not found - run from current directory)"
|
||||
}
|
||||
|
||||
# .ccs/ directory location
|
||||
Write-TableLine "CCS Directory:" "$env:USERPROFILE\.ccs\"
|
||||
|
||||
# Config path
|
||||
Write-TableLine "Config:" $ConfigFile
|
||||
|
||||
# Profiles.json location
|
||||
Write-TableLine "Profiles:" $ProfilesJson
|
||||
|
||||
# Delegation status - check multiple indicators
|
||||
$DelegationConfigured = $false
|
||||
$ReadyProfiles = @()
|
||||
|
||||
# Check for delegation-sessions.json (primary indicator)
|
||||
$DelegationSessions = "$env:USERPROFILE\.ccs\delegation-sessions.json"
|
||||
if (Test-Path $DelegationSessions) {
|
||||
$DelegationConfigured = $true
|
||||
}
|
||||
|
||||
# Check for profiles with valid API keys (secondary indicator)
|
||||
foreach ($profile in @("glm", "kimi")) {
|
||||
$SettingsFile = "$env:USERPROFILE\.ccs\$profile.settings.json"
|
||||
if (Test-Path $SettingsFile) {
|
||||
try {
|
||||
$Settings = Get-Content $SettingsFile -Raw | ConvertFrom-Json
|
||||
$ApiKey = $Settings.env.ANTHROPIC_AUTH_TOKEN
|
||||
if ($ApiKey -and $ApiKey -notmatch "YOUR_.*_API_KEY_HERE" -and $ApiKey -notmatch "sk-test.*") {
|
||||
$ReadyProfiles += $profile
|
||||
$DelegationConfigured = $true
|
||||
}
|
||||
} catch { }
|
||||
}
|
||||
}
|
||||
|
||||
# Config
|
||||
if ($UseColors) {
|
||||
Write-Host " Config: " -ForegroundColor Cyan -NoNewline
|
||||
Write-Host $ConfigFile
|
||||
if ($DelegationConfigured) {
|
||||
Write-TableLine "Delegation:" "Enabled"
|
||||
} else {
|
||||
Write-Host " Config: $ConfigFile"
|
||||
Write-TableLine "Delegation:" "Not configured"
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
|
||||
# Ready Profiles section - make it more prominent
|
||||
if ($ReadyProfiles.Count -gt 0) {
|
||||
if ($UseColors) { Write-Host "Delegation Ready:" -ForegroundColor Cyan }
|
||||
else { Write-Host "Delegation Ready:" }
|
||||
|
||||
$ReadyProfilesStr = $ReadyProfiles -join ", "
|
||||
if ($UseColors) {
|
||||
Write-Host " ✓ " -ForegroundColor Yellow -NoNewline
|
||||
Write-Host "$ReadyProfilesStr profiles are ready for delegation"
|
||||
} else {
|
||||
Write-Host " ! $ReadyProfilesStr profiles are ready for delegation"
|
||||
}
|
||||
Write-Host ""
|
||||
} elseif ($DelegationConfigured) {
|
||||
if ($UseColors) { Write-Host "Delegation Ready:" -ForegroundColor Cyan }
|
||||
else { Write-Host "Delegation Ready:" }
|
||||
|
||||
if ($UseColors) {
|
||||
Write-Host " ! " -ForegroundColor Yellow -NoNewline
|
||||
Write-Host "Delegation configured but no valid API keys found"
|
||||
} else {
|
||||
Write-Host " ! Delegation configured but no valid API keys found"
|
||||
}
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
# Documentation
|
||||
if ($UseColors) {
|
||||
Write-Host "Documentation: https://github.com/kaitranntt/ccs" -ForegroundColor Cyan
|
||||
@@ -845,11 +937,105 @@ function Get-ProfileType {
|
||||
}
|
||||
}
|
||||
|
||||
# --- Sync Command ---
|
||||
|
||||
function Sync-Run {
|
||||
$CcsClaudeDir = "$env:USERPROFILE\.ccs\.claude"
|
||||
$UserClaudeDir = "$env:USERPROFILE\.claude"
|
||||
|
||||
Write-Host "Syncing delegation commands and skills to ~/.claude/..." -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
# Check if source directory exists
|
||||
if (-not (Test-Path $CcsClaudeDir)) {
|
||||
Write-Host "[X] CCS .claude/ directory not found at $CcsClaudeDir" -ForegroundColor Red
|
||||
Write-Host "Reinstall CCS: npm install -g @kaitranntt/ccs --force"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Create ~/.claude/ if missing
|
||||
if (-not (Test-Path $UserClaudeDir)) {
|
||||
Write-Host "[i] Creating ~/.claude/ directory" -ForegroundColor Cyan
|
||||
New-Item -ItemType Directory -Path $UserClaudeDir -Force | Out-Null
|
||||
}
|
||||
|
||||
# Items to symlink
|
||||
$Items = @(
|
||||
@{ Source = "commands\ccs"; Target = "commands\ccs"; Type = "Directory" }
|
||||
@{ Source = "skills\ccs-delegation"; Target = "skills\ccs-delegation"; Type = "Directory" }
|
||||
@{ Source = "agents\ccs-delegator.md"; Target = "agents\ccs-delegator.md"; Type = "File" }
|
||||
)
|
||||
|
||||
$Installed = 0
|
||||
$Skipped = 0
|
||||
|
||||
foreach ($Item in $Items) {
|
||||
$SourcePath = Join-Path $CcsClaudeDir $Item.Source
|
||||
$TargetPath = Join-Path $UserClaudeDir $Item.Target
|
||||
$TargetDir = Split-Path -Parent $TargetPath
|
||||
|
||||
# Check source exists
|
||||
if (-not (Test-Path $SourcePath)) {
|
||||
Write-Host "[!] Source not found: $($Item.Source), skipping" -ForegroundColor Yellow
|
||||
continue
|
||||
}
|
||||
|
||||
# Create parent directory if needed
|
||||
if (-not (Test-Path $TargetDir)) {
|
||||
New-Item -ItemType Directory -Path $TargetDir -Force | Out-Null
|
||||
}
|
||||
|
||||
# Check if already correct symlink
|
||||
if (Test-Path $TargetPath) {
|
||||
$ItemInfo = Get-Item $TargetPath -Force
|
||||
if ($ItemInfo.LinkType -eq "SymbolicLink") {
|
||||
$LinkTarget = $ItemInfo.Target
|
||||
if ($LinkTarget -eq $SourcePath) {
|
||||
$Skipped++
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
# Backup existing file/directory
|
||||
$Timestamp = Get-Date -Format "yyyy-MM-dd"
|
||||
$BackupPath = "$TargetPath.backup-$Timestamp"
|
||||
$Counter = 1
|
||||
|
||||
while (Test-Path $BackupPath) {
|
||||
$BackupPath = "$TargetPath.backup-$Timestamp-$Counter"
|
||||
$Counter++
|
||||
}
|
||||
|
||||
Move-Item -Path $TargetPath -Destination $BackupPath -Force
|
||||
Write-Host "[i] Backed up existing to $(Split-Path -Leaf $BackupPath)" -ForegroundColor Cyan
|
||||
}
|
||||
|
||||
# Create symlink
|
||||
try {
|
||||
$SymlinkType = if ($Item.Type -eq "Directory") { "Junction" } else { "SymbolicLink" }
|
||||
New-Item -ItemType $SymlinkType -Path $TargetPath -Target $SourcePath -Force -ErrorAction Stop | Out-Null
|
||||
Write-Host "[OK] Installed $($Item.Target)" -ForegroundColor Green
|
||||
$Installed++
|
||||
} catch {
|
||||
Write-Host "[X] Failed to install $($Item.Target): $($_.Exception.Message)" -ForegroundColor Red
|
||||
if ($_.Exception.Message -match "privilege") {
|
||||
Write-Host "[i] Run PowerShell as Administrator or enable Developer Mode" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "✓ Update complete" -ForegroundColor Green
|
||||
Write-Host " Installed: $Installed"
|
||||
Write-Host " Already up-to-date: $Skipped"
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
# --- Auth Commands (Phase 3) ---
|
||||
|
||||
function Show-AuthHelp {
|
||||
Write-Host ""
|
||||
Write-Host "CCS Account Management" -ForegroundColor White
|
||||
Write-Host "CCS Concurrent Account Management" -ForegroundColor White
|
||||
Write-Host ""
|
||||
Write-Host "Usage:" -ForegroundColor Cyan
|
||||
Write-Host " ccs auth <command> [options]" -ForegroundColor Yellow
|
||||
@@ -1314,7 +1500,7 @@ if ($Help) {
|
||||
}
|
||||
|
||||
# Special case: shell completion installer
|
||||
if ($RemainingArgs.Count -gt 0 -and $RemainingArgs[0] -eq "--shell-completion") {
|
||||
if ($RemainingArgs.Count -gt 0 -and ($RemainingArgs[0] -eq "--shell-completion" -or $RemainingArgs[0] -eq "-sc")) {
|
||||
$CompletionArgs = if ($RemainingArgs.Count -gt 1) { $RemainingArgs[1..($RemainingArgs.Count-1)] } else { @() }
|
||||
$Result = Install-ShellCompletion $CompletionArgs
|
||||
exit $Result
|
||||
@@ -1327,6 +1513,12 @@ if ($RemainingArgs.Count -gt 0 -and $RemainingArgs[0] -eq "auth") {
|
||||
exit $LASTEXITCODE
|
||||
}
|
||||
|
||||
# Special case: sync command
|
||||
if ($RemainingArgs.Count -gt 0 -and ($RemainingArgs[0] -eq "sync" -or $RemainingArgs[0] -eq "--sync")) {
|
||||
Sync-Run
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Run auto-recovery before main logic
|
||||
if (-not (Invoke-AutoRecovery)) {
|
||||
Write-ErrorMsg "Auto-recovery failed. Check permissions."
|
||||
|
||||
Reference in new issue
Block a user