{"content":"# Ralph Agent Loop\n\nSet up automated agent-driven development with Ralph. Run AI agents in a loop to implement features from user stories, verify acceptance criteria, and log progress for the next agent.\n\n**Install via shadcn registry:**\n\n```bash\nbunx --bun shadcn@latest add https://fullstackrecipes.com/r/ralph.json\n```\n\n**Or copy the source code:**\n\n`scripts/ralph/runner.ts`:\n\n```typescript\n#!/usr/bin/env bun\n\nimport { spawn } from \"bun\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { parseArgs } from \"node:util\";\n\nconst scriptDir = dirname(fileURLToPath(import.meta.url));\nconst promptPath = join(scriptDir, \"prompt.md\");\n\nconst { values } = parseArgs({\n  args: Bun.argv.slice(2),\n  options: {\n    \"max-iterations\": { type: \"string\", default: \"100\" },\n    prompt: { type: \"string\" },\n  },\n});\n\nasync function runRalph() {\n  const baselinePrompt = await Bun.file(promptPath).text();\n\n  const prompt = values.prompt\n    ? `${values.prompt}\\n\\n---\\n\\n${baselinePrompt}`\n    : baselinePrompt;\n\n  const maxIterations = values[\"max-iterations\"] || \"100\";\n\n  // Escape the prompt for shell\n  const escapedPrompt = prompt.replace(/'/g, \"'\\\\''\");\n\n  // Use the official Ralph plugin via /ralph-loop command\n  const ralphCommand = `/ralph-loop:ralph-loop '${escapedPrompt}' --completion-promise \"FINISHED\" --max-iterations ${maxIterations}`;\n\n  console.log(\"[runner] Starting Ralph loop via Claude Code plugin...\\n\");\n  console.log(`[runner] Max iterations: ${maxIterations}\\n`);\n\n  const proc = spawn({\n    cmd: [\n      \"sh\",\n      \"-c\",\n      `claude --permission-mode bypassPermissions --verbose '${ralphCommand.replace(/'/g, \"'\\\\''\")}'`,\n    ],\n    stdout: \"inherit\",\n    stderr: \"inherit\",\n    stdin: \"inherit\",\n  });\n\n  await proc.exited;\n\n  const exitCode = proc.exitCode ?? 0;\n  if (exitCode === 0) {\n    console.log(\"\\n[runner] Ralph loop completed successfully!\");\n  } else {\n    console.log(`\\n[runner] Ralph loop exited with code ${exitCode}`);\n  }\n\n  process.exit(exitCode);\n}\n\nrunRalph().catch((err) => {\n  console.error(\"[runner] Error:\", err);\n  process.exit(1);\n});\n```\n\n`scripts/ralph/prompt.md`:\n\n```md\n# Ralph Agent Task\n\nImplement features from user stories until all are complete.\n\n## Workflow Per Iteration\n\n1. Read `scripts/ralph/log.md` to understand what previous iterations completed.\n\n2. Search `docs/user-stories/` for features with `\"passes\": false`.\n\n3. If no features remain with `\"passes\": false`:\n   - Output: <promise>FINISHED</promise>\n\n4. Pick ONE feature - the highest priority non-passing feature based on dependencies and logical order.\n\n5. Implement the feature following TDD:\n   - Write/update tests for the feature\n   - Implement until all acceptance criteria pass\n   - Generate and migrate DB schema if needed: `bun run db:generate && bun run db:migrate`\n   - Format code: `bun run fmt`\n\n6. Verify the feature:\n   - Run typecheck: `bun run typecheck`\n   - Run build: `bun run build`\n   - Run tests: `bun run test`\n   - Use Playwright MCP to interact with the app at `http://localhost:3000`\n\n7. If verification fails, debug and fix. Repeat until passing.\n\n8. Once verified:\n   - Update the user story's `passes` property to `true`\n   - Append to `scripts/ralph/log.md` (keep it short but helpful)\n   - Commit with a descriptive message\n\n9. The iteration ends here. The next iteration will pick up the next feature.\n\n## Notes\n\n- Dev server should be running on `http://localhost:3000`. Start with `bun run dev` if needed.\n- Connected to test database - use migrate commands freely.\n- Avoid interacting with database directly.\n\n## Completion\n\nWhen ALL user stories have `\"passes\": true`, output:\n\n<promise>FINISHED</promise>\n```\n\n`scripts/ralph/log.md`:\n\n```md\n# Ralph Agent Log\n\nThis file tracks what each agent run has completed. Append your changes below.\n\n---\n\n## 2026-01-09 - Example Entry (Template)\n\n**Task:** Brief description of the task or user story worked on\n\n**Changes:**\n\n- `src/components/example.tsx` - Added new component for X\n- `src/lib/example/queries.ts` - Created query function for Y\n\n**Status:** Completed | In Progress | Blocked\n\n**Notes:** Any relevant context, blockers, or follow-up items\n\n---\n```\n\nRalph is a pattern for automated agent-driven development. It runs AI coding agents in a loop, where each agent picks up a user story, implements it, verifies it passes, and logs what it did for the next agent.\n\n## Background & References\n\n- [Ralph - Geoffrey Huntley](https://ghuntley.com/ralph/) - Original concept and implementation\n- [Effective Harnesses for Long-Running Agents - Anthropic](https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents) - Engineering patterns for agent loops\n- [Matt Pocock on Ralph](https://www.youtube.com/watch?v=_IK18goX4X8) - Video walkthrough\n\n---\n\n### Step 1: Add npm Script\n\nAdd a script to `package.json` to run Ralph:\n\n```json\n{\n  \"scripts\": {\n    \"ralph\": \"bun run scripts/ralph/runner.ts\"\n  }\n}\n```\n\n### Step 2: Install Claude Code CLI\n\nRalph uses the Claude Code CLI to spawn agent sessions. Install it globally:\n\n```bash\nnpm install -g @anthropic-ai/claude-code\n```\n\n---\n\n## Running Ralph\n\nStart the dev server in one terminal, then run Ralph:\n\n```bash\nbun run dev\n```\n\n```bash\nbun run ralph\n```\n\nRalph will:\n\n1. Read the prompt instructions\n2. Check the log for previous work\n3. Find a user story with `\"passes\": false`\n4. Implement and verify the feature\n5. Update the story to `\"passes\": true`\n6. Log what it did\n7. Repeat until all stories pass\n\nTo provide additional context or corrections:\n\n```bash\nbun run ralph --prompt \"Focus on authentication features first\"\n```\n\n---\n\n## Story Categories\n\nAdd a `category` field to help Ralph prioritize work:\n\n```json\n{\n  \"category\": \"functional\",\n  \"description\": \"User signs in with email and password\",\n  \"steps\": [\"Navigate to /sign-in\", \"Enter credentials\", \"Verify redirect\"],\n  \"passes\": false\n}\n```\n\nCategories:\n\n- `functional` - Core feature behavior (highest priority)\n- `edge-case` - Error handling and boundary conditions\n- `integration` - Features that span multiple systems\n- `ui` - Visual and interaction requirements"}