Skip to content

feat(session): implement session expiration with configurable timeout#83

Merged
frankbria merged 1 commit into
mainfrom
feature/session-expiration
Jan 11, 2026
Merged

feat(session): implement session expiration with configurable timeout#83
frankbria merged 1 commit into
mainfrom
feature/session-expiration

Conversation

@frankbria
Copy link
Copy Markdown
Owner

@frankbria frankbria commented Jan 11, 2026

Summary

Implements session expiration for .claude_session_id files to prevent stale sessions from causing unpredictable behavior.

  • Add CLAUDE_SESSION_EXPIRY_HOURS configuration variable (default: 24 hours)
  • Add get_session_file_age_hours() helper function with cross-platform stat support (Linux/macOS)
  • Modify init_claude_session() to check session age and automatically remove expired sessions
  • Add --session-expiry CLI flag to configure expiration time
  • Logs session age when resuming and when expiring

Test Plan

  • 10 new unit tests added (TDD approach)
  • All 286 tests pass (100% pass rate)
  • Tests cover: default value, CLI flag parsing, validation, cross-platform stat

Changes

File Changes
ralph_loop.sh Add config variable, helper function, CLI flag, help text
tests/unit/test_session_continuity.bats Add 10 new tests for session expiration

Closes

Closes #51

Summary by CodeRabbit

Release Notes

  • New Features

    • Added session expiry support for Claude sessions with a configurable timeout (defaults to 24 hours).
    • Introduced new --session-expiry HOURS command-line option to set custom session expiration at runtime.
    • Sessions automatically expire and restart when the configured timeout is exceeded.
  • Tests

    • Added comprehensive unit tests for session expiry functionality and validation.

✏️ Tip: You can customize this high-level summary in your review settings.

- 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)
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 11, 2026

Caution

Review failed

The pull request is closed.

Walkthrough

The changes implement session expiration support for Claude sessions with a configurable 24-hour default. A cross-platform helper function computes session file age, integrated into session initialization to automatically expire and restart sessions when age exceeds the threshold. A new CLI option (--session-expiry) allows runtime configuration with validation. Comprehensive test coverage validates the feature across default behavior, CLI parsing, expiration logic, and edge cases.

Changes

Cohort / File(s) Summary
Session expiry implementation
ralph_loop.sh
Added get_session_file_age_hours() helper for cross-platform session age computation; introduced CLAUDE_SESSION_EXPIRY_HOURS configuration (default 24 hours); modified init_claude_session() to check session age and automatically expire/restart sessions when threshold exceeded; added --session-expiry HOURS CLI option with integer validation; updated help text and logging to reflect session age on resumption.
Test coverage
tests/unit/test_session_continuity.bats
Added extensive unit tests validating: CLAUDE_SESSION_EXPIRY_HOURS definition and default value, --session-expiry flag recognition and validation (rejects non-integers, zero, negative values), session expiration logic and cross-platform stat handling, get_session_file_age_hours() existence and callability, edge cases (damaged/missing session files), and full session lifecycle integration.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant CLI as ralph_loop.sh (CLI)
    participant SessionMgr as init_claude_session()
    participant FileSystem as Session File<br/>(.claude_session_id)
    
    User->>CLI: Execute with --session-expiry 48<br/>(or use default CLAUDE_SESSION_EXPIRY_HOURS=24)
    CLI->>SessionMgr: Call init_claude_session()
    
    SessionMgr->>FileSystem: Check if session file exists
    alt Session file exists
        SessionMgr->>SessionMgr: Call get_session_file_age_hours(file)
        SessionMgr->>SessionMgr: Compare age >= configured expiry
        
        alt Session expired
            SessionMgr->>FileSystem: Delete expired session file
            SessionMgr->>SessionMgr: Log: "Session expired (Xh old)"
            SessionMgr->>CLI: Return empty (start new session)
        else Session valid
            SessionMgr->>FileSystem: Read session ID
            SessionMgr->>SessionMgr: Log: "Resuming session (Xh old)"
            SessionMgr->>CLI: Return session ID
        end
    else Session file missing
        SessionMgr->>SessionMgr: Log: "Starting new session"
        SessionMgr->>CLI: Return empty
    end
    
    CLI->>User: Proceed with session (new or resumed)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A session that ages like fine carrot wine,
Now expires just right at the twenty-four line,
No stale Claude IDs will linger about,
Fresh starts and configurations throughout! 🥕✨

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/session-expiration

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 81fac49 and e9e0add.

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

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

@frankbria frankbria merged commit 9110e3d into main Jan 11, 2026
4 of 5 checks passed
@frankbria frankbria deleted the feature/session-expiration branch January 11, 2026 02:10
@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp Bot commented Jan 11, 2026

