feat(ccs): add --install command for delegation features

- Add installation function for commands and skills
- Implement --install flag in both bash and PowerShell scripts
- Update documentation with installation instructions
- Add comprehensive test suites for installation functionality
- Refactor delegation command to simplify profile handling
- Remove haiku references, focus on GLM delegation model
- Update usage examples and documentation
This commit is contained in:
kaitranntt
2025-11-03 00:29:41 -05:00
parent ade5103ca0
commit 613b92ce60
10 changed files with 1006 additions and 53 deletions
+18 -35
View File
@@ -1,13 +1,13 @@
---
allowed-tools: Glob, Read, Bash(jq:*), Task
description: Delegate commands to alternative models (GLM, Haiku) for token optimization
description: Delegate commands to alternative models (GLM) for token optimization
argument-hint: [profile] /command [args...]
model: haiku
model: sonnet
---
# /ccs - Delegate to Alternative Models
You are a **delegation orchestrator**. Your job is to delegate the user's command to an alternative AI model (GLM, Haiku, etc.) using the CCS (Claude Code Switch) system.
You are a **delegation orchestrator**. Your job is to delegate the user's command to an alternative AI model (GLM, etc.) using the CCS (Claude Code Switch) system.
## User's Input
@@ -20,14 +20,14 @@ Follow these steps to delegate the command:
### Step 1: Parse Arguments
Extract from the user's input:
- **Profile**: Model profile to use (e.g., `glm`, `haiku`, `son`) - defaults to `glm` if omitted
- **Profile**: Model profile to use (e.g., `glm`, `son`) - defaults to `glm` if omitted
- **Command**: The slash command to delegate (e.g., `plan`, `code`, `debug`)
- **Arguments**: Additional arguments to pass to the command
**Examples**:
- `/ccs glm /plan "add auth"` → profile=`glm`, command=`plan`, args=`"add auth"`
- `/ccs /code "fix bug"` → profile=`glm` (default), command=`code`, args=`"fix bug"`
- `/ccs haiku /ask "what is X?"` → profile=`haiku`, command=`ask`, args=`"what is X?"`
- `/ccs glm /ask "what is X?"` → profile=`glm`, command=`ask`, args=`"what is X?"`
### Step 2: Validate Profile
@@ -48,23 +48,11 @@ Usage: /ccs [profile] /command [args]
Example: /ccs glm /plan "add authentication"
```
### Step 3: Resolve Command Path
### Step 3: Validate Command
Find the command file in this priority order:
1. **User-scope**: `~/.ccs/commands/<command>.md`
2. **Project-scope**: `.claude/commands/<command>.md`
The command will be executed in the launched Claude instance, which will look for `<command>.md` in the project's `.claude/commands/` directory.
Use Glob tool to check both locations. If not found in either:
```
❌ Error: Command '/<command>' not found
Searched locations:
- ~/.ccs/commands/<command>.md (user-scope)
- .claude/commands/<command>.md (project-scope)
Check command name spelling or create the command file.
```
**Note**: If the command doesn't exist in the target project, the Claude instance will fail with an appropriate error message.
### Step 4: Launch Subagent with Task Tool
@@ -74,7 +62,7 @@ Use the Task tool to delegate execution:
```typescript
{
subagent_type: "general-purpose",
model: "haiku",
model: "sonnet",
description: "Delegating /<command> to <profile> profile",
prompt: `You are executing a delegated command via CCS (Claude Code Switch).
@@ -82,7 +70,6 @@ Use the Task tool to delegate execution:
- Profile: <profile>
- Command: /<command>
- Arguments: <args>
- Command file: <resolved-path>
**CRITICAL**: Before executing, switch to the CCS profile:
\`\`\`bash
@@ -91,9 +78,8 @@ ccs <profile>
**Instructions**:
1. Run \`ccs <profile>\` to switch to the correct model
2. Read the command file at <resolved-path>
3. Execute the command with arguments: <args>
4. Provide a clear summary of what was accomplished
2. Execute the command with arguments: <args>
3. Provide a clear summary of what was accomplished
Execute now.`
}
@@ -159,18 +145,16 @@ ccs --version
User: /ccs glm /plan "add user authentication"
You: Parse → profile=glm, command=plan, args="add user authentication"
Validate → Check glm exists in config ✓
Resolve → Find ~/.ccs/commands/plan.md ✓
Launch → Task tool with ccs glm
Return → Formatted result
```
**Example 2**: Quick question with Haiku
**Example 2**: Quick question with GLM
```
User: /ccs haiku /ask "explain JWT tokens"
You: Parse → profile=haiku, command=ask, args="explain JWT tokens"
Validate → Check haiku exists ✓
Resolve → Find command ✓
Launch → Delegate to haiku
User: /ccs glm /ask "explain JWT tokens"
You: Parse → profile=glm, command=ask, args="explain JWT tokens"
Validate → Check glm exists ✓
Launch → Delegate to glm
Return → Result
```
@@ -187,11 +171,10 @@ You: Parse → profile=glm (default), command=debug, args="API 500 error"
- Each delegation creates an **isolated subagent session**
- The subagent switches to the specified CCS profile automatically
- **Token optimization** is the primary benefit
- User-scope commands (`~/.ccs/commands/`) are checked first
- Project-scope commands (`.claude/commands/`) are fallback
- Commands are resolved by the launched Claude instance from the project's `.claude/commands/` directory
- If a command doesn't exist, the Claude instance will fail with an error
## Related Documentation
- Setup guide: `tools/ccs/SETUP-DELEGATION.md`
- Delegation patterns: `tools/ccs/skills/ccs-delegation.md`
- CCS Tool: `tools/ccs/README.md`
+4 -9
View File
@@ -1,11 +1,11 @@
---
name: ccs-delegation
description: Use this skill when the user invokes the `/ccs` command or requests delegating tasks to alternative models (GLM, Haiku) for token optimization. This skill guides when and how to delegate commands to save primary model tokens.
description: Use this skill when the user invokes the `/ccs` command or requests delegating tasks to alternative models (GLM) for token optimization. This skill guides when and how to delegate commands to save primary model tokens.
---
# CCS Delegation
Intelligent task delegation to alternative AI models (GLM, Haiku, etc.) for token optimization using the `/ccs` meta-command.
Intelligent task delegation to alternative AI models (GLM, etc.) for token optimization using the `/ccs` meta-command.
## Purpose
@@ -19,7 +19,7 @@ The `/ccs` command delegates simple tasks to alternative models while staying in
Load this skill when:
- User explicitly invokes `/ccs [profile] /command [args]`
- User requests delegating tasks to alternative models
- User asks to use GLM/Haiku for a task
- User asks to use GLM for a task
- User requests token conservation strategies
## Decision Framework
@@ -125,11 +125,6 @@ Claude: "Delegating to GLM (default profile) for implementation."
- Routine fixes
- Default choice for simple tasks
**Haiku (haiku profile)**:
- Quick questions
- Simple explanations
- Fast, lightweight tasks
- When speed matters
**Sonnet (son profile)**:
- Don't delegate—use directly
@@ -145,7 +140,7 @@ Claude: "Delegating to GLM (default profile) for implementation."
**Examples**:
- `/ccs glm /plan "add user authentication"`
- `/ccs haiku /ask "explain JWT tokens"`
- `/ccs glm /ask "explain JWT tokens"`
- `/ccs /code "implement feature"` (defaults to glm)
## Error Handling
@@ -63,15 +63,6 @@ Use GLM for initial implementation, Sonnet for refinement:
- ❌ Performance optimization
- ❌ Architecture decisions
### Haiku - Best For:
- ✅ Quick questions ("what is X?", "explain Y")
- ✅ Simple explanations
- ✅ Code snippet explanations
- ✅ Quick documentation lookups
- ✅ Simple troubleshooting
- ❌ Code implementation
- ❌ Complex analysis
- ❌ Multi-step tasks
### Sonnet 4.5 - Best For:
- ✅ Complex architecture and design
+17
View File
@@ -53,8 +53,25 @@ irm ccs.kaitran.ca/install | iex
ccs # Use Claude subscription (default)
ccs glm # Use GLM fallback
ccs --version # Show CCS version
ccs --install # Install CCS commands and skills to ~/.claude/
```
### Task Delegation
CCS includes intelligent task delegation via the `/ccs` meta-command:
```bash
# After running ccs --install, you can use:
/ccs glm /plan "add user authentication"
/ccs glm /code "implement auth endpoints"
/ccs glm /ask "explain this error"
```
**Benefits**:
- ✅ Save tokens by delegating simple tasks to cheaper models
- ✅ Use right model for each task automatically
- ✅ Seamless integration with existing workflows
## Philosophy
- **YAGNI**: No features "just in case"
+17
View File
@@ -53,8 +53,25 @@ irm ccs.kaitran.ca/install | iex
ccs # Dùng Claude subscription (mặc định)
ccs glm # Dùng GLM fallback
ccs --version # Hiển thị phiên bản CCS
ccs --install # Cài đặt lệnh và kỹ năng CCS vào ~/.claude/
```
### Delegation Tác Vụ
CCS bao gồm delegation tác vụ thông minh qua meta-command `/ccs`:
```bash
# Sau khi chạy ccs --install, bạn có thể dùng:
/ccs glm /plan "add user authentication"
/ccs glm /code "implement auth endpoints"
/ccs glm /ask "explain this error"
```
**Lợi ích**:
- ✅ Tiết kiệm tokens bằng cách delegation tác vụ đơn giản cho model rẻ hơn
- ✅ Dùng đúng model cho từng tác vụ tự động
- ✅ Tích hợp liền mạch với workflows hiện có
## Triết Lý
- **YAGNI**: Không có tính năng "phòng hờ"
+93
View File
@@ -7,6 +7,93 @@ CCS_VERSION="$(cat "$SCRIPT_DIR/VERSION" 2>/dev/null || echo "unknown")"
CONFIG_FILE="${CCS_CONFIG:-$HOME/.ccs/config.json}"
# Installation function for commands and skills
install_commands_and_skills() {
local source_dir="$SCRIPT_DIR/.claude"
local target_dir="$HOME/.claude"
echo "┌─ Installing CCS Commands & Skills"
echo "│ Source: $source_dir"
echo "│ Target: $target_dir"
echo "│"
# Check if source directory exists
if [[ ! -d "$source_dir" ]]; then
echo "│"
echo "✗ Error: Source directory not found: $source_dir"
echo " Make sure you're running this from the CCS repository directory."
return 1
fi
# Create target directories if they don't exist
mkdir -p "$target_dir/commands"
mkdir -p "$target_dir/skills"
local installed_count=0
local skipped_count=0
# Install commands
if [[ -d "$source_dir/commands" ]]; then
echo "│ Installing commands..."
for cmd_file in "$source_dir/commands"/*.md; do
if [[ -f "$cmd_file" ]]; then
local cmd_name=$(basename "$cmd_file" .md)
local target_file="$target_dir/commands/$cmd_name.md"
if [[ -f "$target_file" ]]; then
echo "│ │ Skipping existing command: $cmd_name.md"
skipped_count=$((skipped_count + 1))
else
if cp "$cmd_file" "$target_file"; then
echo "│ │ ✓ Installed command: $cmd_name.md"
installed_count=$((installed_count + 1))
else
echo "│ │ ✗ Failed to install command: $cmd_name.md"
fi
fi
fi
done
else
echo "│ No commands directory found"
fi
echo "│"
# Install skills
if [[ -d "$source_dir/skills" ]]; then
echo "│ Installing skills..."
for skill_dir in "$source_dir/skills"/*; do
if [[ -d "$skill_dir" ]]; then
local skill_name=$(basename "$skill_dir")
local target_skill_dir="$target_dir/skills/$skill_name"
if [[ -d "$target_skill_dir" ]]; then
echo "│ │ Skipping existing skill: $skill_name"
skipped_count=$((skipped_count + 1))
else
if cp -r "$skill_dir" "$target_skill_dir"; then
echo "│ │ ✓ Installed skill: $skill_name"
installed_count=$((installed_count + 1))
else
echo "│ │ ✗ Failed to install skill: $skill_name"
fi
fi
fi
done
else
echo "│ No skills directory found"
fi
echo "└─"
echo ""
echo "✓ Installation complete!"
echo " Installed: $installed_count items"
echo " Skipped: $skipped_count items (already exist)"
echo ""
echo "You can now use the /ccs command in Claude CLI for task delegation."
echo "Example: /ccs glm /plan 'add user authentication'"
}
# Special case: version command (check BEFORE profile detection)
if [[ $# -gt 0 ]] && [[ "${1}" == "version" || "${1}" == "--version" || "${1}" == "-v" ]]; then
echo "CCS (Claude Code Switch) version $CCS_VERSION"
@@ -20,6 +107,12 @@ if [[ $# -gt 0 ]] && [[ "${1}" == "--help" || "${1}" == "-h" || "${1}" == "help"
exec claude --help "$@"
fi
# Special case: install command (check BEFORE profile detection)
if [[ $# -gt 0 ]] && [[ "${1}" == "--install" ]]; then
install_commands_and_skills
exit $?
fi
# Smart profile detection: if first arg starts with '-', it's a flag not a profile
if [[ $# -eq 0 ]] || [[ "${1}" =~ ^- ]]; then
# No args or first arg is a flag → use default profile
+102
View File
@@ -21,6 +21,102 @@ $CCS_VERSION = if (Test-Path $VersionFile) {
"unknown"
}
# Installation function for commands and skills
function Install-CommandsAndSkills {
$SourceDir = Join-Path $ScriptDir ".claude"
$TargetDir = Join-Path $env:USERPROFILE ".claude"
Write-Host "[Installing CCS Commands & Skills]" -ForegroundColor Cyan
Write-Host "| Source: $SourceDir"
Write-Host "| Target: $TargetDir"
Write-Host "|"
# Check if source directory exists
if (-not (Test-Path $SourceDir)) {
Write-Host "|"
Write-Host "[ERROR] Source directory not found: $SourceDir" -ForegroundColor Red
Write-Host " Make sure you're running this from the CCS repository directory."
exit 1
}
# Create target directories if they don't exist
$CommandsDir = Join-Path $TargetDir "commands"
$SkillsDir = Join-Path $TargetDir "skills"
if (-not (Test-Path $CommandsDir)) {
New-Item -ItemType Directory -Path $CommandsDir -Force | Out-Null
}
if (-not (Test-Path $SkillsDir)) {
New-Item -ItemType Directory -Path $SkillsDir -Force | Out-Null
}
$InstalledCount = 0
$SkippedCount = 0
# Install commands
$SourceCommandsDir = Join-Path $SourceDir "commands"
if (Test-Path $SourceCommandsDir) {
Write-Host "| Installing commands..." -ForegroundColor Yellow
Get-ChildItem $SourceCommandsDir -Filter "*.md" | ForEach-Object {
$CmdName = $_.BaseName
$TargetFile = Join-Path $CommandsDir "$CmdName.md"
if (Test-Path $TargetFile) {
Write-Host "| | [i] Skipping existing command: $CmdName.md" -ForegroundColor Yellow
$SkippedCount++
} else {
try {
Copy-Item $_.FullName $TargetFile -ErrorAction Stop
Write-Host "| | [OK] Installed command: $CmdName.md" -ForegroundColor Green
$InstalledCount++
} catch {
Write-Host "| | [!] Failed to install command: $CmdName.md" -ForegroundColor Red
Write-Host "| Error: $($_.Exception.Message)" -ForegroundColor Red
}
}
}
} else {
Write-Host "| [i] No commands directory found" -ForegroundColor Gray
}
Write-Host "|"
# Install skills
$SourceSkillsDir = Join-Path $SourceDir "skills"
if (Test-Path $SourceSkillsDir) {
Write-Host "| Installing skills..." -ForegroundColor Yellow
Get-ChildItem $SourceSkillsDir -Directory | ForEach-Object {
$SkillName = $_.Name
$TargetSkillDir = Join-Path $SkillsDir $SkillName
if (Test-Path $TargetSkillDir) {
Write-Host "| | [i] Skipping existing skill: $SkillName" -ForegroundColor Yellow
$SkippedCount++
} else {
try {
Copy-Item $_.FullName $TargetSkillDir -Recurse -ErrorAction Stop
Write-Host "| | [OK] Installed skill: $SkillName" -ForegroundColor Green
$InstalledCount++
} catch {
Write-Host "| | [!] Failed to install skill: $SkillName" -ForegroundColor Red
Write-Host "| Error: $($_.Exception.Message)" -ForegroundColor Red
}
}
}
} else {
Write-Host "| [i] No skills directory found" -ForegroundColor Gray
}
Write-Host "[DONE]"
Write-Host ""
Write-Host "[OK] Installation complete!" -ForegroundColor Green
Write-Host " Installed: $InstalledCount items"
Write-Host " Skipped: $SkippedCount items (already exist)"
Write-Host ""
Write-Host "You can now use the /ccs command in Claude CLI for task delegation." -ForegroundColor Cyan
Write-Host "Example: /ccs glm /plan 'add user authentication'" -ForegroundColor Cyan
}
# Special case: version command (check BEFORE profile detection)
# Check both $ProfileOrFlag and first element of $RemainingArgs
$FirstArg = if ($ProfileOrFlag -ne "default") { $ProfileOrFlag } elseif ($RemainingArgs.Count -gt 0) { $RemainingArgs[0] } else { $null }
@@ -46,6 +142,12 @@ if ($FirstArg -eq "--help" -or $FirstArg -eq "-h" -or $FirstArg -eq "help") {
}
}
# Special case: install command (check BEFORE profile detection)
if ($FirstArg -eq "--install") {
Install-CommandsAndSkills
exit $LASTEXITCODE
}
# Smart profile detection: if first arg starts with '-', it's a flag not a profile
if ($ProfileOrFlag -match '^-') {
# First arg is a flag → use default profile, keep all args
+36
View File
@@ -77,6 +77,42 @@ ccs glm /code "implement feature"
```bash
ccs --version # Show CCS version
ccs --help # Show Claude CLI help
ccs --install # Install CCS commands and skills to ~/.claude/
```
### Installing Commands and Skills
To use the task delegation feature, you need to install the CCS commands and skills to your Claude CLI directory:
```bash
# Install CCS delegation commands and skills
ccs --install
```
This will:
- Copy `/ccs` command to `~/.claude/commands/ccs.md`
- Copy `ccs-delegation` skill to `~/.claude/skills/ccs-delegation/`
- Skip existing files (won't overwrite your customizations)
**Output Example**:
```
┌─ Installing CCS Commands & Skills
│ Source: /path/to/ccs/.claude
│ Target: /home/user/.claude
│ Installing commands...
│ │ ✓ Installed command: ccs.md
│ Installing skills...
│ │ ✓ Installed skill: ccs-delegation
└─
✓ Installation complete!
Installed: 2 items
Skipped: 0 items (already exist)
You can now use the /ccs command in Claude CLI for task delegation.
Example: /ccs glm /plan 'add user authentication'
```
## Task Delegation
+273
View File
@@ -0,0 +1,273 @@
#!/usr/bin/env pwsh
<#
.SYNOPSIS
Test suite for CCS --install functionality (Windows PowerShell)
.DESCRIPTION
Tests the --install flag for CCS executable on Windows PowerShell.
Tests against actual system installation for simplicity.
.NOTES
Author: CCS Test Suite
Version: 1.0
Based on: edge-cases.ps1 patterns
#>
#Requires -Version 5.1
# Don't exit on errors, we're testing
$ErrorActionPreference = "Continue"
# Test statistics
$Script:TotalTests = 0
$Script:PassedTests = 0
$Script:FailedTests = 0
# Colors
$Colors = @{
Red = "Red"
Green = "Green"
Yellow = "Yellow"
Cyan = "Cyan"
White = "White"
}
function Write-ColorOutput {
param([string]$Message, [string]$Color = "White")
Write-Host $Message -ForegroundColor $Colors[$Color]
}
function Test-Case {
param(
[string]$Name,
[string]$Description,
[scriptblock]$TestCode
)
$Script:TotalTests++
Write-Host ""
Write-ColorOutput "[$Script:TotalTests] $Name" "Cyan"
Write-ColorOutput " Expected: $Description" "White"
try {
if (& $TestCode) {
Write-ColorOutput " Result: PASS" "Green"
$Script:PassedTests++
return $true
} else {
Write-ColorOutput " Result: FAIL" "Red"
$Script:FailedTests++
return $false
}
}
catch {
Write-ColorOutput " Result: FAIL" "Red"
Write-ColorOutput " Error: $($_.Exception.Message)" "Red"
$Script:FailedTests++
return $false
}
}
Write-ColorOutput "========================================" "Yellow"
Write-ColorOutput "CCS --INSTALL FUNCTIONALITY TESTING" "Yellow"
Write-ColorOutput "========================================" "Yellow"
Write-Host ""
# Get script paths
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$CcsRoot = Split-Path -Parent $ScriptDir
$CcsPath = Join-Path $CcsRoot "ccs.ps1"
# Backup existing .claude directory
Write-ColorOutput "Safety: Backing up existing ~/.claude/..." "Cyan"
$BackupDir = Join-Path $env:TEMP "ccs-test-backup-$(Get-Date -Format 'yyyyMMddHHmmss')"
if (Test-Path $env:USERPROFILE\.claude) {
Write-Host " Found existing ~/.claude/, creating backup at $BackupDir"
Copy-Item -Path $env:USERPROFILE\.claude -Destination $BackupDir -Recurse -Force
Write-ColorOutput " Backup created successfully" "Green"
} else {
Write-ColorOutput " No existing ~/.claude/ found" "Yellow"
}
Write-Host ""
# ============================================================================
# PRE-CHECKS
# ============================================================================
Write-ColorOutput "===== PRE-CHECKS =====" "Yellow"
Test-Case "CCS executable exists" "ccs.ps1 script found" {
Test-Path $CcsPath
}
Test-Case "Source .claude directory exists" ".claude/ in CCS repo" {
Test-Path (Join-Path $CcsRoot ".claude")
}
Test-Case "Source commands exist" "ccs.md command file exists" {
Test-Path (Join-Path $CcsRoot ".claude\commands\ccs.md")
}
Test-Case "Source skills exist" "ccs-delegation skill directory exists" {
Test-Path (Join-Path $CcsRoot ".claude\skills\ccs-delegation")
}
# ============================================================================
# SECTION 1: INSTALLATION
# ============================================================================
Write-Host ""
Write-ColorOutput "===== SECTION 1: INSTALLATION =====" "Yellow"
Test-Case "Install: Command executes without error" "Exit code 0" {
$process = Start-Process -FilePath "pwsh" -ArgumentList "-File", "`"$CcsPath`"", "--install" -Wait -PassThru -NoNewWindow
$process.ExitCode -eq 0
}
Test-Case "Install: Commands directory created" "~/.claude/commands/ exists" {
Test-Path "$env:USERPROFILE\.claude\commands"
}
Test-Case "Install: Skills directory created" "~/.claude/skills/ exists" {
Test-Path "$env:USERPROFILE\.claude\skills"
}
Test-Case "Install: ccs.md command installed" "ccs.md file exists" {
Test-Path "$env:USERPROFILE\.claude\commands\ccs.md"
}
Test-Case "Install: ccs-delegation skill installed" "ccs-delegation/ exists" {
Test-Path "$env:USERPROFILE\.claude\skills\ccs-delegation"
}
Test-Case "Install: SKILL.md exists" "SKILL.md in ccs-delegation/" {
Test-Path "$env:USERPROFILE\.claude\skills\ccs-delegation\SKILL.md"
}
Test-Case "Install: references directory exists" "references/ subdirectory present" {
Test-Path "$env:USERPROFILE\.claude\skills\ccs-delegation\references"
}
# ============================================================================
# SECTION 2: IDEMPOTENCY
# ============================================================================
Write-Host ""
Write-ColorOutput "===== SECTION 2: IDEMPOTENCY =====" "Yellow"
Test-Case "Idempotent: Second run succeeds" "Second --install doesn't error" {
$process = Start-Process -FilePath "pwsh" -ArgumentList "-File", "`"$CcsPath`"", "--install" -Wait -PassThru -NoNewWindow
$process.ExitCode -eq 0
}
# ============================================================================
# SECTION 3: FILE INTEGRITY
# ============================================================================
Write-Host ""
Write-ColorOutput "===== SECTION 3: FILE INTEGRITY =====" "Yellow"
Test-Case "Integrity: Command file not empty" "ccs.md has content" {
$content = Get-Content "$env:USERPROFILE\.claude\commands\ccs.md" -Raw
$content.Length -gt 0
}
Test-Case "Integrity: Skill file not empty" "SKILL.md has content" {
$content = Get-Content "$env:USERPROFILE\.claude\skills\ccs-delegation\SKILL.md" -Raw
$content.Length -gt 0
}
Test-Case "Integrity: Command file matches source" "ccs.md content identical" {
$source = Get-Content (Join-Path $CcsRoot ".claude\commands\ccs.md") -Raw
$target = Get-Content "$env:USERPROFILE\.claude\commands\ccs.md" -Raw
$source -eq $target
}
Test-Case "Integrity: Skill file matches source" "SKILL.md content identical" {
$source = Get-Content (Join-Path $CcsRoot ".claude\skills\ccs-delegation\SKILL.md") -Raw
$target = Get-Content "$env:USERPROFILE\.claude\skills\ccs-delegation\SKILL.md" -Raw
$source -eq $target
}
# ============================================================================
# SECTION 4: INTEGRATION
# ============================================================================
Write-Host ""
Write-ColorOutput "===== SECTION 4: INTEGRATION WITH CCS =====" "Yellow"
Test-Case "Integration: --install executes without profile error" "No profile error on --install" {
$process = Start-Process -FilePath "pwsh" -ArgumentList "-File", "`"$CcsPath`"", "--install" -Wait -PassThru -NoNewWindow
$process.ExitCode -eq 0
}
Test-Case "Integration: --version still works" "Version command exits successfully" {
$process = Start-Process -FilePath "pwsh" -ArgumentList "-File", "`"$CcsPath`"", "--version" -Wait -PassThru -NoNewWindow
$process.ExitCode -eq 0
}
Test-Case "Integration: --help still works" "Help command exits successfully" {
$process = Start-Process -FilePath "pwsh" -ArgumentList "-File", "`"$CcsPath`"", "--help" -Wait -PassThru -NoNewWindow
$process.ExitCode -eq 0
}
# ============================================================================
# FINAL RESULTS
# ============================================================================
Write-Host ""
Write-ColorOutput "========================================" "Yellow"
Write-ColorOutput "TEST RESULTS SUMMARY" "Yellow"
Write-ColorOutput "========================================" "Yellow"
Write-Host ""
Write-ColorOutput "Total Tests: $Script:TotalTests" "Cyan"
Write-ColorOutput "Passed: $Script:PassedTests" "Green"
if ($Script:FailedTests -eq 0) {
Write-ColorOutput "Failed: $Script:FailedTests" "Green"
} else {
Write-ColorOutput "Failed: $Script:FailedTests" "Red"
}
Write-Host ""
$SuccessRate = if ($Script:TotalTests -gt 0) {
[math]::Round(($Script:PassedTests / $Script:TotalTests) * 100, 2)
} else { 0 }
if ($SuccessRate -ge 90) {
Write-ColorOutput "Success Rate: $SuccessRate%" "Green"
} elseif ($SuccessRate -ge 70) {
Write-ColorOutput "Success Rate: $SuccessRate%" "Yellow"
} else {
Write-ColorOutput "Success Rate: $SuccessRate%" "Red"
}
Write-Host ""
if ($Script:FailedTests -eq 0) {
Write-ColorOutput "========================================" "Green"
Write-ColorOutput "ALL TESTS PASSED!" "Green"
Write-ColorOutput "========================================" "Green"
Write-ColorOutput "--install functionality is production ready!" "Green"
} else {
Write-ColorOutput "========================================" "Red"
Write-ColorOutput "SOME TESTS FAILED" "Red"
Write-ColorOutput "========================================" "Red"
Write-ColorOutput "Review failed tests above for details" "Red"
}
# Restore backup
Write-Host ""
Write-ColorOutput "Cleaning up and restoring..." "Yellow"
if (Test-Path $env:USERPROFILE\.claude) {
Write-Host " Removing test data from $env:USERPROFILE\.claude"
Remove-Item -Path $env:USERPROFILE\.claude -Recurse -Force
}
if (Test-Path $BackupDir) {
Write-Host " Restoring backup from $BackupDir"
Move-Item -Path $BackupDir -Destination $env:USERPROFILE\.claude
Write-ColorOutput " Backup restored successfully" "Green"
}
# Exit with appropriate code
if ($Script:FailedTests -gt 0) {
exit 1
} else {
exit 0
}
+446
View File
@@ -0,0 +1,446 @@
#!/usr/bin/env bash
# CCS --install Functionality Testing (Linux/macOS)
# Comprehensive tests for the --install command
set +e # Don't exit on errors, we're testing
PASS_COUNT=0
FAIL_COUNT=0
TOTAL_TESTS=0
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
GRAY='\033[0;37m'
NC='\033[0m' # No Color
# Get script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CCS_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
CCS_PATH="$CCS_ROOT/ccs"
# Backup/restore paths
CLAUDE_DIR="$HOME/.claude"
BACKUP_DIR="/tmp/ccs-test-backup-$(date +%s)"
TEST_HOME="/tmp/ccs-test-home"
TEST_CLAUDE_DIR="$TEST_HOME/.claude"
test_case() {
local name="$1"
local expected="$2"
shift 2
((TOTAL_TESTS++))
echo ""
echo -e "${CYAN}[$TOTAL_TESTS] $name${NC}"
echo -e "${GRAY} Expected: $expected${NC}"
if "$@"; then
echo -e "${GREEN} Result: PASS${NC}"
((PASS_COUNT++))
return 0
else
echo -e "${RED} Result: FAIL${NC}"
((FAIL_COUNT++))
return 1
fi
}
cleanup_and_restore() {
echo ""
echo -e "${YELLOW}Cleaning up and restoring...${NC}"
# Remove test directory
rm -rf "$TEST_HOME"
# Restore backup if it exists
if [[ -d "$BACKUP_DIR" ]]; then
if [[ -d "$CLAUDE_DIR" ]]; then
echo " Removing test data from $CLAUDE_DIR"
rm -rf "$CLAUDE_DIR"
fi
echo " Restoring backup from $BACKUP_DIR"
mv "$BACKUP_DIR" "$CLAUDE_DIR"
echo -e "${GREEN} Backup restored successfully${NC}"
fi
}
# Trap to ensure cleanup happens even if script fails
trap cleanup_and_restore EXIT
echo -e "${YELLOW}========================================${NC}"
echo -e "${YELLOW}CCS --INSTALL FUNCTIONALITY TESTING${NC}"
echo -e "${YELLOW}========================================${NC}"
echo ""
# ============================================================================
# SAFETY: BACKUP EXISTING ~/.claude/
# ============================================================================
echo -e "${CYAN}Safety: Backing up existing ~/.claude/...${NC}"
if [[ -d "$CLAUDE_DIR" ]]; then
echo " Found existing ~/.claude/, creating backup at $BACKUP_DIR"
cp -r "$CLAUDE_DIR" "$BACKUP_DIR"
echo -e "${GREEN} Backup created successfully${NC}"
else
echo " No existing ~/.claude/ found, no backup needed"
fi
echo ""
# ============================================================================
# PRE-CHECKS
# ============================================================================
echo -e "${YELLOW}===== PRE-CHECKS =====${NC}"
test_case "CCS executable exists" "ccs script found at $CCS_PATH" bash -c "
[[ -f '$CCS_PATH' ]]
"
test_case "CCS executable is executable" "ccs has execute permissions" bash -c "
[[ -x '$CCS_PATH' ]]
"
test_case "Source .claude directory exists" ".claude/ in CCS repo" bash -c "
[[ -d '$CCS_ROOT/.claude' ]]
"
test_case "Source commands exist" "ccs.md command file exists" bash -c "
[[ -f '$CCS_ROOT/.claude/commands/ccs.md' ]]
"
test_case "Source skills exist" "ccs-delegation skill directory exists" bash -c "
[[ -d '$CCS_ROOT/.claude/skills/ccs-delegation' ]]
"
# ============================================================================
# SECTION 1: FRESH INSTALLATION (NO ~/.claude/)
# ============================================================================
echo ""
echo -e "${YELLOW}===== SECTION 1: FRESH INSTALLATION =====${NC}"
# Clean any existing test directory
rm -rf "$TEST_HOME"
mkdir -p "$TEST_HOME"
test_case "Fresh install: Command executes without error" "Exit code 0" bash -c "
HOME='$TEST_HOME' '$CCS_PATH' --install > /tmp/ccs-install-output.txt 2>&1
"
test_case "Fresh install: Commands directory created" "~/.claude/commands/ exists" bash -c "
[[ -d '$TEST_CLAUDE_DIR/commands' ]]
"
test_case "Fresh install: Skills directory created" "~/.claude/skills/ exists" bash -c "
[[ -d '$TEST_CLAUDE_DIR/skills' ]]
"
test_case "Fresh install: ccs.md command installed" "ccs.md file exists in commands/" bash -c "
[[ -f '$TEST_CLAUDE_DIR/commands/ccs.md' ]]
"
test_case "Fresh install: ccs-delegation skill installed" "ccs-delegation/ exists in skills/" bash -c "
[[ -d '$TEST_CLAUDE_DIR/skills/ccs-delegation' ]]
"
test_case "Fresh install: SKILL.md exists" "SKILL.md in ccs-delegation/" bash -c "
[[ -f '$TEST_CLAUDE_DIR/skills/ccs-delegation/SKILL.md' ]]
"
test_case "Fresh install: references directory exists" "references/ subdirectory present" bash -c "
[[ -d '$TEST_CLAUDE_DIR/skills/ccs-delegation/references' ]]
"
test_case "Fresh install: delegation-patterns.md exists" "Pattern reference file present" bash -c "
[[ -f '$TEST_CLAUDE_DIR/skills/ccs-delegation/references/delegation-patterns.md' ]]
"
# ============================================================================
# SECTION 2: OUTPUT FORMATTING (BOX-DRAWING CHARACTERS)
# ============================================================================
echo ""
echo -e "${YELLOW}===== SECTION 2: OUTPUT FORMATTING =====${NC}"
# Clean for fresh test
rm -rf "$TEST_HOME"
mkdir -p "$TEST_HOME"
test_case "Output: Contains box-drawing header" "Output has ┌─" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ ┌─ ]]
"
test_case "Output: Contains box-drawing footer" "Output has └─" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ └─ ]]
"
test_case "Output: Contains pipe for indentation" "Output has │" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ │ ]]
"
test_case "Output: Contains checkmark indicator" "Output has ✓" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ ✓ ]]
"
test_case "Output: Shows source directory" "Output includes source path" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ Source: ]]
"
test_case "Output: Shows target directory" "Output includes target path" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ Target: ]]
"
test_case "Output: Shows installation complete message" "Success message present" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ 'Installation complete' ]]
"
test_case "Output: Shows installed count" "Displays number of installed items" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ 'Installed:' ]]
"
test_case "Output: NO emoji characters used" "Output uses only box-drawing and symbols" bash -c "
# Check for actual emoji characters (not box-drawing or symbols like ✓ ✗)
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
! [[ \$output =~ [🚀📋🎯🎉] ]]
"
# ============================================================================
# SECTION 3: IDEMPOTENCY (MULTIPLE RUNS)
# ============================================================================
echo ""
echo -e "${YELLOW}===== SECTION 3: IDEMPOTENCY =====${NC}"
# Start fresh
rm -rf "$TEST_HOME"
mkdir -p "$TEST_HOME"
HOME="$TEST_HOME" "$CCS_PATH" --install > /dev/null 2>&1
test_case "Idempotent: Second run succeeds" "Second --install doesn't error" bash -c "
HOME='$TEST_HOME' '$CCS_PATH' --install > /tmp/ccs-install-second.txt 2>&1
"
test_case "Idempotent: Shows skip messages" "Output contains 'Skipping existing'" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ 'Skipping existing' ]]
"
test_case "Idempotent: Uses info indicator " "Skip messages have indicator" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ ]]
"
test_case "Idempotent: Skipped count shown" "Displays number of skipped items" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ 'Skipped:' ]]
"
test_case "Idempotent: Files remain unchanged" "Original files not modified" bash -c "
# Get modification time before second install
mtime1=\$(stat -c %Y '$TEST_CLAUDE_DIR/commands/ccs.md' 2>/dev/null || stat -f %m '$TEST_CLAUDE_DIR/commands/ccs.md')
sleep 1
HOME='$TEST_HOME' '$CCS_PATH' --install > /dev/null 2>&1
mtime2=\$(stat -c %Y '$TEST_CLAUDE_DIR/commands/ccs.md' 2>/dev/null || stat -f %m '$TEST_CLAUDE_DIR/commands/ccs.md')
[[ \$mtime1 == \$mtime2 ]]
"
test_case "Idempotent: Third run still safe" "Multiple runs are safe" bash -c "
HOME='$TEST_HOME' '$CCS_PATH' --install > /dev/null 2>&1
HOME='$TEST_HOME' '$CCS_PATH' --install > /dev/null 2>&1
[[ -f '$TEST_CLAUDE_DIR/commands/ccs.md' ]] && [[ -d '$TEST_CLAUDE_DIR/skills/ccs-delegation' ]]
"
# ============================================================================
# SECTION 4: CONFLICT HANDLING (EXISTING FILES)
# ============================================================================
echo ""
echo -e "${YELLOW}===== SECTION 4: CONFLICT HANDLING =====${NC}"
# Create existing files with different content
rm -rf "$TEST_CLAUDE_DIR"
mkdir -p "$TEST_CLAUDE_DIR/commands"
mkdir -p "$TEST_CLAUDE_DIR/skills/ccs-delegation"
echo "EXISTING COMMAND CONTENT" > "$TEST_CLAUDE_DIR/commands/ccs.md"
echo "EXISTING SKILL CONTENT" > "$TEST_CLAUDE_DIR/skills/ccs-delegation/SKILL.md"
test_case "Conflict: Skips existing command file" "Doesn't overwrite ccs.md" bash -c "
HOME='$TEST_HOME' '$CCS_PATH' --install > /dev/null 2>&1
content=\$(cat '$TEST_CLAUDE_DIR/commands/ccs.md')
[[ \$content == 'EXISTING COMMAND CONTENT' ]]
"
test_case "Conflict: Skips existing skill directory" "Doesn't overwrite skill" bash -c "
content=\$(cat '$TEST_CLAUDE_DIR/skills/ccs-delegation/SKILL.md')
[[ \$content == 'EXISTING SKILL CONTENT' ]]
"
test_case "Conflict: Output shows skip message" "User informed about skips" bash -c "
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1)
[[ \$output =~ 'Skipping existing command: ccs.md' ]]
"
test_case "Conflict: No data loss" "Original files preserved" bash -c "
[[ -f '$TEST_CLAUDE_DIR/commands/ccs.md' ]] &&
grep -q 'EXISTING COMMAND CONTENT' '$TEST_CLAUDE_DIR/commands/ccs.md'
"
# ============================================================================
# SECTION 5: FILE INTEGRITY
# ============================================================================
echo ""
echo -e "${YELLOW}===== SECTION 5: FILE INTEGRITY =====${NC}"
# Fresh install for integrity checks
rm -rf "$TEST_HOME"
mkdir -p "$TEST_HOME"
HOME="$TEST_HOME" "$CCS_PATH" --install > /dev/null 2>&1
test_case "Integrity: Command file not empty" "ccs.md has content" bash -c "
[[ -s '$TEST_CLAUDE_DIR/commands/ccs.md' ]]
"
test_case "Integrity: Skill file not empty" "SKILL.md has content" bash -c "
[[ -s '$TEST_CLAUDE_DIR/skills/ccs-delegation/SKILL.md' ]]
"
test_case "Integrity: Command file matches source" "ccs.md content identical" bash -c "
diff -q '$CCS_ROOT/.claude/commands/ccs.md' '$TEST_CLAUDE_DIR/commands/ccs.md'
"
test_case "Integrity: Skill file matches source" "SKILL.md content identical" bash -c "
diff -q '$CCS_ROOT/.claude/skills/ccs-delegation/SKILL.md' '$TEST_CLAUDE_DIR/skills/ccs-delegation/SKILL.md'
"
test_case "Integrity: Reference file matches source" "delegation-patterns.md identical" bash -c "
diff -q '$CCS_ROOT/.claude/skills/ccs-delegation/references/delegation-patterns.md' \
'$TEST_CLAUDE_DIR/skills/ccs-delegation/references/delegation-patterns.md'
"
test_case "Integrity: Directory structure preserved" "All subdirectories present" bash -c "
[[ -d '$TEST_CLAUDE_DIR/skills/ccs-delegation/references' ]]
"
# ============================================================================
# SECTION 6: ERROR HANDLING
# ============================================================================
echo ""
echo -e "${YELLOW}===== SECTION 6: ERROR HANDLING =====${NC}"
test_case "Error: Missing source directory handled" "Graceful error when source missing" bash -c "
# Temporarily move .claude directory
mv '$CCS_ROOT/.claude' '$CCS_ROOT/.claude.backup'
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1 || true)
mv '$CCS_ROOT/.claude.backup' '$CCS_ROOT/.claude'
[[ \$output =~ 'Error: Source directory not found' ]]
"
test_case "Error: Shows helpful error message" "Error message explains the issue" bash -c "
mv '$CCS_ROOT/.claude' '$CCS_ROOT/.claude.backup'
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1 || true)
mv '$CCS_ROOT/.claude.backup' '$CCS_ROOT/.claude'
[[ \$output =~ 'CCS repository directory' ]]
"
test_case "Error: Uses error indicator ✗" "Error messages have ✗ indicator" bash -c "
mv '$CCS_ROOT/.claude' '$CCS_ROOT/.claude.backup'
output=\$(HOME='$TEST_HOME' '$CCS_PATH' --install 2>&1 || true)
mv '$CCS_ROOT/.claude.backup' '$CCS_ROOT/.claude'
[[ \$output =~ ✗ ]]
"
# ============================================================================
# SECTION 7: PERMISSIONS AND OWNERSHIP
# ============================================================================
echo ""
echo -e "${YELLOW}===== SECTION 7: PERMISSIONS AND OWNERSHIP =====${NC}"
rm -rf "$TEST_CLAUDE_DIR"
HOME=$(dirname "$TEST_CLAUDE_DIR") "$CCS_PATH" --install > /dev/null 2>&1
test_case "Permissions: Command file is readable" "ccs.md has read permissions" bash -c "
[[ -r '$TEST_CLAUDE_DIR/commands/ccs.md' ]]
"
test_case "Permissions: Skill file is readable" "SKILL.md has read permissions" bash -c "
[[ -r '$TEST_CLAUDE_DIR/skills/ccs-delegation/SKILL.md' ]]
"
test_case "Permissions: Directories are accessible" "Can list directory contents" bash -c "
ls '$TEST_CLAUDE_DIR/commands' > /dev/null 2>&1 &&
ls '$TEST_CLAUDE_DIR/skills' > /dev/null 2>&1
"
# ============================================================================
# SECTION 8: INTEGRATION WITH CCS
# ============================================================================
echo ""
echo -e "${YELLOW}===== SECTION 8: INTEGRATION WITH CCS =====${NC}"
test_case "Integration: --install flag recognized" "--install doesn't show 'Profile not found'" bash -c "
output=\$('$CCS_PATH' --install 2>&1 || true)
! [[ \$output =~ 'Profile.*--install.*not found' ]]
"
test_case "Integration: --version still works after --install" "Version command functional" bash -c "
output=\$('$CCS_PATH' --version 2>&1)
[[ \$output =~ 'CCS' ]]
"
test_case "Integration: --help still works after --install" "Help command functional" bash -c "
output=\$('$CCS_PATH' --help 2>&1)
[[ \$output =~ 'Usage' ]] || [[ \$output =~ 'Claude' ]]
"
# ============================================================================
# FINAL RESULTS
# ============================================================================
echo ""
echo -e "${YELLOW}========================================${NC}"
echo -e "${YELLOW}TEST RESULTS SUMMARY${NC}"
echo -e "${YELLOW}========================================${NC}"
echo ""
echo -e "${CYAN}Total Tests: $TOTAL_TESTS${NC}"
echo -e "${GREEN}Passed: $PASS_COUNT${NC}"
if [[ $FAIL_COUNT -eq 0 ]]; then
echo -e "${GREEN}Failed: $FAIL_COUNT${NC}"
else
echo -e "${RED}Failed: $FAIL_COUNT${NC}"
fi
echo ""
SUCCESS_RATE=$(awk "BEGIN {printf \"%.2f\", ($PASS_COUNT / $TOTAL_TESTS) * 100}")
if awk "BEGIN {exit !($SUCCESS_RATE >= 90)}"; then
echo -e "${GREEN}Success Rate: $SUCCESS_RATE%${NC}"
elif awk "BEGIN {exit !($SUCCESS_RATE >= 70)}"; then
echo -e "${YELLOW}Success Rate: $SUCCESS_RATE%${NC}"
else
echo -e "${RED}Success Rate: $SUCCESS_RATE%${NC}"
fi
echo ""
if [[ $FAIL_COUNT -eq 0 ]]; then
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}ALL TESTS PASSED!${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
echo -e "${GREEN}--install functionality is production ready!${NC}"
exit 0
else
echo -e "${YELLOW}========================================${NC}"
echo -e "${YELLOW}SOME TESTS FAILED${NC}"
echo -e "${YELLOW}========================================${NC}"
echo ""
echo -e "${YELLOW}Review failed tests above for details${NC}"
exit 1
fi