UNPKG

@waltcow/claude-code-spec-workflow

Version:

Automated spec-driven workflow for Claude Code. Transforms feature ideas into complete implementations through Requirements → Design → Tasks → Implementation.

446 lines (384 loc) 14 kB
"use strict"; /** * Platform-specific command generation scripts for Claude Code Spec Workflow * * These scripts replace the JavaScript version to avoid conflicts and ensure * cross-platform compatibility. The agent detects the OS and runs the appropriate script. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.getWindowsCommandGenerationScript = getWindowsCommandGenerationScript; exports.getUnixCommandGenerationScript = getUnixCommandGenerationScript; exports.getOSDetectionScript = getOSDetectionScript; exports.getCommandGenerationInstructions = getCommandGenerationInstructions; exports.getCommandGenerationScript = getCommandGenerationScript; function getWindowsCommandGenerationScript() { return `@echo off REM Command Generation Script for Claude Code Spec Workflow (Windows) REM REM This script generates individual task commands for each task in a spec's tasks.md file. REM It creates a folder structure under .claude/commands/{spec-name}/ with individual REM command files for each task that call /spec-execute with the appropriate parameters. REM REM Usage: generate-commands.bat <spec-name> setlocal enabledelayedexpansion if "%~1"=="" ( echo Error: Spec name is required echo Usage: generate-commands.bat ^<spec-name^> exit /b 1 ) set "SPEC_NAME=%~1" set "PROJECT_ROOT=%CD%" set "SPEC_DIR=%PROJECT_ROOT%\\.claude\\specs\\%SPEC_NAME%" set "TASKS_FILE=%SPEC_DIR%\\tasks.md" set "COMMANDS_SPEC_DIR=%PROJECT_ROOT%\\.claude\\commands\\%SPEC_NAME%" REM Check if tasks.md exists if not exist "%TASKS_FILE%" ( echo Error: tasks.md not found at %TASKS_FILE% exit /b 1 ) REM Create spec commands directory if not exist "%COMMANDS_SPEC_DIR%" mkdir "%COMMANDS_SPEC_DIR%" REM Parse tasks and generate commands set "TASK_COUNT=0" echo Parsing tasks from %TASKS_FILE%... for /f "usebackq delims=" %%a in ("%TASKS_FILE%") do ( set "LINE=%%a" call :ParseTaskLine "!LINE!" ) echo. echo Generated !TASK_COUNT! task commands for spec: %SPEC_NAME% echo Commands created in: .claude\\commands\\%SPEC_NAME%\\ echo. echo Generated commands: for /f "usebackq delims=" %%a in ("%TASKS_FILE%") do ( set "LINE=%%a" call :ShowTaskCommand "!LINE!" ) goto :eof :ParseTaskLine set "TASK_LINE=%~1" REM Match task lines like "- [ ] 1. Task description" or "- [ ] 2.1 Task description" REM Use a simpler approach - check if line starts with "- [ ]" and contains a number echo !TASK_LINE! | findstr /b /c:"- [ ]" >nul if !errorlevel! equ 0 ( REM Extract everything after "- [ ] " set "AFTER_CHECKBOX=!TASK_LINE:~6!" call :ExtractTaskInfo "!AFTER_CHECKBOX!" ) goto :eof :ExtractTaskInfo set "REMAINING=%~1" REM Find the first token which should be the task ID for /f "tokens=1,* delims= " %%x in ("!REMAINING!") do ( set "POTENTIAL_ID=%%x" set "REST=%%y" REM Remove trailing dot if present if "!POTENTIAL_ID:~-1!"=="." set "POTENTIAL_ID=!POTENTIAL_ID:~0,-1!" REM Check if it looks like a task ID (starts with digit, may contain dots) echo !POTENTIAL_ID! | findstr /r "^[0-9]" >nul if !errorlevel! equ 0 ( REM Simple validation - check if it matches pattern like 1, 1.2, 1.2.3 etc REM Replace dots with spaces and check each part is numeric set "ID_PARTS=!POTENTIAL_ID:.= !" set "VALID_ID=1" for %%p in (!ID_PARTS!) do ( REM Use arithmetic test to check if part is numeric set /a "TEST_NUM=%%p" 2>nul if !errorlevel! neq 0 set "VALID_ID=0" ) if !VALID_ID! equ 1 ( set "TASK_ID=!POTENTIAL_ID!" set "TASK_DESC=!REST!" call :GenerateTaskCommand "!TASK_ID!" "!TASK_DESC!" set /a TASK_COUNT+=1 ) ) ) goto :eof :GenerateTaskCommand set "TASK_ID=%~1" set "TASK_DESC=%~2" set "COMMAND_FILE=%COMMANDS_SPEC_DIR%\\task-%TASK_ID%.md" ( echo # %SPEC_NAME% - Task %TASK_ID% echo. echo Execute task %TASK_ID% for the %SPEC_NAME% specification. echo. echo ## Task Description echo %TASK_DESC% echo. echo ## Usage echo \`\`\` echo /%SPEC_NAME%-task-%TASK_ID% echo \`\`\` echo. echo ## Instructions echo This command executes a specific task from the %SPEC_NAME% specification. echo. echo **Automatic Execution**: This command will automatically execute: echo \`\`\` echo /spec-execute %TASK_ID% %SPEC_NAME% echo \`\`\` echo. echo **Process**: echo 1. Load the %SPEC_NAME% specification context ^(requirements.md, design.md, tasks.md^) echo 2. Execute task %TASK_ID%: "%TASK_DESC%" echo 3. Follow all implementation guidelines from the main /spec-execute command echo 4. Mark the task as complete in tasks.md echo 5. Stop and wait for user review echo. echo **Important**: This command follows the same rules as /spec-execute: echo - Execute ONLY this specific task echo - Mark task as complete by changing [ ] to [x] in tasks.md echo - Stop after completion and wait for user approval echo - Do not automatically proceed to the next task echo. echo ## Next Steps echo After task completion, you can: echo - Review the implementation echo - Run tests if applicable echo - Execute the next task using /%SPEC_NAME%-task-[next-id] echo - Check overall progress with /spec-status %SPEC_NAME% ) > "%COMMAND_FILE%" goto :eof :ShowTaskCommand set "TASK_LINE=%~1" REM Use same logic as ParseTaskLine echo !TASK_LINE! | findstr /b /c:"- [ ]" >nul if !errorlevel! equ 0 ( set "AFTER_CHECKBOX=!TASK_LINE:~6!" call :ShowTaskInfo "!AFTER_CHECKBOX!" ) goto :eof :ShowTaskInfo set "REMAINING=%~1" for /f "tokens=1,* delims= " %%x in ("!REMAINING!") do ( set "POTENTIAL_ID=%%x" set "REST=%%y" if "!POTENTIAL_ID:~-1!"=="." set "POTENTIAL_ID=!POTENTIAL_ID:~0,-1!" REM Check if it looks like a task ID echo !POTENTIAL_ID! | findstr /r "^[0-9]" >nul if !errorlevel! equ 0 ( REM Simple validation - check if it matches pattern like 1, 1.2, 1.2.3 etc set "ID_PARTS=!POTENTIAL_ID:.= !" set "VALID_ID=1" for %%p in (!ID_PARTS!) do ( REM Use arithmetic test to check if part is numeric set /a "TEST_NUM=%%p" 2>nul if !errorlevel! neq 0 set "VALID_ID=0" ) if !VALID_ID! equ 1 ( echo /%SPEC_NAME%-task-!POTENTIAL_ID! - !REST! ) ) ) goto :eof `; } function getUnixCommandGenerationScript() { return `#!/bin/bash # Command Generation Script for Claude Code Spec Workflow (Unix/Linux/macOS) # # This script generates individual task commands for each task in a spec's tasks.md file. # It creates a folder structure under .claude/commands/{spec-name}/ with individual # command files for each task that call /spec-execute with the appropriate parameters. # # Usage: ./generate-commands.sh <spec-name> set -e if [ -z "$1" ]; then echo "Error: Spec name is required" echo "Usage: ./generate-commands.sh <spec-name>" exit 1 fi SPEC_NAME="$1" PROJECT_ROOT="$(pwd)" SPEC_DIR="$PROJECT_ROOT/.claude/specs/$SPEC_NAME" TASKS_FILE="$SPEC_DIR/tasks.md" COMMANDS_SPEC_DIR="$PROJECT_ROOT/.claude/commands/$SPEC_NAME" # Check if tasks.md exists if [ ! -f "$TASKS_FILE" ]; then echo "Error: tasks.md not found at $TASKS_FILE" exit 1 fi # Create spec commands directory mkdir -p "$COMMANDS_SPEC_DIR" # Parse tasks and generate commands TASK_COUNT=0 echo "Parsing tasks from $TASKS_FILE..." generate_task_command() { local task_id="$1" local task_desc="$2" local command_file="$COMMANDS_SPEC_DIR/task-$task_id.md" cat > "$command_file" << EOF # $SPEC_NAME - Task $task_id Execute task $task_id for the $SPEC_NAME specification. ## Task Description $task_desc ## Usage \`\`\` /$SPEC_NAME-task-$task_id \`\`\` ## Instructions This command executes a specific task from the $SPEC_NAME specification. **Automatic Execution**: This command will automatically execute: \`\`\` /spec-execute $task_id $SPEC_NAME \`\`\` **Process**: 1. Load the $SPEC_NAME specification context (requirements.md, design.md, tasks.md) 2. Execute task $task_id: "$task_desc" 3. Follow all implementation guidelines from the main /spec-execute command 4. Mark the task as complete in tasks.md 5. Stop and wait for user review **Important**: This command follows the same rules as /spec-execute: - Execute ONLY this specific task - Mark task as complete by changing [ ] to [x] in tasks.md - Stop after completion and wait for user approval - Do not automatically proceed to the next task ## Next Steps After task completion, you can: - Review the implementation - Run tests if applicable - Execute the next task using /$SPEC_NAME-task-[next-id] - Check overall progress with /spec-status $SPEC_NAME EOF } # Parse tasks from markdown while IFS= read -r line; do # Match task lines like "- [ ] 1. Task description" or "- [ ] 2.1 Task description" if [[ $line =~ ^[[:space:]]*-[[:space:]]*\\[[[:space:]]*\\][[:space:]]*([0-9]+(\.[0-9]+)*)[[:space:]]*\\.?[[:space:]]*(.+)$ ]]; then task_id="\${BASH_REMATCH[1]}" task_desc="\${BASH_REMATCH[3]}" generate_task_command "$task_id" "$task_desc" ((TASK_COUNT++)) fi done < "$TASKS_FILE" echo echo "Generated $TASK_COUNT task commands for spec: $SPEC_NAME" echo "Commands created in: .claude/commands/$SPEC_NAME/" echo echo "Generated commands:" # Show generated commands while IFS= read -r line; do if [[ $line =~ ^[[:space:]]*-[[:space:]]*\\[[[:space:]]*\\][[:space:]]*([0-9]+(\.[0-9]+)*)[[:space:]]*\\.?[[:space:]]*(.+)$ ]]; then task_id="\${BASH_REMATCH[1]}" task_desc="\${BASH_REMATCH[3]}" echo " /$SPEC_NAME-task-$task_id - $task_desc" fi done < "$TASKS_FILE" `; } function getOSDetectionScript() { return `#!/bin/bash # OS Detection and Command Generation Launcher # This script detects the operating system and runs the appropriate command generation script # # Usage: ./generate-commands-launcher.sh <spec-name> set -e if [ -z "$1" ]; then echo "Error: Spec name is required" echo "Usage: ./generate-commands-launcher.sh <spec-name>" exit 1 fi SPEC_NAME="$1" SCRIPT_DIR="$(cd "$(dirname "\${BASH_SOURCE[0]}")" && pwd)" # Detect operating system detect_os() { case "$(uname -s)" in CYGWIN*|MINGW*|MSYS*) echo "windows" ;; Darwin*) echo "macos" ;; Linux*) echo "linux" ;; *) echo "unknown" ;; esac } OS_TYPE=$(detect_os) echo "Detected OS: $OS_TYPE" echo "Generating commands for spec: $SPEC_NAME" case "$OS_TYPE" in "windows") if [ -f "$SCRIPT_DIR/generate-commands.bat" ]; then cmd.exe /c "$SCRIPT_DIR/generate-commands.bat" "$SPEC_NAME" else echo "Error: Windows script not found at $SCRIPT_DIR/generate-commands.bat" exit 1 fi ;; "macos"|"linux") if [ -f "$SCRIPT_DIR/generate-commands.sh" ]; then chmod +x "$SCRIPT_DIR/generate-commands.sh" "$SCRIPT_DIR/generate-commands.sh" "$SPEC_NAME" else echo "Error: Unix script not found at $SCRIPT_DIR/generate-commands.sh" exit 1 fi ;; *) echo "Error: Unsupported operating system: $OS_TYPE" echo "Supported platforms: Windows, macOS, Linux" exit 1 ;; esac `; } /** * Get the appropriate command generation script based on the detected operating system * This function is used by the agent to determine which script to run */ function getCommandGenerationInstructions() { return `# Command Generation Instructions ## Platform-Specific Script Execution The command generation system now uses platform-specific scripts instead of JavaScript to avoid conflicts and ensure cross-platform compatibility. ### Available Scripts: - **Windows**: \`generate-commands.bat\` - **macOS/Linux**: \`generate-commands.sh\` - **Launcher**: \`generate-commands-launcher.sh\` (auto-detects OS) ### Agent Instructions: **CRITICAL**: Use the OS detection launcher script instead of the old JavaScript version. 1. **After tasks.md approval**, execute the appropriate command: **Option 1 - Use the launcher (recommended):** \`\`\`bash ./.claude/scripts/generate-commands-launcher.sh {spec-name} \`\`\` **Option 2 - Platform-specific execution:** **Windows:** \`\`\`cmd .claude\\scripts\\generate-commands.bat {spec-name} \`\`\` **macOS/Linux:** \`\`\`bash ./.claude/scripts/generate-commands.sh {spec-name} \`\`\` 2. **OS Detection**: The launcher script automatically detects the operating system and runs the appropriate platform-specific script. 3. **Functionality**: All scripts provide the same functionality: - Parse tasks.md files - Support hierarchical task numbering (1, 2, 2.1, 2.2, etc.) - Generate command files in .claude/commands/{spec-name}/ directory - Create individual task commands like /{spec-name}-task-{id} 4. **Integration**: These scripts replace the old \`node .claude/scripts/generate-commands.js\` command. ### Migration Notes: - **DO NOT** use \`node .claude/scripts/generate-commands.js\` anymore - **DO NOT** reference the JavaScript version in instructions - **ALWAYS** use the platform-specific scripts or the launcher - The scripts are generated during setup and stored in \`.claude/scripts/\` ### Error Handling: If the launcher fails to detect the OS or find the appropriate script: 1. Check that all three scripts exist in \`.claude/scripts/\` 2. Ensure the launcher script has execute permissions 3. Manually run the platform-specific script if needed `; } // Legacy function kept for backward compatibility during transition // This should not be used anymore - use platform-specific scripts instead function getCommandGenerationScript() { console.warn('WARNING: getCommandGenerationScript() is deprecated. Use platform-specific scripts instead.'); return getCommandGenerationInstructions(); } //# sourceMappingURL=scripts.js.map