Add configurable session expiration to session.init_claude_session with CLAUDE_SESSION_EXPIRY_HOURS defaulting to 24 hours in ralph_loop.sh

Introduce CLAUDE_SESSION_EXPIRY_HOURS and age-based expiration in session.init_claude_session, add cross-platform session.get_session_file_age_hours, and parse --session-expiry HOURS in ralph_loop.sh. Tests in tests/unit/test_session_continuity.bats cover defaults, help, validation, and expiration logic.

📍Where to Start

Start with session.init_claude_session and session.get_session_file_age_hours in ralph_loop.sh.


Macroscope summarized e9e0add.

frankbria pushed a commit that referenced this pull request Jan 11, 2026
@claude
Copy link
Copy Markdown

claude Bot commented Jan 11, 2026

Code Review - Session Expiration Feature

This PR implements session expiration functionality for Claude Code sessions. Overall, the implementation is solid with good TDD practices. Here are my findings:

Strengths

  1. Excellent Test Coverage: 10 new tests covering configuration, validation, and cross-platform compatibility
  2. TDD Approach: Tests were written first, ensuring the feature is well-specified
  3. Cross-Platform Support: Proper handling of macOS (BSD) and Linux (GNU) stat command differences
  4. Input Validation: Good validation of the --session-expiry flag with appropriate error messages
  5. Clear Documentation: Help text and comments are clear and descriptive

Code Quality Observations

1. Session File Variable Confusion (ralph_loop.sh:492)

There appears to be a mismatch in session file variables:

  • The function checks CLAUDE_SESSION_FILE at line 489
  • But the session is actually stored in RALPH_SESSION_FILE (defined at line 37)
  • These are two different files with different purposes:
    • .claude_session_id (CLAUDE_SESSION_FILE) - Claude's native session
    • .ralph_session (RALPH_SESSION_FILE) - Ralph's lifecycle tracking

Question: Should this function be checking RALPH_SESSION_FILE instead? Or are we intentionally expiring Claude's native session file?

2. Integer Division Truncation (ralph_loop.sh:482)

The code uses integer division which truncates fractional hours. For example:

  • 23 hours 59 minutes = 0 hours (will not expire)
  • 24 hours 1 minute = 24 hours (will expire)

This is likely fine for the use case, but worth noting that a session at 23h59m won't expire until it hits exactly 24h.

3. Edge Case: Stat Command Failure

If stat fails (line 472/475), the function falls back to echo 0, which returns a file age of 0 hours. This means:

  • Failed stat = session appears brand new
  • Session will never expire if stat keeps failing

Consider whether this is the desired behavior or if a failed stat should trigger session expiration.

Test Quality

Test Limitations:

Several tests only check for the presence of code patterns rather than testing actual behavior:

  1. test_session_continuity.bats:307-310 - Only greps for variable name
  2. test_session_continuity.bats:327-331 - Only checks flag exists in code
  3. test_session_continuity.bats:387-391 - Only checks function exists

These are better than nothing, but they don't verify:

  • Actual session expiration behavior
  • Age calculation accuracy
  • File deletion on expiration

Suggestion: Consider adding integration tests that:

  • Create a session file with a specific timestamp
  • Modify its mtime using touch -t
  • Verify init_claude_session() correctly detects expiration

Security and Performance

No security concerns identified. Performance impact is negligible (one stat call per loop iteration).

Documentation

The PR description is excellent. However, CLAUDE.md should be updated to document:

  • The new CLAUDE_SESSION_EXPIRY_HOURS configuration variable
  • The --session-expiry CLI flag
  • Session expiration behavior

Recommendations

  1. Clarify session file intent: Verify whether CLAUDE_SESSION_FILE or RALPH_SESSION_FILE should be checked
  2. Document the truncation behavior: Add a comment explaining integer division behavior
  3. Consider stat failure handling: Decide if failed stat should expire or preserve the session
  4. Add integration tests: Test actual expiration behavior, not just code presence
  5. Update CLAUDE.md: Document the new configuration in the Ralph Loop Configuration and Key Commands sections

Verdict

Approve with suggestions. The implementation is functionally sound, but the session file variable question should be clarified before merging. The feature meets quality standards and follows TDD practices well.

frankbria pushed a commit that referenced this pull request Jan 11, 2026
frankbria added a commit that referenced this pull request Jan 11, 2026
…#84)

* Reapply "feat(session): implement session expiration with configurable timeout (#83)"

This reverts commit 1ba55a4.

* 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>
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.

[P2] Phase 1.5: Implement session expiration for .claude_session_id

1 participant