Pluggable AI skill runner for pull requests.
helPRs spins up ephemeral Docker containers running Claude Code to execute skills against your PRs -- comprehension quizzes, code reviews, security audits -- and streams results back in real time.
BYOK (Bring Your Own Key): you provide your Claude credentials once. The backend never calls the Claude API -- containers use your credentials natively. Costs are billed to your Claude subscription (or Anthropic API account if you use an API key instead).
helPRs is alpha. The architecture is stable, the core flows work end-to-end, but the API and skill spec may still break between releases. Self-hosting is supported and documented -- see the self-hosting guide for hardware requirements and step-by-step setup.
1. PR opened 2. Pick a skill 3. Get results
on GitHub (or auto-trigger) streamed live
┌──────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ GitHub App │ webhook │ helPRs API │ docker │ Claude Code │
│ sends PR │────────> │ creates │───────> │ runs skill │
│ event │ │ session │ │ in container │
└──────────────┘ └──────────────────┘ └────────┬────────┘
│ SSE
v
┌─────────────────┐
│ helPRs UI │
│ renders output │
│ + follow-ups │
└─────────────────┘
Each container is ephemeral -- it clones your repo, runs the skill, streams the output, then self-destructs. No state persists between sessions.
git clone https://github.com/mariuspruvot/helprs.git
cd helprs
cp .env.example .env
# Fill in .env (see docs/self-hosting.md for details)
docker compose up --build # API :8000, Web :5173, Postgres :5432 (+ builds the claude-runner image)Open http://localhost:5173, authenticate with GitHub, and you're ready to go.
For production deployment, see the Self-Hosting Guide.
Skills are pluggable Claude Code agent definitions. Each skill is a self-contained folder with a prompt template, workflow instructions, and configuration.
| Skill | Description | Duration |
|---|---|---|
| challenge-me | Socratic comprehension quiz -- probes whether the PR author truly understands their own changes. Generates 3-5 targeted questions, evaluates answers, and produces a score card. | 5-10 min |
| eli5 | Explain Like I'm 5 -- can you vulgarize your own code? | 5-8 min |
| hot-seat | Architecture Hot Seat -- defend your design choices under pressure. | 5-10 min |
| pair-debug | Pair Debug -- find the subtle bug Claude injected into your code. | 5-12 min |
| test-me | Test Me -- predict whether test cases pass or fail on your code. | 5-8 min |
Want to create your own? See Creating Skills.
apps/api/ FastAPI backend (Python 3.12, uv)
apps/web/ React frontend (Vite, TypeScript, Tailwind 4)
skills/ Claude Code skill definitions (mounted into containers)
infra/docker/ Dockerfiles (api, web, claude-runner)
infra/coolify/ Production docker-compose
docs/ Architecture docs, guides, ADRs
The backend is a container orchestrator, not an AI host. It receives GitHub webhooks, manages Docker containers, and relays SSE streams. All AI work happens inside ephemeral containers running Claude Code CLI.
For the full picture, see:
- Architecture Overview -- system diagram, request flow, module map
- ADR-001: Container Pivot -- why this architecture
| Layer | Technology |
|---|---|
| Backend | Python 3.12, FastAPI, SQLAlchemy 2, uv |
| Frontend | React 19, Vite, Tailwind CSS v4, Zustand |
| Database | PostgreSQL 16 |
| Containers | Docker, aiodocker, Claude Code CLI |
| Auth | GitHub OAuth, JWT, httpOnly refresh tokens |
| Infra | Docker Compose, Coolify, GHCR |
| Document | Audience | Description |
|---|---|---|
| Self-Hosting Guide | Operators | Deploy helPRs from scratch |
| Architecture | Contributors | System design, data flow, protocols |
| Creating Skills | Skill authors | Build custom skills |
| Skill Specification | Skill authors | Formal spec for skill definitions |
| Contributing | Contributors | Dev setup, code style, PR process |
| Security policy | Everyone | Reporting vulnerabilities |
| ADR-001 | Everyone | Why ephemeral containers |
See CONTRIBUTING.md for dev setup, code style, and PR guidelines.
make lint # Ruff (Python) + ESLint (TypeScript)
make test # pytest + vitestMIT