{"id":50666828,"url":"https://github.com/decocms/ralph","last_synced_at":"2026-06-08T07:05:42.365Z","repository":{"id":333741835,"uuid":"1137496431","full_name":"decocms/ralph","owner":"decocms","description":null,"archived":false,"fork":false,"pushed_at":"2026-01-20T20:18:31.000Z","size":41,"stargazers_count":1,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-21T04:41:42.141Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/decocms.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-19T12:52:58.000Z","updated_at":"2026-01-20T20:18:29.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/decocms/ralph","commit_stats":null,"previous_names":["decocms/ralph"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/decocms/ralph","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/decocms%2Fralph","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/decocms%2Fralph/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/decocms%2Fralph/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/decocms%2Fralph/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/decocms","download_url":"https://codeload.github.com/decocms/ralph/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/decocms%2Fralph/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34051797,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-08T07:05:05.696Z","updated_at":"2026-06-08T07:05:42.359Z","avatar_url":"https://github.com/decocms.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ralph - Autonomous Claude Code Runner for GitHub Issues\n\nRalph 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.\n\n[![Release](https://github.com/decocms/ralph/actions/workflows/release.yaml/badge.svg)](https://github.com/decocms/ralph/actions/workflows/release.yaml)\n\n## Features\n\n- **GitHub Issue Integration** — Fetches issue title, description, labels, and comments\n- **Autonomous Loop** — Runs Claude Code iteratively until completion signal\n- **Smart Fork Detection** — Automatically forks repos when no write access, pushes directly when allowed\n- **Automatic PR Creation** — Opens pull requests with proper issue references\n- **Cost Tracking** — Reports token usage and estimated costs at completion\n- **Issue Commenting** — Posts summary with PR link and cost to the original issue\n- **Cross-Repo Issues** — Fetch issues from one repo, implement in another\n- **Safety Limits** — Max iterations and rate limiting prevent runaway costs\n- **Kubernetes Native** — Helm chart for easy deployment\n- **SSH Authentication** — Secure Git operations with SSH keys\n\n## Quick Start\n\n### Prerequisites\n\n- Kubernetes cluster with `kubectl` configured\n- [Helm](https://helm.sh/docs/intro/install/) installed\n- GitHub Personal Access Token\n- Anthropic API Key\n- SSH key for Git push access\n\n### 1. Install the Helm Chart\n\n```bash\n# Add the chart repository (or clone this repo)\ngit clone https://github.com/decocms/ralph.git\ncd ralph\n```\n\n### 2. Create Secrets\n\n```bash\n# Create namespace\nkubectl create namespace ralph\n\n# Create API secrets\nkubectl create secret generic ralph-secrets \\\n  --from-literal=github-token='ghp_xxxxxxxxxxxx' \\\n  --from-literal=anthropic-api-key='sk-ant-xxxxxxxxxxxx' \\\n  -n ralph\n\n# Create SSH key secret\nkubectl create secret generic ralph-ssh-key \\\n  --from-file=ssh-private-key=$HOME/.ssh/id_rsa \\\n  -n ralph\n```\n\n### 3. Run a Job\n\n```bash\n# Using the CLI script\nNAMESPACE=ralph ./ralph.sh git@github.com:owner/repo.git 42 fix/issue-42\n\n# Or directly with Helm\nhelm install my-job ./charts/ralph \\\n  --set job.repo=\"git@github.com:owner/repo.git\" \\\n  --set job.issueId=\"42\" \\\n  --set job.branch=\"fix/issue-42\" \\\n  --namespace ralph\n```\n\n## Usage\n\n### CLI Script\n\n```bash\n./ralph.sh \u003ctarget-repo\u003e \u003cissue\u003e \u003cbranch-name\u003e\n```\n\nThe `\u003cissue\u003e` can be:\n- A number (e.g., `226`) — fetches from target repo\n- A full GitHub URL (e.g., `https://github.com/org/repo/issues/42`) — fetches from that repo\n\n### Examples\n\n```bash\n# Issue from same repo\n./ralph.sh git@github.com:acme/api.git 42 fix/issue-42\n\n# Issue from different repo (cross-repo)\n./ralph.sh git@github.com:acme/api.git https://github.com/acme/tasks/issues/123 fix/task-123\n```\n\n### Environment Variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `NAMESPACE` | `default` | Kubernetes namespace |\n| `CHART_PATH` | `./charts/ralph` | Path to Helm chart |\n| `IMAGE_REPO` | `ghcr.io/decocms/ralph` | Container image |\n| `IMAGE_TAG` | `latest` | Image tag |\n\n## Helm Chart\n\n### Installation\n\n```bash\nhelm install ralph-job ./charts/ralph \\\n  --set job.repo=\"git@github.com:owner/repo.git\" \\\n  --set job.issueId=\"42\" \\\n  --set job.branch=\"fix/issue-42\" \\\n  --namespace ralph\n```\n\n### Values\n\n| Parameter | Description | Default |\n|-----------|-------------|---------|\n| `job.repo` | Target repository URL (required) | `\"\"` |\n| `job.issueId` | GitHub issue ID (required) | `\"\"` |\n| `job.branch` | Branch name (required) | `\"\"` |\n| `job.issueSource` | Cross-repo issue source | `\"\"` |\n| `image.repository` | Container image | `ghcr.io/decocms/ralph` |\n| `image.tag` | Image tag | `latest` |\n| `claude.maxIterations` | Max loop iterations | `10` |\n| `claude.iterationDelay` | Delay between iterations | `5` |\n| `workflow.createPullRequest` | Create PR after push | `true` |\n| `workflow.postIssueComment` | Post summary comment on issue | `true` |\n| `secrets.apiSecretName` | Name of API keys secret | `ralph-secrets` |\n| `secrets.sshSecretName` | Name of SSH key secret | `ralph-ssh-key` |\n\nSee [charts/ralph/values.yaml](charts/ralph/values.yaml) for all options.\n\n## How It Works\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│                         Ralph Flow                          │\n├─────────────────────────────────────────────────────────────┤\n│                                                             │\n│  ./ralph.sh \u003crepo\u003e \u003cissue\u003e \u003cbranch\u003e                        │\n│     │                                                       │\n│     ▼                                                       │\n│  1. Helm install → Creates K8s Job                         │\n│                                                             │\n│  Inside the container:                                      │\n│  ┌────────────────────────────────────────────────────────┐│\n│  │ 2. Fetch issue context from GitHub API                 ││\n│  │ 3. Check write access → Fork if needed                 ││\n│  │ 4. Clone repo (or fork) \u0026 create branch                ││\n│  │ 5. Run Claude Code loop until :::TASK_COMPLETE:::      ││\n│  │ 6. Commit \u0026 push changes                               ││\n│  │ 7. Create Pull Request (via gh CLI)                    ││\n│  │ 8. Post cost summary comment on issue                  ││\n│  └────────────────────────────────────────────────────────┘│\n│                                                             │\n│  Result: PR opened and issue updated with summary           │\n│                                                             │\n└─────────────────────────────────────────────────────────────┘\n```\n\n### Fork Workflow\n\nRalph automatically detects if you have write access to the target repository:\n\n1. **Write access exists** → Pushes directly to the repo, creates PR within same repo\n2. **No write access** → Creates a fork, pushes to fork, creates PR from fork to upstream\n\nThis allows Ralph to work on any public repository without requiring collaborator access.\n\n## Cost Tracking\n\nRalph tracks token usage across all Claude iterations and reports:\n\n- **Input tokens** — Tokens sent to Claude\n- **Output tokens** — Tokens generated by Claude\n- **Estimated cost** — Based on Claude Sonnet 3.5 pricing\n\nAt the end of each run, Ralph:\n1. Prints a cost summary to the logs\n2. Posts a comment on the GitHub issue with the cost breakdown\n\nExample output:\n```\n================================================================================\n                           RALPH COST REPORT\n================================================================================\n\nToken Usage:\n  - Input tokens:  15234\n  - Output tokens: 8921\n  - Total tokens:  24155\n\nEstimated Cost (Claude Sonnet 3.5 pricing):\n  - Input cost:    $0.0457\n  - Output cost:   $0.1338\n  - TOTAL COST:    $0.1795\n\n================================================================================\n```\n\n## The Ralph Wiggum Technique\n\nThis 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.\n\n```bash\n# The core concept:\nwhile :; do cat PROMPT.md | claude ; done\n```\n\n**Key principles:**\n- **Iteration \u003e Perfection** — Don't aim for perfect on first try\n- **Failures Are Data** — Failures are predictable and informative\n- **Persistence Wins** — Keep trying until success\n\n## File Structure\n\n```\n.\n├── ralph.sh              # CLI tool - creates K8s jobs via Helm\n├── entrypoint.sh         # Container entrypoint (runs inside pod)\n├── Dockerfile            # Container image definition\n├── charts/\n│   └── ralph/            # Helm chart\n│       ├── Chart.yaml\n│       ├── values.yaml\n│       └── templates/\n├── .github/\n│   └── workflows/\n│       └── release.yaml  # CI/CD - publishes to GHCR on tags\n└── README.md\n```\n\n## CI/CD\n\nThe project uses GitHub Actions to automatically build and publish:\n\n- **Docker image** → `ghcr.io/decocms/ralph:TAG`\n- **Helm chart** → GitHub Release assets\n\n### Creating a Release\n\n```bash\ngit tag v1.0.0\ngit push origin v1.0.0\n```\n\nThis triggers the workflow to:\n1. Build multi-arch Docker image (amd64, arm64)\n2. Push to GitHub Container Registry\n3. Package and upload Helm chart\n\n## Security\n\n- **Secrets**: Never committed to Git - use Kubernetes secrets\n- **Non-root**: Container runs as `node` user (UID 1000)\n- **Isolation**: Each job runs in its own pod\n- **TTL**: Jobs auto-delete after 1 hour\n\n### Required GitHub Token Permissions\n\nThe PAT needs sufficient permissions for forking, pushing, and creating PRs:\n\n- **Public repos**: `public_repo`, `read:org` (for forking)\n- **Private repos**: `repo` (full control)\n\n**Fine-grained token scopes** (recommended):\n- `contents: write` — Push commits\n- `pull_requests: write` — Create PRs\n- `issues: write` — Post comments\n- `metadata: read` — Read repo info\n\n## Troubleshooting\n\n### Check Job Status\n\n```bash\nkubectl get jobs -n ralph -l app.kubernetes.io/name=ralph\nkubectl logs -f job/ralph-issue-42 -n ralph\n```\n\n### Delete a Job\n\n```bash\nhelm uninstall ralph-issue-42 -n ralph\n```\n\n### SSH Key Issues\n\n```bash\n# Verify secret exists\nkubectl get secret ralph-ssh-key -n ralph\n\n# Check key format\nkubectl get secret ralph-ssh-key -n ralph -o jsonpath='{.data.ssh-private-key}' | base64 -d | head -2\n```\n\n## License\n\nMIT License\n\n## Credits\n\n- [Ralph Wiggum Technique](https://awesomeclaude.ai/ralph-wiggum) - The iterative AI loop methodology\n- [snarktank/ralph](https://github.com/snarktank/ralph) - Original Ralph pattern\n- [Claude Code Docker article](https://medium.com/@dan.avila7/running-claude-code-agents-in-docker-containers-for-complete-isolation-63036a2ef6f4) by Daniel Avila\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdecocms%2Fralph","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdecocms%2Fralph","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdecocms%2Fralph/lists"}