{"id":51623348,"url":"https://github.com/hexclave/exterminator","last_synced_at":"2026-07-12T21:30:41.740Z","repository":{"id":341440682,"uuid":"1169567004","full_name":"hexclave/exterminator","owner":"hexclave","description":null,"archived":false,"fork":false,"pushed_at":"2026-03-01T18:21:45.000Z","size":1194,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-04T20:41:16.650Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hexclave.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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-02-28T21:58:27.000Z","updated_at":"2026-03-31T12:37:17.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/hexclave/exterminator","commit_stats":null,"previous_names":["stack-auth/exterminator","hexclave/exterminator"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/hexclave/exterminator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hexclave%2Fexterminator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hexclave%2Fexterminator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hexclave%2Fexterminator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hexclave%2Fexterminator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hexclave","download_url":"https://codeload.github.com/hexclave/exterminator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hexclave%2Fexterminator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35403794,"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-07-12T02:00:06.386Z","response_time":87,"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-07-12T21:30:39.605Z","updated_at":"2026-07-12T21:30:41.732Z","avatar_url":"https://github.com/hexclave.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Exterminator\n\n**Autonomous bug detection, reproduction, and fixing for web apps.**\n\nExterminator watches your frontend for crashes. When one happens, it spins up an isolated cloud sandbox, reproduces the error on video, patches the code, opens a GitHub PR, then validates the fix — all without human intervention.\n\n```\nError crashes your app\n       │\n       ▼\nBrowser script captures it → Dashboard ingests it\n       │\n       ▼\nDaytona sandbox spins up\n       │\n       ├─ [Reproduce agent]  navigates the app, confirms the crash (video)\n       ├─ [Fix agent]        reads source, patches the bug, opens a PR\n       └─ [Validate agent]   re-runs the app, confirms fix + no regressions (video)\n```\n\n---\n\n## Repo structure\n\n```\nbrowser-script/   TypeScript → single JS bundle for \u003cscript\u003e tags\ndashboard/        Next.js + Convex — error monitoring UI and pipeline orchestrator\ndemo/             Sample React app (Planr) with realistic bugs for end-to-end testing\nai/\n  agent/          Node.js agent server running inside the Daytona sandbox\n  runner/         Python pipeline: reproduce → fix → validate\n  Dockerfile      Image baked with the agent, demo app clone, and all deps\n  entrypoint.sh   Pulls latest demo code, starts Vite dev server + agent server\n  create-snapshot.ts  Builds and registers a new Daytona snapshot\n```\n\n---\n\n## Quick start\n\n### 1. Dashboard\n\n```bash\ncd dashboard\npnpm install\n\n# Start local Convex backend (generates .env.local automatically)\nnpx convex dev\n\n# In a second terminal, start Next.js\npnpm dev -p 3003     # → http://localhost:3003\n```\n\nAdd the following to `dashboard/.env.local`:\n\n| Variable | Source | Purpose |\n|---|---|---|\n| `NEXT_PUBLIC_CONVEX_URL` | Auto-created by `npx convex dev` | Convex backend URL |\n| `CONVEX_DEPLOYMENT` | Auto-created by `npx convex dev` | Convex deployment name |\n| `DAYTONA_API_KEY` | [Daytona dashboard](https://app.daytona.io) | Sandbox creation |\n| `ANTHROPIC_API_KEY` | [Anthropic console](https://console.anthropic.com) | Fix agent (Claude) |\n| `NEXT_PUBLIC_STACK_PROJECT_ID` | [Stack Auth](https://app.stack-auth.com) → project settings | Auth |\n| `NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY` | Stack Auth → API keys | Auth |\n| `STACK_SECRET_SERVER_KEY` | Stack Auth → API keys | Auth (server-side) |\n\n### 2. Demo app\n\n```bash\ncd demo\npnpm install\npnpm dev     # → http://localhost:3001\n```\n\nThe demo app (`Planr`) ships with realistic bugs. The browser script is pre-configured to send errors to the dashboard. Trigger a bug by clicking on a task with no due date — the detail panel will crash with `TypeError: Cannot read properties of null (reading 'split')`.\n\n### 3. Browser script\n\nTo wire up your own app, add to your `index.html`:\n\n```html\n\u003cscript src=\"exterminator.js\" data-endpoint=\"http://localhost:3003/api/events\"\u003e\u003c/script\u003e\n```\n\nTo rebuild the script from source:\n\n```bash\ncd browser-script\npnpm install\npnpm build     # → dist/index.global.js\n```\n\n---\n\n## Authentication (Stack Auth + GitHub OAuth)\n\nThe dashboard uses [Stack Auth](https://stack-auth.com) for auth and to obtain GitHub tokens for PR creation.\n\n1. Create a project at [app.stack-auth.com](https://app.stack-auth.com) and copy the three env vars above\n2. Create a GitHub OAuth App at [github.com/settings/developers](https://github.com/settings/developers):\n   - **Homepage URL**: `http://localhost:3003`\n   - **Authorization callback URL**: `https://api.stack-auth.com/api/v1/auth/oauth/callback/github`\n3. In Stack Auth → **Auth Methods** → **GitHub**, paste your Client ID + Secret\n4. Sign in at `http://localhost:3003/handler/sign-in`\n\n---\n\n## Daytona snapshot\n\nThe AI pipeline runs inside a Daytona sandbox built from `ai/Dockerfile`. The snapshot is pre-baked with Python, Node, pnpm, ffmpeg, Playwright, and a clone of the demo repo.\n\nTo build a new snapshot (replaces the existing one — coordinate with the team first):\n\n```bash\ncd ai\npnpm install\nDAYTONA_API_KEY=... npx tsx create-snapshot.ts\n```\n\nThe snapshot name defaults to `exterminator-ai-8` and is configurable via `DAYTONA_SNAPSHOT_NAME` in `dashboard/.env.local`.\n\n---\n\n## How the pipeline works\n\n1. **Browser script** captures uncaught errors and unhandled rejections, batches them, and POSTs to `POST /api/events`.\n2. **Dashboard** stores the error in Convex. The UI renders an error card and automatically calls `POST /api/sandbox` to spin up a Daytona sandbox.\n3. **Reproduce agent** (`browser-use` + Python) navigates the live app inside the sandbox, confirms the crash, and records a video.\n4. **Fix agent** (`claude-code` SDK) reads the source files implicated in the stack trace and applies a targeted patch. If a previous fix introduced a regression, the agent receives that context and tries again.\n5. **Validate agent** (`browser-use` + Python) re-runs the app, confirms the original crash is gone, performs a full regression sweep across all pages, and records a video. If a new error is found, the loop repeats from step 4.\n6. On success, a **GitHub PR** is opened with the patched files for human review and merging.\n\nAll progress is written to Convex in real time and streamed to the dashboard UI.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhexclave%2Fexterminator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhexclave%2Fexterminator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhexclave%2Fexterminator/lists"}