blog/ralph-autonome-claude-code-loop.mdx
Alle notities

29 april 2026

Ralph: Claude Code autonoom in een loop, dit is de complete setup

Geoffrey Huntley noemde het patroon naar Ralph Wiggum: schattig, meedogenloos volhardend. Je zet een coding agent in een `while true` loop: hij pakt de eerste unchecked taak uit een Markdown PRD, implementeert die, vinkt de checkbox aan, commit, sluit af. De shell loop wekt hem weer. Ik richtte het op een PRD met 127 taken voor een migratie, binnen een OrbStack sandbox met `--dangerously-skip-permissions`, en liet het 3 uur draaien. Echte kosten (€2,50 voor de eerste 3 iteraties), het exacte Dockerfile, en de 5 valkuilen waar niemand je voor waarschuwt.

Wie regelmatig met een coding agent werkt, kent het ritme: je geeft een opdracht, de agent doet iets, stopt, en kijkt jou weer aan. Jij leest het resultaat, keurt het goed, formuleert de volgende opdracht. Dat werkt prima voor tien taken. Bij een takenlijst van 127 items ben jij de flessenhals, en zit je een hele avond op OK te klikken.

In AI-devkringen gaat een patroon rond dat daar rigoureus mee breekt: Ralph. Geoffrey Huntley vernoemde het naar Ralph Wiggum uit The Simpsons, het jongetje dat schattig en meedogenloos volhardend is. Het idee is precies dat: in plaats van een coding agent te vragen één ding te doen en dan te stoppen, zet je hem in een while true loop. Hij pakt de volgende taak, doet die, markeert hem als klaar, sluit af. Het shell script start hem opnieuw op. Verse context. Volgende taak.

Het klinkt dom. Dat is het grotendeels ook. Dat is precies de bedoeling.

Deze post is de praktische versie, zonder gewauwel: hoe ik Ralph zelf heb opgezet, op een echt project heb losgelaten (een PRD met 127 taken voor een migratie; PRD staat voor Product Requirements Document, in dit geval simpelweg een Markdown-takenlijst met checkboxes), en drie uur heb laten draaien terwijl ik koffie dronk en e-mails beantwoordde. Ik behandel:

  1. Wat Ralph precies is en waarom het patroon werkt
  2. De volledige sandboxsetup met OrbStack in plaats van Docker Desktop
  3. Het exacte Dockerfile, loop.sh en run.sh die ik gebruikte
  4. Wat drie iteraties opleverden en hoe goed de code daadwerkelijk was
  5. Wat het kostte (echte cijfers, geen vage schattingen)
  6. De vijf valkuilen waar niemand je voor waarschuwt
  7. Wanneer deze techniek een goed idee is, en wanneer je er beter afblijft

Ralph sandbox architecture, host on the left with .env, Dockerfile, run.sh, loop.sh and the project repo, OrbStack container on the right with /workspace mounted read-write, /loop.sh mounted read-only, and ANTHROPIC_API_KEY injected as env var, the bottom shows the 6-step loop cycle: read PRD, find first unchecked task, implement, flip checkbox and commit, exit, loop wakes

Wat Ralph precies is

De meeste agentic workflows werken zo: je vraagt een model iets te doen, het roept een paar tools aan, produceert een antwoord en de loop stopt. Zelfs multi-step agents stoppen zodra het model besluit dat het klaar is. Het model bepaalt zelf wanneer het klaar is, en dat is meteen zijn grootste blinde vlek.

Ralph verwerpt dat idee: niet het model bepaalt of het werk af is, maar iets daarbuiten. Concreet gaat het om de [ ] checkboxes die nog in je takenlijst staan. Je roept de agent aan, hij kiest er een, werkt eraan, vinkt de box aan naar [x], commit en sluit af. De shell loop wordt weer wakker, ziet dat er nog [ ] boxes over zijn, en draait de agent opnieuw met een schone context.

De eigenschappen die uit dit ontwerp voortvloeien zijn verrassend krachtig:

  • Verse context per taak. Token bloat, lost-in-the-middle problemen, en tegenstrijdige plannen tussen beurten verdwijnen allemaal, omdat er niets van de vorige beurt overblijft behalve wat naar de schijf is geschreven.
  • Verifieerbare voortgang. Elke taak = één git commit. Als het model een fake voltooiing hallucineert, zie je dat direct in de diff.
  • Goedkope retries. Als een taak faalt, probeert de volgende iteratie het gewoon opnieuw met het gedeeltelijke werk als context. Er is geen dure herplanningsstap nodig.
  • Pauzeren/hervatten is gratis. Zet een STOP-bestand neer of druk op Ctrl-C in de terminal. Start de volgende ochtend opnieuw. De state zit gewoon in de repo.

