@sgdt1a/ralph
v0.1.0
Published
Autonomous Claude loop CLI — run Claude Code on a prd.json iteratively.
Maintainers
Readme
ralph
ralph is an autonomous GitHub issue executor. It polls your repo for open issues, injects them into prd.json, and runs ralph run --afk to implement them via Claude Code — all while you're away.
Quick start (local)
npm install -g @sgdt1a/ralph
ralph init --title "My PRD" --issue https://github.com/you/repo/issues/1
ralph runVPS Setup
Run ralph-watch.sh on a VPS so it polls GitHub every 7 minutes and triggers autonomous implementation automatically.
Prerequisites
| Tool | Purpose | Install |
|------|---------|---------|
| gh CLI | GitHub API calls | cli.github.com |
| git | Pull latest code | system package |
| ralph | Run the implementation loop | npm install -g @sgdt1a/ralph |
| python3 | JSON manipulation in ralph-watch.sh | system package |
| GitHub PAT | Authenticate to GitHub | GitHub → Settings → Developer settings → Personal access tokens |
The GitHub PAT needs the repo scope (read issues + post comments).
1. Configure GitHub authentication
Set GITHUB_TOKEN for both gh and git:
# Add to /etc/environment (system-wide) or ~/.bashrc (user-level)
export GITHUB_TOKEN=ghp_your_token_hereConfigure gh to use it:
echo "$GITHUB_TOKEN" | gh auth login --with-token2. Configure git push over HTTPS
So git pull inside ralph-watch.sh works without interactive auth:
# Store credentials for the session (or use git-credential-store for persistence)
git config --global credential.helper store
# Or embed the token directly in the remote URL:
git remote set-url origin https://[email protected]/you/repo.git3. Clone the ralph repo to the VPS
git clone https://github.com/you/repo.git /opt/ralph-repo
cd /opt/ralph-repo
npm install -g @sgdt1a/ralph4. Set environment variables persistently
Add to /etc/environment (requires re-login to take effect) or ~/.bashrc:
export GITHUB_TOKEN=ghp_your_token_here
export RALPH_MAX_ITER=10 # AFK iterations per poll cycle (default: 10)
# Optional overrides:
# export RALPH_WATCH_LOCKFILE=/tmp/ralph-watch.lock
# export RALPH_WATCH_LOG=/opt/ralph-repo/ralph-watch.log5. Register the cron job
RALPH_DIR=/opt/ralph-repo bash /opt/ralph-repo/install-cron.shThis installs the following entry (idempotent — safe to run twice):
*/7 * * * * cd "/opt/ralph-repo" && bash ralph-watch.sh >> ralph-watch.log 2>&1Verify it was added:
crontab -l6. Verify it's working
tail -f /opt/ralph-repo/ralph-watch.logYou should see timestamped lines like:
[2026-03-25T21:00:00Z] ralph-watch starting (repo: you/repo)
[2026-03-25T21:00:00Z] Lock acquired (pid 12345)
[2026-03-25T21:00:01Z] Existing prd.json issues: 10 13 14
[2026-03-25T21:00:02Z] No new issues found
[2026-03-25T21:00:02Z] ralph-watch done
[2026-03-25T21:00:02Z] Lock releasedWhen a new issue is created on GitHub, the next poll cycle will:
- Inject it into
prd.json - Post a "Ralph has queued this" comment on the issue
- Run
git pull --ff-onlyto get latest code - Run
ralph run --afk $RALPH_MAX_ITERto implement it
How it works
GitHub issue created
│
▼ (every 7 min)
ralph-watch.sh
├── gh issue list → find new issues
├── inject into prd.json
├── gh issue comment → "queued" marker
└── ralph run --afk
└── claude --print → implements the issueConfiguration reference
| Env var | Default | Description |
|---------|---------|-------------|
| GITHUB_TOKEN | (required) | GitHub PAT with repo scope |
| REPO | auto-detected | owner/repo (detected from git remote if unset) |
| RALPH_WATCH_LOCKFILE | /tmp/ralph-watch.lock | Prevents concurrent invocations |
| RALPH_WATCH_LOG | <script-dir>/ralph-watch.log | Log file path |
| RALPH_MAX_ITER | 10 | Max AFK iterations per poll cycle |
Running tests
# Install bats (one-time)
git clone --depth 1 https://github.com/bats-core/bats-core.git /tmp/bats-core
# Run ralph-watch.sh tests
/tmp/bats-core/bin/bats test/ralph-watch.bats
# Run Node.js unit tests (requires Node >= 20)
npm test