The Main Loop (ralph_loop.sh)
Relevant source files
The following files were used as context for generating this wiki page:The ralph_loop.sh script is the core autonomous development engine of the Ralph project. Its primary purpose is to repeatedly execute the Claude Code AI, feeding it instructions from a prompt file, until a set of objectives is met. The script manages API usage through rate limiting, logs all operations, tracks progress, and employs an intelligent exit detection mechanism to prevent infinite loops and determine when the project is complete.
This script operates in a continuous cycle: it checks for API call limits, evaluates if the project is finished, executes the AI, and then pauses before repeating the process. It is designed to be a "set and forget" tool that autonomously drives a software project towards completion based on the goals defined in PROMPT.md and @fix_plan.md.
Sources: create_files.sh:7-13, README.md:143-149
Architecture and Core Components
The ralph_loop.sh script is a self-contained bash script that orchestrates interactions between the filesystem, the Claude Code CLI, and various state-tracking files.
The following diagram illustrates the main components and their interactions within the loop's ecosystem.
Sources: create_files.sh:15-305, CLAUDE.md:10-23
Configuration
The script's behavior can be configured through internal variables and command-line arguments.
Internal Configuration Variables
These variables are defined at the top of the ralph_loop.sh script.
| Variable | Default Value | Description |
|---|---|---|
PROMPT_FILE | "PROMPT.md" | The main prompt file to be fed to Claude Code. |
LOG_DIR | "logs" | Directory to store execution logs. |
DOCS_DIR | "docs/generated" | Directory for auto-generated documentation. |
STATUS_FILE | "status.json" | File for storing the current status of the loop. |
CLAUDE_CODE_CMD | "npx @anthropic/claude-code" | The command to execute the Claude Code CLI. |
MAX_CALLS_PER_HOUR | 100 | The maximum number of API calls allowed per hour. |
SLEEP_DURATION | 3600 | The duration in seconds to sleep (not actively used in the main loop logic). |
CALL_COUNT_FILE | ".call_count" | Hidden file to track the number of calls in the current hour. |
TIMESTAMP_FILE | ".last_reset" | Hidden file to track the last time the call counter was reset. |
EXIT_SIGNALS_FILE | ".exit_signals" | Hidden file to track signals for graceful exit. |
MAX_CONSECUTIVE_TEST_LOOPS | 3 | Exit after this many consecutive test-only loops. |
MAX_CONSECUTIVE_DONE_SIGNALS | 2 | Exit after this many "done" signals from the AI. |
TEST_PERCENTAGE_THRESHOLD | 30 | Threshold to flag if a high percentage of recent loops are test-only. |
Sources: create_files.sh:18-35, README.md:310-318
Command-Line Arguments
The script accepts several command-line arguments to override default configurations.
| Flag (Short) | Flag (Long) | Parameter | Description |
|---|---|---|---|
-h | --help | - | Show the help message and exit. |
-c | --calls | NUM | Set the maximum number of API calls per hour. |
-p | --prompt | FILE | Set the path to the prompt file. |
-s | --status | - | Show the current status from status.json and exit. |
Sources: create_files.sh:371-402, README.md:440-446
Main Loop Flow
The main function orchestrates the entire autonomous process. It runs an infinite while loop that is broken only by a graceful exit condition or manual interruption.
This flowchart shows the high-level logic of the main function.
Sources: create_files.sh:308-369
Rate Limiting
To avoid exceeding API usage quotas, the script includes a robust rate-limiting mechanism. It uses two hidden files, .call_count and .last_reset, to track usage within the current hour.
init_call_tracking(): Checks if the current hour is different from the one stored in.last_reset. If so, it resets.call_countto 0.can_make_call(): Reads.call_countand compares it toMAX_CALLS_PER_HOUR. It returns0(true) if a call can be made, and1(false) otherwise.increment_call_counter(): Increments the value in.call_count.wait_for_reset(): If the rate limit is reached, this function calculates the remaining time until the next hour, displays a countdown, and sleeps until the limit resets.
Sources: create_files.sh:45-70, create_files.sh:122-175
Intelligent Exit Detection
A key feature of the loop is its ability to determine when the project is complete and exit gracefully. This logic is encapsulated in the should_exit_gracefully function.
The function checks for several conditions based on the contents of .exit_signals and @fix_plan.md.
This flowchart details the logic of the should_exit_gracefully function.
Exit Conditions
| Condition | Threshold Variable | Default | Description |
|---|---|---|---|
| Consecutive test-only loops | MAX_CONSECUTIVE_TEST_LOOPS | 3 | The AI has only run tests for several loops, suggesting no new implementation is needed. |
| Consecutive "done" signals | MAX_CONSECUTIVE_DONE_SIGNALS | 2 | The AI has signaled completion multiple times. |
| Strong completion indicators | 2 (hardcoded) | 2 | The AI response contains strong indicators that the project is finished. |
@fix_plan.md completion | - | - | All tasks in the @fix_plan.md file are marked as complete ([x]). |
Sources: create_files.sh:30-35, create_files.sh:198-233, README.md:152-157
Execution and Logging
Claude Code Execution
The execute_claude_code function is responsible for calling the AI.
- It increments the API call counter.
- It generates a timestamped output log file (e.g.,
logs/claude_output_2023-10-27_10-30-00.log). - It executes the
CLAUDE_CODE_CMD, redirecting the AI's standard output and error streams to the log file. - It checks the exit code of the command to determine success or failure.
Sources: create_files.sh:242-266
Logging and Status
The script maintains detailed logs and a real-time status file.
log_status(): A centralized function for printing colored status messages to the terminal and appending them tologs/ralph.log. It supports levels likeINFO,WARN,ERROR,SUCCESS, andLOOP.update_status(): This function overwritesstatus.jsonwith the latest state of the loop. This allows external monitoring tools (likeralph_monitor.sh) to observe the process.
The status.json file has the following structure:
{
"timestamp": "2025-09-30T12:00:00-04:00",
"loop_count": 5,
"calls_made_this_hour": 42,
"max_calls_per_hour": 100,
"last_action": "executing",
"status": "running",
"exit_reason": "",
"next_reset": "13:00:00"
}
Sources: create_files.sh:73-92, create_files.sh:95-119, tests/helpers/fixtures.bash:207-221
Conclusion
ralph_loop.sh is the autonomous heart of the Ralph for Claude Code project. It provides a structured, resilient, and intelligent framework for continuous AI-driven development. By combining a simple while loop with sophisticated rate limiting, status tracking, and graceful exit detection, it transforms the Claude Code CLI from a single-shot tool into a persistent agent capable of completing complex software projects with minimal human supervision. Its configurability and detailed logging make it a powerful and observable system for managing autonomous coding tasks.
Sources: create_files.sh, README.md