Local-first AI pull-request review. This is the course starter template: a minimal-but-working tool that does exactly one thing end to end — import a PR and run an agent review on it. Every later course lesson adds one feature back (see What you build in the course).
Several standalone packages (no monorepo workspace — each has its own
package.json and lockfile; cross-package code is shared through tsconfig path
aliases, not published modules):
| Folder | Package | What it is | Port |
|---|---|---|---|
server/ |
@devdigest/api |
Fastify API + Drizzle/Postgres (pgvector) | 3001 |
client/ |
@devdigest/web |
Next.js 15 web app (the studio) | 3000 |
reviewer-core/ |
@devdigest/reviewer-core |
Pure review engine: diff → prompt → LLM → findings | — |
e2e/ |
@devdigest/e2e |
Deterministic browser e2e (agent-browser) | — |
server/src/vendor/shared |
@devdigest/shared |
Zod contracts shared across every package | — |
repo-intel (the codebase indexer that powers the Indexed badge and feeds
project context into reviews) lives inside the server at
server/src/modules/repo-intel. Only
Postgres runs in Docker; the API and web app run on the host via pnpm dev.
flowchart LR
subgraph Studio["Local studio (your machine)"]
WEB["client/<br/>Next.js · :3000"]
API["server/<br/>Fastify · :3001"]
PG[("Postgres<br/>pgvector")]
WEB -->|"REST /repos /pulls /agents /runs …"| API
API --> PG
end
CLONE["git clone (add repo)"] --> INDEX["repo-intel<br/>index symbols + import graph<br/>→ repo map"]
API --> CLONE
INDEX -->|"repo map = review context"| ENGINE
ENGINE["reviewer-core/<br/>diff + repo map → prompt → LLM<br/>→ structured findings → grounding gate"]
LLM["LLM<br/>OpenAI · Anthropic · OpenRouter"]
API -->|"run review"| ENGINE
ENGINE --> LLM
SHARED["@devdigest/shared<br/>Zod contracts"]
SHARED -.->|"one schema, every package"| WEB
SHARED -.-> API
SHARED -.-> ENGINE
The review flow end to end: add a repo → server clones it and repo-intel
indexes it (the Indexed badge) → import PRs from GitHub → open a PR and
Review → reviewer-core assembles a prompt from the diff + the repo map,
calls the LLM, validates every finding against the diff (the grounding gate
drops hallucinated line references), and persists structured findings with a
severity and score. All local; the only outbound calls are to GitHub (PR data)
and the LLM (via OpenRouter).
Each package has its own README with deeper diagrams:
client (UI route map) ·
server (API map) ·
reviewer-core (review pipeline) ·
e2e.
- Local launch — one command brings up Postgres (Docker) + API + web.
- Settings — store your LLM API key (OpenAI / Anthropic) and GitHub token.
- Add repository — paste a repo URL; the server clones and indexes it.
- Import pull requests — pull open PRs and their diff, commits, body, and linked issue.
- View diff — GitHub-like diff in the browser.
- Agents — two built-in reviewers (General + Security); create/edit your own (model + system prompt).
- Run a review — single-pass analysis returning structured findings (severity + score), with the grounding gate and repo-map context working from the start.
These are intentionally not in the starter — each lesson adds one back:
| Lesson | You build |
|---|---|
| L01 | Run cost badge · severity filter on findings |
| L02 | Skills in the product · Conventions extractor |
| L03 | Intent layer · Smart Diff |
| L04 | devdigest-mcp server · Blast Radius (reads repo-intel) |
| L05 | Project Context Folder · Onboarding generator · PR Brief card |
| L06 | Eval pipeline · Secret/Phantom gates · Plan Verifier · Export to CI |
| L07 | Multi-agent review · Run Trace / Live Log · Persistent memory · per-agent stats |
| L08 | Plugin export/import · Agent performance dashboard · weekly digest |
- Node ≥ 22 · pnpm ≥ 10 (
npm i -g pnpm) · Docker (for Postgres)
./scripts/dev.shThis script:
- starts Postgres (
docker compose up -d) and waits until it's healthy, - creates
server/.envandclient/.envfrom.env.exampleif missing, - installs deps in
server/andclient/(only whennode_modulesis absent), - applies DB migrations and seeds demo data,
- launches the API (
:3001) and the web app (:3000).
Open http://localhost:3000. Press Ctrl-C to stop the dev servers —
Postgres keeps running (docker compose down to stop it).
Flags: --no-seed · --no-client · --db-only · --help.
Add your keys in
server/.env(OPENAI_API_KEY/ANTHROPIC_API_KEY,GITHUB_TOKEN) or via the Settings UI at runtime.
docker compose up -d # Postgres + pgvector
cd server && pnpm install
pnpm db:migrate # apply migrations (NOT run automatically on boot)
pnpm db:seed # idempotent demo data (optional)
pnpm dev # API on :3001
cd ../client && pnpm install && pnpm dev # web on :3000server/: dev · build · db:migrate · db:seed · db:generate · test · typecheck
(unit/integration split: pnpm exec vitest run --exclude '**/*.it.test.ts' / pnpm exec vitest run .it.test)
client/: dev · build · start · test · typecheck
One test suite per package, each gated by its own GitHub Actions workflow with a
path filter — full strategy in TESTING.md.
| Suite | Workflow | Needs Docker |
|---|---|---|
| client (vitest + jsdom) | client.yml |
no |
| server unit (hermetic) | server-unit.yml |
no |
| server integration (real Postgres) | server-integration.yml |
yes |
| reviewer-core (engine) | reviewer-core.yml |
no |
| web e2e (agent-browser, real stack) | e2e-web.yml |
yes |
Server tests split by filename: *.it.test.ts are DB-backed (testcontainers
Postgres); everything else is hermetic. The browser e2e flows live in
e2e/ and run deterministically (no LLM).
relation ... does not exist/ API errors on first run — migrations weren't applied. The server does not migrate on boot: runcd server && pnpm db:migrate.- Port 5432 already in use — another Postgres is running. Stop it, or change the
host port in
docker-compose.yml. vectortype errors — the pgvector extension is enabled by migration0000; make sure migrations ran against the Dockerized DB, not a different one.- Reset everything —
docker compose down -vdrops the volume, then re-run./scripts/dev.sh.
MIT — fork it, extend it, run it inside your own company. The only requirement is that the copyright notice travels with the copy.
This starter is built for participants of the AI Agentic Engineering course: you are meant to copy it, keep it in your own fork, and grow it lesson by lesson into your own working PR-review tool — including using it for your own projects and at work.