Turn runtime errors into reviewable pull/merge requests, automatically.
nreactive is an open-source, self-hostable tool. You POST an error (plus the
code area and any context) to its API; it queues the error, packs the relevant
code with repomix, asks an LLM for a
fix, and opens a draft PR (GitHub) or MR (GitLab) on your repo for human
review. A dashboard lists every error, whether a PR was opened, and exactly why
if it wasn't.
HTTP POST /api/send ──> store record (status=pending) ──> 202 { id }
│
in-process poller (every POLL_INTERVAL_MS)
│ claim up to QUEUE_BATCH_SIZE pending
▼
per record:
1. shallow-clone the target repo into a temp workdir
2. repomix --include <area globs> ──> packed code context
3. build prompt(error, context, packed code)
4. LLM generateFix() ──> { title, summary, files:[{path,content}] }
5. guardrails (allowed paths, max files, max diff size)
6. git: branch (nreactive/...), write files, commit, push
7. open PR (GitHub) / MR (GitLab) ──> mrUrl
8. record status = done + mrUrl (or failed + failureReason)
Status lifecycle: pending → done | failed. A claimed-but-crashed record is
re-claimed after LEASE_TIMEOUT_MS (crash recovery).
# 1. clone + install
git clone https://github.com/your-org/nreactive.git
cd nreactive
npm install
# 2. configure
cp .env.example .env
# edit .env: set your LLM key, git host token, DEFAULT_REPO, INGEST_API_KEY
# 3. start a database (Postgres + Mongo both provided)
docker compose up -d postgres # or: docker compose up -d mongo
# 4. (Postgres only) run migrations
npm run prisma:migrate
# 5. run
npm run dev- Landing page: http://localhost:3000/
- Dashboard: http://localhost:3000/dashboard
Send your first error:
curl -X POST http://localhost:3000/api/send \
-H "content-type: application/json" \
-H "x-api-key: $INGEST_API_KEY" \
-d '{
"error": "TypeError: Cannot read properties of undefined (reading \"id\")",
"area": ["src/users", "src/lib/auth"],
"context": "Thrown in production when a session token is expired."
}'Watch the worker logs; the record flips pending → done and a draft PR/MR
appears on your repo.
nreactive needs a token that can read repo contents, push a branch, and open a
PR/MR. Use a token scoped to only the repos you want it to touch.
- Go to GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token.
- Resource owner: pick the user/org that owns the target repo.
- Repository access: choose Only select repositories and pick the repo(s)
you want
nreactiveto open PRs on. - Repository permissions — set these to Read and write:
- Contents (clone, push branch)
- Pull requests (open the PR)
- Leave everything else at No access.
- Generate, copy the token, and set it in
.env:GIT_HOST=github GITHUB_TOKEN=github_pat_xxx DEFAULT_REPO=owner/repo
Classic PATs also work — give them the
reposcope — but fine-grained tokens are strongly preferred because you can limit them to specific repos.
- Go to GitLab → your repo → Settings → Access tokens (project token, most scoped), or User Settings → Access tokens for a personal token.
- Name it (e.g.
nreactive) and set an expiry. - Role: at least Developer (needed to push branches and open MRs).
- Scopes: select
api(covers repo read/write + merge requests). If you prefer minimal scopes,write_repositoryplus MR access also works. - Create, copy the token, and set it in
.env:GIT_HOST=gitlab GITLAB_TOKEN=glpat-xxx GITLAB_BASE_URL=https://gitlab.com # or your self-hosted instance DEFAULT_REPO=group/project # full project path
The target repo is DEFAULT_REPO by default; any request can override it with a
repo field in the payload (as long as the token has access).
nreactive ships a storage adapter with two interchangeable backends, selected
by DB_DRIVER.
DB_DRIVER=postgres
DATABASE_URL=postgresql://nreactive:nreactive@localhost:5432/nreactive?schema=public
Run migrations before first use (and after pulling schema changes):
npm run prisma:migrate # prisma migrate deployDB_DRIVER=mongo
MONGODB_URI=mongodb://localhost:27017/nreactive
No migration step is needed — Mongoose creates the collection and indexes on first write.
Ingest an error for processing.
Headers
| header | required | notes |
|---|---|---|
content-type: application/json |
yes | |
x-api-key: <INGEST_API_KEY> |
only if INGEST_API_KEY is set |
Authorization: Bearer <key> is also accepted |
Body
Response — 202 Accepted
{ "id": "…", "status": "pending" }Errors: 400 (invalid JSON / payload), 401 (bad or missing API key).
Paginated list for the dashboard.
Query params: page (default 1), limit (default 20, max 100), status
(pending | done | failed).
{ "items": [ /* ErrorRecord[] */ ], "total": 0, "page": 1, "limit": 20 }All configurable via env vars (see .env.example):
| var | default | purpose |
|---|---|---|
QUEUE_BATCH_SIZE |
5 |
pending records claimed per poll tick |
POLL_INTERVAL_MS |
10000 |
how often the poller runs |
LEASE_TIMEOUT_MS |
300000 |
stuck-record re-claim window (crash recovery) |
MAX_FILES_CHANGED |
10 |
reject fixes touching more files |
MAX_DIFF_BYTES |
200000 |
reject oversized fixes |
MAX_ATTEMPTS |
3 |
stop retrying a record |
BRANCH_PREFIX |
nreactive |
generated branches are always prefixed |
ENABLE_WORKER |
true |
set false to run the web app without the poller |
The fix is also restricted to paths under the request's area (path allowlist),
and nreactive never pushes to the default branch — it always opens a
PR/MR for human review.
- The background worker boots from Next.js
instrumentation.tsand is gated byENABLE_WORKER. To scale, run the web app withENABLE_WORKER=falseand a single separatenext startinstance withENABLE_WORKER=trueas the worker. docker-compose.ymlprovides Postgres and Mongo for local development. Bring up only the one matchingDB_DRIVER.- repomix is invoked as a CLI (
npx repomix) against the cloned repo, so the upstream tool is tracked as-is. - Set
WORK_DIRto control where repos are cloned during processing (default/tmp/nreactive-work); each job uses a fresh temp dir that is cleaned up after.
npm run dev # next dev
npm run build # production build (+ typecheck)
npm test # vitest run
npm run test:watch # vitest watchTests live in tests/ and cover the core (prompt builder, guardrails, LLM
output parsing, store CRUD + claim-batch, and the full process-record pipeline
with mocked LLM + git host).
Open source. See LICENSE (add the license of your choice).
{ "error": "string (required) — the message + stacktrace", "area": ["string"], // optional — folder globs to scope the code context "context": "string", // optional — extra runtime/user context "repo": "owner/repo" // optional — overrides DEFAULT_REPO }