Skip to content

Commit a3f29f3

Browse files
duyetduyetbot
andcommitted
fix(ralph-wiggum): fix stop hook exit code and add CLAUDE.md
- Fix get_session_id() to always return 0 (was failing with set -euo pipefail) - Add CLAUDE.md with commands, hooks, key files, and testing instructions - Bump version to 1.1.1 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: duyetbot <duyetbot@users.noreply.github.com>
1 parent 51704ed commit a3f29f3

3 files changed

Lines changed: 68 additions & 4 deletions

File tree

ralph-wiggum/.claude-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ralph-wiggum",
3-
"version": "1.1.0",
3+
"version": "1.1.1",
44
"description": "Self-referential development loop for Claude Code with session isolation. Run iterative tasks with automatic progress detection and safety controls.",
55
"author": {
66
"name": "duyet",

ralph-wiggum/CLAUDE.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Ralph Wiggum Plugin
2+
3+
Self-referential development loop for Claude Code with session isolation.
4+
5+
## Commands
6+
7+
- `/ralph-loop` - Start iterative loop with a prompt
8+
- `/status` - Show current loop status
9+
- `/cancel-ralph` - Cancel active loop
10+
- `/help` - Usage documentation
11+
12+
## Hooks
13+
14+
Two hooks in `hooks/hooks.json`:
15+
16+
| Hook | File | Purpose |
17+
|------|------|---------|
18+
| SessionStart | `session-start-hook.sh` | Initialize session ID for state isolation |
19+
| Stop | `stop-hook.sh` | Intercept exit, feed prompt back for next iteration |
20+
21+
## Key Files
22+
23+
```
24+
lib/
25+
├── utils.sh # Session isolation utilities (get_session_id, get_state_file_path)
26+
├── circuit_breaker.sh # Safety circuit breaker for error detection
27+
├── response_analyzer.sh # Smart exit detection based on response patterns
28+
├── api_limit_handler.sh # Rate limit detection and handling
29+
└── task_manager.sh # Task tracking across iterations
30+
```
31+
32+
## State Files
33+
34+
State stored in `.claude/ralph-session.local/` with session ID suffix:
35+
- `ralph-loop.{session_id}.md` - Loop state (iteration, prompt, settings)
36+
- `ralph-circuit.{session_id}.json` - Circuit breaker state
37+
- `ralph-analysis.{session_id}.json` - Response analysis data
38+
39+
## Testing Hooks
40+
41+
Test stop hook manually:
42+
```bash
43+
cd ralph-wiggum
44+
echo '{"session_id": "test", "transcript_path": "/tmp/test.json"}' | ./hooks/stop-hook.sh
45+
```
46+
47+
Test with set -euo pipefail (catches exit code issues):
48+
```bash
49+
bash -euo pipefail -c 'source lib/utils.sh && get_session_id'
50+
```
51+
52+
## Common Issues
53+
54+
1. **Hook exits with code 1**: Check that all functions in `lib/utils.sh` return 0 explicitly
55+
2. **Session state persists**: State files use session ID suffix for isolation
56+
3. **Circuit breaker trips**: Check `.claude/ralph-session.local/ralph-circuit.*.json`

ralph-wiggum/lib/utils.sh

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
# Provides session-specific state management to prevent cross-session interference
55

66
# Set CLAUDE_PLUGIN_ROOT with fallback to script location
7-
CLAUDE_PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
7+
# Use ${VAR-default} (without colon) to avoid unbound variable error with set -u
8+
if [[ -z "${CLAUDE_PLUGIN_ROOT:-}" ]]; then
9+
CLAUDE_PLUGIN_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
10+
fi
811

912
CLAUDE_ENV_FILE="${CLAUDE_ENV_FILE:-${CLAUDE_PLUGIN_ROOT}/.env}"
1013
RALPH_SESSION_DIR=".claude/ralph-session.local"
@@ -17,9 +20,14 @@ get_session_id() {
1720
fi
1821

1922
if [[ -f "$CLAUDE_ENV_FILE" ]]; then
20-
grep -q "^CLAUDE_SESSION_ID=" "$CLAUDE_ENV_FILE" && \
21-
source "$CLAUDE_ENV_FILE" && echo "$CLAUDE_SESSION_ID"
23+
if grep -q "^CLAUDE_SESSION_ID=" "$CLAUDE_ENV_FILE"; then
24+
source "$CLAUDE_ENV_FILE"
25+
echo "${CLAUDE_SESSION_ID:-}"
26+
fi
2227
fi
28+
29+
# Always return 0 even when no session found (caller handles empty string)
30+
return 0
2331
}
2432

2533
# Get state directory (always .claude/ralph-session in project directory)

0 commit comments

Comments
 (0)