How it's built.
Ralpharium is a small Python daemon that sits next to your repo. It reads the markdown files your AI runner cares about, spawns the runner as a subprocess, watches what comes out, and streams everything to a dashboard in your browser. Nothing leaves your machine. No accounts, no databases — just files, processes, and a WebSocket.
Home
Local-first. The whole product runs on one Python process on your machine. There is no server you pay for, no SaaS to log into. The dashboard is just a static frontend served by the same daemon at localhost:3000.
The runner is the AI. Ralpharium doesn't replace Claude Code, Codex, or Aider — it runs them. You pick which one in the dashboard. Each iteration spawns the runner as a subprocess, the daemon captures stdout, parses what came out, and records the result. Swap runners by changing one config field.
The four input files the runner reads each iteration: PROMPT.md (instructions), AGENTS.md (rules), IMPLEMENTATION_PLAN.md (task list), and specs/*.md (acceptance criteria). The daemon parses all four and surfaces them on the dashboard.
┌─────────────┐ reads ┌─────────────────────────┐ streams ┌──────────────┐
│ your runner │ ──────────► │ ralph studio daemon │ ─────────────►│ dashboard │
│ (codex / │ PROMPT.md │ • repo inspector │ websocket │ (operator) │
│ claude / │ PLAN.md │ • plan parser │ │ │
│ aider) │ AGENTS.md │ • spec coverage │ │ │
│ │ specs/* │ • backpressure runner │ │ │
│ │ git diff │ • iteration store │ │ │
│ │ │ • RAM event stream │ │ │
└─────────────┘ └─────────────────────────┘ └──────────────┘
│
.ralph/iterations.jsonl (append-only history)
Three execution surfaces
Disk
durable
The Ralph artifacts (PROMPT.md, AGENTS.md, IMPLEMENTATION_PLAN.md, specs/*) plus .ralph/iterations.jsonl. Survives restarts.
RAM
volatile
Live event stream, blackboard slots, scratchpad, in-memory checkpoints. Wiped on daemon restart.
Process
runner
The configured runner (codex, claude, aider, custom shell) — spawned as a subprocess; stdout streamed live.
Ralph artifacts
Every iteration starts by re-reading the same files. Studio parses each one and surfaces structure to the dashboard.
Plan parser
The parser reads checkbox tasks (- [ ], - [x], plus [/] in-progress, [!] blocked, [~] stale) and groups them by section. It picks "next" as the first pending task and raises warnings for repeated text, all-completed plans, and 24h+ staleness.
Iteration model
Each loop pass is one Iteration. Studio creates one when you click Start (or when your runner POSTs to /api/iterations) and finalizes it on success / failure / stop. The full record is appended to .ralph/iterations.jsonl — a flat file you can tail -f, grep, or ship anywhere.
{
"id": "it_1736172000_a3f9c1d8",
"number": 42,
"mode": "build",
"status": "passed",
"started_at": 1736172000.12,
"ended_at": 1736172094.55,
"summary": "Add /api/specs endpoint",
"files_changed": ["backend/main.py", "backend/specs.py"],
"commit_sha": "9af2b7c",
"test_status": "passed",
"validation": [{"name": "Tests", "status": "passed"}],
"command_output": "...",
"failure_reason": null
}
The dashboard timeline lists the latest 30; click any row and the replay drawer fills with the prompt mode used, the validation results, the files changed, the tail of stdout, and the commit it produced.
Backpressure (validation)
Backpressure is just a name for "the loop stops when tests fail." Ralpharium looks for npm test / npm run lint / npm run build in your package.json and offers them as one-click checks. If you turn on stop_on_failure, a red check halts the loop before bad code lands. Same idea for git: turn on stop_if_dirty_before_run and Ralph won't start a new iteration on uncommitted changes.
Auto-detect
Reads package.json scripts (test, lint, typecheck, build). Falls back to pytest -q for Python projects.
Status & output
Each check tracks status, last-run timestamp, duration, and the tail of stdout — exposed at /api/backpressure and live over WS.
Guardrail learning
Repeated failures turn into AGENTS.md suggestions: "Tests failed 3× — require npm test before commit."
RAM observability
Beyond the durable iteration log, Studio keeps a volatile RAM layer that the dashboard can stream live. Nothing here is written to disk — it's the live nervous system of the running daemon.
Event stream
Ring buffer of typed events: boot, iteration start/end, validation, scratchpad notes, checkpoints. Capped at 600 entries.
Blackboard
Named volatile slots: loop_mode, runner, current_task, last_error, last_commit, files_changed.
Scratchpad
Pin a thought during the session. Survives across iterations, dies on restart. Useful for "the spec was wrong" notes you'll lose otherwise.
Checkpoints
Snapshot the repo + plan + prompt at any moment. Compare two checkpoints to see what changed during the session.
Memory pressure
Real numbers: prompt context bytes, repo scan size, event buffer size, runner RSS — surfaced as bars in the dashboard.
Process
The runner subprocess: PID, RSS via ps/tasklist, command, runtime. Live stdout streams over WebSocket.
API surface
Everything is REST + a single WebSocket. The dashboard only uses these — your CLI can use them too.
GET /api/state # aggregate first-paint snapshot
GET /api/status # mode, iter count, runner, branch, dirty
GET /api/repo-state # git + Ralph file detection
GET /api/plan-health # IMPLEMENTATION_PLAN.md parsed
GET /api/spec-coverage # specs/* mapped to plan + commits
GET /api/backpressure # auto-detected validation checks
GET /api/guardrails # PROMPT/AGENTS + suggestions
GET /api/iterations?limit=N # iteration history
GET /api/iterations/{id} # single iteration detail
POST /api/iterations # CLI hook: begin iteration
PATCH /api/iterations/{id} # CLI hook: finish/update iteration
POST /api/loop/{start|pause|resume|stop|panic} # control
POST /api/check/{id} # run a backpressure check
POST /api/runner # set runner + command
GET /api/ram # full volatile snapshot
GET /api/ram/events # ring buffer
GET /api/ram/blackboard # kv slots
GET /api/ram/pressure # memory pressure
POST /api/ram/scratchpad # pin a note
POST /api/ram/checkpoints # snapshot repo+plan
WS /ws # live updates: status, iteration_*, ram_*, log
Stack & run
Backend
- Python 3.11+
- FastAPI · Uvicorn
asyncio.subprocess- stdlib only — no NumPy, no DB
- JSONL persistence
Frontend
- Vanilla HTML · CSS · JS
- WebSocket client
- Inline SVG, no canvas
- Responsive 12-col grid
- Zero build step
Run locally
pip install -r backend/requirements.txt python backend/main.py # http://localhost:3000 # optional config RALPH_REPO_PATH=/path/to/repo \ RALPH_RUNNER=claude \ RALPH_RUNNER_CMD="claude -p PROMPT.md" \ python backend/main.py
See it run.
Open the live console and watch every Ralph iteration — plan, validation, commit — through one observable surface.