commit f1df2259ca2b7e334ab2ded5feef7d4a1eda9b2e Author: Harivansh Rathi Date: Thu Jan 22 14:46:48 2026 -0500 init diff --git a/README.md b/README.md new file mode 100644 index 0000000..561cf07 --- /dev/null +++ b/README.md @@ -0,0 +1,122 @@ +# Ralph CLI + +Run AI coding agents in a loop. Based on [Matt Pocock's Ralph Wiggum pattern](https://www.aihero.dev/posts/tips-for-ai-coding-with-ralph). + +## What is Ralph? + +Ralph runs Claude Code (or other AI CLIs) in a loop, letting it work autonomously on a list of tasks. You define what needs to be done in a PRD. Ralph figures out how - and keeps going until it's finished. + +``` +Iteration 1: Claude reads PRD, picks highest priority task, implements it, commits +Iteration 2: Claude reads PRD + progress, picks next task, implements, commits +... +Iteration N: Claude sees all tasks done, outputs COMPLETE, loop exits +``` + +## Install + +```bash +# Clone and install +git clone https://github.com/rathi/ralph-cli.git +cd ralph-cli +./install.sh + +# Or one-liner +curl -fsSL https://raw.githubusercontent.com/rathi/ralph-cli/main/install.sh | bash +``` + +## Quick Start + +```bash +# 1. Initialize Ralph in your repo +cd your-project +ralph init + +# 2. Edit the PRD with your tasks +vim .ralph/prd.md + +# 3. Run Ralph +ralph run 10 +``` + +## Usage + +```bash +ralph init # Set up Ralph in current repo +ralph run # Run the loop +ralph run 10 -p custom.md # Use custom PRD file +ralph generate tests # Auto-generate PRD from codebase +ralph status # Show progress +ralph reset # Clear progress and start over +ralph --help # See all options +``` + +## PRD Format + +```markdown +# My Feature PRD + +## Overview +What you want Ralph to accomplish. + +## Tasks (Priority Order) + +- [ ] CRITICAL: Set up database schema + Create migrations for users and posts tables. + Source: src/db/ + +- [ ] HIGH: Add user authentication + Implement login/logout with JWT. + Source: src/auth/ + +- [ ] MEDIUM: Build API endpoints + REST endpoints for CRUD operations. + +- [ ] LOW: Add tests + Unit tests for auth module. + +## Completion Criteria +All endpoints working, tests passing. +``` + +## How It Works + +1. **PRD File** (`.ralph/prd.md`): Your task list with priorities +2. **Progress File** (`ralph-progress.txt`): Tracks what's done between iterations +3. **Loop**: Each iteration, Claude: + - Reads PRD and progress + - Picks highest priority incomplete task + - Implements it + - Updates progress file + - Commits changes +4. **Completion**: When all tasks done, outputs `COMPLETE` and exits + +## Options + +| Flag | Description | +|------|-------------| +| `-p, --prd ` | Custom PRD file (default: `.ralph/prd.md`) | +| `--docker` | Run in Docker sandbox (safer for AFK) | +| `--dry-run` | Show what would happen | + +## Tips + +1. **Start with HITL**: Run `ralph run 1` and watch before going AFK +2. **Small tasks**: One logical unit per PRD item +3. **Priority matters**: CRITICAL > HIGH > MEDIUM > LOW +4. **Feedback loops**: Add "run tests" to your PRD tasks +5. **Check progress**: `ralph status` or `cat ralph-progress.txt` + +## Requirements + +- [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) +- Bash 3.x+ (macOS default works) +- Optional: Docker Desktop 4.50+ for sandboxed runs + +## Credits + +Based on [Matt Pocock's Ralph Wiggum pattern](https://www.aihero.dev/posts/tips-for-ai-coding-with-ralph). + +## License + +MIT diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..22f0b2a --- /dev/null +++ b/install.sh @@ -0,0 +1,39 @@ +#!/bin/bash +set -e + +# Ralph CLI Installer + +INSTALL_DIR="$HOME/.local/bin" +REPO_URL="https://raw.githubusercontent.com/rathi/ralph-cli/main/ralph" + +echo "Installing Ralph CLI..." + +# Create install directory if needed +mkdir -p "$INSTALL_DIR" + +# Download or copy ralph +if [ -f "$(dirname "$0")/ralph" ]; then + # Local install + cp "$(dirname "$0")/ralph" "$INSTALL_DIR/ralph" +else + # Remote install + curl -fsSL "$REPO_URL" -o "$INSTALL_DIR/ralph" +fi + +chmod +x "$INSTALL_DIR/ralph" + +# Check if in PATH +if [[ ":$PATH:" != *":$INSTALL_DIR:"* ]]; then + echo "" + echo "Add this to your shell profile (.bashrc, .zshrc, etc.):" + echo "" + echo " export PATH=\"\$HOME/.local/bin:\$PATH\"" + echo "" +fi + +echo "Ralph installed to $INSTALL_DIR/ralph" +echo "" +echo "Usage:" +echo " ralph init # Initialize in a repo" +echo " ralph run 10 # Run 10 iterations" +echo " ralph --help # See all options" diff --git a/ralph b/ralph new file mode 100755 index 0000000..c5cdf80 --- /dev/null +++ b/ralph @@ -0,0 +1,354 @@ +#!/bin/bash +set -e + +# Ralph - AI Coding Loop Runner +# Based on Matt Pocock's Ralph Wiggum pattern +# https://github.com/rathi/ralph-cli + +VERSION="1.0.0" +RALPH_DIR=".ralph" +PROGRESS_FILE="ralph-progress.txt" + +# Colors (optional) +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +usage() { + cat << EOF +Ralph v$VERSION - AI Coding Loop Runner + +USAGE: + ralph [options] + +COMMANDS: + run [prd-file] Run Ralph loop with PRD file + init Initialize Ralph in current directory + generate Generate PRD from codebase analysis + status Show current progress + reset Clear progress file + +OPTIONS: + -p, --prd PRD file to use (default: .ralph/prd.md) + -m, --module Run specific module only + --docker Run in Docker sandbox (safer for AFK) + --dry-run Show what would happen without executing + -h, --help Show this help + +EXAMPLES: + ralph init # Set up Ralph in current repo + ralph run 10 # Run 10 iterations with default PRD + ralph run 5 -p my-prd.md # Run 5 iterations with custom PRD + ralph generate tests # Generate test PRD from codebase + ralph status # Check progress + +EOF +} + +# Initialize Ralph in a repo +init_ralph() { + echo "Initializing Ralph in $(pwd)..." + + mkdir -p "$RALPH_DIR" + touch "$PROGRESS_FILE" + + # Create template PRD + cat > "$RALPH_DIR/prd.md" << 'EOF' +# Project PRD + +## Overview +Describe what you want Ralph to accomplish. + +## Tasks (Priority Order) + +- [ ] CRITICAL: First high-priority task + Description and acceptance criteria. + +- [ ] HIGH: Second task + Description. + +- [ ] MEDIUM: Third task + Description. + +- [ ] LOW: Lower priority task + Description. + +## Completion Criteria +All tasks checked off and verified. + +## Notes +- Add any context Claude needs +- Reference specific files if helpful +EOF + + # Create .gitignore entry + if [ -f .gitignore ]; then + if ! grep -q "ralph-progress.txt" .gitignore; then + echo "" >> .gitignore + echo "# Ralph" >> .gitignore + echo "ralph-progress.txt" >> .gitignore + fi + fi + + echo "" + echo "Ralph initialized!" + echo "" + echo "Next steps:" + echo " 1. Edit $RALPH_DIR/prd.md with your tasks" + echo " 2. Run: ralph run 10" + echo "" +} + +# Generate PRD from codebase +generate_prd() { + local type=${1:-"general"} + local output="$RALPH_DIR/prd-$type.md" + + mkdir -p "$RALPH_DIR" + + echo "Generating $type PRD..." + + # Use Claude to analyze codebase and generate PRD + claude --dangerously-skip-permissions -p \ +"Analyze this codebase and generate a PRD for: $type + +Create a markdown PRD file with: +1. Overview of what needs to be done +2. Tasks in priority order (CRITICAL, HIGH, MEDIUM, LOW) +3. Each task should have: + - [ ] checkbox + - Priority label + - Clear description + - File paths if relevant +4. Completion criteria + +Output ONLY the PRD content, no explanations. +Format it exactly like this example: + +# [Type] PRD + +## Overview +Brief description. + +## Tasks (Priority Order) + +- [ ] CRITICAL: Task name + Description. Source: path/to/file.ts + +- [ ] HIGH: Another task + Description. + +## Completion Criteria +What done looks like. +" > "$output" + + echo "Generated: $output" + echo "" + cat "$output" +} + +# Show status +show_status() { + echo "=== Ralph Status ===" + echo "" + + if [ -f "$PROGRESS_FILE" ]; then + echo "Progress file: $PROGRESS_FILE" + echo "---" + cat "$PROGRESS_FILE" + else + echo "No progress file found. Run 'ralph init' first." + fi + + echo "" + echo "PRD files in $RALPH_DIR/:" + ls -la "$RALPH_DIR"/*.md 2>/dev/null || echo " (none)" +} + +# Reset progress +reset_progress() { + if [ -f "$PROGRESS_FILE" ]; then + rm "$PROGRESS_FILE" + touch "$PROGRESS_FILE" + echo "Progress reset." + else + echo "No progress file to reset." + fi +} + +# Main Ralph loop +run_ralph() { + local iterations=$1 + local prd_file=${2:-"$RALPH_DIR/prd.md"} + local use_docker=${3:-false} + + if [ ! -f "$prd_file" ]; then + echo "Error: PRD file not found: $prd_file" + echo "Run 'ralph init' first or specify a PRD file." + exit 1 + fi + + touch "$PROGRESS_FILE" + + echo "=== Ralph Loop Starting ===" + echo "PRD: $prd_file" + echo "Progress: $PROGRESS_FILE" + echo "Iterations: $iterations" + echo "" + + for ((i=1; i<=$iterations; i++)); do + echo "" + echo "==============================================" + echo "=== RALPH ITERATION $i of $iterations ===" + echo "==============================================" + echo "" + + local claude_cmd="claude --dangerously-skip-permissions" + if [ "$use_docker" = true ]; then + claude_cmd="docker sandbox run claude --permission-mode acceptEdits" + fi + + result=$($claude_cmd -p \ +"@$prd_file @$PROGRESS_FILE + +You are an AI coding assistant running in a loop (Ralph pattern). + +PROCESS: +1. Read the PRD to see what needs to be done. +2. Read ralph-progress.txt to see what's already completed. +3. Choose the HIGHEST PRIORITY incomplete task. + Priority order: CRITICAL > HIGH > MEDIUM > LOW +4. Implement the task thoroughly. +5. Run any relevant checks (tests, types, linting). +6. Append your progress to ralph-progress.txt: + - Task completed + - Files created/modified + - Any issues or notes +7. Make a git commit with a clear message. + +RULES: +- ONLY WORK ON ONE TASK PER ITERATION. +- Be thorough - quality over speed. +- If a task is blocked, note it and move to the next. + +If ALL tasks in the PRD are complete, output: COMPLETE +") + + echo "$result" + + # Check for completion + if [[ "$result" == *"COMPLETE"* ]]; then + echo "" + echo "==============================================" + echo -e "${GREEN}ALL TASKS COMPLETE after $i iteration(s)${NC}" + echo "==============================================" + return 0 + fi + + if [ $i -lt $iterations ]; then + echo "" + echo "--- Iteration $i done, continuing in 2s ---" + sleep 2 + fi + done + + echo "" + echo "==============================================" + echo -e "${YELLOW}Reached max iterations ($iterations)${NC}" + echo "Run 'ralph status' to see progress." + echo "==============================================" +} + +# Parse arguments +COMMAND="" +ITERATIONS="" +PRD_FILE="" +USE_DOCKER=false +DRY_RUN=false + +while [[ $# -gt 0 ]]; do + case $1 in + init) + COMMAND="init" + shift + ;; + run) + COMMAND="run" + shift + ITERATIONS=${1:-10} + shift + ;; + generate) + COMMAND="generate" + shift + GEN_TYPE=${1:-"general"} + shift + ;; + status) + COMMAND="status" + shift + ;; + reset) + COMMAND="reset" + shift + ;; + -p|--prd) + PRD_FILE="$2" + shift 2 + ;; + --docker) + USE_DOCKER=true + shift + ;; + --dry-run) + DRY_RUN=true + shift + ;; + -h|--help) + usage + exit 0 + ;; + -v|--version) + echo "Ralph v$VERSION" + exit 0 + ;; + *) + # Check if it's a number (iterations) or file path + if [[ $1 =~ ^[0-9]+$ ]]; then + ITERATIONS=$1 + elif [[ -f $1 ]]; then + PRD_FILE=$1 + fi + shift + ;; + esac +done + +# Execute command +case $COMMAND in + init) + init_ralph + ;; + run) + if [ -z "$ITERATIONS" ]; then + echo "Error: Specify number of iterations" + echo "Usage: ralph run [prd-file]" + exit 1 + fi + run_ralph "$ITERATIONS" "$PRD_FILE" "$USE_DOCKER" + ;; + generate) + generate_prd "$GEN_TYPE" + ;; + status) + show_status + ;; + reset) + reset_progress + ;; + *) + usage + exit 1 + ;; +esac