Skip to content

fix(loop): respect .ralphrc CLAUDE_CODE_CMD; add CLAUDE_MODEL/EFFORT (#228)#231

Merged
frankbria merged 3 commits into
mainfrom
fix/228-claude-code-cmd-env-precedence
Mar 25, 2026
Merged

fix(loop): respect .ralphrc CLAUDE_CODE_CMD; add CLAUDE_MODEL/EFFORT (#228)#231
frankbria merged 3 commits into
mainfrom
fix/228-claude-code-cmd-env-precedence

Conversation

@frankbria
Copy link
Copy Markdown
Owner

@frankbria frankbria commented Mar 24, 2026

Summary

Fixes #228.ralphrc CLAUDE_CODE_CMD was silently ignored; any custom value was always overwritten by the hardcoded "claude" default.

Root cause: CLAUDE_CODE_CMD="claude" was assigned unconditionally at line 27, before the env snapshot block at line 46. So _env_CLAUDE_CODE_CMD always captured "claude" (never empty), and the load_ralphrc() restore at line 158 always overwrote the .ralphrc value with "claude".

Fix: Remove the unconditional line-27 assignment. CLAUDE_CODE_CMD is now set with ${CLAUDE_CODE_CMD:-claude} after the env snapshot, consistent with MAX_CALLS_PER_HOUR, CLAUDE_OUTPUT_FORMAT, and all other tunables.

Bonus (requested in issue): Adds CLAUDE_MODEL and CLAUDE_EFFORT config variables:

# .ralphrc
CLAUDE_MODEL="claude-sonnet-4-6"
CLAUDE_EFFORT="high"

These are passed as --model / --effort flags to the Claude CLI. Env vars take precedence over .ralphrc (same pattern as all other vars).

Changes

  • ralph_loop.sh — move CLAUDE_CODE_CMD default to after env snapshot; add CLAUDE_MODEL/CLAUDE_EFFORT snapshot, defaults, load_ralphrc() restore, and build_claude_command() flags
  • tests/unit/test_cli_modern.bats — 8 new tests + update test stubs

Test plan

  • CLAUDE_CODE_CMD default uses ${:-} parameter expansion (not unconditional assignment)
  • .ralphrc CLAUDE_CODE_CMD is respected when no env var is exported
  • CLAUDE_MODEL loads from .ralphrc; env var overrides it
  • CLAUDE_EFFORT loads from .ralphrc
  • build_claude_command adds --model flag when CLAUDE_MODEL is set
  • build_claude_command adds --effort flag when CLAUDE_EFFORT is set
  • Both flags omitted when vars are empty
  • All 595 tests pass

Summary by CodeRabbit

  • New Features

    • Add configurable Claude Code options: set CLAUDE_MODEL and CLAUDE_EFFORT via environment or config file to control model and effort flags on Claude invocations.
  • Documentation

    • Documented the new CLAUDE_MODEL and CLAUDE_EFFORT settings and their precedence (env over config).
  • Tests

    • Expanded tests covering env/config precedence and conditional inclusion of model/effort flags.

…228)

CLAUDE_CODE_CMD was hardcoded to "claude" at line 27 — before the env
snapshot block at line 46. This made _env_CLAUDE_CODE_CMD always
non-empty ("claude"), so the load_ralphrc() restore at line 158
unconditionally overwrote any .ralphrc value with "claude". Both
.ralphrc configuration AND shell environment overrides were silently
discarded.

Fix: remove the unconditional assignment. CLAUDE_CODE_CMD is now set
with parameter expansion (${CLAUDE_CODE_CMD:-claude}) AFTER the env
snapshot block, consistent with MAX_CALLS_PER_HOUR and other tunables.
The snapshot now captures "" when no env var is exported, allowing
.ralphrc to take effect.

Also adds CLAUDE_MODEL and CLAUDE_EFFORT config variables (requested in
the issue):
  - Set in .ralphrc: CLAUDE_MODEL="claude-sonnet-4-6", CLAUDE_EFFORT="high"
  - Passed as --model / --effort flags in build_claude_command()
  - Env vars take precedence over .ralphrc (same pattern as other vars)

Adds 8 tests covering: parameter expansion assertion, .ralphrc loading,
env var precedence, and CLI flag generation for both new variables.

Fixes #228
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 24, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 19efb40e-9eda-476d-9c99-eba8f4b8e31d

📥 Commits

Reviewing files that changed from the base of the PR and between 5235b4f and 2ef2d0a.

📒 Files selected for processing (1)
  • CLAUDE.md
✅ Files skipped from review due to trivial changes (1)
  • CLAUDE.md

Walkthrough

Adds CLAUDE_MODEL and CLAUDE_EFFORT configuration variables to ralph_loop.sh, preserves environment snapshots for them when sourcing .ralphrc, conditionally appends --model/--effort to the Claude command, and moves CLAUDE_CODE_CMD defaulting to conditional initialization; tests and docs updated.

Changes

Cohort / File(s) Summary
Core configuration & command building
ralph_loop.sh
Introduce CLAUDE_MODEL and CLAUDE_EFFORT; snapshot _env_CLAUDE_MODEL/_env_CLAUDE_EFFORTfrom the env and restore precedence when sourcing.ralphrc; use CLAUDE_CODE_CMD="${CLAUDE_CODE_CMD:-claude}"; append --modeland--efforttoCLAUDE_CMD_ARGS` only when set.
Unit tests (Bats)
tests/unit/test_cli_modern.bats
Extend test setup to snapshot/restore CLAUDE_MODEL and CLAUDE_EFFORT; add tests for CLAUDE_CODE_CMD defaulting and precedence; verify conditional inclusion/omission of --model/--effort in build_claude_command.
Docs
CLAUDE.md
Document new env vars CLAUDE_MODEL and CLAUDE_EFFORT, their effect on CLI flags, precedence rules, and reference to Issue #228.

Sequence Diagram(s)

sequenceDiagram
  participant User as User
  participant Script as RalphScript
  participant RC as .ralphrc
  participant Claude as ClaudeCLI
  User->>Script: invoke ralph_loop
  Script->>Script: snapshot env (CLAUDE_CODE_CMD, CLAUDE_MODEL, CLAUDE_EFFORT)
  Script->>RC: source .ralphrc (may set CLAUDE_*)
  RC-->>Script: return (variables possibly set)
  Script->>Script: restore env snapshots if present (preserve precedence)
  Script->>Script: build_claude_command (append --model/--effort if non-empty)
  Script->>Claude: execute constructed CLI command
  Claude-->>Script: response
Loading

(Note: rectangle colors omitted because sequence diagram uses actors/flow only.)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐇 I nibble configs by the moonlit glade,
CLAUDE_MODEL and effort neatly laid.
No more silent overwrites to dread,
Flags line up tidy, arguments fed.
Hop—Ralph sings code while carrots are spread.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: fixing .ralphrc CLAUDE_CODE_CMD precedence and adding CLAUDE_MODEL/EFFORT variables, directly matching the PR's primary objectives.
Linked Issues check ✅ Passed All coding requirements from issue #228 are addressed: fixed .ralphrc CLAUDE_CODE_CMD override behavior, added CLAUDE_MODEL and CLAUDE_EFFORT variables with proper env override precedence, and added comprehensive tests.
Out of Scope Changes check ✅ Passed All changes are directly scoped to issue #228 requirements: environment snapshot handling, default initialization, .ralphrc loading, flag construction, and corresponding test coverage with no unrelated modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/228-claude-code-cmd-env-precedence

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

Review Summary

This PR effectively fixes issue #228 by moving the default assignment to after the environment snapshot, and adds support for and configuration variables.

Code Quality & Best Practices

  1. Root cause correctly identified and fixed: Moving from unconditional assignment to parameter expansion after the env snapshot (line 63) allows the .ralphrc value to take precedence when no env var is set.

  2. Consistent pattern applied: New variables and follow the exact same env-snapshot pattern:

    • Lines 47-48: Capture env state before defaults
    • Lines 64-65: Set empty defaults
    • Lines 164-165: Restore env vars in load_ralphrc()
  3. Safe command building: build_claude_command() uses array-based approach (lines 1126-1134) that prevents shell injection and conditionally adds --model and --effort flags only when vars are non-empty.

  4. Test stubs updated: Both load_ralphrc() (lines 189-206) and build_claude_command() (lines 500-558) test stubs include the new functionality, ensuring behavioral tests stay in sync.

Test Coverage

Eight comprehensive tests added (lines 1821-1907):

  • Validates parameter expansion syntax (regression test)
  • Tests .ralphrc loading for all three vars
  • Confirms env var precedence over .ralphrc
  • Verifies --model and --effort flags are added conditionally
  • Ensures flags are omitted when vars are empty

⚠️ Minor: Documentation Should Be Updated

CLAUDE.md should document the new configuration options:

  1. Add CLAUDE_MODEL and CLAUDE_EFFORT to the "Modern CLI Configuration" section (around line 58)

  2. Update load_ralphrc() documentation block (lines 108-169) to include:

    • CLAUDE_MODEL - Model override (e.g., claude-sonnet-4-6)
    • CLAUDE_EFFORT - Effort level override (e.g., high, low)
  3. Consider adding example .ralphrc snippet:

    CLAUDE_MODEL="claude-sonnet-4-6"
    CLAUDE_EFFORT="high"

This is a documentation-only follow-up task—the code implementation is complete and correct.

Security & Performance

  • No security concerns: Values from .ralphrc are safely handled via array-based command construction
  • No performance impact: Simple string assignments and conditionals

Overall Assessment

LGTM with minor documentation follow-up. The implementation is solid, well-tested, and correctly addresses the reported issue.

@github-actions
Copy link
Copy Markdown

The review has been posted successfully. The comment URL is: #231 (comment)

Summary: The PR is well-implemented and correctly fixes issue #228. The code is solid, follows existing patterns, and has comprehensive test coverage. The only follow-up needed is documentation updates to mention the new CLAUDE_MODEL and CLAUDE_EFFORT configuration options.

New%20session%20-%202026-03-24T23%3A26%3A19.770Z
opencode session  |  github run

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
tests/unit/test_cli_modern.bats (1)

1865-1874: Consider adding a parallel test for CLAUDE_EFFORT env precedence.

There's a test verifying CLAUDE_MODEL env var takes precedence over .ralphrc, but no equivalent test for CLAUDE_EFFORT. For completeness and to ensure parity in test coverage:

📝 Suggested test to add after line 1874
+@test "CLAUDE_EFFORT env var takes precedence over .ralphrc" {
+    cat > "$TEST_DIR/.ralphrc" << 'EOF'
+CLAUDE_EFFORT="low"
+EOF
+    _env_CLAUDE_EFFORT="high"
+    CLAUDE_EFFORT="high"
+
+    load_ralphrc
+    assert_equal "$CLAUDE_EFFORT" "high"
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/unit/test_cli_modern.bats` around lines 1865 - 1874, Add a new test
mirroring the CLAUDE_MODEL precedence test that verifies CLAUDE_EFFORT
environment variable overrides the value in .ralphrc: create a `@test` block
(e.g., "CLAUDE_EFFORT env var takes precedence over .ralphrc") that writes
CLAUDE_EFFORT into "$TEST_DIR/.ralphrc", sets _env_CLAUDE_EFFORT and
CLAUDE_EFFORT to a different value, calls load_ralphrc, and uses assert_equal to
confirm "$CLAUDE_EFFORT" matches the environment value; follow the same
structure and assertions used in the CLAUDE_MODEL test to ensure parity.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@tests/unit/test_cli_modern.bats`:
- Around line 1865-1874: Add a new test mirroring the CLAUDE_MODEL precedence
test that verifies CLAUDE_EFFORT environment variable overrides the value in
.ralphrc: create a `@test` block (e.g., "CLAUDE_EFFORT env var takes precedence
over .ralphrc") that writes CLAUDE_EFFORT into "$TEST_DIR/.ralphrc", sets
_env_CLAUDE_EFFORT and CLAUDE_EFFORT to a different value, calls load_ralphrc,
and uses assert_equal to confirm "$CLAUDE_EFFORT" matches the environment value;
follow the same structure and assertions used in the CLAUDE_MODEL test to ensure
parity.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 18fc040b-d389-48df-8dce-3e345ee7934e

📥 Commits

Reviewing files that changed from the base of the PR and between f702543 and 087f8f2.

📒 Files selected for processing (2)
  • ralph_loop.sh
  • tests/unit/test_cli_modern.bats

@github-actions
Copy link
Copy Markdown

Test comment from review agent

@github-actions
Copy link
Copy Markdown

Contributing to Ralph for Claude Code

Thank you for your interest in contributing to Ralph! This guide will help you get started and ensure your contributions follow our established patterns and quality standards.

Every contribution matters - from fixing typos to implementing major features. We appreciate your help in making Ralph better!

Table of Contents

  1. Getting Started
  2. Development Workflow
  3. Code Style Guidelines
  4. Testing Requirements
  5. Pull Request Process
  6. Code Review Guidelines
  7. Quality Standards
  8. Community Guidelines

Getting Started

Prerequisites

Before contributing, ensure you have the following installed:

  • Bash 4.0+ - For script execution
  • jq - JSON processing (required)
  • git - Version control (required)
  • tmux - Terminal multiplexer (recommended)
  • Node.js 18+ - For running tests via npm

Clone the Repository

# Fork the repository on GitHub first, then clone your fork
git clone https://github.com/YOUR_USERNAME/ralph-claude-code.git
cd ralph-claude-code

Install Dependencies

# Install BATS testing framework and dependencies
npm install

# Verify BATS is available
./node_modules/.bin/bats --version

# Optional: Install Ralph globally for testing
./install.sh

Verify Your Setup

# Run the test suite to ensure everything works
npm test

# You should see output like:
# ✓ 276 tests passed (100% pass rate)

Project Structure

ralph-claude-code/
├── ralph_loop.sh        # Main loop script
├── ralph_monitor.sh     # Live monitoring dashboard
├── setup.sh             # Project initialization
├── ralph_import.sh      # PRD import tool
├── install.sh           # Global installation script
├── lib/                 # Modular library components
│   ├── circuit_breaker.sh
│   ├── response_analyzer.sh
│   └── date_utils.sh
├── templates/           # Project templates
├── tests/               # Test suite
│   ├── unit/            # Unit tests
│   ├── integration/     # Integration tests
│   ├── e2e/             # End-to-end tests
│   └── helpers/         # Test utilities
└── docs/                # Documentation

Development Workflow

Branch Naming Conventions

Always create a feature branch - never work directly on main:

Branch Type Format Example
New features feature/<feature-name> feature/log-rotation
Bug fixes fix/<issue-name> fix/rate-limit-reset
Documentation docs/<doc-update> docs/api-reference
Tests test/<test-area> test/circuit-breaker
Refactoring refactor/<area> refactor/response-analyzer
# Create a new feature branch
git checkout -b feature/my-awesome-feature

Commit Message Format

We use Conventional Commits for clear, structured commit history:

<type>(<scope>): <description>

[optional body]

[optional footer]

Types:

Type Description Example
feat New feature feat(loop): add dry-run mode
fix Bug fix fix(monitor): correct refresh rate
docs Documentation only docs(readme): update installation steps
test Adding/updating tests test(setup): add template validation tests
refactor Code change (no features/fixes) refactor(analyzer): simplify error detection
chore Maintenance tasks chore(deps): update bats-assert

Examples from Recent Commits:

# Feature addition
feat(import): add JSON output format support

# Bug fix with scope
fix(loop): replace non-existent --prompt-file with -p flag

# Documentation update
docs(status): update IMPLEMENTATION_STATUS.md with phased structure

# Test addition
test(cli): add 27 comprehensive CLI parsing tests

Writing Good Commit Messages:

  • Use imperative mood ("add" not "added")
  • Explain WHAT changed and WHY (not HOW)
  • Keep the subject line under 72 characters
  • Reference issues when applicable (fixes #123)

Workflow Diagram

┌─────────────────────────────────────────────────────────────────────┐
│                    Contribution Workflow                            │
└─────────────────────────────────────────────────────────────────────┘

  ┌──────────┐     ┌──────────┐     ┌──────────┐     ┌──────────┐
  │  1. Fork │────>│ 2. Clone │────>│ 3. Branch│────>│ 4. Code  │
  └──────────┘     └──────────┘     └──────────┘     └──────────┘
                                                           │
                                                           v
  ┌──────────┐     ┌──────────┐     ┌──────────┐     ┌──────────┐
  │ 8. Merge │<────│  7. PR   │<────│ 6. Push  │<────│ 5. Test  │
  └──────────┘     │ Approved │     └──────────┘     │ (100%)   │
                   └──────────┘                      └──────────┘
                        ^
                        │
                   ┌──────────┐
                   │  CI/CD   │
                   │  Passes  │
                   └──────────┘

Code Style Guidelines

Bash Best Practices

Ralph follows consistent bash conventions across all scripts:

File Structure:

#!/bin/bash
# Script description
# Purpose and usage notes

# Source dependencies
source "$(dirname "${BASH_SOURCE[0]}")/lib/date_utils.sh"

# Configuration constants (UPPER_CASE)
MAX_CALLS_PER_HOUR=100
CB_NO_PROGRESS_THRESHOLD=3
STATUS_FILE="status.json"

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

# Helper functions (snake_case)
helper_function() {
    local param1=$1
    local param2=$2
    # Implementation
}

# Main logic
main() {
    # Entry point
}

# Export functions for reuse
export -f helper_function

# Execute main if run directly
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main "$@"
fi

Naming Conventions:

Element Convention Example
Functions snake_case get_circuit_state()
Local variables snake_case local loop_count=0
Constants UPPER_SNAKE_CASE MAX_CALLS_PER_HOUR
File names snake_case.sh circuit_breaker.sh
Control files snake_case.md fix_plan.md, AGENT.md

Function Documentation:

# Get current circuit breaker state
# Returns the state as a string: CLOSED, HALF_OPEN, or OPEN
# Falls back to CLOSED if state file doesn't exist
get_circuit_state() {
    if [[ ! -f "$CB_STATE_FILE" ]]; then
        echo "$CB_STATE_CLOSED"
        return
    fi

    jq -r '.state' "$CB_STATE_FILE" 2>/dev/null || echo "$CB_STATE_CLOSED"
}

Error Handling:

# Always validate inputs
if [[ -z "$1" ]]; then
    echo -e "${RED}Error: Missing required argument${NC}" >&2
    exit 1
fi

# Use proper exit codes
# 0 = success, 1 = general error, 2 = invalid usage

Cross-Platform Compatibility:

# Use portable date commands
if command -v gdate &> /dev/null; then
    DATE_CMD="gdate"  # macOS with coreutils
else
    DATE_CMD="date"   # Linux
fi

JSON State Management:

# Always validate JSON before parsing
if ! jq '.' "$STATE_FILE" > /dev/null 2>&1; then
    echo "Error: Invalid JSON in state file"
    return 1
fi

# Use jq for safe parsing
local state=$(jq -r '.state' "$STATE_FILE" 2>/dev/null || echo "CLOSED")

Testing Requirements

Mandatory Testing Standards

All new features must include tests. This is non-negotiable.

Requirement Standard Enforcement
Test Pass Rate 100% Mandatory - CI blocks merge
Test Coverage 85% Aspirational - informational only

Note on Coverage: Bash code coverage with kcov cannot trace subprocess executions. Test pass rate is the enforced quality gate, not coverage percentage.

Test Organization

tests/
├── unit/                       # Fast, isolated tests
│   ├── test_cli_parsing.bats   # CLI argument tests
│   ├── test_json_parsing.bats  # JSON output parsing
│   ├── test_exit_detection.bats
│   ├── test_rate_limiting.bats
│   ├── test_session_continuity.bats
│   └── test_cli_modern.bats
├── integration/                # Multi-component tests
│   ├── test_loop_execution.bats
│   ├── test_edge_cases.bats
│   ├── test_installation.bats
│   ├── test_project_setup.bats
│   └── test_prd_import.bats
├── e2e/                        # End-to-end workflows
└── helpers/
    └── test_helper.bash        # Shared test utilities

Running Tests

Command Purpose When to Use
npm test Run all tests Before committing, before PR
npm run test:unit Unit tests only During development
npm run test:integration Integration tests only Testing interactions
bats tests/unit/test_file.bats Single test file Debugging specific tests

Writing Tests

Test Structure:

#!/usr/bin/env bats
# Unit Tests for Feature X

load '../helpers/test_helper'

# Setup runs before each test
setup() {
    source "$(dirname "$BATS_TEST_FILENAME")/../helpers/test_helper.bash"

    # Create isolated test environment
    export TEST_TEMP_DIR="$(mktemp -d /tmp/ralph-test.XXXXXX)"
    cd "$TEST_TEMP_DIR"

    # Initialize test state
    echo "0" > ".call_count"
}

# Teardown runs after each test
teardown() {
    cd /
    rm -rf "$TEST_TEMP_DIR"
}

# Test: Descriptive name explaining what's being tested
@test "can_make_call returns success when under limit" {
    echo "50" > ".call_count"
    export MAX_CALLS_PER_HOUR=100

    run can_make_call
    assert_success
}

# Test: Failure case
@test "can_make_call returns failure when at limit" {
    echo "100" > ".call_count"
    export MAX_CALLS_PER_HOUR=100

    run can_make_call
    assert_failure
}

Test Best Practices:

  1. Test both success and failure cases
  2. Use descriptive test names that explain the scenario
  3. Isolate tests - each test should be independent
  4. Mock external dependencies (Claude CLI, tmux, etc.)
  5. Test edge cases (empty files, invalid input, boundary values)
  6. Add comments for complex test scenarios

Available Test Helpers:

# From tests/helpers/test_helper.bash

assert_success      # Check command succeeded (exit 0)
assert_failure      # Check command failed (exit != 0)
assert_equal        # Compare two values
assert_output       # Check command output
assert_file_exists  # Verify file exists
assert_dir_exists   # Verify directory exists
strip_colors        # Remove ANSI color codes
create_mock_prompt  # Create test PROMPT.md
create_mock_fix_plan # Create test fix_plan.md
create_mock_status  # Create test status.json

Pull Request Process

Before Creating a PR

Run through this checklist:

  • All tests pass locally (npm test)
  • New code includes appropriate tests
  • Commits follow conventional format
  • Documentation updated if needed
  • No debug code or console.log statements
  • No secrets or credentials committed

Creating the PR

  1. Push your branch:

    git push origin feature/my-feature
  2. Open a Pull Request on GitHub with:

PR Title: Follow conventional commit format

feat(loop): add dry-run mode for testing

PR Description Template:

## Summary

Brief description of what this PR does (1-3 bullet points).

- Adds dry-run mode to preview loop execution
- Includes new CLI flag `--dry-run`
- Logs actions without making actual changes

## Test Plan

- [ ] Unit tests added/updated
- [ ] Integration tests added/updated
- [ ] Manual testing completed

## Related Issues

Fixes #123
Related to #456

## Screenshots (if applicable)

[Add screenshots for UI/output changes]

## Breaking Changes

[List any breaking changes, or "None"]

After PR Creation

  1. Wait for CI/CD - GitHub Actions will run all tests
  2. Address review feedback - Make requested changes promptly
  3. Keep PR updated - Rebase if main branch has changed

Code Review Guidelines

For Contributors

Responding to Feedback:

  • Thank reviewers for their time
  • Ask questions if requirements are unclear
  • Make requested changes promptly
  • Update PR description as changes evolve
  • Don't take feedback personally - it's about the code

If You Disagree:

  • Explain your reasoning clearly
  • Provide context for your decisions
  • Be open to alternative approaches
  • Defer to maintainer judgment when in doubt

For Reviewers

What to Check:

Area Questions to Ask
Correctness Does the code do what it claims?
Tests Are tests comprehensive? Do they pass?
Style Does it follow bash conventions?
Documentation Are comments and docs updated?
Breaking Changes Will this affect existing users?
Performance Any obvious performance issues?

Review Best Practices:

  1. Be constructive - Focus on improvements, not criticism
  2. Be specific - Point to exact lines when possible
  3. Explain why - Help contributors learn
  4. Acknowledge good work - Note well-written code
  5. Approve when ready - Don't hold PRs hostage

Quality Standards

Quality Gates

All PRs must pass these automated checks:

Gate Requirement Enforcement
Unit Tests 100% pass Blocks merge
Integration Tests 100% pass Blocks merge
Coverage 85% Informational only
Conventional Commits Required Manual review
Documentation Updated Manual review

Documentation Standards

When to Update Documentation:

  • Adding new CLI flags → Update README.md, CLAUDE.md
  • Adding new features → Update README.md "Features" section
  • Changing behavior → Update relevant docs
  • Adding new patterns → Update CLAUDE.md

Keep in Sync:

  1. CLAUDE.md - Technical specifications, quality standards
  2. README.md - User-facing documentation, installation
  3. Templates - Keep template files current
  4. Inline comments - Update when code changes

Feature Completion Checklist

Before marking any feature complete:

  • All tests pass (100% pass rate)
  • Script functionality manually tested
  • Commits follow conventional format
  • All commits pushed to remote
  • CI/CD pipeline passes
  • CLAUDE.md updated (if new patterns)
  • README.md updated (if user-facing)
  • Breaking changes documented
  • Installation verified (if applicable)

Community Guidelines

Priority Contribution Areas

High Priority - Help Needed!

  1. Test Implementation - Expand test coverage

  2. Feature Development

    • Log rotation functionality
    • Dry-run mode
    • Config file support (.ralphrc)
    • Metrics tracking
    • Desktop notifications
    • Backup/rollback system
  3. Documentation

    • Usage tutorials and examples
    • Troubleshooting guides
    • Video walkthroughs
  4. Real-World Testing

    • Use Ralph on your projects
    • Report bugs and edge cases
    • Share your experience

Communication

Before Major Changes:

  • Open an issue for discussion
  • Check existing issues for planned work
  • Join discussions on pull requests

Getting Help:

  • Review documentation first (README.md, CLAUDE.md)
  • Check IMPLEMENTATION_PLAN.md for roadmap
  • Open issues for questions
  • Reference related issues in discussions

Code of Conduct

  • Be respectful and professional
  • Welcome newcomers and help them succeed
  • Focus on constructive feedback
  • Assume good intentions
  • Celebrate diverse perspectives

Recognition

  • All contributors acknowledged in release notes
  • Significant contributions noted in README
  • Active contributors may become maintainers

Additional Resources


Thank you for contributing to Ralph! Your efforts help make autonomous AI development more accessible to everyone.

@github-actions
Copy link
Copy Markdown

REVIEW_PLACEHOLDER

@github-actions
Copy link
Copy Markdown

test with

@github-actions
Copy link
Copy Markdown

line1
line2
line3

@github-actions
Copy link
Copy Markdown

line1
line2
line3
last line

@github-actions
Copy link
Copy Markdown

heading

some text

@github-actions
Copy link
Copy Markdown

Ralph for Claude Code

CI
License: MIT
Version
Tests
GitHub Issues
Mentioned in Awesome Claude Code
Follow on X

Autonomous AI development loop with intelligent exit detection and rate limiting

Ralph is an implementation of the Geoffrey Huntley's technique for Claude Code that enables continuous autonomous development cycles he named after Ralph Wiggum. It enables continuous autonomous development cycles where Claude Code iteratively improves your project until completion, with built-in safeguards to prevent infinite loops and API overuse.

Install once, use everywhere - Ralph becomes a global command available in any directory.

Project Status

Version: v0.11.5 - Active Development
Core Features: Working and tested
Test Coverage: 566 tests, 100% pass rate

What's Working Now

  • Autonomous development loops with intelligent exit detection
  • Dual-condition exit gate: Requires BOTH completion indicators AND explicit EXIT_SIGNAL
  • Rate limiting with hourly reset (100 calls/hour, configurable)
  • Circuit breaker with advanced error detection (prevents runaway loops)
  • Response analyzer with semantic understanding and two-stage error filtering
  • JSON output format support with automatic fallback to text parsing
  • Session continuity with --resume flag for context preservation (no session hijacking)
  • Session expiration with configurable timeout (default: 24 hours)
  • Modern CLI flags: --output-format, --allowed-tools, --no-continue
  • Interactive project enablement with ralph-enable wizard
  • .ralphrc configuration file for project settings
  • Live streaming output with --live flag for real-time Claude Code visibility
  • Multi-line error matching for accurate stuck loop detection
  • 5-hour API limit handling with user prompts
  • tmux integration for live monitoring
  • PRD import functionality
  • CI/CD pipeline with GitHub Actions
  • Dedicated uninstall script for clean removal

Recent Improvements

v0.11.5 - Community Bug Fixes (latest)

v0.11.4 - Bug Fixes & Compatibility

v0.11.3 - Live Streaming & Beads Fix

v0.11.2 - Setup Permissions Fix

v0.11.1 - Completion Indicators Fix

  • Fixed premature exit after exactly 5 loops in JSON output mode
  • completion_indicators now only accumulates when EXIT_SIGNAL: true
  • Aligns with documented dual-condition exit gate behavior

v0.11.0 - Ralph Enable Wizard

  • Added ralph-enable interactive wizard for enabling Ralph in existing projects
  • 5-phase wizard: Environment Detection → Task Source Selection → Configuration → File Generation → Verification
  • Auto-detects project type (TypeScript, Python, Rust, Go) and framework (Next.js, FastAPI, Django)
  • Imports tasks from beads, GitHub Issues, or PRD documents
  • Added ralph-enable-ci non-interactive version for CI/automation
  • New library components: enable_core.sh, wizard_utils.sh, task_sources.sh

v0.10.1 - Bug Fixes & Monitor Path Corrections

  • Fixed ralph_monitor.sh hardcoded paths for v0.10.0 compatibility
  • Fixed EXIT_SIGNAL parsing in JSON format
  • Added safety circuit breaker (force exit after 5 consecutive completion indicators)
  • Fixed checkbox parsing for indented markdown

v0.10.0 - .ralph/ Subfolder Structure (BREAKING CHANGE)

  • Breaking: Moved all Ralph-specific files to .ralph/ subfolder
  • Project root stays clean: only src/, README.md, and user files remain
  • Added ralph-migrate command for upgrading existing projects
Earlier versions (v0.9.x)

v0.9.9 - EXIT_SIGNAL Gate & Uninstall Script

  • Fixed premature exit bug: completion indicators now require Claude's explicit EXIT_SIGNAL: true
  • Added dedicated uninstall.sh script for clean Ralph removal

v0.9.8 - Modern CLI for PRD Import

  • Modernized ralph_import.sh to use Claude Code CLI JSON output format
  • Enhanced error handling with structured JSON error messages

v0.9.7 - Session Lifecycle Management

  • Complete session lifecycle management with automatic reset triggers
  • Added --reset-session CLI flag for manual session reset

v0.9.6 - JSON Output & Session Management

  • Extended parse_json_response() to support Claude Code CLI JSON format
  • Added session management functions

v0.9.5 - v0.9.0 - PRD import tests, project setup tests, installation tests, prompt file fix, modern CLI commands, circuit breaker enhancements

In Progress

  • Expanding test coverage
  • Log rotation functionality
  • Dry-run mode
  • Metrics and analytics tracking
  • Desktop notifications
  • Git backup and rollback system
  • Automated badge updates

Timeline to v1.0: ~4 weeks | Full roadmap | Contributions welcome!

Features

  • Autonomous Development Loop - Continuously executes Claude Code with your project requirements
  • Intelligent Exit Detection - Dual-condition check requiring BOTH completion indicators AND explicit EXIT_SIGNAL
  • Session Continuity - Preserves context across loop iterations with automatic session management
  • Session Expiration - Configurable timeout (default: 24 hours) with automatic session reset
  • Rate Limiting - Built-in API call management with hourly limits and countdown timers
  • 5-Hour API Limit Handling - Three-layer detection (timeout guard, JSON parsing, filtered text) with auto-wait for unattended mode
  • Live Monitoring - Real-time dashboard showing loop status, progress, and logs
  • Task Management - Structured approach with prioritized task lists and progress tracking
  • Project Templates - Quick setup for new projects with best-practice structure
  • Interactive Project Setup - ralph-enable wizard for existing projects with task import
  • Configuration Files - .ralphrc for project-specific settings and tool permissions
  • Comprehensive Logging - Detailed execution logs with timestamps and status tracking
  • Configurable Timeouts - Set execution timeout for Claude Code operations (1-120 minutes)
  • Verbose Progress Mode - Optional detailed progress updates during execution
  • Response Analyzer - AI-powered analysis of Claude Code responses with semantic understanding
  • Circuit Breaker - Advanced error detection with two-stage filtering, multi-line error matching, and automatic recovery
  • CI/CD Integration - GitHub Actions workflow with automated testing
  • Clean Uninstall - Dedicated uninstall script for complete removal
  • Live Streaming Output - Real-time visibility into Claude Code execution with --live flag

Quick Start

Ralph has two phases: one-time installation and per-project setup.

INSTALL ONCE              USE MANY TIMES
+-----------------+          +----------------------+
| ./install.sh    |    ->    | ralph-setup project1 |
|                 |          | ralph-enable         |
| Adds global     |          | ralph-import prd.md  |
| commands        |          | ...                  |
+-----------------+          +----------------------+

Phase 1: Install Ralph (One Time Only)

Install Ralph globally on your system:

git clone https://github.com/frankbria/ralph-claude-code.git
cd ralph-claude-code
./install.sh

This adds ralph, ralph-monitor, ralph-setup, ralph-import, ralph-migrate, ralph-enable, and ralph-enable-ci commands to your PATH.

Note: You only need to do this once per system. After installation, you can delete the cloned repository if desired.

Phase 2: Initialize Projects (Per Project)

Option A: Enable Ralph in Existing Project (Recommended)

cd my-existing-project

# Interactive wizard - auto-detects project type and imports tasks
ralph-enable

# Or with specific task source
ralph-enable --from beads
ralph-enable --from github --label "sprint-1"
ralph-enable --from prd ./docs/requirements.md

# Start autonomous development
ralph --monitor

Option B: Import Existing PRD/Specifications

# Convert existing PRD/specs to Ralph format
ralph-import my-requirements.md my-project
cd my-project

# Review and adjust the generated files:
# - .ralph/PROMPT.md (Ralph instructions)
# - .ralph/fix_plan.md (task priorities)
# - .ralph/specs/requirements.md (technical specs)

# Start autonomous development
ralph --monitor

Option C: Create New Project from Scratch

# Create blank Ralph project
ralph-setup my-awesome-project
cd my-awesome-project

# Configure your project requirements manually
# Edit .ralph/PROMPT.md with your project goals
# Edit .ralph/specs/ with detailed specifications
# Edit .ralph/fix_plan.md with initial priorities

# Start autonomous development
ralph --monitor

Ongoing Usage (After Setup)

Once Ralph is installed and your project is initialized:

# Navigate to any Ralph project and run:
ralph --monitor              # Integrated tmux monitoring (recommended)

# Or use separate terminals:
ralph                        # Terminal 1: Ralph loop
ralph-monitor               # Terminal 2: Live monitor dashboard

Uninstalling Ralph

To completely remove Ralph from your system:

# Run the uninstall script
./uninstall.sh

# Or if you deleted the repo, download and run:
curl -sL https://raw.githubusercontent.com/frankbria/ralph-claude-code/main/uninstall.sh | bash

Understanding Ralph Files

After running ralph-enable or ralph-import, you'll have a .ralph/ directory with several files. Here's what each file does and whether you need to edit it:

File Auto-Generated? You Should...
.ralph/PROMPT.md Yes (smart defaults) Review & customize project goals and principles
.ralph/fix_plan.md Yes (can import tasks) Add/modify specific implementation tasks
.ralph/AGENT.md Yes (detects build commands) Rarely edit (auto-maintained by Ralph)
.ralph/specs/ Empty directory Add files when PROMPT.md isn't detailed enough
.ralph/specs/stdlib/ Empty directory Add reusable patterns and conventions
.ralphrc Yes (project-aware) Rarely edit (sensible defaults)

Key File Relationships

PROMPT.md (high-level goals)
    ↓
specs/ (detailed requirements when needed)
    ↓
fix_plan.md (specific tasks Ralph executes)
    ↓
AGENT.md (build/test commands - auto-maintained)

When to Use specs/

  • Simple projects: PROMPT.md + fix_plan.md is usually enough
  • Complex features: Add specs/feature-name.md for detailed requirements
  • Team conventions: Add specs/stdlib/convention-name.md for reusable patterns

See the User Guide for detailed explanations and the examples/ directory for realistic project configurations.

How It Works

Ralph operates on a simple but powerful cycle:

  1. Read Instructions - Loads PROMPT.md with your project requirements
  2. Execute Claude Code - Runs Claude Code with current context and priorities
  3. Track Progress - Updates task lists and logs execution results
  4. Evaluate Completion - Checks for exit conditions and project completion signals
  5. Repeat - Continues until project is complete or limits are reached

Intelligent Exit Detection

Ralph uses a dual-condition check to prevent premature exits during productive iterations:

Exit requires BOTH conditions:

  1. completion_indicators >= 2 (heuristic detection from natural language patterns)
  2. Claude's explicit EXIT_SIGNAL: true in the RALPH_STATUS block

Example behavior:

Loop 5: Claude outputs "Phase complete, moving to next feature"
        → completion_indicators: 3 (high confidence from patterns)
        → EXIT_SIGNAL: false (Claude says more work needed)
        → Result: CONTINUE (respects Claude's explicit intent)

Loop 8: Claude outputs "All tasks complete, project ready"
        → completion_indicators: 4
        → EXIT_SIGNAL: true (Claude confirms done)
        → Result: EXIT with "project_complete"

Other exit conditions:

  • All tasks in .ralph/fix_plan.md marked complete
  • Multiple consecutive "done" signals from Claude Code
  • Too many test-focused loops (indicating feature completeness)
  • Claude API 5-hour usage limit reached (with user prompt to wait or exit)

Enabling Ralph in Existing Projects

The ralph-enable command provides an interactive wizard for adding Ralph to existing projects:

cd my-existing-project
ralph-enable

The wizard:

  1. Detects Environment - Identifies project type (TypeScript, Python, etc.) and framework
  2. Selects Task Sources - Choose from beads, GitHub Issues, or PRD documents
  3. Configures Settings - Set tool permissions and loop parameters
  4. Generates Files - Creates .ralph/ directory and .ralphrc configuration
  5. Verifies Setup - Confirms all files are created correctly

Non-interactive mode for CI/automation:

ralph-enable-ci                              # Sensible defaults
ralph-enable-ci --from github               # Import from GitHub Issues
ralph-enable-ci --project-type typescript   # Override detection
ralph-enable-ci --json                      # Machine-readable output

Importing Existing Requirements

Ralph can convert existing PRDs, specifications, or requirement documents into the proper Ralph format using Claude Code.

Supported Formats

  • Markdown (.md) - Product requirements, technical specs
  • Text files (.txt) - Plain text requirements
  • JSON (.json) - Structured requirement data
  • Word documents (.docx) - Business requirements
  • PDFs (.pdf) - Design documents, specifications
  • Any text-based format - Ralph will intelligently parse the content

Usage Examples

# Convert a markdown PRD
ralph-import product-requirements.md my-app

# Convert a text specification
ralph-import requirements.txt webapp

# Convert a JSON API spec
ralph-import api-spec.json backend-service

# Let Ralph auto-name the project from filename
ralph-import design-doc.pdf

What Gets Generated

Ralph-import creates a complete project with:

  • .ralph/PROMPT.md - Converted into Ralph development instructions
  • .ralph/fix_plan.md - Requirements broken down into prioritized tasks
  • .ralph/specs/requirements.md - Technical specifications extracted from your document
  • .ralphrc - Project configuration file with tool permissions
  • Standard Ralph structure - All necessary directories and template files in .ralph/

The conversion is intelligent and preserves your original requirements while making them actionable for autonomous development.

Configuration

Project Configuration (.ralphrc)

Each Ralph project can have a .ralphrc configuration file:

# .ralphrc - Ralph project configuration
PROJECT_NAME="my-project"
PROJECT_TYPE="typescript"

# Claude Code CLI command (auto-detected, override if needed)
CLAUDE_CODE_CMD="claude"
# CLAUDE_CODE_CMD="npx @anthropic-ai/claude-code"  # Alternative: use npx

# Loop settings
MAX_CALLS_PER_HOUR=100
CLAUDE_TIMEOUT_MINUTES=15
CLAUDE_OUTPUT_FORMAT="json"

# Tool permissions
ALLOWED_TOOLS="Write,Read,Edit,Bash(git *),Bash(npm *),Bash(pytest)"

# Session management
SESSION_CONTINUITY=true
SESSION_EXPIRY_HOURS=24

# Circuit breaker thresholds
CB_NO_PROGRESS_THRESHOLD=3
CB_SAME_ERROR_THRESHOLD=5

Rate Limiting & Circuit Breaker

Ralph includes intelligent rate limiting and circuit breaker functionality:

# Default: 100 calls per hour
ralph --calls 50

# With integrated monitoring
ralph --monitor --calls 50

# Check current usage
ralph --status

The circuit breaker automatically:

  • Detects API errors and rate limit issues with advanced two-stage filtering
  • Opens circuit after 3 loops with no progress or 5 loops with same errors
  • Eliminates false positives from JSON fields containing "error"
  • Accurately detects stuck loops with multi-line error matching
  • Gradually recovers with half-open monitoring state
  • Auto-recovers after cooldown period (default: 30 minutes) — OPEN → HALF_OPEN → CLOSED
  • Provides detailed error tracking and logging with state history

Auto-recovery options:

# Default: 30-minute cooldown before auto-recovery attempt
CB_COOLDOWN_MINUTES=30     # Set in .ralphrc (0 = immediate)

# Auto-reset on startup (for fully unattended operation)
ralph --auto-reset-circuit
# Or set in .ralphrc: CB_AUTO_RESET=true

Claude API 5-Hour Limit

When Claude's 5-hour usage limit is reached, Ralph:

  1. Detects the limit using three-layer verification (timeout guard → structural JSON → filtered text fallback)
  2. Prompts you to choose:
    • Option 1: Wait 60 minutes for the limit to reset (with countdown timer)
    • Option 2: Exit gracefully
  3. Unattended mode: Auto-waits on prompt timeout (30s) instead of exiting
  4. Prevents false positives from echoed file content mentioning "5-hour limit"

Custom Prompts

# Use custom prompt file
ralph --prompt my_custom_instructions.md

# With integrated monitoring
ralph --monitor --prompt my_custom_instructions.md

Execution Timeouts

# Set Claude Code execution timeout (default: 15 minutes)
ralph --timeout 30  # 30-minute timeout for complex tasks

# With monitoring and custom timeout
ralph --monitor --timeout 60  # 60-minute timeout

# Short timeout for quick iterations
ralph --verbose --timeout 5  # 5-minute timeout with progress

Verbose Mode

# Enable detailed progress updates during execution
ralph --verbose

# Combine with other options
ralph --monitor --verbose --timeout 30

Live Streaming Output

# Enable real-time visibility into Claude Code execution
ralph --live

# Combine with monitoring for best experience
ralph --monitor --live

# Live output is written to .ralph/live.log
tail -f .ralph/live.log  # Watch in another terminal

Live streaming mode shows Claude Code's output in real-time as it works, providing visibility into what's happening during each loop iteration.

Session Continuity

Ralph maintains session context across loop iterations for improved coherence:

# Sessions are enabled by default with --continue flag
ralph --monitor                 # Uses session continuity

# Start fresh without session context
ralph --no-continue             # Isolated iterations

# Reset session manually (clears context)
ralph --reset-session           # Clears current session

# Check session status
cat .ralph/.ralph_session              # View current session file
cat .ralph/.ralph_session_history      # View session transition history

Session Auto-Reset Triggers:

  • Circuit breaker opens (stagnation detected)
  • Manual interrupt (Ctrl+C / SIGINT)
  • Project completion (graceful exit)
  • Manual circuit breaker reset (--reset-circuit)
  • Session expiration (default: 24 hours)

Sessions are persisted to .ralph/.ralph_session with a configurable expiration (default: 24 hours). The last 50 session transitions are logged to .ralph/.ralph_session_history for debugging.

Exit Thresholds

Modify these variables in ~/.ralph/ralph_loop.sh:

Exit Detection Thresholds:

MAX_CONSECUTIVE_TEST_LOOPS=3     # Exit after 3 test-only loops
MAX_CONSECUTIVE_DONE_SIGNALS=2   # Exit after 2 "done" signals
TEST_PERCENTAGE_THRESHOLD=30     # Flag if 30%+ loops are test-only

Circuit Breaker Thresholds:

CB_NO_PROGRESS_THRESHOLD=3       # Open circuit after 3 loops with no file changes
CB_SAME_ERROR_THRESHOLD=5        # Open circuit after 5 loops with repeated errors
CB_OUTPUT_DECLINE_THRESHOLD=70   # Open circuit if output declines by >70%
CB_COOLDOWN_MINUTES=30           # Minutes before OPEN → HALF_OPEN auto-recovery
CB_AUTO_RESET=false              # true = reset to CLOSED on startup (bypasses cooldown)

Completion Indicators with EXIT_SIGNAL Gate:

completion_indicators EXIT_SIGNAL Result
>= 2 true Exit ("project_complete")
>= 2 false Continue (Claude still working)
>= 2 missing Continue (defaults to false)
< 2 true Continue (threshold not met)

Project Structure

Ralph creates a standardized structure for each project with a .ralph/ subfolder for configuration:

my-project/
├── .ralph/                 # Ralph configuration and state (hidden folder)
│   ├── PROMPT.md           # Main development instructions for Ralph
│   ├── fix_plan.md        # Prioritized task list
│   ├── AGENT.md           # Build and run instructions
│   ├── specs/              # Project specifications and requirements
│   │   └── stdlib/         # Standard library specifications
│   ├── examples/           # Usage examples and test cases
│   ├── logs/               # Ralph execution logs
│   └── docs/generated/     # Auto-generated documentation
├── .ralphrc                # Ralph configuration file (tool permissions, settings)
└── src/                    # Source code implementation (at project root)

Migration: If you have existing Ralph projects using the old flat structure, run ralph-migrate to automatically move files to the .ralph/ subfolder.

Best Practices

Writing Effective Prompts

  1. Be Specific - Clear requirements lead to better results
  2. Prioritize - Use .ralph/fix_plan.md to guide Ralph's focus
  3. Set Boundaries - Define what's in/out of scope
  4. Include Examples - Show expected inputs/outputs

Project Specifications

  • Place detailed requirements in .ralph/specs/
  • Use .ralph/fix_plan.md for prioritized task tracking
  • Keep .ralph/AGENT.md updated with build instructions
  • Document key decisions and architecture

Monitoring Progress

  • Use ralph-monitor for live status updates
  • Check logs in .ralph/logs/ for detailed execution history
  • Monitor .ralph/status.json for programmatic access
  • Watch for exit condition signals

System Requirements

  • Bash 4.0+ - For script execution
  • Claude Code CLI - npm install -g @anthropic-ai/claude-code (or use npx — set CLAUDE_CODE_CMD in .ralphrc)
  • tmux - Terminal multiplexer for integrated monitoring (recommended)
  • jq - JSON processing for status tracking
  • Git - Version control (projects are initialized as git repos)
  • GNU coreutils - For the timeout command (execution timeouts)
    • Linux: Pre-installed on most distributions
    • macOS: Install via brew install coreutils (provides gtimeout)
  • Standard Unix tools - grep, date, etc.

Testing Requirements (Development)

See TESTING.md for the comprehensive testing guide.

If you want to run the test suite:

# Install BATS testing framework
npm install -g bats bats-support bats-assert

# Run all tests (566 tests)
npm test

# Run specific test suites
bats tests/unit/test_rate_limiting.bats
bats tests/unit/test_exit_detection.bats
bats tests/unit/test_json_parsing.bats
bats tests/unit/test_cli_modern.bats
bats tests/unit/test_cli_parsing.bats
bats tests/unit/test_session_continuity.bats
bats tests/unit/test_enable_core.bats
bats tests/unit/test_task_sources.bats
bats tests/unit/test_ralph_enable.bats
bats tests/unit/test_wizard_utils.bats
bats tests/unit/test_circuit_breaker_recovery.bats
bats tests/integration/test_loop_execution.bats
bats tests/integration/test_prd_import.bats
bats tests/integration/test_project_setup.bats
bats tests/integration/test_installation.bats

# Run error detection and circuit breaker tests
./tests/test_error_detection.sh
./tests/test_stuck_loop_detection.sh

Current test status:

  • 566 tests across 18 test files
  • 100% pass rate (556/556 passing)
  • Comprehensive unit and integration tests
  • Specialized tests for JSON parsing, CLI flags, circuit breaker, EXIT_SIGNAL behavior, enable wizard, and installation workflows

Note on Coverage: Bash code coverage measurement with kcov has fundamental limitations when tracing subprocess executions. Test pass rate (100%) is the quality gate. See bats-core#15 for details.

Installing tmux

# Ubuntu/Debian
sudo apt-get install tmux

# macOS
brew install tmux

# CentOS/RHEL
sudo yum install tmux

Installing GNU coreutils (macOS)

Ralph uses the timeout command for execution timeouts. On macOS, you need to install GNU coreutils:

# Install coreutils (provides gtimeout)
brew install coreutils

# Verify installation
gtimeout --version

Ralph automatically detects and uses gtimeout on macOS. No additional configuration is required after installation.

Monitoring and Debugging

Live Dashboard

# Integrated tmux monitoring (recommended)
ralph --monitor

# Manual monitoring in separate terminal
ralph-monitor

Shows real-time:

  • Current loop count and status
  • API calls used vs. limit
  • Recent log entries
  • Rate limit countdown

tmux Controls:

  • Ctrl+B then D - Detach from session (keeps Ralph running)
  • Ctrl+B then ←/→ - Switch between panes
  • tmux list-sessions - View active sessions
  • tmux attach -t <session-name> - Reattach to session

Status Checking

# JSON status output
ralph --status

# Manual log inspection
tail -f .ralph/logs/ralph.log

Common Issues

  • Ralph exits silently on first loop - Claude Code CLI may not be installed or not in PATH. Ralph validates the command at startup and shows installation instructions. If using npx, add CLAUDE_CODE_CMD="npx @anthropic-ai/claude-code" to .ralphrc
  • Rate Limits - Ralph automatically waits and displays countdown
  • 5-Hour API Limit - Ralph detects and prompts for user action (wait or exit)
  • Stuck Loops - Check fix_plan.md for unclear or conflicting tasks
  • Early Exit - Review exit thresholds if Ralph stops too soon
  • Premature Exit - Check if Claude is setting EXIT_SIGNAL: false (Ralph now respects this)
  • Execution Timeouts - Increase --timeout value for complex operations
  • Missing Dependencies - Ensure Claude Code CLI and tmux are installed
  • tmux Session Lost - Use tmux list-sessions and tmux attach to reconnect
  • Session Expired - Sessions expire after 24 hours by default; use --reset-session to start fresh
  • timeout: command not found (macOS) - Install GNU coreutils: brew install coreutils
  • Permission Denied - Ralph halts when Claude Code is denied permission for commands:
    1. Edit .ralphrc and update ALLOWED_TOOLS to include required tools
    2. Common patterns: Bash(npm *), Bash(git *), Bash(pytest)
    3. Run ralph --reset-session after updating .ralphrc
    4. Restart with ralph --monitor

Contributing

Ralph is actively seeking contributors! We're working toward v1.0.0 with clear priorities and a detailed roadmap.

See CONTRIBUTING.md for the complete contributor guide including:

  • Getting started and setup instructions
  • Development workflow and commit conventions
  • Code style guidelines
  • Testing requirements (100% pass rate mandatory)
  • Pull request process and code review guidelines
  • Quality standards and checklists

Quick Start

# Fork and clone
git clone https://github.com/YOUR_USERNAME/ralph-claude-code.git
cd ralph-claude-code

# Install dependencies and run tests
npm install
npm test  # All 566 tests must pass

Priority Contribution Areas

  1. Test Implementation - Help expand test coverage
  2. Feature Development - Log rotation, dry-run mode, metrics
  3. Documentation - Tutorials, troubleshooting guides, examples
  4. Real-World Testing - Use Ralph, report bugs, share feedback

Every contribution matters - from fixing typos to implementing major features!

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

  • Inspired by the Ralph technique created by Geoffrey Huntley
  • Built for Claude Code by Anthropic
  • Community feedback and contributions

Related Projects

  • Claude Code - The AI coding assistant that powers Ralph
  • Aider - Original Ralph technique implementation

Command Reference

Installation Commands (Run Once)

./install.sh              # Install Ralph globally
./uninstall.sh            # Remove Ralph from system (dedicated script)
./install.sh uninstall    # Alternative: Remove Ralph from system
./install.sh --help       # Show installation help
ralph-migrate             # Migrate existing project to .ralph/ structure

Ralph Loop Options

ralph [OPTIONS]
  -h, --help              Show help message
  -c, --calls NUM         Set max calls per hour (default: 100)
  -p, --prompt FILE       Set prompt file (default: PROMPT.md)
  -s, --status            Show current status and exit
  -m, --monitor           Start with tmux session and live monitor
  -v, --verbose           Show detailed progress updates during execution
  -l, --live              Enable live streaming output (real-time Claude Code visibility)
  -t, --timeout MIN       Set Claude Code execution timeout in minutes (1-120, default: 15)
  --output-format FORMAT  Set output format: json (default) or text
  --allowed-tools TOOLS   Set allowed Claude tools (default: Write,Read,Edit,Bash(git *),Bash(npm *),Bash(pytest))
  --no-continue           Disable session continuity (start fresh each loop)
  --reset-circuit         Reset the circuit breaker
  --circuit-status        Show circuit breaker status
  --auto-reset-circuit    Auto-reset circuit breaker on startup (bypasses cooldown)
  --reset-session         Reset session state manually

Project Commands (Per Project)

ralph-setup project-name     # Create new Ralph project
ralph-enable                 # Enable Ralph in existing project (interactive)
ralph-enable-ci              # Enable Ralph in existing project (non-interactive)
ralph-import prd.md project  # Convert PRD/specs to Ralph project
ralph --monitor              # Start with integrated monitoring
ralph --status               # Check current loop status
ralph --verbose              # Enable detailed progress updates
ralph --timeout 30           # Set 30-minute execution timeout
ralph --calls 50             # Limit to 50 API calls per hour
ralph --reset-session        # Reset session state manually
ralph --live                 # Enable live streaming output
ralph-monitor                # Manual monitoring dashboard

tmux Session Management

tmux list-sessions        # View active Ralph sessions
tmux attach -t <name>     # Reattach to detached session
# Ctrl+B then D           # Detach from session (keeps running)

Development Roadmap

Ralph is under active development with a clear path to v1.0.0. See IMPLEMENTATION_PLAN.md for the complete roadmap.

Current Status: v0.11.5

What's Delivered:

  • Core loop functionality with intelligent exit detection
  • Dual-condition exit gate (completion indicators + EXIT_SIGNAL)
  • Rate limiting (100 calls/hour) and circuit breaker pattern
  • Response analyzer with semantic understanding
  • 556 comprehensive tests (100% pass rate)
  • Live streaming output mode for real-time Claude Code visibility
  • tmux integration and live monitoring
  • PRD import functionality with modern CLI JSON parsing
  • Installation system and project templates
  • Modern CLI commands with JSON output support
  • CI/CD pipeline with GitHub Actions
  • Interactive ralph-enable wizard for existing projects
  • .ralphrc configuration file support
  • Session lifecycle management with auto-reset triggers
  • Session expiration with configurable timeout
  • Dedicated uninstall script

Test Coverage Breakdown:

  • Unit Tests: 420 (CLI parsing, JSON, exit detection, rate limiting, session continuity, enable wizard, live streaming, circuit breaker recovery, file protection, integrity checks)
  • Integration Tests: 136 (loop execution, edge cases, installation, project setup, PRD import)
  • Test Files: 18

Path to v1.0.0 (~4 weeks)

Enhanced Testing

  • Installation and setup workflow tests
  • tmux integration tests
  • Monitor dashboard tests

Core Features

  • Log rotation functionality
  • Dry-run mode

Advanced Features & Polish

  • Metrics and analytics tracking
  • Desktop notifications
  • Git backup and rollback system
  • End-to-end tests
  • Final documentation and release prep

See IMPLEMENTATION_STATUS.md for detailed progress tracking.

How to Contribute

Ralph is seeking contributors! See CONTRIBUTING.md for the complete guide. Priority areas:

  1. Test Implementation - Help expand test coverage (see plan)
  2. Feature Development - Log rotation, dry-run mode, metrics
  3. Documentation - Usage examples, tutorials, troubleshooting guides
  4. Bug Reports - Real-world usage feedback and edge cases

Ready to let AI build your project? Start with ./install.sh and let Ralph take it from there!

Star History

Star History Chart

@github-actions
Copy link
Copy Markdown

Review part 1 of 4: The core bug fix is clean and correct. Removing the unconditional line-27 assignment of CLAUDE_CODE_CMD and replacing it with the default-value syntax (CLAUDE_CODE_CMD:-claude) after the env snapshot is exactly the right approach. The CLAUDE_MODEL and CLAUDE_EFFORT additions follow the established env-snapshot/default/restore pattern perfectly. Positive observations: (1) Regression test for the root bug (checking for the default-value syntax) is a smart way to guard against that class of mistake recurring. (2) All 8 new tests are targeted and meaningful -- they test behavior, not just coverage. (3) The fix is minimal and surgical -- no unrelated changes.

@github-actions
Copy link
Copy Markdown

Review part 2 of 4 -- Issues to address: (1) templates/ralphrc.template not updated: The .ralphrc template file and the generated version in lib/enable_core.sh do not include commented-out entries for the new variables. Users who run ralph enable or ralph-setup get a .ralphrc without any hint that CLAUDE_MODEL and CLAUDE_EFFORT exist. Adding them as commented-out optional settings in the Advanced Settings section would make discoverability much better (e.g. CLAUDE_MODEL="" with comment 'Model override, empty = CLI default' and CLAUDE_EFFORT="" with 'Effort level, valid values: low/medium/high'). (2) CLAUDE.md not updated: The Modern CLI Configuration section lists configuration variables but does not include CLAUDE_MODEL or CLAUDE_EFFORT. Per the project's own standards, implementation documentation must stay synchronized with the codebase.

@github-actions
Copy link
Copy Markdown

Review part 3 of 4 -- Issues (continued): (3) No validation of CLAUDE_EFFORT value: The --effort flag accepts a specific set of values (low/medium/high). If a user sets CLAUDE_EFFORT with a typo (e.g. 'meduim'), the error will come from the Claude CLI at runtime with no context about where the bad value came from. A simple warn-only guard in build_claude_command would improve UX -- a case statement matching low|medium|high, logging WARN for unexpected values, then still passing the value through. This is non-blocking, so it will not break operation if the CLI ever adds new values.

@github-actions
Copy link
Copy Markdown

Review part 4 of 4 -- Minor notes and summary: Minor notes: (a) The test 'CLAUDE_MODEL env var takes precedence over .ralphrc' pre-sets CLAUDE_MODEL before calling load_ralphrc. This works but relies on load_ralphrc not overwriting an already-set value when _env_CLAUDE_MODEL is non-empty. The logic is correct, just worth confirming the test accurately reflects the real startup sequence (env var exported -> snapshot captures it -> ralphrc cannot overwrite). (b) The build_claude_command stub in the test file now duplicates the --model/--effort block from production. This is expected for the test harness pattern used throughout this file, but it means both places need updating if the flag names change in the Claude CLI. Summary: The bug fix is solid and well-tested. The main gaps are documentation (CLAUDE.md and ralphrc.template) -- these are called out explicitly in the project's own Feature Completion Checklist. The effort validation is a nice-to-have. With those addressed this is ready to merge.

@github-actions
Copy link
Copy Markdown

Review comment test - checking if direct body posting works

@github-actions
Copy link
Copy Markdown

Deleting previous test comment — full review incoming.

@github-actions
Copy link
Copy Markdown

Review — Building on Prior Feedback

The core fix is solid (covered well in previous reviews). This note focuses on what still needs to land before merge.

@github-actions
Copy link
Copy Markdown

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Repository Overview

This is the Ralph for Claude Code repository - an autonomous AI development loop system that enables continuous development cycles with intelligent exit detection and rate limiting.

See README.md for version info, changelog, and user documentation.

Core Architecture

The system consists of four main bash scripts and a modular library system:

Main Scripts

  1. ralph_loop.sh - The main autonomous loop that executes Claude Code repeatedly
  2. ralph_monitor.sh - Live monitoring dashboard for tracking loop status
  3. setup.sh - Project initialization script for new Ralph projects
  4. create_files.sh - Bootstrap script that creates the entire Ralph system
  5. ralph_import.sh - PRD/specification import tool that converts documents to Ralph format
    • Uses modern Claude Code CLI with --output-format json for structured responses
    • Implements detect_response_format() and parse_conversion_response() for JSON parsing
    • Backward compatible with older CLI versions (automatic text fallback)
  6. ralph_enable.sh - Interactive wizard for enabling Ralph in existing projects
    • Multi-step wizard with environment detection, task source selection, configuration
    • Imports tasks from beads, GitHub Issues, or PRD documents
    • Generates .ralphrc project configuration file
  7. ralph_enable_ci.sh - Non-interactive version for CI/automation
    • Same functionality as interactive version with CLI flags
    • JSON output mode for machine parsing
    • Exit codes: 0 (success), 1 (error), 2 (already enabled)

Library Components (lib/)

The system uses a modular architecture with reusable components in the lib/ directory:

  1. lib/circuit_breaker.sh - Circuit breaker pattern implementation

    • Prevents runaway loops by detecting stagnation
    • Three states: CLOSED (normal), HALF_OPEN (monitoring), OPEN (halted)
    • Configurable thresholds for no-progress and error detection
    • Automatic state transitions and recovery
  2. lib/response_analyzer.sh - Intelligent response analysis

    • Analyzes Claude Code output for completion signals
    • JSON output format detection and parsing (with text fallback)
    • Supports both flat JSON format and Claude CLI format (result, sessionId, metadata)
    • Extracts structured fields: status, exit_signal, work_type, files_modified, asking_questions, question_count
    • Question detection: detect_questions() with QUESTION_PATTERNS array — detects when Claude asks questions instead of acting autonomously (Issue [BUG] Loop persistence misidentified as active session despite "completed" status in progress.json #190)
    • Session management: store_session_id(), get_last_session_id(), should_resume_session()
    • Automatic session persistence to .ralph/.claude_session_id file with 24-hour expiration
    • Session lifecycle: get_session_id(), reset_session(), log_session_transition(), init_session_tracking()
    • Session history tracked in .ralph/.ralph_session_history (last 50 transitions)
    • Session auto-reset on: circuit breaker open, manual interrupt, project completion
    • Detects test-only loops, stuck error patterns, and question-only loops
    • Two-stage error filtering to eliminate false positives
    • Multi-line error matching for accurate stuck loop detection
    • Confidence scoring for exit decisions
  3. lib/date_utils.sh - Cross-platform date utilities

    • ISO timestamp generation for logging
    • Epoch time calculations for rate limiting
    • ISO-to-epoch conversion for cooldown timer comparisons (parse_iso_to_epoch())
  4. lib/timeout_utils.sh - Cross-platform timeout command utilities

    • Detects and uses appropriate timeout command for the platform
    • Linux: Uses standard timeout from GNU coreutils
    • macOS: Uses gtimeout from Homebrew coreutils
    • portable_timeout() function for seamless cross-platform execution
    • Automatic detection with caching for performance
  5. lib/enable_core.sh - Shared logic for ralph enable commands

    • Idempotency checks: check_existing_ralph(), is_ralph_enabled()
    • Safe file operations: safe_create_file(), safe_create_dir()
    • Project detection: detect_project_context(), detect_git_info(), detect_task_sources()
    • Template generation: generate_prompt_md(), generate_agent_md(), generate_fix_plan_md(), generate_ralphrc()
  6. lib/wizard_utils.sh - Interactive prompt utilities for enable wizard

    • User prompts: confirm(), prompt_text(), prompt_number()
    • Selection utilities: select_option(), select_multiple(), select_with_default()
    • Output formatting: print_header(), print_bullet(), print_success/warning/error/info()
    • POSIX-compatible: Uses tr '[:upper:]' '[:lower:]' instead of ${,,} for bash 3.x support (Issue Ralph import from prd leads to bad substitution error #187)
  7. lib/task_sources.sh - Task import from external sources

    • Beads integration: check_beads_available(), fetch_beads_tasks(), get_beads_count()
    • GitHub integration: check_github_available(), fetch_github_tasks(), get_github_issue_count()
    • PRD extraction: extract_prd_tasks(), supports checkbox and numbered list formats
    • Task normalization: normalize_tasks(), prioritize_tasks(), import_tasks_from_sources()
  8. lib/file_protection.sh - File integrity validation for Ralph projects (Issue Bug: ralph deletes its own .ralph/ directory during cleanup + .ralphrc not generated #149)

    • RALPH_REQUIRED_PATHS array: critical files needed for the loop to function
    • validate_ralph_integrity(): checks all required paths exist, sets RALPH_MISSING_FILES
    • get_integrity_report(): human-readable report with missing files and recovery instructions
    • Lightweight validation that runs every loop iteration

Key Commands

Installation

# Install Ralph globally (run once)
./install.sh

# Uninstall Ralph
./install.sh uninstall

Setting Up a New Project

# Create a new Ralph-managed project (run from anywhere)
ralph-setup my-project-name
cd my-project-name

Migrating Existing Projects

# Migrate from flat structure to .ralph/ subfolder (v0.10.0+)
cd existing-project
ralph-migrate

Enabling Ralph in Existing Projects

# Interactive wizard (recommended for humans)
cd existing-project
ralph-enable

# With specific task source
ralph-enable --from beads
ralph-enable --from github --label "sprint-1"
ralph-enable --from prd ./docs/requirements.md

# Force overwrite existing .ralph/
ralph-enable --force

# Non-interactive for CI/scripts
ralph-enable-ci                              # Sensible defaults
ralph-enable-ci --from github               # With task source
ralph-enable-ci --project-type typescript   # Override detection
ralph-enable-ci --json                      # Machine-readable output

Running the Ralph Loop

# Start with integrated tmux monitoring (recommended)
ralph --monitor

# Start without monitoring
ralph

# With custom parameters and monitoring
ralph --monitor --calls 50 --prompt my_custom_prompt.md

# Check current status
ralph --status

# Circuit breaker management
ralph --reset-circuit
ralph --circuit-status
ralph --auto-reset-circuit   # Auto-reset OPEN state on startup

# Session management
ralph --reset-session    # Reset session state manually

Monitoring

# Integrated tmux monitoring (recommended)
ralph --monitor

# Manual monitoring in separate terminal
ralph-monitor

# tmux session management
tmux list-sessions
tmux attach -t <session-name>

Running Tests

# Run all tests
npm test

# Run specific test suites
npm run test:unit
npm run test:integration

# Run individual test files
bats tests/unit/test_cli_parsing.bats
bats tests/unit/test_json_parsing.bats
bats tests/unit/test_cli_modern.bats
bats tests/unit/test_enable_core.bats
bats tests/unit/test_task_sources.bats
bats tests/unit/test_ralph_enable.bats
bats tests/unit/test_circuit_breaker_recovery.bats
bats tests/unit/test_file_protection.bats
bats tests/unit/test_integrity_check.bats

Ralph Loop Configuration

The loop is controlled by several key files and environment variables within the .ralph/ subfolder:

  • .ralph/PROMPT.md - Main prompt file that drives each loop iteration
  • .ralph/fix_plan.md - Prioritized task list that Ralph follows
  • .ralph/AGENT.md - Build and run instructions maintained by Ralph
  • .ralph/status.json - Real-time status tracking (JSON format)
  • .ralph/logs/ - Execution logs for each loop iteration

Rate Limiting

  • Default: 100 API calls per hour (configurable via --calls flag)
  • Automatic hourly reset with countdown display
  • Call tracking persists across script restarts

Modern CLI Configuration (Phase 1.1)

Ralph uses modern Claude Code CLI flags for structured communication:

Configuration Variables:

CLAUDE_CODE_CMD="claude"              # Claude Code CLI command (configurable via .ralphrc, Issue #97)
CLAUDE_OUTPUT_FORMAT="json"           # Output format: json (default) or text
CLAUDE_ALLOWED_TOOLS="Write,Read,Edit,Bash(git add *),Bash(git commit *),...,Bash(npm *),Bash(pytest)"  # Allowed tool permissions (see File Protection)
CLAUDE_USE_CONTINUE=true              # Enable session continuity
CLAUDE_MIN_VERSION="2.0.76"           # Minimum Claude CLI version
CLAUDE_AUTO_UPDATE=true               # Auto-update Claude CLI at startup (set false for air-gapped environments)

Auto-Update Configuration:

  • CLAUDE_AUTO_UPDATE controls whether Ralph checks npm registry and attempts npm update -g at startup
  • Local workstation / home server: Keep true (default) — CLI updates include bug fixes and new features that improve Ralph's effectiveness. The 200-500ms startup overhead is negligible for loops that run hours
  • Docker container: Set false in .ralphrc — container is ephemeral and version is pinned at image build time. The npm registry query and potential update are pure overhead
  • Air-gapped environment: Set false — npm registry is unreachable, the check will timeout and log a warning
  • Update failure is non-blocking: Ralph logs a warning and continues the loop normally

Claude Code CLI Command (Issue #97):

  • CLAUDE_CODE_CMD defaults to "claude" (global install)
  • Configurable via .ralphrc for alternative installations (e.g., "npx @anthropic-ai/claude-code")
  • Auto-detected during ralph-enable and ralph-setup (prefers claude if available, falls back to npx)
  • Validated at startup with validate_claude_command() — displays clear error with installation instructions if not found
  • After validation, check_claude_version() verifies minimum version compatibility and check_claude_updates() queries npm registry for latest version with auto-update attempt (Issue [BUG] Loop persistence misidentified as active session despite "completed" status in progress.json #190)
  • Both functions use compare_semver() for proper major→minor→patch sequential comparison (safe for any patch number, unlike integer arithmetic)
  • Environment variable CLAUDE_CODE_CMD takes precedence over .ralphrc

CLI Options:

  • --output-format json|text - Set Claude output format (default: json). Note: --live mode requires JSON and will auto-switch from text to json.
  • --allowed-tools "Write,Read,Bash(git *)" - Restrict allowed tools
  • --no-continue - Disable session continuity, start fresh each loop

Loop Context:
Each loop iteration injects context via build_loop_context():

Session Continuity:

  • Sessions are preserved in .ralph/.claude_session_id
  • Use --continue flag to maintain context across loops
  • Disable with --no-continue for isolated iterations

Intelligent Exit Detection

The loop uses a dual-condition check to prevent premature exits during productive iterations:

Exit requires BOTH conditions:

  1. recent_completion_indicators >= 2 (heuristic-based detection from natural language patterns)
  2. Claude's explicit EXIT_SIGNAL: true in the RALPH_STATUS block

The EXIT_SIGNAL value is read from .ralph/.response_analysis (at .analysis.exit_signal) which is populated by response_analyzer.sh from Claude's RALPH_STATUS output block.

Other exit conditions (checked before completion indicators):

  • Multiple consecutive "done" signals from Claude Code (done_signals >= 2)
  • Too many test-only loops indicating feature completeness (test_loops >= 3)
  • All items in .ralph/fix_plan.md marked as completed

Example behavior when EXIT_SIGNAL is false:

Loop 5: Claude outputs "Phase complete, moving to next feature"
        → completion_indicators: 3 (high confidence from patterns)
        → EXIT_SIGNAL: false (Claude explicitly says more work needed)
        → Result: CONTINUE (respects Claude's explicit intent)

Loop 8: Claude outputs "All tasks complete, project ready"
        → completion_indicators: 4
        → EXIT_SIGNAL: true (Claude confirms project is done)
        → Result: EXIT with "project_complete"

Rationale: Natural language patterns like "done" or "complete" can trigger false positives during productive work (e.g., "feature done, moving to tests"). By requiring Claude's explicit EXIT_SIGNAL confirmation, Ralph avoids exiting mid-iteration when Claude is still working.

CI/CD Pipeline

Ralph uses GitHub Actions for continuous integration:

Workflows (.github/workflows/)

  1. test.yml - Main test suite

    • Runs on push to main/develop and PRs to main
    • Executes unit, integration, and E2E tests
    • Coverage reporting with kcov (informational only)
    • Uploads coverage artifacts
  2. claude.yml - Claude Code GitHub Actions integration

    • Automated code review capabilities
  3. claude-code-review.yml - PR code review workflow

    • Automated review on pull requests

Coverage Note

Bash code coverage measurement with kcov has fundamental limitations when tracing subprocess executions. The COVERAGE_THRESHOLD is set to 0 (disabled) because kcov cannot instrument subprocesses spawned by bats. Test pass rate (100%) is the quality gate. See bats-core#15 for details.

Project Structure for Ralph-Managed Projects

Each project created with ./setup.sh follows this structure with a .ralph/ subfolder:

project-name/
├── .ralph/                # Ralph configuration and state (hidden folder)
│   ├── PROMPT.md          # Main development instructions
│   ├── fix_plan.md       # Prioritized TODO list
│   ├── AGENT.md          # Build/run instructions
│   ├── specs/             # Project specifications
│   ├── examples/          # Usage examples
│   ├── logs/              # Loop execution logs
│   └── docs/generated/    # Auto-generated documentation
└── src/                   # Source code (at project root)

Migration: Existing projects can be migrated with ralph-migrate.

Template System

Templates in templates/ provide starting points for new projects:

  • PROMPT.md - Instructions for Ralph's autonomous behavior
  • fix_plan.md - Initial task structure
  • AGENT.md - Build system template

File Naming Conventions

  • Ralph control files (fix_plan.md, AGENT.md, PROMPT.md) reside in the .ralph/ directory
  • Hidden files within .ralph/ (e.g., .ralph/.call_count, .ralph/.exit_signals) track loop state
  • .ralph/logs/ contains timestamped execution logs
  • .ralph/docs/generated/ for Ralph-created documentation
  • docs/code-review/ for code review reports (at project root)

Global Installation

Ralph installs to:

  • Commands: ~/.local/bin/ (ralph, ralph-monitor, ralph-setup, ralph-import, ralph-migrate, ralph-enable, ralph-enable-ci)
  • Templates: ~/.ralph/templates/
  • Scripts: ~/.ralph/ (ralph_loop.sh, ralph_monitor.sh, setup.sh, ralph_import.sh, migrate_to_ralph_folder.sh, ralph_enable.sh, ralph_enable_ci.sh)
  • Libraries: ~/.ralph/lib/ (circuit_breaker.sh, response_analyzer.sh, date_utils.sh, timeout_utils.sh, enable_core.sh, wizard_utils.sh, task_sources.sh, file_protection.sh)

After installation, the following global commands are available:

  • ralph - Start the autonomous development loop
  • ralph-monitor - Launch the monitoring dashboard
  • ralph-setup - Create a new Ralph-managed project
  • ralph-import - Import PRD/specification documents to Ralph format
  • ralph-migrate - Migrate existing projects from flat structure to .ralph/ subfolder
  • ralph-enable - Interactive wizard to enable Ralph in existing projects
  • ralph-enable-ci - Non-interactive version for CI/automation

Integration Points

Ralph integrates with:

  • Claude Code CLI: Uses npx @anthropic/claude-code as the execution engine
  • tmux: Terminal multiplexer for integrated monitoring sessions
  • Git: Expects projects to be git repositories
  • jq: For JSON processing of status and exit signals
  • GitHub Actions: CI/CD pipeline for automated testing
  • Standard Unix tools: bash, grep, date, etc.

Exit Conditions and Thresholds

Ralph uses multiple mechanisms to detect when to exit:

Exit Detection Thresholds

  • MAX_CONSECUTIVE_TEST_LOOPS=3 - Exit if too many test-only iterations
  • MAX_CONSECUTIVE_DONE_SIGNALS=2 - Exit on repeated completion signals
  • TEST_PERCENTAGE_THRESHOLD=30% - Flag if testing dominates recent loops
  • Completion detection via .ralph/fix_plan.md checklist items

Startup State Reset (Issue #194)

Every new ralph invocation unconditionally resets .exit_signals and removes .response_analysis before the main loop begins. This prevents stale completion signals from a prior run (crash, SIGKILL, API-limit exit) from triggering should_exit_gracefully() on the first iteration before any Claude execution occurs. The API-limit "user chose exit" path also calls reset_session() to clean up state.

Completion Indicators with EXIT_SIGNAL Gate

The completion_indicators exit condition requires dual verification:

completion_indicators EXIT_SIGNAL .response_analysis Result
>= 2 true exists Exit ("project_complete")
>= 2 false exists Continue (Claude still working)
>= 2 N/A missing Continue (defaults to false)
>= 2 N/A malformed Continue (defaults to false)
< 2 true exists Continue (threshold not met)

Implementation (ralph_loop.sh:312-327):

local claude_exit_signal="false"
if [[ -f "$RALPH_DIR/.response_analysis" ]]; then
    claude_exit_signal=$(jq -r '.analysis.exit_signal // false' "$RALPH_DIR/.response_analysis" 2>/dev/null || echo "false")
fi

if [[ $recent_completion_indicators -ge 2 ]] && [[ "$claude_exit_signal" == "true" ]]; then
    echo "project_complete"
    return 0
fi

Conflict Resolution: When STATUS: COMPLETE but EXIT_SIGNAL: false in RALPH_STATUS, the explicit EXIT_SIGNAL takes precedence. This allows Claude to mark a phase complete while indicating more phases remain.

Timeout Handling (Issues #175, #198)

When Claude Code exceeds CLAUDE_TIMEOUT_MINUTES, portable_timeout terminates the process with exit code 124. The loop handles this differently depending on the execution mode:

Live mode (--live/--monitor): The streaming pipeline captures per-command exit codes via PIPESTATUS. Timeout events are logged as a WARN:

[timestamp] [WARN] Claude Code execution timed out after 15 minutes

Background mode (default): The Claude process runs in a background subshell (&). The exit code is captured via wait $claude_pid.

Productive Timeout Detection (Issue #198):

In both modes, when exit code 124 is detected, the timeout handler checks git for actual work done during the execution (comparing HEAD to .loop_start_sha). This prevents treating productive timeouts as failures:

Timeout + Git State Result
Files changed (committed/staged/unstaged) Productive timeout: runs full analysis pipeline (save_claude_session, analyze_response, update_exit_signals, record_loop_result), writes timed_out_productive status, returns 0
No files changed Idle timeout: returns 1 (generic error)

Session ID Fallback: When the stream is truncated (missing "type":"result" message), session ID is extracted from the "type":"system" message, which is always written first and survives truncation.

API Limit Detection (Issues #183, #100)

The API limit detection uses a four-layer approach to avoid false positives. In stream-json mode, output files contain echoed file content from tool results ("type":"user" lines). If project files mention "5-hour limit", naive grep patterns match those echoed strings, incorrectly triggering the API limit recovery flow.

Layer 1 — Timeout guard:
Exit code 124 (timeout) is checked first. Productive timeouts (files changed) return 0; idle timeouts return 1 (generic error). Neither returns code 2 (API limit).

Layer 2 — Structural JSON detection (primary):
Parses rate_limit_event JSON in the output for "status":"rejected". This is the definitive signal from the Claude CLI.

Layer 3 — Filtered text fallback:
Only searches tail -30 of the output file, filtering out "type":"user", "tool_result", and "tool_use_id" lines before matching text patterns for standard 5-hour limit messages.

Layer 4 — Extra Usage quota (Issue #100):
Detects Claude Code "Extra Usage" mode exhaustion ("You're out of extra usage · resets 9pm"). Uses the same noise filtering as Layer 3.

Unattended mode: When the API limit prompt times out (no user response within 30s), Ralph auto-waits instead of exiting, supporting unattended operation.

Circuit Breaker Thresholds

  • CB_NO_PROGRESS_THRESHOLD=3 - Open circuit after 3 loops with no file changes
  • CB_SAME_ERROR_THRESHOLD=5 - Open circuit after 5 loops with repeated errors
  • CB_OUTPUT_DECLINE_THRESHOLD=70% - Open circuit if output declines by >70%
  • CB_PERMISSION_DENIAL_THRESHOLD=2 - Open circuit after 2 loops with permission denials (Issue No Approval Request, silent fail #101)
  • Question loop suppression (Issue [BUG] Loop persistence misidentified as active session despite "completed" status in progress.json #190): When asking_questions=true, the consecutive_no_progress counter is held steady (not incremented). This prevents the circuit breaker from opening prematurely when Claude asks questions in headless mode. A corrective message is injected via build_loop_context() in the next loop iteration.

Circuit Breaker Auto-Recovery (Issue #160)

The OPEN state is no longer terminal. Two recovery mechanisms are available:

Cooldown Timer (default): After CB_COOLDOWN_MINUTES (default: 30) in OPEN state, the circuit transitions to HALF_OPEN on next init_circuit_breaker() call. The existing HALF_OPEN logic handles recovery (progress → CLOSED) or re-trip (no progress → OPEN).

Auto-Reset: When CB_AUTO_RESET=true, the circuit resets directly to CLOSED on startup, bypassing the cooldown. Use for fully unattended operation.

Configuration:

CB_COOLDOWN_MINUTES=30    # Minutes before OPEN → HALF_OPEN (0 = immediate)
CB_AUTO_RESET=false       # true = bypass cooldown, reset to CLOSED on startup

CLI flag: ralph --auto-reset-circuit sets CB_AUTO_RESET=true for a single run.

State file: The opened_at field tracks when the circuit entered OPEN state. Old state files without this field fall back to last_change for backward compatibility.

Permission Denial Detection (Issue #101)

When Claude Code is denied permission to execute commands (e.g., npm install), Ralph detects this from the permission_denials array in the JSON output and halts the loop immediately:

  1. Detection: The parse_json_response() function extracts permission_denials from Claude Code output
  2. Fields tracked:
    • has_permission_denials (boolean)
    • permission_denial_count (integer)
    • denied_commands (array of command strings)
  3. Exit behavior: When has_permission_denials=true, Ralph exits with reason "permission_denied"
  4. User guidance: Ralph displays instructions to update ALLOWED_TOOLS in .ralphrc

Example .ralphrc tool patterns:

# Broad patterns (recommended for development)
ALLOWED_TOOLS="Write,Read,Edit,Bash(git *),Bash(npm *),Bash(pytest)"

# Specific patterns (more restrictive)
ALLOWED_TOOLS="Write,Read,Edit,Bash(git commit),Bash(npm install)"

API Error Detection via is_error Field (Issues #134, #199)

The Claude CLI can exit with code 0 but set is_error: true in the JSON output for API-level failures (400 concurrency errors, 401 OAuth token expiry). Ralph detects this before persisting any session state:

  1. Detection: In execute_claude_code(), after exit code 0, jq reads .is_error from the output JSON
  2. Session protection: If is_error is true, the session is NOT persisted (prevents infinite retry with bad session ID)
  3. Session reset: The session is explicitly reset so the next loop starts fresh
  4. Specific handling: "tool use concurrency" errors get a targeted reset reason for logging clarity
  5. Defense in depth: save_claude_session() independently checks is_error as a guard, preventing bad sessions even if call order changes in refactors

Error Detection

Ralph uses advanced error detection with two-stage filtering to eliminate false positives:

Stage 1: JSON Field Filtering

  • Filters out JSON field patterns like "is_error": false that contain the word "error" but aren't actual errors
  • Pattern: grep -v '"[^"]*error[^"]*":'

Stage 2: Actual Error Detection

  • Detects real error messages in specific contexts:
    • Error prefixes: Error:, ERROR:, error:
    • Context-specific errors: ]: error, Link: error
    • Error occurrences: Error occurred, failed with error
    • Exceptions: Exception, Fatal, FATAL
  • Pattern: grep -cE '(^Error:|^ERROR:|^error:|\]: error|Link: error|Error occurred|failed with error|[Ee]xception|Fatal|FATAL)'

Multi-line Error Matching

  • Detects stuck loops by verifying ALL error lines appear in ALL recent history files
  • Uses literal fixed-string matching (grep -qF) to avoid regex edge cases
  • Prevents false negatives when multiple distinct errors occur simultaneously

File Protection (Issue #149)

Ralph uses a multi-layered strategy to prevent Claude from accidentally deleting its own configuration files:

Layer 1: ALLOWED_TOOLS Restriction

  • The default CLAUDE_ALLOWED_TOOLS uses granular Bash(git add *), Bash(git commit *) etc. instead of Bash(git *), preventing git clean, git rm, and other destructive git commands
  • Users can override in .ralphrc but the defaults are safe

Layer 2: PROMPT.md Warning

  • The PROMPT.md template includes a "Protected Files (DO NOT MODIFY)" section listing .ralph/ and .ralphrc
  • This instructs Claude to never delete, move, rename, or overwrite these files

Layer 3: Pre-Loop Integrity Check

  • validate_ralph_integrity() from lib/file_protection.sh runs at startup and before every loop iteration
  • Checks for required paths: .ralph/, .ralph/PROMPT.md, .ralph/fix_plan.md, .ralph/AGENT.md, .ralphrc
  • On failure: logs error, displays recovery report, resets session, and halts the loop
  • Recovery: ralph-enable --force restores missing files

Required vs Optional Files:

Required (validation fails) Optional (no validation)
.ralph/ directory .ralph/logs/
.ralph/PROMPT.md .ralph/status.json
.ralph/fix_plan.md .ralph/.call_count
.ralph/AGENT.md .ralph/.exit_signals
.ralphrc .ralph/.circuit_breaker_state

Test Suite

Test Files (584 tests total)

File Tests Description
test_circuit_breaker_recovery.bats 22 Cooldown timer, auto-reset, parse_iso_to_epoch, CLI flag (Issue #160) + current_loop init/display fix (#194)
test_cli_parsing.bats 35 CLI argument parsing for all flags + monitor parameter forwarding
test_cli_modern.bats 111 Modern CLI commands (Phase 1.1) + build_claude_command fix + live mode text format fix (#164) + errexit pipeline guard (#175) + ALLOWED_TOOLS tightening (#149) + API limit false positive detection (#183) + Claude CLI command validation (#97) + stale call counter fix (#196) + is_error detection (#134, #199) + set-e removal (#208) + question detection + version check + semver comparison + stderr separation (#190) + productive timeout detection + session ID fallback + stale analysis cleanup (#198) + Extra Usage quota detection (#100)
test_json_parsing.bats 52 JSON output format parsing + Claude CLI format + session management + array format + question detection (#190)
test_session_continuity.bats 26 Session lifecycle management + expiration + circuit breaker integration + issue #91 fix
test_exit_detection.bats 54 Exit signal detection + EXIT_SIGNAL-based completion indicators + progress detection + question detection integration (#190) + stale exit signal prevention (#194)
test_rate_limiting.bats 11 Rate limiting behavior
test_loop_execution.bats 20 Integration tests
test_edge_cases.bats 25 Edge case handling
test_installation.bats 15 Global installation/uninstall workflows + dotfile template copying (#174)
test_project_setup.bats 50 Project setup (setup.sh) validation + .ralphrc permissions + .gitignore (#174)
test_prd_import.bats 33 PRD import (ralph_import.sh) workflows + modern CLI tests
test_enable_core.bats 38 Enable core library (idempotency, project detection, template generation, .gitignore #174)
test_task_sources.bats 23 Task sources (beads, GitHub, PRD extraction, normalization)
test_ralph_enable.bats 24 Ralph enable integration tests (wizard, CI version, JSON output, .ralphrc validation #149)
test_wizard_utils.bats 20 Wizard utility functions (stdout/stderr separation, prompt functions)
test_file_protection.bats 15 File integrity validation (RALPH_REQUIRED_PATHS, validate_ralph_integrity, get_integrity_report) (Issue #149)
test_integrity_check.bats 10 Pre-loop integrity check in ralph_loop.sh (startup + in-loop validation) (Issue #149)

Running Tests

# All tests
npm test

# Unit tests only
npm run test:unit

# Specific test file
bats tests/unit/test_cli_parsing.bats

Feature Development Quality Standards

CRITICAL: All new features MUST meet the following mandatory requirements before being considered complete.

Testing Requirements

  • Test Pass Rate: 100% - all tests must pass, no exceptions
  • Test Types Required:
    • Unit tests for bash script functions (if applicable)
    • Integration tests for Ralph loop behavior
    • End-to-end tests for full development cycles
  • Test Quality: Tests must validate behavior, not just achieve coverage metrics
  • Test Documentation: Complex test scenarios must include comments explaining the test strategy

Note on Coverage: The 85% coverage threshold is aspirational for bash scripts. Due to kcov subprocess limitations, test pass rate is the enforced quality gate.

E2E Testing Philosophy (v2 UI)

When Ralph introduces a web-based UI (v2), end-to-end testing is the primary quality gate for all frontend work:

  • Framework: Playwright for all browser automation and E2E tests
  • Real services only: E2E tests run against real backends — no mocked APIs or stubbed services
  • User journey coverage: Every user-facing workflow must have at least one E2E test covering the happy path
  • Visual regression: Use Playwright screenshot comparisons for layout-critical components
  • Accessibility: Include automated a11y checks (e.g., @axe-core/playwright) in E2E runs
  • CI integration: E2E tests must pass in the GitHub Actions pipeline before merge

Git Workflow Requirements

Before moving to the next feature, ALL changes must be:

  1. Committed with Clear Messages:

    git add .
    git commit -m "feat(module): descriptive message following conventional commits"
    • Use conventional commit format: feat:, fix:, docs:, test:, refactor:, etc.
    • Include scope when applicable: feat(loop):, fix(monitor):, test(setup):
    • Write descriptive messages that explain WHAT changed and WHY
  2. Pushed to Remote Repository:

    git push origin <branch-name>
    • Never leave completed features uncommitted
    • Push regularly to maintain backup and enable collaboration
    • Ensure CI/CD pipelines pass before considering feature complete
  3. Branch Hygiene:

    • Work on feature branches, never directly on main
    • Branch naming convention: feature/<feature-name>, fix/<issue-name>, docs/<doc-update>
    • Create pull requests for all significant changes
  4. Ralph Integration:

    • Update .ralph/fix_plan.md with new tasks before starting work
    • Mark items complete in .ralph/fix_plan.md upon completion
    • Update .ralph/PROMPT.md if Ralph's behavior needs modification
    • Test Ralph loop with new features before completion

Documentation Requirements

ALL implementation documentation MUST remain synchronized with the codebase:

  1. Script Documentation:

    • Bash: Comments for all functions and complex logic
    • Update inline comments when implementation changes
    • Remove outdated comments immediately
  2. Implementation Documentation:

    • Update relevant sections in this CLAUDE.md file
    • Keep template files in templates/ current
    • Update configuration examples when defaults change
    • Document breaking changes prominently
  3. README Updates:

    • Keep feature lists current
    • Update setup instructions when commands change
    • Maintain accurate command examples
    • Update version compatibility information
  4. Template Maintenance:

    • Update template files when new patterns are introduced
    • Keep PROMPT.md template current with best practices
    • Update AGENT.md template with new build patterns
    • Document new Ralph configuration options
  5. CLAUDE.md Maintenance:

    • Add new commands to "Key Commands" section
    • Update "Exit Conditions and Thresholds" when logic changes
    • Keep installation instructions accurate and tested
    • Document new Ralph loop behaviors or quality gates

Feature Completion Checklist

Before marking ANY feature as complete, verify:

  • All tests pass (if applicable)
  • Script functionality manually tested
  • All changes committed with conventional commit messages
  • All commits pushed to remote repository
  • CI/CD pipeline passes
  • .ralph/fix_plan.md task marked as complete
  • Implementation documentation updated
  • Inline code comments updated or added
  • CLAUDE.md updated (if new patterns introduced)
  • Template files updated (if applicable)
  • Breaking changes documented
  • Ralph loop tested with new features
  • Installation process verified (if applicable)

Rationale

These standards ensure:

  • Quality: Thorough testing prevents regressions in Ralph's autonomous behavior
  • Traceability: Git commits and fix_plan.md provide clear history of changes
  • Maintainability: Current documentation reduces onboarding time and prevents knowledge loss
  • Collaboration: Pushed changes enable team visibility and code review
  • Reliability: Consistent quality gates maintain Ralph loop stability
  • Automation: Ralph integration ensures continuous development practices

Enforcement: AI agents should automatically apply these standards to all feature development tasks without requiring explicit instruction for each task.

@github-actions
Copy link
Copy Markdown

{
"name": "ralph-claude-code",
"version": "1.0.0",
"description": "> Autonomous AI development loop with intelligent exit detection and rate limiting",
"main": "index.js",
"directories": {
"doc": "docs",
"example": "examples",
"test": "tests"
},
"scripts": {
"test": "bats tests/unit/ tests/integration/",
"test:unit": "bats tests/unit/",
"test:integration": "bats tests/integration/",
"test:e2e": "bats tests/e2e/"
},
"repository": {
"type": "git",
"url": "git+https://github.com/frankbria/ralph-claude-code.git"
},
"keywords": [],
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/frankbria/ralph-claude-code/issues"
},
"homepage": "https://github.com/frankbria/ralph-claude-code#readme",
"devDependencies": {
"bats": "^1.12.0",
"bats-assert": "^2.2.0",
"bats-support": "^0.3.0"
}
}

@github-actions
Copy link
Copy Markdown

Review — Building on Prior Feedback

The core fix is solid (covered well in previous reviews). This note focuses on what still needs to land before merge.


Blockers per project CLAUDE.md standards

The Feature Completion Checklist in CLAUDE.md explicitly requires documentation to stay in sync. Two items remain open:

1. CLAUDE.md — Modern CLI Configuration section

CLAUDE_MODEL and CLAUDE_EFFORT should be listed alongside the existing config variable table (around the CLAUDE_AUTO_UPDATE entry):

CLAUDE_MODEL=""          (string; model override, e.g. claude-sonnet-4-6; empty = CLI default)
CLAUDE_EFFORT=""         (string; effort level low/medium/high; empty = CLI default)

2. templates/ralphrc.template and lib/enable_core.sh — generated .ralphrc

New users running ralph-enable or ralph-setup get a .ralphrc with no hint these options exist. Adding commented-out entries in the Advanced Settings block would make them discoverable. Example:

// CLAUDE_MODEL=""  (model override - leave empty for CLI default)
// CLAUDE_EFFORT="" (effort level: low / medium / high - leave empty for default)

Non-blocking: CLAUDE_EFFORT validation

Previous reviews flagged this. A lightweight guard in build_claude_command() that logs a warning without blocking would be ideal. Warn-only is the right default since the CLI may add new values without notice.


One test observation

The CLAUDE_CODE_CMD regression test uses grep on the script file and checks output with a glob match. This would also pass if the expected string appeared inside a comment. Excluding comment lines before matching would make the test more precise.


Summary: Bug fix is correct, tests are thorough. Documentation gaps (CLAUDE.md + template files) are the only items required by the project's own standards before merge. Effort validation is a nice-to-have follow-up.

@github-actions
Copy link
Copy Markdown

Code Review: PR #231

✅ Implementation Quality

The core implementation is solid and follows established patterns correctly:

  1. CLAUDE_CODE_CMD fix (ralph_loop.sh:63): Correctly changed from unconditional assignment to after env snapshot (line 45), allowing .ralphrc to override when no env var is set

  2. CLAUDE_MODEL/EFFORT addition (lines 47-48, 64-65, 164-165, 1126-1134): Follows exact env-snapshot → default → restore pattern, with safe array-based command building

  3. Test coverage (8 new tests): Excellent behavioral tests including:

    • Regression test for parameter expansion syntax
    • .ralphrc loading for all three vars
    • Env var precedence over .ralphrc
    • Conditional --model/--effort flag inclusion/omission

⚠️ Missing Documentation per Project Standards

Per CLAUDE.md's own Feature Completion Checklist: ALL implementation documentation MUST remain synchronized with codebase.

templates/ralphrc.template should include in ADVANCED SETTINGS section (after line 97):

# Model override (e.g., claude-sonnet-4-6); leave empty for CLI default
CLAUDE_MODEL=

# Effort level: low / medium / high; leave empty for default
CLAUDE_EFFORT=

Impact: New users running ralph-enable or ralph-setup won't know these options exist, reducing discoverability.

✅ Other Notes

  • CLAUDE.md: Already updated (lines 226-227, 247-248) ✓
  • CLAUDE_EFFORT precedence test: Exists at line 1876 (CodeRabbit comment was outdated) ✓
  • Code style: Clean, consistent with existing patterns ✓

📝 Recommendation

LGTM pending template file update. The code implementation and tests are excellent — only the ralphrc.template needs updating to meet project documentation standards.

@github-actions
Copy link
Copy Markdown

Review comment posted: #231 (comment)

New%20session%20-%202026-03-25T00%3A09%3A07.552Z
opencode session  |  github run

@github-actions
Copy link
Copy Markdown

Follow-up review: CLAUDE.md documentation has been updated as requested. The implementation is correct and tests are solid. One optional improvement: add a combined test for --model and --effort being set simultaneously. Ready to merge.

@github-actions
Copy link
Copy Markdown

Deleting the placeholder above — full review below.

@frankbria frankbria merged commit b31640a into main Mar 25, 2026
6 checks passed
@frankbria frankbria deleted the fix/228-claude-code-cmd-env-precedence branch March 25, 2026 00:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

.ralphrc CLAUDE_CODE_CMD is silently ignored — always overwritten by claude

1 participant