Het verschil met een gewone interactieve sessie in één oogopslag:

Handmatige agent-sessieRalph loop
Wie bepaalt “klaar”Het model, of jij per beurtDe checkboxlijst buiten het model
ContextGroeit de hele sessie doorVers per taak
VoortgangChatgeschiedenisÉén git commit per taak
Jouw rolContinu meekijken en goedkeurenAchteraf diffs reviewen
Als het misgaatSessie ontspoort, jij grijpt inÉén iteratie mislukt, de volgende probeert opnieuw

Geoffrey Huntley beweert, half schertsend en half serieus, dat “alles een Ralph loop is.” Ik denk dat de eerlijke claim beperkter is: telkens wanneer je een lange, goed gedefinieerde takenlijst hebt en geen continuïteit tussen taken nodig hebt, verslaat Ralph het handmatig aansturen van een coding agent.

Waarom ik het wilde draaien

Ik had zo’n PRD liggen in een verse GitHub repo: 15 fases, 127 individuele taken, meestal het soort werk dat mechanisch is, maar niet over te slaan. SQLAlchemy models. Alembic migraties. JWT auth scaffolding. Hetzelfde patroon, tientallen keren herhaald.

Dit is precies het werk dat ik niet om 8 uur ’s avonds op een vrijdag wil doen, en precies het werk dat ik niet aan één one-shot LLM call durf toe te vertrouwen. Dus: Ralph.

De PRD was hiervoor perfect gestructureerd. Elke taak was al een Markdown checkbox onder een duidelijke faseheader. Ik hoefde niets te converteren.

## Fase 1 · Foundation

- [ ] Nieuw project scaffolden: lege Next.js + FastAPI repo met naam "leadforge"
- [ ] `Agency` model aanmaken in `database.py`: id (UUID PK), name, slug...
- [ ] Alembic migratie `001_initial_schema.py` aanmaken met Agency tabel

Dat is het invoerformaat waar Ralph in floreert. Geen semantische onduidelijkheid. Geen “bedenk zelf wat er hierna gebouwd moet worden,” gewoon de lijst afwerken.

Waarom je een sandbox nodig hebt

Een sandbox is een afgeschermde omgeving waarin de agent vrij mag schrijven, maar niets daarbuiten kan aanraken. Waarom dat hier geen luxe is maar noodzaak, is het onderdeel dat mensen verrast: Ralph draait met --dangerously-skip-permissions ingeschakeld in Claude Code. Die flag doet precies wat hij zegt. De agent stopt niet om toestemming te vragen voordat hij bestanden verwijdert, shell commando’s draait, packages installeert, of netwerkverzoeken doet.

Zonder die flag werkt de loop niet. Het model zou vastlopen bij de eerste prompt die om goedkeuring van de gebruiker vraagt. Met die flag heb je een agent die zonder aarzelen rm -rf draait op plekken waar dat beslist niet de bedoeling is.

Dit betekent dat de sandbox geen optionele versiering is. Het is het enige dat tussen Ralph en je home directory staat. Behandel het ook zo.

Er zijn een paar manieren om die grens te trekken:

AanpakIsolatieSetup-kostenOordeel
Docker container (elke runtime)Process namespaces, mount-gecontroleerde bestandssysteemtoegangLaagGoed genoeg voor de meeste gevallen
Docker Desktop’s docker sandbox (4.50+)MicroVM (KVM)Laag, maar alleen Docker DesktopSterkst, overkill voor indie gebruik
Gewone VM (UTM, Parallels, OrbStack VM)Volledige kernel isolatieGemiddeldSterk, maar lastiger te koppelen aan je editor
Geen sandboxGeenNulDoe dit niet

Ik koos voor een gewone Docker container in OrbStack. De reden: OrbStack is aanzienlijk sneller dan Docker Desktop op Apple Silicon, gebruikt een fractie van het RAM, en biedt 99% van de beveiligingsgrens die je nodig hebt voor een coding agent. Het gat van 1% (microVM vs namespace-isolatie) doet er alleen toe als Claude een kernel exploit gaat schrijven. Als dat gebeurt, is je sandbox-keuze het kleinste van je problemen.

