State Management
Relevant source files
The following files were used as context for generating this wiki page:State management in the Ralph for Claude Code project is a decentralized, file-based system designed to track and control the autonomous development loop. It ensures resilience, enables monitoring, and manages operational constraints like API rate limits. The state is persisted in a series of hidden (dotfiles) and explicit JSON files within the project's root directory, allowing the system to be stateless across script executions and recoverable after interruptions.
The core scripts, ralph_loop.sh and ralph_monitor.sh, act as the primary writer and reader of this state, respectively. This system also includes declarative state through control files like @fix_plan.md and specifications in specs/, which guide the agent's behavior and define the project's target state.
Sources: create_files.sh:10-27, CLAUDE.md:44-50, CONTRIBUTING.md:200-204
Core State Files
The system relies on several key files to manage its state. These are typically located in the root of a Ralph-managed project.
| File | Purpose | Managed By |
|---|---|---|
status.json | Provides real-time status for external monitoring. | ralph_loop.sh |
.call_count | Tracks the number of API calls made in the current hour. | ralph_loop.sh |
.last_reset | Stores the timestamp of the last hourly API call counter reset. | ralph_loop.sh |
.exit_signals | Stores a history of recent completion and test-only signals to detect when to exit gracefully. | ralph_loop.sh |
.claude_session_id | Persists the session ID from the Claude Code CLI to maintain context across loops. | ralph_loop.sh |
.ralph_session_history | Logs the last 50 session transitions for debugging purposes. | ralph_loop.sh |
.circuit_breaker_state | Manages the state of the circuit breaker (CLOSED, HALF_OPEN, OPEN). | lib/circuit_breaker.sh |
Sources: create_files.sh:15-27, CLAUDE.md:48-50, 62, 214-215
This diagram illustrates the relationship between the main loop, the monitor, and the core state files.
Sources: create_files.sh:10-485
Loop Status (status.json)
The status.json file is the primary mechanism for external monitoring. It provides a snapshot of the Ralph loop's current state in a structured JSON format. The ralph_monitor.sh script reads this file to populate its dashboard.
Sources: create_files.sh:98-116, 492-495
Data Structure
The file contains key metrics about the loop's progress and health.
| Field | Type | Description |
|---|---|---|
timestamp | String (ISO 8601) | The time of the last status update. |
loop_count | Integer | The number of loops executed so far. |
calls_made_this_hour | Integer | API calls used in the current hour. |
max_calls_per_hour | Integer | The configured maximum calls per hour. |
last_action | String | The most recent action taken (e.g., "executing", "completed"). |
status | String | The overall status of the loop (e.g., "running", "stopped", "completed"). |
exit_reason | String | If exited, the reason for termination (e.g., "plan_complete"). |
next_reset | String | The time of the next scheduled API call counter reset. |
Sources: create_files.sh:100-115, [tests/helpers/fixtures.bash:221-231]
An example of a status.json file for a running process:
{
"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": ""
}
Sources: tests/helpers/fixtures.bash:221-231
Update Flow
The update_status function in ralph_loop.sh is responsible for writing to status.json at various points in the loop lifecycle.
This sequence diagram shows how the status is updated during a typical loop.
API Rate Limiting State
To avoid exceeding API usage quotas, Ralph uses .call_count and .last_reset to manage rate limiting.
.call_count: A simple integer file storing the number of API calls in the current hour..last_reset: Stores the hour of the last reset (e.g.,2023010112) to determine if a new hour has begun.
Sources: create_files.sh:16, 17, 52-66
The init_call_tracking function checks if the current hour matches the one in .last_reset. If not, it resets .call_count to 0. The can_make_call function checks if the value in .call_count is less than MAX_CALLS_PER_HOUR.
This flowchart shows the rate limit check logic.
Sources: create_files.sh:125-135, 299-303
Graceful Exit State
The .exit_signals file is a JSON file that tracks signals for graceful termination, preventing infinite loops on completed or stalled projects.
Sources: create_files.sh:20, 63-66
Data Structure
The file is initialized with empty arrays to track recent loop outcomes.
{
"test_only_loops": [],
"done_signals": [],
"completion_indicators": []
}
Sources: create_files.sh:64-66
The should_exit_gracefully function in ralph_loop.sh reads this file and checks against configured thresholds to determine if the loop should stop.
Exit Conditions
| Condition | Threshold Variable | Default | Description |
|---|---|---|---|
| Consecutive test-only loops | MAX_CONSECUTIVE_TEST_LOOPS | 3 | The agent is only running tests, suggesting no new work is being done. |
| Consecutive "done" signals | MAX_CONSECUTIVE_DONE_SIGNALS | 2 | The AI has repeatedly signaled that it believes the work is complete. |
All tasks in @fix_plan.md are complete | N/A | N/A | The agent has completed its entire task list. |
Sources: create_files.sh:21-23, 203-239, [CLAUDE.md:237-239]
Session Management State
To maintain context between individual executions of the Claude Code CLI, Ralph manages a session state. This is crucial for coherent, multi-step development.
.claude_session_id: Stores the current session ID provided by the Claude Code CLI. It has a 24-hour expiration..ralph_session_history: A log file that records the last 50 session transitions (e.g., creation, reset), including the reason for the change. This is used for debugging.
Sources: CLAUDE.md:60-66, 214-228
Session Lifecycle
The session is automatically managed throughout the Ralph loop. It is reset under specific conditions to prevent the agent from getting stuck with bad context.
This diagram shows the session lifecycle management.
Sources: CLAUDE.md:60-66, 310-322
Declarative State (@fix_plan.md and specs/)
In addition to the operational state files, Ralph uses a set of "declarative" state files to define the project's goals and current tasks.
@fix_plan.md: A markdown file with checkboxes that acts as a prioritized TODO list for the agent. The agent reads this file to determine its next task and updates it upon completion. The loop can exit when all tasks are marked as complete.specs/*.md: Contains the detailed technical specifications for the project. The agent refers to these files to understand the requirements.PROMPT.md: The main instruction set for the agent, defining its objectives, principles, and reporting structure.
The ralph_import.sh script is responsible for generating this initial declarative state by converting user-provided documents (like a PRD) into the structured PROMPT.md, @fix_plan.md, and specs/requirements.md files.
Sources: create_files.sh:436-483, ralph_import.sh:255-334, templates/fix_plan.md, templates/PROMPT.md
Summary
The state management system in Ralph is a robust, file-based architecture that effectively decouples the agent's "memory" from its execution. By using a combination of operational state files (like status.json and .call_count) and declarative state files (like @fix_plan.md), the system achieves a high degree of autonomy, resilience, and observability. This allows the Ralph loop to run continuously, handle interruptions gracefully, and intelligently determine when its work is complete.
Sources: create_files.sh, CLAUDE.md