https://github.com/decocms/ralph
https://github.com/decocms/ralph
Last synced: about 1 month ago
JSON representation
- Host: GitHub
- URL: https://github.com/decocms/ralph
- Owner: decocms
- License: apache-2.0
- Created: 2026-01-19T12:52:58.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2026-01-20T20:18:31.000Z (6 months ago)
- Last Synced: 2026-01-21T04:41:42.141Z (6 months ago)
- Language: Shell
- Size: 40 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Ralph - Autonomous Claude Code Runner for GitHub Issues
Ralph is a Kubernetes-native tool that runs Claude Code autonomously to implement solutions for GitHub issues. Pass it a repo, issue number, and branch name — Claude will read the issue context and work until the task is complete.
[](https://github.com/decocms/ralph/actions/workflows/release.yaml)
## Features
- **GitHub Issue Integration** — Fetches issue title, description, labels, and comments
- **Autonomous Loop** — Runs Claude Code iteratively until completion signal
- **Smart Fork Detection** — Automatically forks repos when no write access, pushes directly when allowed
- **Automatic PR Creation** — Opens pull requests with proper issue references
- **Cost Tracking** — Reports token usage and estimated costs at completion
- **Issue Commenting** — Posts summary with PR link and cost to the original issue
- **Cross-Repo Issues** — Fetch issues from one repo, implement in another
- **Safety Limits** — Max iterations and rate limiting prevent runaway costs
- **Kubernetes Native** — Helm chart for easy deployment
- **SSH Authentication** — Secure Git operations with SSH keys
## Quick Start
### Prerequisites
- Kubernetes cluster with `kubectl` configured
- [Helm](https://helm.sh/docs/intro/install/) installed
- GitHub Personal Access Token
- Anthropic API Key
- SSH key for Git push access
### 1. Install the Helm Chart
```bash
# Add the chart repository (or clone this repo)
git clone https://github.com/decocms/ralph.git
cd ralph
```
### 2. Create Secrets
```bash
# Create namespace
kubectl create namespace ralph
# Create API secrets
kubectl create secret generic ralph-secrets \
--from-literal=github-token='ghp_xxxxxxxxxxxx' \
--from-literal=anthropic-api-key='sk-ant-xxxxxxxxxxxx' \
-n ralph
# Create SSH key secret
kubectl create secret generic ralph-ssh-key \
--from-file=ssh-private-key=$HOME/.ssh/id_rsa \
-n ralph
```
### 3. Run a Job
```bash
# Using the CLI script
NAMESPACE=ralph ./ralph.sh git@github.com:owner/repo.git 42 fix/issue-42
# Or directly with Helm
helm install my-job ./charts/ralph \
--set job.repo="git@github.com:owner/repo.git" \
--set job.issueId="42" \
--set job.branch="fix/issue-42" \
--namespace ralph
```
## Usage
### CLI Script
```bash
./ralph.sh
```
The `` can be:
- A number (e.g., `226`) — fetches from target repo
- A full GitHub URL (e.g., `https://github.com/org/repo/issues/42`) — fetches from that repo
### Examples
```bash
# Issue from same repo
./ralph.sh git@github.com:acme/api.git 42 fix/issue-42
# Issue from different repo (cross-repo)
./ralph.sh git@github.com:acme/api.git https://github.com/acme/tasks/issues/123 fix/task-123
```
### Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `NAMESPACE` | `default` | Kubernetes namespace |
| `CHART_PATH` | `./charts/ralph` | Path to Helm chart |
| `IMAGE_REPO` | `ghcr.io/decocms/ralph` | Container image |
| `IMAGE_TAG` | `latest` | Image tag |
## Helm Chart
### Installation
```bash
helm install ralph-job ./charts/ralph \
--set job.repo="git@github.com:owner/repo.git" \
--set job.issueId="42" \
--set job.branch="fix/issue-42" \
--namespace ralph
```
### Values
| Parameter | Description | Default |
|-----------|-------------|---------|
| `job.repo` | Target repository URL (required) | `""` |
| `job.issueId` | GitHub issue ID (required) | `""` |
| `job.branch` | Branch name (required) | `""` |
| `job.issueSource` | Cross-repo issue source | `""` |
| `image.repository` | Container image | `ghcr.io/decocms/ralph` |
| `image.tag` | Image tag | `latest` |
| `claude.maxIterations` | Max loop iterations | `10` |
| `claude.iterationDelay` | Delay between iterations | `5` |
| `workflow.createPullRequest` | Create PR after push | `true` |
| `workflow.postIssueComment` | Post summary comment on issue | `true` |
| `secrets.apiSecretName` | Name of API keys secret | `ralph-secrets` |
| `secrets.sshSecretName` | Name of SSH key secret | `ralph-ssh-key` |
See [charts/ralph/values.yaml](charts/ralph/values.yaml) for all options.
## How It Works
```
┌─────────────────────────────────────────────────────────────┐
│ Ralph Flow │
├─────────────────────────────────────────────────────────────┤
│ │
│ ./ralph.sh │
│ │ │
│ ▼ │
│ 1. Helm install → Creates K8s Job │
│ │
│ Inside the container: │
│ ┌────────────────────────────────────────────────────────┐│
│ │ 2. Fetch issue context from GitHub API ││
│ │ 3. Check write access → Fork if needed ││
│ │ 4. Clone repo (or fork) & create branch ││
│ │ 5. Run Claude Code loop until :::TASK_COMPLETE::: ││
│ │ 6. Commit & push changes ││
│ │ 7. Create Pull Request (via gh CLI) ││
│ │ 8. Post cost summary comment on issue ││
│ └────────────────────────────────────────────────────────┘│
│ │
│ Result: PR opened and issue updated with summary │
│ │
└─────────────────────────────────────────────────────────────┘
```
### Fork Workflow
Ralph automatically detects if you have write access to the target repository:
1. **Write access exists** → Pushes directly to the repo, creates PR within same repo
2. **No write access** → Creates a fork, pushes to fork, creates PR from fork to upstream
This allows Ralph to work on any public repository without requiring collaborator access.
## Cost Tracking
Ralph tracks token usage across all Claude iterations and reports:
- **Input tokens** — Tokens sent to Claude
- **Output tokens** — Tokens generated by Claude
- **Estimated cost** — Based on Claude Sonnet 3.5 pricing
At the end of each run, Ralph:
1. Prints a cost summary to the logs
2. Posts a comment on the GitHub issue with the cost breakdown
Example output:
```
================================================================================
RALPH COST REPORT
================================================================================
Token Usage:
- Input tokens: 15234
- Output tokens: 8921
- Total tokens: 24155
Estimated Cost (Claude Sonnet 3.5 pricing):
- Input cost: $0.0457
- Output cost: $0.1338
- TOTAL COST: $0.1795
================================================================================
```
## The Ralph Wiggum Technique
This project implements the **[Ralph Wiggum AI Loop Technique](https://awesomeclaude.ai/ralph-wiggum)** — an iterative AI development methodology where a simple loop repeatedly feeds Claude a prompt until a completion marker is detected.
```bash
# The core concept:
while :; do cat PROMPT.md | claude ; done
```
**Key principles:**
- **Iteration > Perfection** — Don't aim for perfect on first try
- **Failures Are Data** — Failures are predictable and informative
- **Persistence Wins** — Keep trying until success
## File Structure
```
.
├── ralph.sh # CLI tool - creates K8s jobs via Helm
├── entrypoint.sh # Container entrypoint (runs inside pod)
├── Dockerfile # Container image definition
├── charts/
│ └── ralph/ # Helm chart
│ ├── Chart.yaml
│ ├── values.yaml
│ └── templates/
├── .github/
│ └── workflows/
│ └── release.yaml # CI/CD - publishes to GHCR on tags
└── README.md
```
## CI/CD
The project uses GitHub Actions to automatically build and publish:
- **Docker image** → `ghcr.io/decocms/ralph:TAG`
- **Helm chart** → GitHub Release assets
### Creating a Release
```bash
git tag v1.0.0
git push origin v1.0.0
```
This triggers the workflow to:
1. Build multi-arch Docker image (amd64, arm64)
2. Push to GitHub Container Registry
3. Package and upload Helm chart
## Security
- **Secrets**: Never committed to Git - use Kubernetes secrets
- **Non-root**: Container runs as `node` user (UID 1000)
- **Isolation**: Each job runs in its own pod
- **TTL**: Jobs auto-delete after 1 hour
### Required GitHub Token Permissions
The PAT needs sufficient permissions for forking, pushing, and creating PRs:
- **Public repos**: `public_repo`, `read:org` (for forking)
- **Private repos**: `repo` (full control)
**Fine-grained token scopes** (recommended):
- `contents: write` — Push commits
- `pull_requests: write` — Create PRs
- `issues: write` — Post comments
- `metadata: read` — Read repo info
## Troubleshooting
### Check Job Status
```bash
kubectl get jobs -n ralph -l app.kubernetes.io/name=ralph
kubectl logs -f job/ralph-issue-42 -n ralph
```
### Delete a Job
```bash
helm uninstall ralph-issue-42 -n ralph
```
### SSH Key Issues
```bash
# Verify secret exists
kubectl get secret ralph-ssh-key -n ralph
# Check key format
kubectl get secret ralph-ssh-key -n ralph -o jsonpath='{.data.ssh-private-key}' | base64 -d | head -2
```
## License
MIT License
## Credits
- [Ralph Wiggum Technique](https://awesomeclaude.ai/ralph-wiggum) - The iterative AI loop methodology
- [snarktank/ralph](https://github.com/snarktank/ralph) - Original Ralph pattern
- [Claude Code Docker article](https://medium.com/@dan.avila7/running-claude-code-agents-in-docker-containers-for-complete-isolation-63036a2ef6f4) by Daniel Avila