De setup, stap voor stap

De hele setup bestaat uit twee mappen. De buitenste map is het harness, de besturing om de agent heen: Dockerfile, scripts, secrets. De binnenste map is het project (een normale git repo). Alleen de binnenste map wordt in de container gemount, zodat Ralph niets anders op de host kan aanraken.

/Users/me/new-tech-stack/         <- harness (host-only)
├── Dockerfile                    <- sandbox image
├── run.sh                        <- launcher
├── loop.sh                       <- de Ralph loop
├── .env                          <- ANTHROPIC_API_KEY (gitignored)
└── new-tech-stack/               <- het project (gemount als /workspace)
    ├── .git/
    ├── PRD.md                    <- bron van waarheid (de takenlijst)
    └── progress.txt              <- Ralph voegt één regel per taak toe

Stap 1: OrbStack installeren

brew install --cask orbstack
open -a OrbStack

OrbStack registreert zichzelf als de Docker daemon. De CLI blijft ongewijzigd. Elk docker run commando blijft werken.

Stap 2: het Dockerfile

De image is gewoon Node 22 met Claude Code geïnstalleerd en een non-root user.

FROM node:22-bookworm-slim

RUN apt-get update && apt-get install -y --no-install-recommends \
      git curl ca-certificates ripgrep jq less ssh-client \
      python3 python3-pip python3-venv \
    && rm -rf /var/lib/apt/lists/*

RUN npm install -g @anthropic-ai/claude-code

USER node
WORKDIR /workspace

CMD ["bash"]

Twee opmerkingen die je debugtijd besparen:

  1. Draai als non-root user. Claude Code weigert te draaien met --dangerously-skip-permissions als root. De eerste keer dat ik dit probeerde, crashte elke iteratie met de melding cannot be used with root/sudo privileges for security reasons. Overschakelen naar USER node (UID 1000, ingebakken in de officiële Node image) loste het meteen op.
  2. Installeer ook Python en pip. Zelfs als je project JavaScript is, roept Claude Code vaak Python aan voor data parsing of eenmalige scripts. 200MB besparen op de imagegrootte is niet de moeite waard als je daarmee een tool verliest die de agent wil gebruiken.

Stap 3: de loop

loop.sh draait binnen de container. Het is het eigenlijke Ralph-mechanisme.

#!/usr/bin/env bash
set -uo pipefail
cd /workspace

ITER=0
MAX_ITER="${MAX_ITER:-50}"
SLEEP_SECONDS="${SLEEP_SECONDS:-10}"

git config --global --add safe.directory /workspace
git config --global user.name "Ralph"
git config --global user.email "ralph@local"

read -r -d '' RALPH_PROMPT <<'EOF' || true
You are Ralph, an autonomous coding agent.

PROCEDURE:
1. Read PRD.md and progress.txt.
2. Find the FIRST unchecked task in PRD.md (`- [ ]`).
3. Implement that ONE task fully. No skipping.
4. Mark it `- [x]`, append a line to progress.txt, commit.
5. Exit.

If PRD.md has zero unchecked tasks, run `touch STOP` and exit.

HARD RULES:
- NEVER read /workspace/.env or print ANTHROPIC_API_KEY.
- Stay inside /workspace.
- Local commits only, do not push.
- One task = one commit.
EOF

while [ "$ITER" -lt "$MAX_ITER" ]; do
  ITER=$((ITER + 1))
  echo "[ralph] iteration $ITER / $MAX_ITER"

  [ -f STOP ] && exit 0

  REMAINING=$(grep -c '^- \[ \]' PRD.md || true)
  echo "[ralph] $REMAINING unchecked tasks remain"
  [ "$REMAINING" -eq 0 ] && touch STOP && exit 0

  claude -p "$RALPH_PROMPT" --dangerously-skip-permissions || true

  sleep "${SLEEP_SECONDS}"
done

Een paar dingen in dit script zijn het vermelden waard:

  • set -uo pipefail niet set -euo. We stoppen bewust niet bij fouten. Als een Claude-aanroep faalt, willen we dat loggen en het bij de volgende iteratie opnieuw proberen, niet de hele loop stopzetten.
  • git config --global --add safe.directory /workspace is nodig omdat de gemounte .git directory een ander eigenaarschap heeft binnen de container dan erbuiten. Zonder dit faalt elk git commando binnen de loop met “dubious ownership.”
  • De prompt zelf is een heredoc zodat we ons nooit zorgen hoeven te maken over quoting of escaping.

Stap 4: de launcher

run.sh draait op de host. Het bouwt de image indien nodig en start dan de container met de juiste mounts.

#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "$0")"

IMAGE="ralph-sandbox:latest"

# Build once
if ! docker image inspect "$IMAGE" >/dev/null 2>&1; then
  docker build -t "$IMAGE" .
fi

docker run --rm -it \
  --name ralph \
  --env-file .env \
  -e MAX_ITER="${MAX_ITER:-50}" \
  -v "$(pwd)/new-tech-stack":/workspace \
  -v "$(pwd)/loop.sh":/loop.sh:ro \
  -w /workspace \
  "$IMAGE" \
  bash /loop.sh

De veiligheid zit hem in de mount-strategie:

  • Project gemount als read-write op /workspace: Ralph kan hier schrijven, dat is het hele punt.
  • Loopscript gemount als read-only op /loop.sh: Ralph kan niet per ongeluk zijn eigen driver herschrijven.
  • Referentiecodebase gemount als read-only (in mijn geval een oud project waarvan ik migreerde): de agent kan het lezen ter inspiratie, maar niet aanpassen.
  • .env doorgegeven als omgevingsvariabelen, niet als bestandsmount. Dit betekent dat de agent de waarde van ANTHROPIC_API_KEY uit zijn omgeving kan lezen maar niet het daadwerkelijke .env-bestand van de schijf kan lezen, wat een veelvoorkomende route afsnijdt waarlangs secrets naar buiten lekken (in het vak: een exfiltratievector).

Dat laatste detail doet ertoe. Met --dangerously-skip-permissions moet je ervan uitgaan dat de agent in staat is je API-key te lekken (naar een log printen, in een commit message stoppen, naar een webhook posten). De defense-in-depth-tactiek hier is om het secret via een kanaal te sturen dat de agent niet kan doorzoeken.

Wat Ralph daadwerkelijk bouwde

Ik draaide MAX_ITER=3 ./run.sh voor een sanity check. Drie iteraties, drie minuten wall time per iteratie, en de output was, eerlijk gezegd, beter dan ik verwachtte.

Iteratie 1 zette de complete monorepo neer (één repository met backend en frontend samen):

  • backend/ met FastAPI main.py, SQLAlchemy 2.0 database.py, requirements.txt met tien vastgepinde production dependencies, een Dockerfile, een railway.toml, en een volledig werkende Alembic-configuratie.
  • frontend/ met Next.js 15 App Router, TypeScript, Tailwind, een multi-stage Dockerfile, een Railway config, en output: "standalone" voor productiebuilds.
  • Een root-level docker-compose.yml voor Postgres 16 plus beide services voor lokale ontwikkeling.

24 bestanden, 404 regels code, één commit message: feat(fase-1): scaffold monorepo with FastAPI backend, Next.js frontend, Railway config, and Alembic setup.

Iteratie 2 voegde één SQLAlchemy model toe. Moderne syntax, type-geannoteerde Mapped[] kolommen, UUID primary key, JSONB kolom met een default factory, timezone-aware created_at. Ongeveer zoals een competente senior het zou schrijven.

Iteratie 3 schreef de Alembic migratie die bij dat model past. Correcte upgrade en downgrade paden, benoemde unique constraint, aparte index. Het soort migratie dat niet herschreven hoeft te worden voordat het live gaat.

Drie commits, drie taken, drie checkboxes aangevinkt. In de PRD staat nu 124 unchecked tasks remain.

De kwaliteitscheck

Voordat ik het ging vieren, deed ik de saaie maar noodzakelijke review:

cd new-tech-stack
git log --stat origin/main..HEAD               # diff overview
grep -rni "forbidden-term" backend/ frontend/   # forbidden refs
git diff origin/main..HEAD -- '*.env*'          # any secrets leaked?

Alles schoon. Geen achtergebleven branding van de bron-codebase, geen per ongeluk gecommitte secrets, geen overduidelijke rommelbestanden. Ralph respecteerde de verboden in CLAUDE.md (het instructiebestand op projectniveau) zonder dat ik erbovenop zat.

Één minpuntje: Ralph faket de timestamps in progress.txt in plaats van date -u te draaien om de echte UTC-tijd te krijgen. Geen correctheidsprobleem, gewoon een klein eerlijkheidsprobleempje. Makkelijk op te lossen door de prompt aan te scherpen met “gebruik de output van date -u +%Y-%m-%dT%H:%M:%SZ, verzin niets.”

De kostenrealiteit

Drie iteraties van Sonnet 4.6 kostten me ongeveer €2,50. Het merendeel daarvan (€1,20) was de scaffold-iteratie, waarbij Claude Code veel referentiemateriaal leest om te achterhalen hoe een “moderne Next.js + FastAPI monorepo” er in 2026 uitziet. Iteraties 2 en 3 kwamen onder €0,40 elk uit, vooral omdat de relevante context inmiddels al in de workspace stond.

Geëxtrapoleerd naar de volledige PRD van 127 taken, met prompt caching meegerekend (de caching van Claude Code is agressief: je krijgt doorgaans 70-90% van de inputtokens uit cache geserveerd tegen €0,30/M in plaats van €3/M):

ScenarioKosten per taakTotaal 127 taken
Beste geval (kleine taken, vroege fases, weinig retries)€0,40~€50
Realistisch (gemengde taken, af en toe een retry)€0,80~€100-200
Slechtste geval (grote taken laat in de PRD, repo groeit naar 50k+ LoC)€2,50~€300+

Het slechtste geval is reëel. Taken die laat in de PRD staan, hebben te maken met een project dat inmiddels flink is gegroeid; Claude moet dan meer bestaande code herlezen om zijn werk te doen. Als je repo verdubbelt in grootte tegen de tijd dat je Fase 12 bereikt, verwacht dan dat die taken ruwweg twee keer zo duur zijn als de vroege.

Ter vergelijking: Geoffrey Huntley rapporteert ongeveer $1500/maand uit te geven aan zijn lopende Ralph-experimenten. Hij draait veel langere loops op veel grotere codebases met retry-zware taken. Een gefocuste run van 127 taken op een schone PRD is een ordegrootte kleiner.

Stel een dagelijks bestedingslimiet in de Anthropic console in voordat je begint. Ik kan dit niet genoeg benadrukken. Een MAX_ITER=200 loop die vastloopt doordat hij steeds opnieuw dezelfde onmogelijke taak probeert, kan een creditcard sneller leegtrekken dan enige redelijke monitoring kan opvangen.

Vijf valkuilen waar niemand je voor waarschuwt

1. De valkuil van de root user

Claude Code weigert te draaien met --dangerously-skip-permissions als root. Dit is een bewuste veiligheidscheck. Als de WORKDIR van je container onder root draait (de standaard bij de meeste base images), faalt elke iteratie stilzwijgend. Gebruik USER node of maak je eigen non-root user aan.

2. Git en “dubious ownership”

Als je een repo vanaf je Mac bind-mount in een Linux-container, komen de UID’s van bestandseigendom niet overeen tussen host en container. Git weigert standaard om met zulke repo’s te werken. De fix is één regel:

git config --global --add safe.directory /workspace

Zet dit in loop.sh, niet in het Dockerfile, want de mount bestaat alleen tijdens runtime.

3. API-key-hygiëne

Als je je API-key plakt in een chat, een Slackkanaal, een screenshot, of iets anders dat gelogd of gebackupt wordt, roteer hem onmiddellijk. Twee keer in dit project moest ik mezelf eraan herinneren: een gelekte key in een privéchat is nog steeds een gelekte key. De Anthropic-console maakt roteren triviaal (het duurt 20 seconden), en de kosten van paranoia zijn veel lager dan die van een op hol geslagen agent met andermans gecompromitteerde credentials.

4. De valkuil van de self-push

Laat Ralph niet naar GitHub pushen. Laat hem alleen lokaal committen. Pushen vereist een personal access token of een SSH-key binnen de sandbox, en zodra je die beschikbaar maakt voor een --dangerously-skip-permissions agent, heb je de schade die hij maximaal kan aanrichten (de blast radius) verbreed van “bestanden in /workspace” naar “alles waartoe je GitHub-toegang hebt.” Draai git push origin main zelf nadat je de diffs hebt gecontroleerd.

5. De “dezelfde taak voor altijd”-loop

Als je PRD een taak bevat die te vaag of onverifieerbaar is, gaat Ralph ermee aan de slag maar kan zichzelf niet overtuigen dat hij klaar is. De checkbox blijft op [ ] staan, en de volgende iteratie probeert het gewoon opnieuw. Voor altijd, tot je portemonnee leeg is. Twee verdedigingen:

  • Maak taken specifiek en observeerbaar. “Voeg een /health endpoint toe” is prima. “Verbeter error handling” is onverifieerbaar: er is geen punt waarop het aantoonbaar af is.
  • Beperk het aantal iteraties. MAX_ITER=50 is een goede standaard. Als Ralph je PRD niet in 50 pogingen kan afronden, heb je een ander probleem dan runtime.

Wanneer je dit gebruikt (en wanneer niet)

Ralph is het juiste gereedschap wanneer:

  • Je een lange, goed gedefinieerde takenlijst hebt die grotendeels mechanische uitvoering is.
  • Elke taak klein en onafhankelijk genoeg is om in één Claude context te passen.
  • Het werk duidelijke voltooiingscriteria heeft: de taak is af of niet.
  • Je commit-batches kunt reviewen met dezelfde inspanning als een normale pull request.

Ralph is het verkeerde gereedschap wanneer:

  • Het werk cross-task geheugen of ontwerpcontinuïteit nodig heeft (Ralph vergeet alles tussen iteraties).
  • De taken exploratief zijn (“bedenk de juiste aanpak voor X”).
  • De codebase subtiele invarianten heeft die de agent niet uit de code kan afleiden.
  • Je een mens in de loop nodig hebt bij elke wijziging, om compliance-, review- of productredenen.

Voor migraties, scaffolds, repetitieve refactors, testgeneratie, en het meeste “boilerplate met structuur”-werk, is Ralph in mijn ervaring oprecht transformatief. Voor greenfield productontwerp wil je nog steeds zelf achter het stuur zitten.

Voor wie is dit nu interessant?

Mijn indruk van de Nederlandse markt: de meeste devteams gebruiken AI inmiddels in de editor, als autocomplete of chatvenster, soms als agent waar je live naast zit. Volledig autonome loops zoals Ralph zijn hier nog zeldzaam. Dat is geen achterstand om je voor te schamen, maar wel een kans: het gereedschap is er, de kosten zijn overzichtelijk, en de leercurve is een middag.

  • Nu interessant voor: teams met een migratie of legacy-conversie op de plank, bureaus die hetzelfde type project vaker bouwen, en iedereen met een achterstand in tests of boilerplate. Precies het werk dat mechanisch is maar niet overgeslagen kan worden.
  • Nog even niet voor: teams zonder reviewdiscipline of testdekking (Ralph produceert commits, iemand moet ze kunnen lezen), bedrijfskritische systemen zonder vangnet, en organisaties waar niemand een diff kan beoordelen. Zonder review is een autonome agent geen versneller maar een risico.
  • Realistische eerste stap: schrijf een PRD van tien kleine, verifieerbare taken voor een zijproject, zet de sandbox uit dit artikel op, stel een bestedingslimiet in en draai MAX_ITER=3. Dat kost een middag en een paar euro, en daarna weet je of dit iets voor jouw werk is.

Wat dit betekent voor 2026

Hierachter schuilt een dieper punt. Coding agents worden in hoog tempo goedkoper, sneller en capabeler. Mijn inschatting is dat het knelpunt voor autonoom werk daardoor verschuift: steeds minder de modelcapaciteit, steeds meer de omringende harness. Het protocol dat beslist wanneer het model aangeroepen wordt, welke context het krijgt, hoe zijn output geverifieerd wordt, en wat er gebeurt als het faalt.

Ralph is een van de simpelst mogelijke harnesses, en daarom werkt het. Een bash script van 30 regels en een checkbox-lijst. Geen frameworks, geen orchestratieplatformen, geen vectordatabases. Gewoon while, grep, git, en een verse context per aanroep.

Ik denk dat we hier het komende jaar veel meer van gaan zien: kleine harnesses rond krachtige modellen, gebouwd door mensen die hun automatisering liever zelf begrijpen dan kant-en-klaar inkopen. Als je beroepsmatig code schrijft en er nog geen hebt gebouwd, ligt je weekendproject hier voor het oprapen.

TL;DR: de hele setup in één blok

# 1. Install OrbStack (Apple Silicon, low RAM, faster than Docker Desktop)
brew install --cask orbstack
open -a OrbStack

# 2. Create harness directory
mkdir -p ~/ralph-project/project && cd ~/ralph-project

# 3. Drop in Dockerfile, loop.sh, run.sh from this post

# 4. Add your API key
echo "ANTHROPIC_API_KEY=sk-ant-..." > .env
chmod 600 .env

# 5. Initialize the project repo with PRD.md (your task list)
cd project
git init
echo "# My Project" > README.md
echo "## Tasks" > PRD.md
echo "- [ ] First task" >> PRD.md
git add . && git commit -m "init"
cd ..

# 6. Set a spend limit at console.anthropic.com/settings/limits
#    €50/day is sane

# 7. Run it
MAX_ITER=3 ./run.sh

Dat is het. Je hebt nu een autonome coding agent die werkt aan een gesandboxde kopie van je project. Zet koffie. Kom over twintig minuten terug. Lees de diff.

Als je hier iets tofs mee bouwt, zou ik het graag zien. Mail me op info@jermayads.nl met wat je hebt gebouwd, of open het Contact-icoon op het bureaublad.

Veelgestelde vragen

Is Ralph hetzelfde als een “self-improving agent” of AGI?

Nee, en het onderscheid doet ertoe. Ralph leert niet tussen iteraties. Elke iteratie begint vanaf een verse context. Het is mechanische volharding toegepast op een takenlijst, geen emergent redeneersysteem. Juist die eenvoud maakt het voorspelbaar en goedkoop.

Heb ik Docker Desktop hiervoor nodig?

Nee. OrbStack werkt perfect voor de standaard Ralph-setup. Je hebt Docker Desktop alleen nodig als je de docker sandbox subcommando wilt gebruiken die in Docker Desktop 4.50 werd geïntroduceerd, wat isolatie op microVM-niveau biedt. Voor 95% van de use cases is een OrbStack container genoeg.

Kan ik Ralph draaien met een ander model dan Claude Code?

Ja. Het Ralph-patroon is model-agnostisch. Vervang de claude -p "$PROMPT" regel in loop.sh door aider, codex, opencode, gemini-cli, of elke andere CLI agent die een prompt aanneemt en naar schijf schrijft. De loop, de PRD, de sandbox, en de commit-per-taak-discipline blijven identiek.

Hoe stop ik Ralph halverwege zonder werk kwijt te raken?

Zet een STOP-bestand neer in de projectdirectory (touch /workspace/STOP vanuit de container, of touch project/STOP vanaf je host). De huidige iteratie maakt zijn commit af, waarna de loop netjes afsluit. Ctrl-C werkt ook maar kan halverwege een bewerking onderbreken, waardoor gedeeltelijke bestanden achterblijven.

Wat weerhoudt Ralph ervan oneindig rommel naar mijn repo te schrijven?

Drie dingen, in volgorde: de MAX_ITER-cap, je dagelijkse Anthropic-bestedingslimiet, en je eigen git log --oneline review voordat je naar een remote pusht. Ralph pusht niet, per ontwerp: elke commit is lokaal totdat jij hem goedkeurt.

Is --dangerously-skip-permissions daadwerkelijk gevaarlijk?

Ja, daarom heet de flag zoals hij heet. Zonder sandbox zou Claude Code met deze flag plausibel bestanden kunnen verwijderen, kwaadaardige dependencies kunnen installeren, of data kunnen exfiltreren. De sandbox zorgt ervoor dat je die flag kunt overleven. Draai Ralph nooit zonder sandbox.

Hoeveel kost Sonnet 4.6 in vergelijking met Opus 4.7 hiervoor?

Sonnet 4.6 is per token ongeveer 5x goedkoper dan Opus 4.7 en iets sneller. Voor Ralph-workloads, veel kleine en goed afgebakende taken, is Sonnet meestal de juiste keuze. Reserveer Opus voor taken waar je specifiek het diepste redeneervermogen nodig hebt, zoals complexe refactors met subtiele semantische beperkingen.

Werkt dit op Windows?

Het Dockerfile en de scripts draaien op elke host met Docker. De bash scripts werken ongewijzigd in WSL2. Native Windows PowerShell zou een kleine aanpassing nodig hebben, maar het patroon is hetzelfde.

Mijn PRD staat in Notion / Linear / een database. Kan ik Ralph nog steeds gebruiken?

Converteer het eenmalig naar een Markdownbestand met - [ ] checkboxes. Ralph leest het bestand elke iteratie; het heeft geen live API-verbinding met je takentracker nodig. Na de run kun je de voltooide checkboxes handmatig of met een script terugsynchroniseren naar je tracker.