Created
January 31, 2026 22:20
-
-
Save svenmalvik/9a174835eabfc729749e2192a5b15f2e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Feature Workflow Automation | |
| # Automates the feature development workflow using Claude CLI | |
| # Based on the workflow defined in feature_workflow.md | |
| set -e # Exit on error | |
| # Configuration | |
| MAX_ITERATIONS=5 | |
| MAX_LOC=300 | |
| MAX_REFACTOR_ROUNDS=10 | |
| # Colors for output | |
| GREEN='\033[0;32m' | |
| YELLOW='\033[1;33m' | |
| RED='\033[0;31m' | |
| BLUE='\033[0;34m' | |
| NC='\033[0m' # No Color | |
| # Function to log messages | |
| log() { | |
| local message="$1" | |
| local timestamp=$(date +"%Y-%m-%d %H:%M:%S") | |
| echo -e "${BLUE}[${timestamp}]${NC} $message" | |
| } | |
| # Function to check if output contains blocking questions (not informational) | |
| has_blocking_questions() { | |
| local output="$1" | |
| # Only match questions that truly block progress - be more selective | |
| # Avoid matching informational "?" in explanations | |
| if echo "$output" | grep -qiE '(Which (approach|option|method|one)|Should I (proceed|continue|use)|Would you like me to|Ready to proceed\?|Please (choose|select)|waiting for.*input)'; then | |
| return 0 # Has blocking questions | |
| fi | |
| return 1 # No blocking questions | |
| } | |
| # Function to run Claude CLI with automatic question resolution | |
| run_claude() { | |
| local prompt="$1" | |
| local step_name="$2" | |
| local max_followups=2 # Reduced from 5 - fail fast if stuck | |
| local followup_count=0 | |
| echo "" | |
| log "${GREEN}============================================================${NC}" | |
| log "${GREEN}Step: $step_name${NC}" | |
| log "${GREEN}============================================================${NC}" | |
| echo "" | |
| # Run Claude CLI with --continue flag and capture output | |
| log "${YELLOW}⟳ Executing Claude CLI command...${NC}" | |
| log "${YELLOW}Prompt: ${NC}$prompt" | |
| echo "" | |
| local output | |
| output=$(claude -p "$prompt" --continue 2>&1 | tee /dev/tty) | |
| # Check if output contains blocking questions and auto-answer them | |
| while has_blocking_questions "$output" && [ $followup_count -lt $max_followups ]; do | |
| followup_count=$((followup_count + 1)) | |
| log "${YELLOW}⟳ Detected blocking question, auto-selecting (followup $followup_count/$max_followups)...${NC}" | |
| local followup_prompt="STOP ASKING QUESTIONS. Choose option 1 (or the first/recommended option) and execute it NOW. | |
| Do not explain options. Do not ask for confirmation. Do not present alternatives. | |
| Just proceed with the implementation using the simplest approach that works in this session." | |
| log "${YELLOW}Followup Prompt: ${NC}$followup_prompt" | |
| echo "" | |
| output=$(claude -p "$followup_prompt" --continue 2>&1 | tee /dev/tty) | |
| done | |
| if [ $followup_count -ge $max_followups ]; then | |
| log "${YELLOW}⚠ Reached max followups ($max_followups), proceeding to next step${NC}" | |
| fi | |
| log "${GREEN}✓ Step '$step_name' completed${NC}" | |
| } | |
| # Function to sanitize filename | |
| sanitize_filename() { | |
| echo "$1" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/-\+/-/g' | cut -c1-50 | |
| } | |
| # Function to find code files exceeding MAX_LOC | |
| # Returns list of files with their line counts | |
| find_long_files() { | |
| local folder="$1" | |
| local max_lines="$2" | |
| # Find common code file extensions, count lines, filter by threshold | |
| find "$folder" -type f \( \ | |
| -name "*.go" -o -name "*.py" -o -name "*.js" -o -name "*.ts" -o \ | |
| -name "*.jsx" -o -name "*.tsx" -o -name "*.java" -o -name "*.c" -o \ | |
| -name "*.cpp" -o -name "*.h" -o -name "*.hpp" -o -name "*.rs" -o \ | |
| -name "*.rb" -o -name "*.php" -o -name "*.swift" -o -name "*.kt" -o \ | |
| -name "*.scala" -o -name "*.cs" -o -name "*.sh" -o -name "*.bash" \ | |
| \) 2>/dev/null | while read -r file; do | |
| local lines=$(wc -l < "$file" 2>/dev/null | tr -d ' ') | |
| if [ "$lines" -gt "$max_lines" ]; then | |
| echo "$file:$lines" | |
| fi | |
| done | |
| } | |
| # Main function | |
| main() { | |
| if [ $# -ne 1 ]; then | |
| echo "Usage: $0 <spec_file.md>" | |
| echo "Example: $0 docs/specs/my-feature-spec.md" | |
| exit 1 | |
| fi | |
| local spec_file="$1" | |
| # Validate spec file exists | |
| if [ ! -f "$spec_file" ]; then | |
| echo -e "${RED}Error: Specification file not found: $spec_file${NC}" | |
| exit 1 | |
| fi | |
| # Create project folder based on spec filename | |
| local spec_basename=$(basename "$spec_file" .md) | |
| local project_folder="projects/${spec_basename}" | |
| mkdir -p "$project_folder" | |
| log "${BLUE}========================================${NC}" | |
| log "${BLUE}Feature Workflow Automation${NC}" | |
| log "${BLUE}========================================${NC}" | |
| log "Spec File: $spec_file" | |
| log "Project Folder: $project_folder" | |
| echo "" | |
| # Phase 1: Planning | |
| log "${BLUE}========================================${NC}" | |
| log "${BLUE}PHASE 1: PLANNING${NC}" | |
| log "${BLUE}========================================${NC}" | |
| # Instruction suffix to prevent questions | |
| local NO_QUESTIONS="IMPORTANT: Do not ask questions or present options. Make autonomous decisions. Use the simplest approach that works in the current session. Proceed immediately." | |
| # Step 1: Create Implementation Plan | |
| run_claude "Read the specification file at $spec_file and create a detailed implementation plan based on it. All new code files must be created in the folder: $project_folder. Use the superpowers:writing-plans skill if available. $NO_QUESTIONS" "Create Implementation Plan" | |
| # Step 2: Add Skill Application to Plan | |
| run_claude "Add todo items to the plan for applying these skills after implementation: coding skill, security skill, and tracing skill. $NO_QUESTIONS" "Add Skill Applications to Plan" | |
| # Step 3: Implement the Plan | |
| run_claude "Start implementing the plan you created. Remember: all new code files must be created in the folder: $project_folder. $NO_QUESTIONS" "Implement the Plan" | |
| # Phase 2: Test-Fix Loop | |
| log "" | |
| log "${BLUE}========================================${NC}" | |
| log "${BLUE}PHASE 2: TEST-FIX LOOP${NC}" | |
| log "${BLUE}========================================${NC}" | |
| for iteration in $(seq 1 $MAX_ITERATIONS); do | |
| log "" | |
| log "${YELLOW}⟳ Test-Fix Iteration $iteration/$MAX_ITERATIONS${NC}" | |
| # Step A: Test from user perspective and analyze results | |
| log "" | |
| log "${GREEN}============================================================${NC}" | |
| log "${GREEN}Step: Test Feature (Iteration $iteration)${NC}" | |
| log "${GREEN}============================================================${NC}" | |
| echo "" | |
| local test_prompt="Test the implemented feature from a user's perspective. Run the code/script as if you were the end user. After testing, you MUST end your response with exactly one of these lines: | |
| TEST_RESULT: PASS | |
| or | |
| TEST_RESULT: FAIL | |
| Use PASS only if all tests succeed with no errors. Use FAIL if there are any errors, failures, or issues. $NO_QUESTIONS" | |
| log "${YELLOW}⟳ Executing Claude CLI command...${NC}" | |
| log "${YELLOW}Prompt: ${NC}$test_prompt" | |
| echo "" | |
| local test_output | |
| test_output=$(claude -p "$test_prompt" --continue 2>&1 | tee /dev/tty) | |
| # Analyze the test output for pass/fail | |
| if echo "$test_output" | grep -q "TEST_RESULT: PASS"; then | |
| log "${GREEN}✓ All tests passed on iteration $iteration!${NC}" | |
| break | |
| fi | |
| log "${RED}✗ Tests failed on iteration $iteration. Attempting fixes...${NC}" | |
| # Step C: Fix errors found | |
| run_claude "Fix the errors you found during testing. $NO_QUESTIONS" "Fix Errors (Iteration $iteration)" | |
| # Step D: Apply skills (separate calls) | |
| run_claude "Use the coding skill to review the code. All warnings must be fixed - do not leave any compiler warnings, linter warnings, or code quality warnings unresolved. $NO_QUESTIONS" "Apply Coding Skill (Iteration $iteration)" | |
| run_claude "Use the security skill to check for vulnerabilities. $NO_QUESTIONS" "Apply Security Skill (Iteration $iteration)" | |
| run_claude "Use the tracing skill to add proper logging/tracing. $NO_QUESTIONS" "Apply Tracing Skill (Iteration $iteration)" | |
| run_claude "Use the code simplification skill to clean up the code. $NO_QUESTIONS" "Apply Code Simplification Skill (Iteration $iteration)" | |
| done | |
| # Phase 3: File Length Check Loop | |
| log "" | |
| log "${BLUE}========================================${NC}" | |
| log "${BLUE}PHASE 3: FILE LENGTH CHECK${NC}" | |
| log "${BLUE}========================================${NC}" | |
| log "Checking for code files exceeding $MAX_LOC lines..." | |
| local refactor_round=0 | |
| while [ $refactor_round -lt $MAX_REFACTOR_ROUNDS ]; do | |
| refactor_round=$((refactor_round + 1)) | |
| # Find all long files | |
| local long_files=$(find_long_files "$project_folder" "$MAX_LOC") | |
| if [ -z "$long_files" ]; then | |
| log "${GREEN}✓ All code files are under $MAX_LOC lines!${NC}" | |
| break | |
| fi | |
| # Count how many long files | |
| local file_count=$(echo "$long_files" | wc -l | tr -d ' ') | |
| log "${YELLOW}⟳ Refactor Round $refactor_round/$MAX_REFACTOR_ROUNDS - Found $file_count file(s) exceeding $MAX_LOC lines:${NC}" | |
| echo "$long_files" | while read -r entry; do | |
| local filepath=$(echo "$entry" | cut -d: -f1) | |
| local linecount=$(echo "$entry" | cut -d: -f2) | |
| log " ${RED}• $filepath ($linecount lines)${NC}" | |
| done | |
| # Build a list of files for Claude to refactor | |
| local file_list=$(echo "$long_files" | cut -d: -f1 | tr '\n' ' ') | |
| run_claude "The following code files exceed $MAX_LOC lines and need to be refactored into smaller, focused modules: | |
| $long_files | |
| For each file: | |
| 1. Split it into multiple smaller files (each under $MAX_LOC lines) | |
| 2. Extract logical components, utilities, or handlers into separate files | |
| 3. Update imports/exports to maintain functionality | |
| 4. Ensure no circular dependencies are created | |
| 5. Keep related code together in the same file | |
| $NO_QUESTIONS" "Refactor Long Files (Round $refactor_round)" | |
| # Verify the refactoring didn't break anything | |
| run_claude "Run a quick smoke test to verify the refactored code still works correctly. $NO_QUESTIONS" "Verify Refactoring (Round $refactor_round)" | |
| done | |
| if [ $refactor_round -ge $MAX_REFACTOR_ROUNDS ]; then | |
| local remaining=$(find_long_files "$project_folder" "$MAX_LOC") | |
| if [ -n "$remaining" ]; then | |
| log "${RED}⚠ Warning: Max refactor rounds reached. Some files still exceed $MAX_LOC lines:${NC}" | |
| echo "$remaining" | while read -r entry; do | |
| log " ${RED}• $entry${NC}" | |
| done | |
| fi | |
| fi | |
| # Phase 4: Final Instructions | |
| log "" | |
| log "${BLUE}========================================${NC}" | |
| log "${BLUE}PHASE 4: FINAL INSTRUCTIONS${NC}" | |
| log "${BLUE}========================================${NC}" | |
| run_claude "Provide clear instructions for the user on how to test and run what you implemented. Include: 1) Prerequisites or dependencies needed, 2) Step-by-step commands to run the feature, 3) Expected output or behavior, 4) Any configuration or environment variables required. Format as a clear, actionable guide. $NO_QUESTIONS" "Provide Testing and Running Instructions" | |
| # Summary | |
| log "" | |
| log "${BLUE}========================================${NC}" | |
| log "${BLUE}WORKFLOW SUMMARY${NC}" | |
| log "${BLUE}========================================${NC}" | |
| log "Spec File: $spec_file" | |
| log "Project Folder: $project_folder" | |
| log "${BLUE}========================================${NC}" | |
| } | |
| # Run main function | |
| main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment