{"id":50364046,"url":"https://github.com/chloeilabs/chloeicode","last_synced_at":"2026-05-30T03:02:31.137Z","repository":{"id":359798024,"uuid":"1247190848","full_name":"chloeilabs/chloeicode","owner":"chloeilabs","description":"Cloud coding agents control plane powered by the Cursor TypeScript SDK","archived":false,"fork":false,"pushed_at":"2026-05-23T15:16:50.000Z","size":418,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-23T15:20:07.163Z","etag":null,"topics":["cloud-agents","cursor-sdk","neon","nextjs","prisma","typescript","vercel"],"latest_commit_sha":null,"homepage":"https://chloeicode.vercel.app","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/chloeilabs.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":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-23T02:19:55.000Z","updated_at":"2026-05-23T15:06:11.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/chloeilabs/chloeicode","commit_stats":null,"previous_names":["chloeilabs/chloeicode"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/chloeilabs/chloeicode","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chloeilabs%2Fchloeicode","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chloeilabs%2Fchloeicode/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chloeilabs%2Fchloeicode/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chloeilabs%2Fchloeicode/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chloeilabs","download_url":"https://codeload.github.com/chloeilabs/chloeicode/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chloeilabs%2Fchloeicode/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33678271,"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-05-30T02:00:06.278Z","response_time":92,"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":["cloud-agents","cursor-sdk","neon","nextjs","prisma","typescript","vercel"],"created_at":"2026-05-30T03:02:30.111Z","updated_at":"2026-05-30T03:02:31.130Z","avatar_url":"https://github.com/chloeilabs.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Chloei Code\n\nChloei Code is a production-ready MVP control plane for Cursor cloud coding agent runs against GitHub repositories.\n\nThe app lets an authenticated user create, monitor, refresh, cancel, retry, and review Cursor cloud agent runs. It stores raw Cursor statuses/events defensively, keeps `CURSOR_API_KEY` server-side only, and supports optional Cursor pull request creation.\n\n## Stack\n\n- Next.js App Router, TypeScript, React 19\n- Cursor TypeScript SDK: `@cursor/sdk`\n- Postgres with Prisma\n- Auth.js / NextAuth v5 beta with GitHub OAuth and Prisma adapter\n- Tailwind CSS v4 and shadcn/ui\n- Vercel Web Analytics and Speed Insights\n- Vitest for unit tests\n\n## Setup\n\n```bash\npnpm install\ncp .env.example .env\npnpm db:generate\npnpm db:migrate\npnpm dev\n```\n\nThe Cursor SDK currently pulls in `sqlite3`; this repo allows that native build through `pnpm-workspace.yaml`.\n\nOpen `http://localhost:3000`.\n\n## Environment Variables\n\nRequired:\n\n- `DATABASE_URL`: Postgres connection string.\n- `CURSOR_API_KEY`: Cursor Cloud Agents API key from Cursor Dashboard integrations.\n- `AUTH_SECRET`: Auth.js secret.\n- `AUTH_GITHUB_ID`: GitHub OAuth app client ID.\n- `AUTH_GITHUB_SECRET`: GitHub OAuth app secret.\n\nThe GitHub OAuth provider requests `read:user`, `user:email`, `repo`, and\n`read:org` so the app can list the signed-in user's own, collaborator, private,\nand organization repositories without exposing the GitHub token to the browser.\nExisting local sessions created before these scopes were added should sign out\nand sign back in to grant the expanded repository discovery scope.\n\nOptional:\n\n- `ALLOW_DEV_AUTH_BYPASS=true`: local development only. Creates/uses a `dev-user` without OAuth.\n- `DEFAULT_CURSOR_MODEL`: optional model ID. It is validated against `Cursor.models.list()` before run creation.\n- `ALLOWED_GIT_HOSTS`: comma-separated allowed Git hosts. Defaults to `github.com`.\n- `ALLOWED_GITHUB_ORGS`: comma-separated GitHub owners/orgs allowed for submitted repository URLs.\n- `ALLOWED_GITHUB_USERS`: comma-separated GitHub usernames allowed to sign in. If empty and `ALLOWED_EMAILS` is also empty, any GitHub OAuth user can sign in.\n- `ALLOWED_EMAILS`: comma-separated email addresses allowed to sign in. If either user or email allowlist is configured, a sign-in must match one of them.\n- `AGENT_RUN_RATE_LIMIT`: create/cancel/retry requests per user per minute. Defaults to `10`.\n- `AGENT_RUN_ACTIVE_LIMIT`: maximum active `creating`/`running` Cursor runs per user. Defaults to `3`; set `0` to disable.\n- `AGENT_RUN_DAILY_LIMIT`: maximum runs created per user in a rolling 24-hour window. Defaults to `25`; set `0` to disable.\n- `CRON_REFRESH_BATCH_SIZE`: maximum active runs refreshed by each scheduled cron invocation. Defaults to `10`.\n- `STALE_ACTIVE_RUN_MINUTES`: minutes before an active run is reported as stale on `/status`. Defaults to `15`.\n- `CRON_SECRET`: bearer token for the Vercel cron endpoint that refreshes active Cursor runs.\n\nNever expose Cursor credentials through `NEXT_PUBLIC_*` variables.\n\nFor production, configure a dedicated GitHub OAuth app with:\n\n```text\nHomepage URL: https://your-production-domain\nAuthorization callback URL: https://your-production-domain/api/auth/callback/github\n```\n\nFor local development, use a separate GitHub OAuth app with:\n\n```text\nHomepage URL: http://localhost:3000\nAuthorization callback URL: http://localhost:3000/api/auth/callback/github\n```\n\nThis project is currently configured with separate GitHub OAuth apps for:\n\n- Local development: `http://localhost:3000`\n- Preview branch deployments: `https://chloeicode-git-preview-chloei.vercel.app`\n- Production: `https://chloeicode.vercel.app`\n\nVercel preview OAuth is intentionally tied to the `preview` branch URL because\nGitHub OAuth callback URLs must be stable. Ad hoc preview URLs can still deploy,\nbut sign-in should be tested on the `preview` branch deployment.\n\n## Cursor Integration\n\nThe server-side wrapper lives under `src/lib/cursor`.\n\n- `Cursor.models.list()` populates the model selector.\n- `Cursor.repositories.list()` provides connected repository suggestions.\n- `Agent.create({ cloud })` creates repo-scoped cloud agents.\n- `agent.send(prompt, { idempotencyKey })` starts a run.\n- `Agent.getRun(runId, { runtime: \"cloud\", agentId })` reconnects.\n- `run.stream()`, `run.wait()`, and `run.cancel()` power live updates and actions.\n\nThe installed SDK types are the implementation source of truth. Cursor cloud API shapes are beta, so raw statuses, events, and result payloads are stored as JSON alongside normalized app status.\n\n## GitHub Repository Discovery\n\nThe new-run form loads repositories from:\n\n```text\nGET /api/github/repositories\n```\n\nWhen a repository is selected, the form also loads branches from:\n\n```text\nGET /api/github/branches?repoUrl=https://github.com/owner/repo\n```\n\nThat route reads the signed-in user's GitHub OAuth token from the server-side\nAuth.js `Account` record and calls GitHub's authenticated repository API. The\nclient receives only repository and branch metadata, never the OAuth token.\nCursor-connected repositories from `Cursor.repositories.list()` are merged into\nthe same selector and tagged when a GitHub repository is also connected in\nCursor.\n\n## Pull Request Lifecycle\n\nCompleted runs with a Cursor-created PR show live GitHub metadata on the run\ndetail page. The server loads PR state, checks, commit statuses, reviews, inline\nreview comments, branch existence, and safe cleanup eligibility through:\n\n```text\nGET /api/agent-runs/:id/pull-request\nPOST /api/agent-runs/:id/pull-request/cleanup\n```\n\nCleanup closes the linked PR and deletes only the matching stored head branch\nwhen it is in the same repository, is not the base/default branch, and still\nmatches the branch returned by Cursor for that run. Cleanup writes an app event\nto the run log.\n\n## Database\n\nThe Prisma schema includes:\n\n- Auth.js `User`, `Account`, `Session`, and `VerificationToken` models.\n- `AgentRun` for Cursor IDs, repo/ref/model/prompt, normalized/raw statuses, PR metadata, result payloads, and retry linkage.\n- `AgentRunEvent` for ordered raw Cursor/app events.\n- `AgentRunArtifact` for optional SDK artifact metadata.\n\nRun `pnpm db:migrate` after configuring a real `DATABASE_URL`.\n\n### Environment Isolation\n\nThe Vercel project is configured to use separate Neon branches for runtime\ndatabase isolation:\n\n- Production (`main`): Neon branch `main`\n- Preview branch deployment (`preview`): Neon branch `preview`\n- Development/local: Neon branch `development`\n\nThe app reads `DATABASE_URL` at runtime. Additional Neon/Postgres URL and host\nvariables are kept aligned in Vercel for operator tooling, but application code\nshould continue to use `DATABASE_URL` only. Non-production branches are intended\nfor testing and should not be treated as production data stores.\n\n`pg_stat_statements` is enabled on production for database egress diagnostics.\nCurrent observed top-row queries are dominated by Neon internal monitoring, not\napplication overfetching. Re-run the stats after meaningful production traffic\nbefore making query tuning changes.\n\n## Streaming And Polling\n\nRun detail pages load persisted events first, then attach to:\n\n```text\nGET /api/agent-runs/:id/stream\n```\n\nThe SSE route persists Cursor stream events and finalizes with `run.wait()` when the stream closes. The UI also polls persisted events as a fallback. On Vercel, `vercel.json` schedules:\n\n```text\nGET /api/cron/refresh-runs\n```\n\nevery five minutes. The endpoint requires `Authorization: Bearer $CRON_SECRET`, refreshes a bounded batch of active runs, and records a safe app event if a background refresh fails. Final status is not solely dependent on a connected browser tab. A durable queue/worker is still recommended if run volume grows.\n\n## Run Safety Controls\n\nRun creation is guarded before any Cursor SDK call by:\n\n- `AGENT_RUN_RATE_LIMIT`: in-memory per-process request rate limit.\n- `AGENT_RUN_ACTIVE_LIMIT`: persistent per-user active run cap.\n- `AGENT_RUN_DAILY_LIMIT`: persistent per-user rolling 24-hour run cap.\n\nThe new-run page displays current capacity, and `/api/agent-runs/limits`\nreturns the same server-calculated policy for operator tooling.\n\n## Production Status\n\nSigned-in users can open:\n\n```text\n/status\n```\n\nto verify database, Cursor API, GitHub API, Vercel runtime, and active-run health. A basic unauthenticated health endpoint is also available at:\n\n```text\nGET /api/health\n```\n\nThe basic endpoint reports only safe configuration status and does not expose secret values.\n\nVercel Web Analytics and Speed Insights are installed in the root App Router\nlayout, so production deployments report page views and real-user performance\nmetrics to the Vercel project dashboard.\n\n## Security Notes\n\n- All Cursor SDK calls happen in route handlers or server-only modules.\n- Repository URLs are validated, normalized, and restricted by host/org env vars.\n- Per-user ownership checks guard every run, event, action, and artifact endpoint.\n- Production sign-in can be restricted with `ALLOWED_GITHUB_USERS` and/or `ALLOWED_EMAILS`.\n- Create/cancel/retry routes use an in-memory per-process rate limiter for burst control, plus persistent per-user active and 24-hour run caps for costly Cursor run creation. Use a shared limiter for stricter multi-instance burst control.\n- Raw event JSON is escaped by React and shown only in explicit debug disclosures.\n- The app never accepts arbitrary shell commands as a separate input.\n\n## Commands\n\n```bash\npnpm dev\npnpm build\npnpm lint\npnpm typecheck\npnpm test\npnpm db:generate\npnpm db:migrate\npnpm db:studio\n```\n\n## CI\n\nGitHub Actions runs `pnpm lint`, `pnpm typecheck`, `pnpm test`, and\n`pnpm build` on pushes to `main`/`preview` and pull requests into `main`.\nProtect `main` by requiring the `quality` status check before merging.\n\n## Manual QA\n\n1. Configure Cursor/GitHub integration and env vars.\n2. Create a run against a small test repository.\n3. Confirm it appears on the dashboard with normalized and raw status.\n4. Confirm detail page events update through SSE or polling.\n5. Cancel an active run and verify status/event persistence.\n6. Retry a completed or failed run and verify the retry links to the original.\n7. Confirm PR URL and branch metadata appear when Cursor returns them.\n8. Confirm the PR panel shows GitHub checks/review comments and can clean up a disposable test PR.\n9. Inspect browser HTML, network payloads, and bundles for absence of `CURSOR_API_KEY`.\n\n## Troubleshooting\n\n- No models: verify the API key belongs to a Cursor account/team with cloud agents enabled.\n- Run creation fails with `usage_limit_exceeded`: enable Cursor usage-based\n  pricing and set a spend limit with at least $2 remaining before starting a\n  Background Agent run.\n- Repo unavailable: confirm Cursor’s GitHub integration has access, or enter a valid allowed GitHub URL manually.\n- GitHub repos missing: sign out and sign back in so GitHub grants the current\n  repository discovery scopes. Also confirm organization SSO/access policies.\n- No PR URL: PR creation depends on Cursor settings, repo permissions, and the `autoCreatePR` toggle.\n- Stream disconnects: refresh the page; persisted events are the source of truth.\n- Artifact list empty: artifact support depends on installed SDK/runtime behavior for the run.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchloeilabs%2Fchloeicode","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchloeilabs%2Fchloeicode","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchloeilabs%2Fchloeicode/lists"}