* Reapply "feat(session): implement session expiration with configurable timeout (#83)"
This reverts commit 1ba55a4b9c.
* fix(session): address code review feedback
- Fix integer overflow: return -1 from get_session_file_age_hours on stat
failure instead of 0, preventing false expiration
- Handle stat failure in init_claude_session with WARN log
- Add comprehensive documentation for return values and expiration strategy
- Add 6 behavioral integration tests that verify actual functionality
- Add inline comments explaining 24-hour default rationale
Test count: 286 → 292 (100% pass rate)
* fix(test): use grep-based verification to fix CI failures
Tests that sourced ralph_loop.sh with --help flag failed in GitHub
Actions due to BATS environment differences. Changed behavioral tests
to grep-based code verification that checks implementation patterns
exist without executing the script.
* fix(test): guard main with BASH_SOURCE for safe sourcing
- Add BASH_SOURCE check to only execute main when script is run directly
- Update tests to source script without --help flag
- Convert grep-based verification tests back to functional tests
- Fixes CI failures caused by script execution during sourcing
---------
Co-authored-by: Test User <test@example.com>
- Add CLAUDE_SESSION_EXPIRY_HOURS configuration variable (default: 24)
- Add get_session_file_age_hours() helper with cross-platform stat support
- Modify init_claude_session() to check session age and remove expired sessions
- Add --session-expiry CLI flag to configure expiration (positive integers only)
- Update help text with new option and example
- Add 10 new tests for session expiration (TDD approach)
Closes#51
Test count: 276 → 286 (100% pass rate)
Co-authored-by: Test User <test@example.com>
- Fix SC2155: separate declare from assign in get_session_id(),
log_session_transition(), init_session_tracking()
- Use jq for safe JSON generation in reset_session() and init_session_tracking()
instead of heredocs (prevents special character issues)
- Add corruption tolerance to log_session_transition() with JSON validation
and fallback to empty array on parse failures
- Add generate_session_id() to create unique session IDs (ralph-<epoch>-<random>)
- Add update_session_last_used() helper called on each loop iteration
- init_session_tracking() now generates unique session_id and sets last_used
- Add session files to .gitignore (.ralph_session, .ralph_session_history,
.claude_session_id)
All 265 tests pass.
- Add init_session_tracking() call in main() before loop starts
- Use literal escape codes for color in --reset-session output
- Remove conditional in reset_session() to always create file
- Remove unused old_session_id variable
- Remove duplicate SESSION_EXPIRATION_SECONDS (keep in response_analyzer.sh)
- Add clarifying comments for RALPH_SESSION_FILE vs CLAUDE_SESSION_FILE
All 265 tests pass.
The build_claude_command() function was incorrectly using --prompt-file
which doesn't exist in Claude Code CLI. This fix:
- Replaces --prompt-file with -p flag plus prompt content
- Reads prompt content via $(cat "$prompt_file") before execution
- Adds error handling for missing prompt files
- Maintains shell injection safety through array-based command building
- Updates comments to reflect the correct approach
Adds 6 TDD tests verifying the fix:
- Uses -p flag instead of --prompt-file
- Reads prompt file content correctly
- Handles missing prompt file
- Includes all modern CLI flags
- Handles multiline prompt content
- Prevents shell injection
Test count: 145 -> 151 (all passing)
Fixes three security issues identified in Phase 1.1 code review:
1. JSON injection in parse_json_response() (response_analyzer.sh:113-132)
- Replace heredoc with jq construction using --arg for strings
- Use --argjson for numeric/boolean fields
- Ensures proper escaping of quotes, newlines, backslashes
2. Input validation for --allowed-tools flag (ralph_loop.sh:903-905)
- Add VALID_TOOL_PATTERNS whitelist
- Add validate_allowed_tools() function
- Validate against whitelist in argument parsing
- Allow Bash(...) patterns with any content
3. Shell injection in build_claude_command() (ralph_loop.sh:439-444)
- Convert from string concatenation to command array
- Use global CLAUDE_CMD_ARGS array
- Execute with "${CLAUDE_CMD_ARGS[@]}" instead of bash -c
- No manual escaping needed - array handles metacharacters
All 98 tests passing.
Closes#48, #50
Implements Issue #28 - modernize CLI commands for better Claude integration.
Key changes:
- Add JSON output format support with --output-format flag (default: json)
- Add session continuity with --continue flag and .claude_session_id file
- Add tool permissions via --allowed-tools flag
- Add build_loop_context() for loop-aware context injection
- Add detect_output_format() and parse_json_response() for JSON parsing
- Maintain backward compatibility with text output fallback
- Add version checking with check_claude_version()
New CLI options:
- --output-format json|text: Control Claude output format
- --allowed-tools "Write,Read,Bash(git *)": Restrict tool permissions
- --no-continue: Disable session continuity
Test coverage:
- 20 new JSON parsing tests (test_json_parsing.bats)
- 23 new CLI modern tests (test_cli_modern.bats)
- All 98 tests passing (100% pass rate)
Add cross-platform date utility library to handle differences between
GNU date (Linux) and BSD date (macOS). Fixes issues with:
- ISO 8601 timestamp formatting (-Iseconds flag)
- Date arithmetic operations (-d vs -v flags)
Changes:
- Created lib/date_utils.sh with get_iso_timestamp() and get_next_hour_time()
- Updated ralph_loop.sh to use date utilities (2 instances)
- Updated lib/circuit_breaker.sh to use date utilities (4 instances)
- Updated lib/response_analyzer.sh to use date utilities (1 instance)
All date operations now work consistently across both platforms without
modification. The utility automatically detects the OS and uses the
appropriate date command syntax.
Tested on Linux with GNU date - all syntax checks and integration tests pass.
Fixes circuit breaker opening prematurely due to naive error pattern matching
that treated JSON field names like "is_error": false as actual errors.
Changes:
- ralph_loop.sh: Implement two-stage error detection with JSON filtering
- lib/response_analyzer.sh: Apply same filtering to error counting
- tests/test_error_detection.sh: Add comprehensive test suite (12 scenarios)
Error detection now:
- Filters out JSON field patterns before searching for errors
- Uses context-specific patterns (^Error:, ]: error, Exception, Fatal)
- Avoids type annotations (error: Error) and code identifiers
- Includes debug logging when VERBOSE_PROGRESS=true
Test coverage validates:
✓ JSON fields don't trigger false positives
✓ Real error messages are correctly detected
✓ Mixed content handled properly
✓ Code diffs and documentation excluded
This prevents the consecutive_same_error counter from incrementing on
false positives, eliminating unnecessary circuit breaker trips.
- Added detection for API 5-hour limit error messages in execute_claude_code()
- Returns special exit code (2) when API limit is detected
- Added interactive prompt for user to choose: wait 60 minutes or exit
- Implements proper countdown timer when waiting for API reset
- Prevents infinite 30-second retry loops on API limit errors
- Improves status tracking with new api_limit and api_limit_exit states
The original `|| echo 0` fallback was executing even when grep -c succeeded
but returned 0 matches (exit code 1), resulting in "0\n0" being assigned
to variables. This multi-line string caused syntax errors in [[ ]] tests.
Fixed by removing the fallback and explicitly handling empty variables
instead, which properly addresses the root cause of the line 280 error.
Ensures total_items and completed_items are explicitly cast to integers
using $((...)) arithmetic expansion to prevent floating point values
from causing syntax errors in double bracket tests at line 280.
- Eliminate double function call in should_exit_gracefully check
- Use consistent string return pattern instead of mixed return codes
- Resolves script error on line 280 with exit code handling
Features added:
- Added --timeout/-t option to set execution timeout in minutes
- Default timeout increased from 10 to 15 minutes
- Validation: timeout must be 1-120 minutes
- Shows timeout in execution start message
Usage examples:
- ralph --monitor # 15-minute default timeout
- ralph --monitor --timeout 30 # 30-minute timeout for complex tasks
- ralph --verbose --timeout 5 # 5-minute timeout with progress logs
Benefits:
- Prevents hanging on very complex tasks requiring >15 minutes
- Allows shorter timeouts for simpler tasks to fail faster
- User can adjust based on their specific project complexity
- Clear feedback about configured timeout in logs
Key improvements:
- Added --verbose flag to control 10-second progress updates in logs
- Real-time progress now shows in monitor display only (not logs)
- Created progress.json file for monitor communication
- Monitor shows live Claude Code progress with spinner and elapsed time
- Clean logs by default, detailed progress available with --verbose
Usage:
- ralph --monitor # Clean logs, progress in monitor only
- ralph --monitor --verbose # Progress in both monitor and logs
- ralph --verbose # Just verbose logs without monitor
Monitor now displays:
┌─ Claude Code Progress ──────────────────────────────┐
│ Status: ⠋ Working (120s elapsed)
│ Output: Analyzing authentication system...
└─────────────────────────────────────────────────────┘
This keeps logs clean while providing rich real-time feedback in the monitor.
Features added:
- Animated progress spinner (⠋⠙⠹⠸) during Claude Code execution
- Real-time display of last output line from Claude Code
- Timer showing elapsed execution time in 10-second intervals
- 10-minute timeout for Claude Code execution to prevent hanging
- Visual indicators: ⏳ starting, ✅ success, ❌ failure
Counter fixes:
- Fixed call counter jumping issue by only incrementing on successful execution
- Counter now accurately reflects actual successful Claude Code calls
- Prevents double-counting on retries or failures
Monitoring improvements:
- Shows 'Claude Code working... (30s elapsed)' with spinner
- Displays last line of output: 'Claude Code: Reading file... (40s)'
- Clear success/failure indicators in logs
- Better visibility into long-running operations
- Changed from 'npx @anthropic-ai/claude-code' to 'claude'
- This assumes Claude Code is installed globally with npm install -g
- Updated ralph_loop.sh, ralph_import.sh, and README.md
- Much cleaner and faster execution without npx overhead
- Updated from @anthropic/claude-code to @anthropic-ai/claude-code
- This was causing npm 404 errors when trying to execute Claude Code
- Fixed in ralph_loop.sh, ralph_import.sh, install.sh, and README.md
- Ralph should now be able to successfully execute Claude Code commands
The issue was in line 378: if [[ $? -eq 0 ]]
- $? was checking the return code of 'local exit_reason=$(...)'
- This command always succeeds, so $? was always 0
- This caused Ralph to always exit immediately after loop #1
Fixed by:
- Calling should_exit_gracefully directly in the if condition
- Only calling it again to get exit reason if it returns 0 (exit needed)
- This properly checks the function's actual return code
- Add logging to show total_items and completed_items counts
- Add final debug statement to confirm function completion
- This will help identify if the fix_plan completion check is the culprit
- The debug log_status calls in should_exit_gracefully() were being
captured as stdout when called with
- This caused the debug messages to be treated as the exit reason
- Fixed by redirecting debug logging to stderr with >&2
- Ralph should now continue past the exit condition check properly
- Add debug statements to identify which exit condition is triggering
- Log each step of @fix_plan.md parsing and task completion checking
- Add logging for jq operations and file reading
- This should help identify why Ralph immediately exits after loop #1
🐛 Bug Fix: Silent Exit Issue
- Ralph was silently exiting when PROMPT.md not found (no error shown)
- Added comprehensive error handling with helpful guidance
- Now clearly explains when directory is not a Ralph project
🎯 Enhanced User Experience:
- Detects partial Ralph projects vs completely wrong directories
- Provides specific actionable solutions:
1. ralph-setup my-project (create new)
2. ralph-import requirements.md (import existing)
3. Navigate to existing Ralph project
4. Create PROMPT.md manually
- Updated help text with "IMPORTANT" note about project directories
- Added example workflow in help documentation
🔧 Technical Improvements:
- Better error detection logic
- Informative messages instead of silent failures
- Maintains proper exit codes for scripting
- Clear guidance for different scenarios
This resolves the confusing behavior where ralph would start logging
but then silently exit without explanation when run outside a Ralph project.
Major architectural change to make Ralph available as global commands:
🌟 New Global Installation System:
- Add install.sh script for global installation to ~/.local/bin
- Creates ralph, ralph-monitor, ralph-setup global commands
- Installs templates and scripts to ~/.ralph/ directory
- Automatic dependency checking and PATH configuration
🚀 Enhanced User Experience:
- ralph-setup my-project (run from anywhere, no directory constraints)
- ralph --monitor (start from any project directory)
- ralph-monitor (global monitoring command)
- No more ../ralph_loop.sh relative path requirements
🔧 Improved Architecture:
- Global template system in ~/.ralph/templates/
- Smart path detection (global commands vs local scripts)
- Maintains backward compatibility during transition
- Clean separation of installation vs project files
📚 Updated Documentation:
- All examples now use global commands (ralph vs ../ralph_loop.sh)
- Clear installation instructions with ./install.sh
- Global command reference in CLAUDE.md
- Streamlined Quick Start workflow
This makes Ralph much more professional and user-friendly by eliminating
directory structure requirements and providing standard Unix command experience.
- Add --monitor flag to ralph_loop.sh for integrated tmux monitoring
- Automatically creates split-pane session with Ralph loop and monitor
- Include tmux availability check with installation instructions
- Update documentation to recommend tmux workflow
- Add tmux session management commands and controls
- Preserve all existing functionality for users without tmux
New workflow:
../ralph_loop.sh --monitor # Creates split session automatically
Traditional workflow still supported:
../ralph_loop.sh # Terminal 1
../ralph_monitor.sh # Terminal 2
System requirements updated to include tmux (recommended).
- Fix nested EOF heredoc conflicts in update_status() and show_help() functions
- Use unique delimiters (STATUSEOF, HELPEOF) to avoid conflicts
- Complete Ralph for Claude Code implementation with all components:
- ralph_loop.sh: Main autonomous development loop with rate limiting
- ralph_monitor.sh: Live monitoring dashboard
- setup.sh: Project initialization script
- templates/: Template files for new projects
- .gitignore: Comprehensive ignore rules
All scripts are now executable and syntax-validated.
Features:
- Intelligent exit detection (knows when project is done)
- Test limiting (enforces 20% rule to prevent busy work)
- Rate limiting with graceful API usage management
- Live monitoring dashboard with real-time progress
- Auto-generated documentation every 10 iterations
- Specification-driven development approach
Based on Geoffrey Huntley's Ralph technique, adapted for Claude Code.