An autonomous development pipeline for iOS projects, powered by Claude Code. You describe a feature, the pipeline builds it — writing code, running tests, and enforcing quality gates in a git worktree, iteration by iteration.
Distributed as a Claude Code plugin.
/ralph-loop:spec— structured JTBD conversation produces a spec committed to aspec/<slug>branch/ralph-loop:run— orchestrates the pipeline: creates a worktree, plans the work, runs the build loop, gates the output- Build loop runs Claude (Haiku for iterations, Sonnet on escalation) autonomously: build → unit tests → static gates (code quality, architecture, security, accessibility) → lint → commit
- Post-loop gates: precise static gates → LLM gates (semantic review with blast radius analysis) → UI tests → opens a draft PR via
gh→ worktree cleanup - You review the branch and merge
Human decisions: spec approval and branch review. Everything else is automated.
The Claude Code session you run /ralph-loop:run from acts as the orchestrator — it finds the spec, creates the worktree, and kicks off loop.sh. The build loop and post-loop gates run entirely inside loop.sh as a subprocess. The orchestrator monitors the output and only steps in when something goes wrong. Use a capable model for this session (Sonnet or Opus recommended).
The build loop spawns subagents for each iteration using Haiku by default — fast and cheap for the repetitive write-build-fix cycle.
claude plugin install Olunuga/ralph-loopOr test locally during development:
claude --plugin-dir /path/to/ralph-loopOpen a Claude Code session in your iOS project root:
/ralph-loop:init
This auto-discovers your Xcode scheme, simulator, and test targets, then writes:
ralph/config.sh— build commandsralph/AGENTS.md— codebase architecture (via bootstrap)ralph/gates/— directory for custom project gates.claude/settings.json— workspace boundary hook + permissions
If you previously used /ralph-install to copy pipeline files into ralph/:
/ralph-loop:migrate
This preserves your config, AGENTS.md, and specs, moves any custom gates to ralph/gates/, and removes pipeline files now served by the plugin.
/ralph-loop:spec my-feature # describe what to build, get a spec
/ralph-loop:run my-feature # run the pipeline autonomously
A draft PR is opened automatically when all gates pass. Review the ralph/my-feature branch and mark it ready when satisfied.
Each feature runs in its own git worktree (.worktrees/<slug>) branched off the spec, keeping all in-progress changes isolated from the main working tree. The worktree is removed automatically after the post-loop gates pass.
The init skill writes a PreToolUse hook into .claude/settings.json that blocks any agent from reading or writing files outside the project directory.
The pipeline enforces quality through gates — checks that code must pass before it can be committed or merged. Gates come from two sources:
- Plugin gates — default checks shipped with the plugin (
scripts/gates/) - Project gates — custom checks in your project's
ralph/gates/directory
Project gates override plugin gates with the same filename.
Deterministic checks (grep, awk, lint, AST analysis). Fast-tier checks run every iteration; precise-tier checks run once post-loop.
scripts/gates/static/
├── code_quality/ # force unwraps, @Observable, stubs, access control, print(), etc.
├── architecture/ # layer boundaries, dependency direction, modelContext ownership
├── security/ # hardcoded secrets, insecure HTTP, NSLog, UserDefaults credentials
└── accessibility/ # missing labels, hardcoded fonts, color-only differentiation
Semantic checks that require LLM judgment — one Sonnet call per category, post-loop only.
scripts/gates/llm/
├── code_quality.md # naming clarity, SRP, feature envy, error handling, test quality
├── architecture.md # DI compliance, god objects, pattern consistency
├── security.md # data sensitivity, auth flow correctness, input validation
└── accessibility.md # label quality, nav order, custom component a11y
Drop files into your project's ralph/gates/ directory:
Static gate (ralph/gates/static/<category>/my_check.sh):
#!/bin/bash
set -euo pipefail
gate_name() { echo "My custom check"; }
gate_category() { echo "org"; }
gate_tier() { echo "fast"; }
gate_check() {
BASE_REF=$(git merge-base main HEAD 2>/dev/null || echo "HEAD~1")
# Your check logic — exit 0 = pass, exit 1 = fail
}LLM gate (ralph/gates/llm/compliance.md):
---
category: compliance
---
You are reviewing Swift code changes for [your criteria].
Respond with exactly:
1: PASS|FAIL — [reason]
OVERALL: PASS|FAILNo changes to any pipeline code needed. The dispatchers auto-discover gates from both directories.
When an LLM gate flags an architectural issue, the pipeline measures the blast radius of the affected type before attempting a fix.
| Dimension | What it measures | Low (0) | Medium (1) | High (2) |
|---|---|---|---|---|
| File fan-out | Files referencing the type | <= 5 | 6-15 | > 15 |
| Type coupling | Distinct types that depend on it | <= 3 | 4-10 | > 10 |
| Layers crossed | Architectural layers (dirs) affected | 1 | 2 | >= 3 |
| Infra reach | Directories containing references | 1-2 | 3-4 | 5+ |
| Test coupling | Test files referencing the type | <= 1 | 2-3 | > 3 |
The composite score (0-10) determines the action:
- Score 0-3 (auto): Escalate to Opus for a careful, contained fix
- Score 4-6 (conditional): Escalate to Opus, but only if the change stays within one architectural layer — otherwise defer
- Score 7-10 (defer): Create a GitHub issue labeled
tech-debtwith the gate feedback, blast radius report, and recommended refactoring approach. The gate passes — architectural improvements don't block feature delivery
Deferred issues are always saved to ralph/deferred_issues.md as a backup. Duplicate GitHub issues are detected via search before creation.
All thresholds are configurable per-project via ralph/gate_context.md:
blast_radius_fanout_thresholds: 5,15
blast_radius_coupling_thresholds: 3,10
blast_radius_layer_thresholds: 1,2
blast_radius_infra_thresholds: 2,4
blast_radius_test_thresholds: 1,3
blast_radius_auto_max: 3
blast_radius_conditional_max: 6
You can run the analysis manually:
blast_radius.sh WorkoutSession Geyns/These live in your project's ralph/ directory (not in the plugin):
| File | Created by | Purpose |
|---|---|---|
ralph/config.sh |
/ralph-loop:init |
Build commands, paths, simulator |
ralph/AGENTS.md |
loop.sh bootstrap |
Architecture and conventions |
ralph/specs/ |
/ralph-loop:spec |
Feature specifications |
ralph/gates/ |
/ralph-loop:init |
Custom project gates |
ralph/gate_context.md |
Bootstrap / manual | Gate calibration and blast radius thresholds |
ralph/lessons.md |
loop.sh |
Persistent lessons for hard problems |
ralph/deferred_issues.md |
loop.sh |
Tech debt deferred by blast radius analysis |
- macOS with Xcode
- Claude Code with plugin support
python3(ships with Xcode Command Line Tools)ghCLI (optional, for draft PR creation and tech debt issues)