Appearance
Fix pull requests on a Cursor cloud VM
This agent coordinates from chat and Slack, then hands each opted-in pull request to a Cursor cloud VM with a real checkout. The same cloud conversation resumes when you drive the PR again, GitHub reports a change on that PR, or a merge-conflict reminder fires.
Chat never has the target checkout. gh and git run on the VM. Opening a pull request does not start a session. Drive a PR from the playground, Slack, or HTTP to opt in. After that, the agent auto-fixes: it pushes verified fixes to the PR head and performs workflow actions. It never merges, enables auto-merge, or force-pushes.
Scaffold
On a TTY, init asks which GitHub repos to watch. Scripts pass the same answer with --var:
bash
npx @cursor/july init ./pr-autofixer --template pr-autofixer
npx @cursor/july init ./pr-autofixer --template pr-autofixer \
--var repos=acme/widgets,acme/api --jsoninit writes the project, installs dependencies, and puts agent-sdk on PATH. You can still edit agent/lib/repos.ts later, or override the list with PR_AUTOFIXER_REPOS.
Log in
Model turns and cloud agents use your Cursor account.
bash
cd pr-autofixer
agent-sdk loginThe command opens a browser if you have no stored credential. Cloud turns spend cloud-agent budget under that account.
Point it at a repo
init writes the repo list into agent/lib/repos.ts. One owner. Up to 20 repos. The GitHub channel requests contents-write so the agent can push to the PR head.
First drive
bash
agent-sdk devOpen the playground. Paste a PR URL or owner/repo#N. The local agent calls drive_pr, which attaches the PR to a cloud session and returns when that session exists. Autofix continues in the background. bcId / agentUrl are included when already bound.
You can also POST:
bash
curl -X POST http://127.0.0.1:3000/pr-autofixer/v1/channels/drive \
-H 'content-type: application/json' \
-d '{
"pr": "https://github.com/acme/widgets/pull/1"
}'HTTP and drive_pr both return when the session exists, not when triage finishes. bcId / agentUrl are included when already bound.
A merged or closed PR returns status: "finished" and does not start a session.
The VM starts from the PR base. The agent creates autofix/pr-<N> off the PR head the first time it needs code, then pushes verified fixes with git push origin HEAD:<headRef>. Workflow actions run through gh. autoCreatePR is off, so the agent never opens a new PR.
GitHub wakes
Mounted at /v1/channels/github. Cursor relays pull request, comment, review, check, and failing status events for the repos you listed. A wake only starts or resumes a cloud conversation after that PR has been driven. pull_request.opened is ignored. A PR comment or review on an opted-in PR wakes the agent. A comment on a plain GitHub issue does not. The channel buffers about 3 seconds per PR. Payload details are dropped on purpose. The follow-up says something changed.
Pending wakes snapshot to host.kv (webhook-buffer) before the webhook is ACKed, and restore on restart. Affinity is affinity/{owner/repo#N} → bc-… in the same store, written from agent.bound. agent/storage.ts uses cursorHostedStorage, so both survive host replace. Local serve without that plug-in falls back to --state-root/kv.
Closing a PR cancels its merge-conflict reminder and drops buffered wakes.
See GitHub for cursorAccount login and fixture replay.
Slack
agent/channels/slack.ts uses your signed-in Cursor account. Mention the agent or DM it with a PR URL. Same drive_pr path as the playground. See Slack.
Evals
One smoke case. Chat without a PR must not call drive_pr, so a routine eval cannot spawn a cloud agent.
bash
agent-sdk evalDo not add cases that pass a PR URL unless you intend to spend cloud budget.
Deploy
bash
agent-sdk deployRun it from the agent's git checkout. It infers repository, ref, path, and slug, builds on Cursor-managed hosting, and prints the URL. agent-sdk deployments shows status.
See Cloud runtime for what changes on the VM.