mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-17 18:13:43 +00:00
fix(completion): improve shell completion UI/UX and fix mkdir errors (#10)
* fix(shell-completion): resolve ENOTDIR error when parent path is a file
Fixes issue where `--shell-completion` fails with ENOTDIR error when
a file exists where a directory should be created (e.g., ~/.zsh exists
as a file instead of a directory).
Changes:
- Added ensureDirectory() helper that safely creates directories
- Validates parent paths are directories, not files
- Provides clear error message when file conflicts occur
- Applied to all shell installers (bash, zsh, fish, powershell)
- Maintains idempotent behavior (safe to call multiple times)
Before: mkdir with recursive:true fails silently with ENOTDIR
After: Clear error message guides user to resolve file conflict
* chore: bump version to 4.1.4
* feat(completion): improve UI/UX with descriptions and grouping
Improves shell completion UI/UX across all shells (bash, zsh, fish,
PowerShell) with better organization and clearer descriptions.
Changes:
- Zsh: Added descriptions for all profiles and grouped by category
- Commands: "auth", "doctor" with descriptions
- Model profiles: glm, glmt, kimi, etc. with descriptions
- Account profiles: Dynamic with "Account-based profile" label
- Used _alternative for visual grouping
- Fish: Added explicit completions with descriptions for known profiles
- Replaced generic profile listing with specific entries
- Each profile now shows clear description (e.g., "GLM-4.6 (cost-optimized)")
- Bash: Added --shell-completion flag and subflags completion
- PowerShell: Added --shell-completion flag and subflags completion
- All shells: Added completion for --shell-completion subflags
Before (zsh):
ccs
auth -- Manage multiple Claude accounts
doctor -- Run health check and diagnostics
default glm glmt kimi max
After (zsh):
commands
auth -- Manage multiple Claude accounts
doctor -- Run health check and diagnostics
model profiles
default -- Default Claude Sonnet 4.5
glm -- GLM-4.6 (cost-optimized)
glmt -- GLM-4.6 with thinking mode
kimi -- Kimi for Coding (long-context)
max -- Claude Opus (maximum capability)
account profiles
work -- Account-based profile
personal -- Account-based profile
Consistent, organized, and informative completion across all shells.
* fix(completion): handle custom profiles and fix zsh syntax errors
Fixes two issues:
1. Zsh syntax errors with _describe -t flag in _alternative
2. Adds general handling for custom settings profiles (e.g., m2)
Changes:
- Zsh: Fixed _alternative syntax (removed -t tag from _describe calls)
- Error was: "_describe:21: bad option: -M"
- Cause: Tag is auto-derived in _alternative, don't specify with -t
- Fish: Added __fish_ccs_get_custom_settings_profiles function
- Dynamically loads non-hardcoded profiles from config.json
- Shows "Settings-based profile" description for custom profiles
- Removed 'max' from hardcoded known profiles
- 'max' is user's account-based profile, not a default setting
Now supports any custom settings profile (e.g., m2.settings.json for
Minimax M2) without hardcoding. Custom profiles show with generic
"Settings-based profile" description.
Installation properly overwrites:
- fs.copyFileSync overwrites completion files by default
- RC files only modified if marker not already present
* fix(zsh): simplify completion to avoid _alternative syntax issues
Replaced _alternative with multiple _describe calls to fix persistent
zsh completion errors.
The _alternative approach was causing:
- '_describe:21: bad option: -M'
- '(eval):1: bad substitution'
- Unwanted variable expansion in completion menu
New approach uses sequential _describe calls which zsh handles correctly.
Simpler, more reliable, and still shows grouped completion with
descriptions.
Before: _alternative with complex nested _describe calls (broken)
After: Three simple _describe calls (works correctly)
* feat(zsh): add colors and improved formatting to completion
Enhances zsh completion UI/UX with colors and better spacing:
Colors:
- Blue: commands (auth, doctor)
- Green: model profiles (default, glm, glmt, kimi, custom)
- Yellow: account profiles
- Gray: descriptions
Formatting:
- Wider separator ( -- ) for better readability
- Group headers in bold cyan
- Menu selection enabled for navigation
- list-rows-first for better column layout
Before:
auth -- Manage multiple Claude accounts
default -- Default Claude Sonnet 4.5
doctor -- Run health check and diagnostics
glm -- GLM-4.6 (cost-optimized)
After:
commands (cyan header)
auth -- Manage multiple Claude accounts (blue)
doctor -- Run health check and diagnostics (blue)
model profiles (cyan header)
default -- Default Claude Sonnet 4.5 (green)
glm -- GLM-4.6 (cost-optimized) (green)
glmt -- GLM-4.6 with thinking mode (green)
kimi -- Kimi for Coding (long-context) (green)
account profiles (cyan header)
max -- Account-based profile (yellow)
Table-like appearance with colors matching --help output style.
* feat(fish): add colors to completion descriptions
Adds color-coded descriptions to Fish completion matching zsh style:
Colors:
- Blue: commands (auth, doctor)
- Green: model profiles (default, glm, glmt, kimi, custom)
- Yellow: account profiles
Fish has excellent native color support via set_color, making this
straightforward to implement.
Before:
auth Manage multiple Claude accounts
default Default Claude Sonnet 4.5
glm GLM-4.6 (cost-optimized)
max Account profile
After:
auth Manage multiple Claude accounts (blue)
default Default Claude Sonnet 4.5 (green)
glm GLM-4.6 (cost-optimized) (green)
max Account profile (yellow)
Consistent color scheme across zsh and fish shells.
* fix(zsh): correct color application for commands vs descriptions
Fixed color codes being applied backwards - commands were gray while
descriptions were colorful.
Issue:
- Used '1;34' format which zsh misinterpreted
- Commands appeared gray (unreadable)
- Descriptions appeared in color
Fix:
- Simplified color codes from '1;34' to '34' (just the color, no style prefix)
- Pattern now: =(#b)(command)(-- description)=34=90
- First group (command): color 34 (blue/green/yellow)
- Second group (description): color 90 (gray)
Before:
auth -- Manage multiple Claude accounts (gray) (blue)
After:
auth -- Manage multiple Claude accounts (blue) (gray)
Commands now properly colored, descriptions muted.
* feat(zsh): improve section header visibility with separators
Makes section headers more distinct and recognizable as dividers:
Before:
commands
auth -- ...
After:
── commands ──
auth -- ...
Changes:
- Added blank line before headers ($'\n')
- Bold yellow with decorative separators (── text ──)
- Clearly distinguishes section headers from actual commands
Now it's obvious that 'commands', 'model profiles', and 'account
profiles' are just section labels, not completable items.
* fix(zsh): use full ANSI color codes to fix reversed colors
The issue was using shorthand color codes (34, 90) instead of full
ANSI format (0;34, 2;37). Zsh was misinterpreting the shorthand,
causing colors to be applied to wrong groups.
Fixed:
- Commands: 0;34 (normal blue) - was appearing gray
- Model profiles: 0;32 (normal green) - was appearing gray
- Account profiles: 0;33 (normal yellow) - was appearing gray
- Descriptions: 2;37 (dim white) - was appearing colorful
Color codes must be escaped as 0\;34 in zsh strings.
Before fix:
auth (gray) -- description (blue)
After fix:
auth (blue) -- description (dim gray)
* fix(zsh): swap color order for completion groups
Zsh may apply colors in reverse order to capture groups on some systems.
Swapped color order: group 2 first, then group 1.
Pattern: (command)(separator + description)
Was: =blue=dim_white (applied as: blue to cmd, dim to desc)
Now: =dim_white=blue (applied as: dim to desc, blue to cmd)
Testing if this resolves the reversed color issue.
* fix(zsh): add empty leading color to fix reversed coloring
ROOT CAUSE: Zsh list-colors apply first color to WHOLE match, then
override with subsequent colors for each group. Without an empty
leading color, the whole match color leaks to groups without overrides.
Pattern behavior:
=(#b)(cmd)(desc)=BLUE=DIM
→ Whole: BLUE, Group1: DIM (override), Group2: BLUE (no override)
→ Result: cmd=dim, desc=BLUE (REVERSED!)
=(#b)(cmd)(desc)==BLUE=DIM
→ Whole: none, Group1: BLUE, Group2: DIM
→ Result: cmd=BLUE, desc=dim (CORRECT!)
The '==' at start means 'no whole-match color', preventing color bleed.
Now commands will be colorful (blue/green/yellow) and descriptions dim.
* refactor(help): remove specific account examples and generalize description
Removed deterministic account examples (work, personal, team) to make
the help text more generic and less prescriptive.
Changes:
- Removed 'ccs work' and 'ccs personal' example lines
- Removed 'Multi-account workflow' examples section
- Updated description from 'multiple Claude accounts (work, personal, team)'
to 'multiple Claude accounts and alternative models'
- Changed to 'Run different Claude CLI sessions concurrently'
- Applied consistently across Node.js (bin/ccs.js), bash (lib/ccs),
and PowerShell (lib/ccs.ps1)
This makes the help text more flexible and doesn't imply specific
use cases or account naming conventions.
* refactor(help): clarify delegation section and remove non-existent command
Updated delegation section in help text across all implementations:
Changes:
- Renamed section from 'Delegation (Token Optimization)' to
'Delegation (inside Claude Code CLI)' to clarify context
- Removed non-existent '/ccs:create m2' command
- Simplified description to focus on cost savings
- Updated command descriptions:
- '/ccs:glm' now 'for simple tasks' (clearer use case)
- '/ccs:kimi' unchanged (already clear)
- Added delegation section to PowerShell help (was missing)
- Consistent messaging across Node.js, bash, and PowerShell
The new section makes it immediately clear that delegation commands
are used within Claude Code CLI sessions, not as standalone commands.
---------
This commit is contained in:
1 parent
ae03e85730
commit
2671b97039
12 files changed
+188
-90
No files matched your search
+9
-18
@@ -126,9 +126,9 @@ function handleHelpCommand() {
|
|||||||
|
|
||||||
// Description
|
// Description
|
||||||
console.log(colored('Description:', 'cyan'));
|
console.log(colored('Description:', 'cyan'));
|
||||||
console.log(' Switch between multiple Claude accounts (work, personal, team) and');
|
console.log(' Switch between multiple Claude accounts and alternative models');
|
||||||
console.log(' alternative models (GLM, Kimi) instantly. Concurrent sessions with');
|
console.log(' (GLM, Kimi) instantly. Run different Claude CLI sessions concurrently');
|
||||||
console.log(' auto-recovery. Zero downtime.');
|
console.log(' with auto-recovery. Zero downtime.');
|
||||||
console.log('');
|
console.log('');
|
||||||
|
|
||||||
// Model Switching
|
// Model Switching
|
||||||
@@ -144,17 +144,13 @@ function handleHelpCommand() {
|
|||||||
// Account Management
|
// Account Management
|
||||||
console.log(colored('Account Management:', 'cyan'));
|
console.log(colored('Account Management:', 'cyan'));
|
||||||
console.log(` ${colored('ccs auth --help', 'yellow')} Manage multiple Claude accounts`);
|
console.log(` ${colored('ccs auth --help', 'yellow')} Manage multiple Claude accounts`);
|
||||||
console.log(` ${colored('ccs work', 'yellow')} Switch to work account`);
|
|
||||||
console.log(` ${colored('ccs personal', 'yellow')} Switch to personal account`);
|
|
||||||
console.log('');
|
console.log('');
|
||||||
|
|
||||||
// Delegation (NEW)
|
// Delegation (inside Claude Code CLI)
|
||||||
console.log(colored('Delegation (Token Optimization):', 'cyan'));
|
console.log(colored('Delegation (inside Claude Code CLI):', 'cyan'));
|
||||||
console.log(` ${colored('/ccs:glm "task"', 'yellow')} Delegate to GLM-4.6 within Claude session`);
|
console.log(` ${colored('/ccs:glm "task"', 'yellow')} Delegate to GLM-4.6 for simple tasks`);
|
||||||
console.log(` ${colored('/ccs:kimi "task"', 'yellow')} Delegate to Kimi for long context`);
|
console.log(` ${colored('/ccs:kimi "task"', 'yellow')} Delegate to Kimi for long context`);
|
||||||
console.log(` ${colored('/ccs:create m2', 'yellow')} Create custom delegation command`);
|
console.log(' Save tokens by delegating simple tasks to cost-optimized models');
|
||||||
console.log(' Use delegation to save tokens on simple tasks');
|
|
||||||
console.log(' Commands work inside Claude Code sessions only');
|
|
||||||
console.log('');
|
console.log('');
|
||||||
|
|
||||||
// Diagnostics
|
// Diagnostics
|
||||||
@@ -189,13 +185,8 @@ function handleHelpCommand() {
|
|||||||
|
|
||||||
// Examples
|
// Examples
|
||||||
console.log(colored('Examples:', 'cyan'));
|
console.log(colored('Examples:', 'cyan'));
|
||||||
console.log(' Quick start:');
|
console.log(` ${colored('$ ccs', 'yellow')} # Use default account`);
|
||||||
console.log(` ${colored('$ ccs', 'yellow')} # Use default account`);
|
console.log(` ${colored('$ ccs glm "implement API"', 'yellow')} # Cost-optimized model`);
|
||||||
console.log(` ${colored('$ ccs glm "implement API"', 'yellow')} # Cost-optimized model`);
|
|
||||||
console.log('');
|
|
||||||
console.log(' Multi-account workflow:');
|
|
||||||
console.log(` ${colored('$ ccs auth create work', 'yellow')} # Create work profile`);
|
|
||||||
console.log(` ${colored('$ ccs work "review PR"', 'yellow')} # Use work account`);
|
|
||||||
console.log('');
|
console.log('');
|
||||||
console.log(` For more: ${colored('https://github.com/kaitranntt/ccs#usage', 'cyan')}`);
|
console.log(` For more: ${colored('https://github.com/kaitranntt/ccs#usage', 'cyan')}`);
|
||||||
console.log('');
|
console.log('');
|
||||||
|
|||||||
@@ -52,6 +52,34 @@ class ShellCompletionInstaller {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Safely create directory, checking for file conflicts
|
||||||
|
* @param {string} dirPath - Path to create
|
||||||
|
* @throws {Error} If path exists but is a file
|
||||||
|
*/
|
||||||
|
ensureDirectory(dirPath) {
|
||||||
|
if (fs.existsSync(dirPath)) {
|
||||||
|
const stat = fs.statSync(dirPath);
|
||||||
|
if (!stat.isDirectory()) {
|
||||||
|
throw new Error(
|
||||||
|
`Cannot create directory: ${dirPath} exists but is a file.\n` +
|
||||||
|
`Please remove or rename this file and try again.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Directory exists, nothing to do
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check parent directories recursively
|
||||||
|
const parentDir = path.dirname(dirPath);
|
||||||
|
if (parentDir !== dirPath) {
|
||||||
|
this.ensureDirectory(parentDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the directory
|
||||||
|
fs.mkdirSync(dirPath);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Install bash completion
|
* Install bash completion
|
||||||
*/
|
*/
|
||||||
@@ -97,10 +125,8 @@ class ShellCompletionInstaller {
|
|||||||
throw new Error('Completion file not found. Please reinstall CCS.');
|
throw new Error('Completion file not found. Please reinstall CCS.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create zsh completion directory
|
// Create zsh completion directory (with file conflict checking)
|
||||||
if (!fs.existsSync(zshCompDir)) {
|
this.ensureDirectory(zshCompDir);
|
||||||
fs.mkdirSync(zshCompDir, { recursive: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy to zsh completion directory
|
// Copy to zsh completion directory
|
||||||
const destFile = path.join(zshCompDir, '_ccs');
|
const destFile = path.join(zshCompDir, '_ccs');
|
||||||
@@ -142,10 +168,8 @@ class ShellCompletionInstaller {
|
|||||||
throw new Error('Completion file not found. Please reinstall CCS.');
|
throw new Error('Completion file not found. Please reinstall CCS.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create fish completion directory
|
// Create fish completion directory (with file conflict checking)
|
||||||
if (!fs.existsSync(fishCompDir)) {
|
this.ensureDirectory(fishCompDir);
|
||||||
fs.mkdirSync(fishCompDir, { recursive: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy to fish completion directory (fish auto-loads from here)
|
// Copy to fish completion directory (fish auto-loads from here)
|
||||||
const destFile = path.join(fishCompDir, 'ccs.fish');
|
const destFile = path.join(fishCompDir, 'ccs.fish');
|
||||||
@@ -178,11 +202,9 @@ class ShellCompletionInstaller {
|
|||||||
const sourceCmd = `. "${completionPath.replace(/\\/g, '\\\\')}"`;
|
const sourceCmd = `. "${completionPath.replace(/\\/g, '\\\\')}"`;
|
||||||
const block = `\n${marker}\n${sourceCmd}\n`;
|
const block = `\n${marker}\n${sourceCmd}\n`;
|
||||||
|
|
||||||
// Create profile directory if needed
|
// Create profile directory if needed (with file conflict checking)
|
||||||
const profileDir = path.dirname(profilePath);
|
const profileDir = path.dirname(profilePath);
|
||||||
if (!fs.existsSync(profileDir)) {
|
this.ensureDirectory(profileDir);
|
||||||
fs.mkdirSync(profileDir, { recursive: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if already installed
|
// Check if already installed
|
||||||
if (fs.existsSync(profilePath)) {
|
if (fs.existsSync(profilePath)) {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ $InstallMethod = if ($ScriptDir -and ((Test-Path "$ScriptDir\lib\ccs.ps1") -or (
|
|||||||
# IMPORTANT: Update this version when releasing new versions!
|
# IMPORTANT: Update this version when releasing new versions!
|
||||||
# This hardcoded version is used for standalone installations (irm | iex)
|
# This hardcoded version is used for standalone installations (irm | iex)
|
||||||
# For git installations, VERSION file is read if available
|
# For git installations, VERSION file is read if available
|
||||||
$CcsVersion = "4.1.3"
|
$CcsVersion = "4.1.4"
|
||||||
|
|
||||||
# Try to read VERSION file for git installations
|
# Try to read VERSION file for git installations
|
||||||
if ($ScriptDir) {
|
if ($ScriptDir) {
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ fi
|
|||||||
# IMPORTANT: Update this version when releasing new versions!
|
# IMPORTANT: Update this version when releasing new versions!
|
||||||
# This hardcoded version is used for standalone installations (curl | bash)
|
# This hardcoded version is used for standalone installations (curl | bash)
|
||||||
# For git installations, VERSION file is read if available
|
# For git installations, VERSION file is read if available
|
||||||
CCS_VERSION="4.1.3"
|
CCS_VERSION="4.1.4"
|
||||||
|
|
||||||
# Try to read VERSION file for git installations
|
# Try to read VERSION file for git installations
|
||||||
if [[ -f "$SCRIPT_DIR/VERSION" ]]; then
|
if [[ -f "$SCRIPT_DIR/VERSION" ]]; then
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# Version (updated by scripts/bump-version.sh)
|
# Version (updated by scripts/bump-version.sh)
|
||||||
CCS_VERSION="4.1.3"
|
CCS_VERSION="4.1.4"
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
readonly CONFIG_FILE="${CCS_CONFIG:-$HOME/.ccs/config.json}"
|
readonly CONFIG_FILE="${CCS_CONFIG:-$HOME/.ccs/config.json}"
|
||||||
readonly PROFILES_JSON="$HOME/.ccs/profiles.json"
|
readonly PROFILES_JSON="$HOME/.ccs/profiles.json"
|
||||||
@@ -171,9 +171,9 @@ show_help() {
|
|||||||
echo -e " ${YELLOW}ccs${RESET} [flags]"
|
echo -e " ${YELLOW}ccs${RESET} [flags]"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${CYAN}Description:${RESET}"
|
echo -e "${CYAN}Description:${RESET}"
|
||||||
echo -e " Switch between multiple Claude accounts (work, personal, team) and"
|
echo -e " Switch between multiple Claude accounts and alternative models"
|
||||||
echo -e " alternative models (GLM, Kimi) instantly. Concurrent sessions with"
|
echo -e " (GLM, Kimi) instantly. Run different Claude CLI sessions concurrently"
|
||||||
echo -e " auto-recovery. Zero downtime."
|
echo -e " with auto-recovery. Zero downtime."
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${CYAN}Model Switching:${RESET}"
|
echo -e "${CYAN}Model Switching:${RESET}"
|
||||||
echo -e " ${YELLOW}ccs${RESET} Use default Claude account"
|
echo -e " ${YELLOW}ccs${RESET} Use default Claude account"
|
||||||
@@ -184,15 +184,11 @@ show_help() {
|
|||||||
echo ""
|
echo ""
|
||||||
echo -e "${CYAN}Account Management:${RESET}"
|
echo -e "${CYAN}Account Management:${RESET}"
|
||||||
echo -e " ${YELLOW}ccs auth --help${RESET} Manage multiple Claude accounts"
|
echo -e " ${YELLOW}ccs auth --help${RESET} Manage multiple Claude accounts"
|
||||||
echo -e " ${YELLOW}ccs work${RESET} Switch to work account"
|
|
||||||
echo -e " ${YELLOW}ccs personal${RESET} Switch to personal account"
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${CYAN}Delegation (Token Optimization):${RESET}"
|
echo -e "${CYAN}Delegation (inside Claude Code CLI):${RESET}"
|
||||||
echo -e " ${YELLOW}/ccs:glm \"task\"${RESET} Delegate to GLM-4.6 within Claude session"
|
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 " ${YELLOW}/ccs:kimi \"task\"${RESET} Delegate to Kimi for long context"
|
||||||
echo -e " ${YELLOW}/ccs:create m2${RESET} Create custom delegation command"
|
echo -e " Save tokens by delegating simple tasks to cost-optimized models"
|
||||||
echo -e " Use delegation to save tokens on simple tasks"
|
|
||||||
echo -e " Commands work inside Claude Code sessions only"
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${CYAN}Diagnostics:${RESET}"
|
echo -e "${CYAN}Diagnostics:${RESET}"
|
||||||
echo -e " ${YELLOW}ccs doctor${RESET} Run health check and diagnostics"
|
echo -e " ${YELLOW}ccs doctor${RESET} Run health check and diagnostics"
|
||||||
@@ -214,13 +210,8 @@ show_help() {
|
|||||||
echo -e " Note: Commands, skills, and agents are symlinked across all profiles"
|
echo -e " Note: Commands, skills, and agents are symlinked across all profiles"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${CYAN}Examples:${RESET}"
|
echo -e "${CYAN}Examples:${RESET}"
|
||||||
echo -e " Quick start:"
|
echo -e " ${YELLOW}\$ ccs${RESET} # Use default account"
|
||||||
echo -e " ${YELLOW}\$ ccs${RESET} # Use default account"
|
echo -e " ${YELLOW}\$ ccs glm \"implement API\"${RESET} # Cost-optimized model"
|
||||||
echo -e " ${YELLOW}\$ ccs glm \"implement API\"${RESET} # Cost-optimized model"
|
|
||||||
echo ""
|
|
||||||
echo -e " Multi-account workflow:"
|
|
||||||
echo -e " ${YELLOW}\$ ccs auth create work${RESET} # Create work profile"
|
|
||||||
echo -e " ${YELLOW}\$ ccs work \"review PR\"${RESET} # Use work account"
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e " For more: ${CYAN}https://github.com/kaitranntt/ccs#usage${RESET}"
|
echo -e " For more: ${CYAN}https://github.com/kaitranntt/ccs#usage${RESET}"
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
+11
-15
@@ -12,7 +12,7 @@ param(
|
|||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
# Version (updated by scripts/bump-version.sh)
|
# Version (updated by scripts/bump-version.sh)
|
||||||
$CcsVersion = "4.1.3"
|
$CcsVersion = "4.1.4"
|
||||||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||||
$ConfigFile = if ($env:CCS_CONFIG) { $env:CCS_CONFIG } else { "$env:USERPROFILE\.ccs\config.json" }
|
$ConfigFile = if ($env:CCS_CONFIG) { $env:CCS_CONFIG } else { "$env:USERPROFILE\.ccs\config.json" }
|
||||||
$ProfilesJson = "$env:USERPROFILE\.ccs\profiles.json"
|
$ProfilesJson = "$env:USERPROFILE\.ccs\profiles.json"
|
||||||
@@ -218,9 +218,9 @@ function Show-Help {
|
|||||||
Write-ColorLine " ccs [flags]" "Yellow"
|
Write-ColorLine " ccs [flags]" "Yellow"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-ColorLine "Description:" "Cyan"
|
Write-ColorLine "Description:" "Cyan"
|
||||||
Write-Host " Switch between multiple Claude accounts (work, personal, team) and"
|
Write-Host " Switch between multiple Claude accounts and alternative models"
|
||||||
Write-Host " alternative models (GLM, Kimi) instantly. Concurrent sessions with"
|
Write-Host " (GLM, Kimi) instantly. Run different Claude CLI sessions concurrently"
|
||||||
Write-Host " auto-recovery. Zero downtime."
|
Write-Host " with auto-recovery. Zero downtime."
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-ColorLine "Model Switching:" "Cyan"
|
Write-ColorLine "Model Switching:" "Cyan"
|
||||||
Write-ColorLine " ccs Use default Claude account" "Yellow"
|
Write-ColorLine " ccs Use default Claude account" "Yellow"
|
||||||
@@ -230,22 +230,18 @@ function Show-Help {
|
|||||||
Write-ColorLine " ccs glm 'debug this code' Use GLM and run command" "Yellow"
|
Write-ColorLine " ccs glm 'debug this code' Use GLM and run command" "Yellow"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-ColorLine "Examples:" "Cyan"
|
Write-ColorLine "Examples:" "Cyan"
|
||||||
Write-Host " Quick start:"
|
Write-ColorLine " `$ ccs" "Yellow" -NoNewline
|
||||||
Write-ColorLine " `$ ccs" "Yellow" -NoNewline
|
|
||||||
Write-Host " # Use default account"
|
Write-Host " # Use default account"
|
||||||
Write-ColorLine " `$ ccs glm `"implement API`"" "Yellow" -NoNewline
|
Write-ColorLine " `$ ccs glm `"implement API`"" "Yellow" -NoNewline
|
||||||
Write-Host " # Cost-optimized model"
|
Write-Host " # Cost-optimized model"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " Profile usage:"
|
|
||||||
Write-ColorLine " `$ ccs work `"debug code`"" "Yellow" -NoNewline
|
|
||||||
Write-Host " # Switch to work profile"
|
|
||||||
Write-ColorLine " `$ ccs personal" "Yellow" -NoNewline
|
|
||||||
Write-Host " # Open personal account"
|
|
||||||
Write-Host ""
|
|
||||||
Write-ColorLine "Account Management:" "Cyan"
|
Write-ColorLine "Account Management:" "Cyan"
|
||||||
Write-ColorLine " ccs auth --help Manage multiple Claude accounts" "Yellow"
|
Write-ColorLine " ccs auth --help Manage multiple Claude accounts" "Yellow"
|
||||||
Write-ColorLine " ccs work Switch to work account" "Yellow"
|
Write-Host ""
|
||||||
Write-ColorLine " ccs personal Switch to personal account" "Yellow"
|
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-Host ""
|
||||||
Write-ColorLine "Diagnostics:" "Cyan"
|
Write-ColorLine "Diagnostics:" "Cyan"
|
||||||
Write-ColorLine " ccs doctor Run health check and diagnostics" "Yellow"
|
Write-ColorLine " ccs doctor Run health check and diagnostics" "Yellow"
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@kaitranntt/ccs",
|
"name": "@kaitranntt/ccs",
|
||||||
"version": "4.1.3",
|
"version": "4.1.4",
|
||||||
"description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6",
|
"description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"cli",
|
"cli",
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ _ccs_completion() {
|
|||||||
# Top-level completion (first argument)
|
# Top-level completion (first argument)
|
||||||
if [[ ${COMP_CWORD} -eq 1 ]]; then
|
if [[ ${COMP_CWORD} -eq 1 ]]; then
|
||||||
local commands="auth doctor"
|
local commands="auth doctor"
|
||||||
local flags="--help --version -h -v"
|
local flags="--help --version --shell-completion -h -v"
|
||||||
local profiles=""
|
local profiles=""
|
||||||
|
|
||||||
# Add profiles from config.json (settings-based profiles)
|
# Add profiles from config.json (settings-based profiles)
|
||||||
@@ -74,6 +74,12 @@ _ccs_completion() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Flags for shell-completion command
|
||||||
|
if [[ ${prev} == "--shell-completion" ]]; then
|
||||||
|
COMPREPLY=( $(compgen -W "--bash --zsh --fish --powershell" -- ${cur}) )
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+46
-11
@@ -9,22 +9,41 @@
|
|||||||
# Fish will automatically load completions from this directory.
|
# Fish will automatically load completions from this directory.
|
||||||
# No need to source or reload - completions are loaded on demand.
|
# No need to source or reload - completions are loaded on demand.
|
||||||
|
|
||||||
# Helper function to get profiles
|
# Helper function to get settings profiles
|
||||||
function __fish_ccs_get_profiles
|
function __fish_ccs_get_settings_profiles
|
||||||
set -l config_path ~/.ccs/config.json
|
set -l config_path ~/.ccs/config.json
|
||||||
set -l profiles_path ~/.ccs/profiles.json
|
|
||||||
|
|
||||||
# Get settings-based profiles from config.json
|
# Get settings-based profiles from config.json
|
||||||
if test -f $config_path
|
if test -f $config_path
|
||||||
jq -r '.profiles | keys[]' $config_path 2>/dev/null
|
jq -r '.profiles | keys[]' $config_path 2>/dev/null
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Get account-based profiles from profiles.json
|
# Helper function to get custom/unknown settings profiles
|
||||||
if test -f $profiles_path
|
# (profiles not in the hardcoded known list)
|
||||||
jq -r '.profiles | keys[]' $profiles_path 2>/dev/null
|
function __fish_ccs_get_custom_settings_profiles
|
||||||
|
set -l config_path ~/.ccs/config.json
|
||||||
|
set -l known_profiles default glm glmt kimi
|
||||||
|
|
||||||
|
# Get all settings profiles
|
||||||
|
if test -f $config_path
|
||||||
|
set -l all_profiles (jq -r '.profiles | keys[]' $config_path 2>/dev/null)
|
||||||
|
|
||||||
|
# Filter out known profiles
|
||||||
|
for profile in $all_profiles
|
||||||
|
if not contains $profile $known_profiles
|
||||||
|
echo $profile
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Helper function to get profiles with all types
|
||||||
|
function __fish_ccs_get_profiles
|
||||||
|
__fish_ccs_get_settings_profiles
|
||||||
|
__fish_ccs_get_account_profiles
|
||||||
|
end
|
||||||
|
|
||||||
# Helper function to get account profiles only
|
# Helper function to get account profiles only
|
||||||
function __fish_ccs_get_account_profiles
|
function __fish_ccs_get_account_profiles
|
||||||
set -l profiles_path ~/.ccs/profiles.json
|
set -l profiles_path ~/.ccs/profiles.json
|
||||||
@@ -51,13 +70,29 @@ complete -c ccs -f
|
|||||||
# Top-level flags
|
# Top-level flags
|
||||||
complete -c ccs -s h -l help -d 'Show help message'
|
complete -c ccs -s h -l help -d 'Show help message'
|
||||||
complete -c ccs -s v -l version -d 'Show version information'
|
complete -c ccs -s v -l version -d 'Show version information'
|
||||||
|
complete -c ccs -l shell-completion -d 'Install shell completion'
|
||||||
|
|
||||||
# Top-level commands
|
# Top-level commands (blue color for commands)
|
||||||
complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor' -a 'auth' -d 'Manage multiple Claude accounts'
|
complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor' -a 'auth' -d (set_color blue)'Manage multiple Claude accounts'(set_color normal)
|
||||||
complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor' -a 'doctor' -d 'Run health check and diagnostics'
|
complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor' -a 'doctor' -d (set_color blue)'Run health check and diagnostics'(set_color normal)
|
||||||
|
|
||||||
# Top-level profile completion (all profiles)
|
# Top-level known settings profiles (green color for model profiles)
|
||||||
complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor' -a '(__fish_ccs_get_profiles)' -d 'Switch to profile'
|
complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor' -a 'default' -d (set_color green)'Default Claude Sonnet 4.5'(set_color normal)
|
||||||
|
complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor' -a 'glm' -d (set_color green)'GLM-4.6 (cost-optimized)'(set_color normal)
|
||||||
|
complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor' -a 'glmt' -d (set_color green)'GLM-4.6 with thinking mode'(set_color normal)
|
||||||
|
complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor' -a 'kimi' -d (set_color green)'Kimi for Coding (long-context)'(set_color normal)
|
||||||
|
|
||||||
|
# Top-level custom settings profiles (dynamic, with generic description in green)
|
||||||
|
complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor' -a '(__fish_ccs_get_custom_settings_profiles)' -d (set_color green)'Settings-based profile'(set_color normal)
|
||||||
|
|
||||||
|
# Top-level account profiles (dynamic, yellow color for account profiles)
|
||||||
|
complete -c ccs -n 'not __fish_seen_subcommand_from auth doctor' -a '(__fish_ccs_get_account_profiles)' -d (set_color yellow)'Account profile'(set_color normal)
|
||||||
|
|
||||||
|
# shell-completion subflags
|
||||||
|
complete -c ccs -n '__fish_seen_argument -l shell-completion' -l bash -d 'Install for bash'
|
||||||
|
complete -c ccs -n '__fish_seen_argument -l shell-completion' -l zsh -d 'Install for zsh'
|
||||||
|
complete -c ccs -n '__fish_seen_argument -l shell-completion' -l fish -d 'Install for fish'
|
||||||
|
complete -c ccs -n '__fish_seen_argument -l shell-completion' -l powershell -d 'Install for PowerShell'
|
||||||
|
|
||||||
# auth subcommands
|
# auth subcommands
|
||||||
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'
|
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 @@
|
|||||||
Register-ArgumentCompleter -CommandName ccs -ScriptBlock {
|
Register-ArgumentCompleter -CommandName ccs -ScriptBlock {
|
||||||
param($commandName, $wordToComplete, $commandAst, $fakeBoundParameters)
|
param($commandName, $wordToComplete, $commandAst, $fakeBoundParameters)
|
||||||
|
|
||||||
$commands = @('auth', 'doctor', '--help', '--version', '-h', '-v')
|
$commands = @('auth', 'doctor', '--help', '--version', '--shell-completion', '-h', '-v')
|
||||||
$authCommands = @('create', 'list', 'show', 'remove', 'default', '--help', '-h')
|
$authCommands = @('create', 'list', 'show', 'remove', 'default', '--help', '-h')
|
||||||
|
$shellCompletionFlags = @('--bash', '--zsh', '--fish', '--powershell')
|
||||||
$listFlags = @('--verbose', '--json')
|
$listFlags = @('--verbose', '--json')
|
||||||
$removeFlags = @('--yes', '-y')
|
$removeFlags = @('--yes', '-y')
|
||||||
$showFlags = @('--json')
|
$showFlags = @('--json')
|
||||||
@@ -67,6 +68,21 @@ Register-ArgumentCompleter -CommandName ccs -ScriptBlock {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# shell-completion flag completion
|
||||||
|
if ($words[1] -eq '--shell-completion') {
|
||||||
|
if ($position -eq 3) {
|
||||||
|
$shellCompletionFlags | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
|
||||||
|
[System.Management.Automation.CompletionResult]::new(
|
||||||
|
$_,
|
||||||
|
$_,
|
||||||
|
'ParameterValue',
|
||||||
|
$_
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
# auth subcommand completion
|
# auth subcommand completion
|
||||||
if ($words[1] -eq 'auth') {
|
if ($words[1] -eq 'auth') {
|
||||||
if ($position -eq 3) {
|
if ($position -eq 3) {
|
||||||
|
|||||||
+51
-10
@@ -12,41 +12,75 @@
|
|||||||
# Or install system-wide:
|
# Or install system-wide:
|
||||||
# sudo cp scripts/completion/ccs.zsh /usr/local/share/zsh/site-functions/_ccs
|
# sudo cp scripts/completion/ccs.zsh /usr/local/share/zsh/site-functions/_ccs
|
||||||
|
|
||||||
|
# Set up completion styles for better formatting and colors
|
||||||
|
# Color codes: 0;34=blue, 0;32=green, 0;33=yellow, 2;37=dim white
|
||||||
|
# Pattern format: =(#b)(group1)(group2)==color_for_group1=color_for_group2
|
||||||
|
# The leading '=' means no color for whole match, then each '=' assigns to each group
|
||||||
|
zstyle ':completion:*:*:ccs:*:commands' list-colors '=(#b)(auth|doctor)([[:space:]]#--[[:space:]]#*)==0\;34=2\;37'
|
||||||
|
zstyle ':completion:*:*:ccs:*:model-profiles' list-colors '=(#b)(default|glm|glmt|kimi|[^[:space:]]##)([[:space:]]#--[[:space:]]#*)==0\;32=2\;37'
|
||||||
|
zstyle ':completion:*:*:ccs:*:account-profiles' list-colors '=(#b)([^[:space:]]##)([[:space:]]#--[[:space:]]#*)==0\;33=2\;37'
|
||||||
|
zstyle ':completion:*:*:ccs:*' group-name ''
|
||||||
|
zstyle ':completion:*:*:ccs:*:descriptions' format $'\n%B%F{yellow}── %d ──%f%b'
|
||||||
|
zstyle ':completion:*:*:ccs:*' list-separator ' -- '
|
||||||
|
zstyle ':completion:*:*:ccs:*' list-rows-first true
|
||||||
|
zstyle ':completion:*:*:ccs:*' menu select
|
||||||
|
|
||||||
_ccs() {
|
_ccs() {
|
||||||
local -a commands profiles settings_profiles account_profiles
|
local -a commands settings_profiles_described account_profiles_described
|
||||||
local curcontext="$curcontext" state line
|
local curcontext="$curcontext" state line
|
||||||
typeset -A opt_args
|
typeset -A opt_args
|
||||||
|
|
||||||
# Define top-level commands
|
# Define top-level commands (padded for alignment)
|
||||||
commands=(
|
commands=(
|
||||||
'auth:Manage multiple Claude accounts'
|
'auth:Manage multiple Claude accounts'
|
||||||
'doctor:Run health check and diagnostics'
|
'doctor:Run health check and diagnostics'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Define known settings profiles with descriptions (consistent padding)
|
||||||
|
local -A profile_descriptions
|
||||||
|
profile_descriptions=(
|
||||||
|
'default' 'Default Claude Sonnet 4.5'
|
||||||
|
'glm' 'GLM-4.6 (cost-optimized)'
|
||||||
|
'glmt' 'GLM-4.6 with thinking mode'
|
||||||
|
'kimi' 'Kimi for Coding (long-context)'
|
||||||
|
)
|
||||||
|
|
||||||
# Load settings-based profiles from config.json
|
# Load settings-based profiles from config.json
|
||||||
if [[ -f ~/.ccs/config.json ]]; then
|
if [[ -f ~/.ccs/config.json ]]; then
|
||||||
settings_profiles=(${(f)"$(jq -r '.profiles | keys[]' ~/.ccs/config.json 2>/dev/null)"})
|
local -a raw_settings_profiles
|
||||||
|
raw_settings_profiles=(${(f)"$(jq -r '.profiles | keys[]' ~/.ccs/config.json 2>/dev/null)"})
|
||||||
|
|
||||||
|
# Add descriptions to settings profiles
|
||||||
|
for profile in $raw_settings_profiles; do
|
||||||
|
local desc="${profile_descriptions[$profile]:-Settings-based profile}"
|
||||||
|
settings_profiles_described+=("${profile}:${desc}")
|
||||||
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Load account-based profiles from profiles.json
|
# Load account-based profiles from profiles.json
|
||||||
if [[ -f ~/.ccs/profiles.json ]]; then
|
if [[ -f ~/.ccs/profiles.json ]]; then
|
||||||
account_profiles=(${(f)"$(jq -r '.profiles | keys[]' ~/.ccs/profiles.json 2>/dev/null)"})
|
local -a raw_account_profiles
|
||||||
fi
|
raw_account_profiles=(${(f)"$(jq -r '.profiles | keys[]' ~/.ccs/profiles.json 2>/dev/null)"})
|
||||||
|
|
||||||
# Combine all profiles
|
# Add descriptions to account profiles
|
||||||
profiles=($settings_profiles $account_profiles)
|
for profile in $raw_account_profiles; do
|
||||||
|
account_profiles_described+=("${profile}:Account-based profile")
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
_arguments -C \
|
_arguments -C \
|
||||||
'(- *)'{-h,--help}'[Show help message]' \
|
'(- *)'{-h,--help}'[Show help message]' \
|
||||||
'(- *)'{-v,--version}'[Show version information]' \
|
'(- *)'{-v,--version}'[Show version information]' \
|
||||||
|
'(- *)--shell-completion[Install shell completion]' \
|
||||||
'1: :->command' \
|
'1: :->command' \
|
||||||
'*:: :->args'
|
'*:: :->args'
|
||||||
|
|
||||||
case $state in
|
case $state in
|
||||||
command)
|
command)
|
||||||
local -a all_options
|
# Describe commands and profiles with proper tagging for colors
|
||||||
all_options=($commands $profiles)
|
_describe -t commands 'commands' commands
|
||||||
_describe -t commands 'ccs commands' all_options
|
_describe -t model-profiles 'model profiles' settings_profiles_described
|
||||||
|
_describe -t account-profiles 'account profiles' account_profiles_described
|
||||||
;;
|
;;
|
||||||
|
|
||||||
args)
|
args)
|
||||||
@@ -58,6 +92,13 @@ _ccs() {
|
|||||||
_arguments \
|
_arguments \
|
||||||
'(- *)'{-h,--help}'[Show help for doctor command]'
|
'(- *)'{-h,--help}'[Show help for doctor command]'
|
||||||
;;
|
;;
|
||||||
|
--shell-completion)
|
||||||
|
_arguments \
|
||||||
|
'--bash[Install for bash]' \
|
||||||
|
'--zsh[Install for zsh]' \
|
||||||
|
'--fish[Install for fish]' \
|
||||||
|
'--powershell[Install for PowerShell]'
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
# For profile names, complete with Claude CLI arguments
|
# For profile names, complete with Claude CLI arguments
|
||||||
_message 'Claude CLI arguments'
|
_message 'Claude CLI arguments'
|
||||||
|
|||||||
Reference in new issue
Block a user