How It Works¶
Technical deep-dive into Ralph's architecture and execution model.
Architecture¶
+------------------------------------------------------------------+
| ralph.sh |
| (Orchestration Loop) |
+--------------------------------+---------------------------------+
|
v
+------------------------------------------------------------------+
| PROMPT_*.md |
| (Mode-specific instructions) |
| |
| PROMPT_plan.md ------> Analysis & task breakdown |
| PROMPT_build.md ------> Implementation & validation |
+--------------------------------+---------------------------------+
|
v
+------------------------------------------------------------------+
| Claude CLI |
| claude -p --dangerously-skip-permissions |
+--------------------------------+---------------------------------+
|
v
+------------------------------------------------------------------+
| Progress File |
| <plan-name>_PROGRESS.md |
| |
| - Shared state between iterations |
| - Task list with completion status |
| - RALPH_DONE on its own line signals completion (build only) |
+------------------------------------------------------------------+
Execution Flow¶
Initialization¶
- Validate plan file exists
- Determine progress file name
- Create progress file if missing
- Select prompt template
- Send start notification
The Loop¶
Each iteration:
1. Check exit conditions
|-- RALPH_DONE on its own line in progress file? -> Exit (build mode)
+-- Max iterations reached? -> Exit
2. Build prompt
+-- Substitute ${PLAN_FILE}, ${PROGRESS_FILE}, ${PLAN_NAME}
3. Execute Claude
+-- Claude reads files, implements task, updates progress
4. Post-iteration
|-- Plan mode? -> Exit immediately (runs once only)
|-- Send notification (every 5 iterations, build mode only)
|-- Sleep 2 seconds
+-- Loop back to step 1
Termination¶
| Exit Condition | Mode | Meaning |
|---|---|---|
| Plan mode complete | Plan | Success - task list created (exits after 1 iteration) |
RALPH_DONE on own line |
Build | Success - all tasks complete |
| Max iterations | Both | Limit reached |
Ctrl+C |
Both | Manual stop |
Detection
The completion marker must appear on its own line in the progress file to be detected. This prevents false positives from instructional text like "do not write RALPH_DONE" being mistakenly matched.
Prompt Templates¶
PROMPT_plan.md¶
Used in plan mode. Instructs Claude to:
- Read and analyze the plan file
- Explore the codebase using subagents from multiple perspectives
- Identify what exists vs. what's needed
- Consider all contingencies and dependencies
- Create a prioritized task breakdown (ordered by dependencies)
- Update progress file with analysis
- Set status to
IN_PROGRESSwhen done
Important
Plan mode makes no code changes—analysis only. It runs once then exits automatically.
Critical
Plan mode must NEVER set RALPH_DONE under any circumstances. It always sets status to IN_PROGRESS when planning is complete, signaling that build mode can begin.
PROMPT_build.md¶
Used in build mode. Instructs Claude to:
- Read plan and progress files
- Select ONE uncompleted task
- Use subagents to search codebase (verify not already done)
- Implement the task
- Run validation (tests, build, lint)
- Update progress file
- Commit changes
- Count ALL tasks - only set
RALPH_DONEif EVERY task is [x] complete and verified
Important
Build mode does one task per iteration.
Completion Rules
Build mode must verify ALL tasks are complete before writing RALPH_DONE. The marker must be written on its own line in the Status section. When in doubt, leave status as IN_PROGRESS—it's better to run an extra iteration than exit prematurely.
State Management¶
Fresh Context Each Iteration¶
Each Claude invocation starts fresh—no memory of previous iterations. The progress file is the only persistent state:
# Progress: feature-name
## Status
IN_PROGRESS <-- Controls loop
## Task List
- [x] Completed <-- What's done
- [ ] Pending <-- What's left
## Notes
- Discoveries <-- Knowledge transfer
Why Fresh Context?¶
| Benefit | Description |
|---|---|
| No overflow | Long sessions don't degrade |
| Clean slate | No accumulated confusion |
| Explicit state | Everything written down |
| Debuggable | Progress shows what happened |
Variable Substitution¶
| Variable | Example |
|---|---|
${PLAN_FILE} |
/home/user/repo/feature.md |
${PROGRESS_FILE} |
feature_PROGRESS.md |
${PLAN_NAME} |
feature |
Notifications¶
Flow¶
notify.sh
|
|---> Slack (webhook)
|---> Discord (webhook)
|---> Telegram (bot API)
+---> Custom (your script)
Messages sent to all configured platforms. Unconfigured platforms silently skipped.
Custom Script Interface¶
Your script handles delivery. Exit code ignored.
Files¶
~/ralph/
|-- ralph.sh # Orchestration loop
|-- notify.sh # Notification dispatcher
|-- setup-notifications.sh # Setup wizard
|-- PROMPT_plan.md # Plan mode prompt
|-- PROMPT_build.md # Build mode prompt
|-- .env.example # Config template
+-- docs/ # Documentation
Security¶
dangerously-skip-permissions¶
Ralph uses claude -p --dangerously-skip-permissions:
- Allows any command execution
- Skips confirmation prompts
- Enables autonomous operation
Warning
Use with caution. Review commits. Set max-iterations for unattended runs.
Credential Protection¶
.gitignoreblocks.env*files- Config stored in
~/.ralph.env(outside repo) - Wizard sets
chmod 600on config - No credentials in prompt templates