Skip to content

CascadiaTech/cursor-event-receiver

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cursor-event-receiver

Poll GitHub issues from a single project workspace and auto-fix them with a local Cursor agent (via @cursor/sdk). Each project gets its own config — a watcher in project-a never touches project-b.

What it does

  1. Polls GitHub every 60s (configurable) for open issues
  2. Creates a fix branch: fix/issue-123-short-title
  3. Runs a local Cursor agent against your repo checkout
  4. Commits + pushes the branch (never main / master)
  5. Comments on the issue with testing instructions

Install

From this repo:

cd cursor-event-receiver
npm install
npm link

Or run without linking:

npm run dev -- init
npm run dev -- watch

Setup (per project)

Run these inside the target repo, not inside this tool's repo:

cd ~/path/to/your-project

export GITHUB_PAT=ghp_...      # repo + issues write scopes
export CURSOR_API_KEY=cursor_...

cursor-event-receiver init

init writes .cursor/event-receiver.yaml and detects owner/repo from git remote origin when possible.

Example config:

github:
  owner: your-org
  repo: your-project
  pat: ${GITHUB_PAT}
poll:
  interval_seconds: 60
issues:
  mode: all
  labels: []
  numbers: []
cursor:
  api_key: ${CURSOR_API_KEY}
  model: composer-2.5
output:
  comment_on_issue: true
git:
  branch_prefix: fix/issue-
  never_push: [main, master]

Add to the project's .gitignore (or run init, which adds these automatically):

.cursor/event-receiver-state.json
.cursor/event-receiver.yaml

Why gitignore matters

The watcher updates .cursor/event-receiver-state.json on every poll (including the first tick when watch starts). If that file is tracked by git, your working tree stays dirty and branch checkout fails with:

Working tree has uncommitted changes. Commit or stash before running the receiver.

Minimum (recommended): ignore receiver config + runtime state:

.cursor/event-receiver-state.json
.cursor/event-receiver.yaml

Alternative: ignore the whole .cursor/ folder if you do not want any Cursor-local files in git:

.cursor/

If you ignore all of .cursor/, run cursor-event-receiver init locally in each clone -- config is not shared via git unless you commit .cursor/event-receiver.yaml separately (safe when secrets use ${ENV} placeholders, not literal tokens).

You can commit .cursor/event-receiver.yaml while still gitignoring the state file — that is the usual setup for a shared repo config without leaking processed-issue history into commits.

Resuming a fix branch

If you are already on a branch matching the issue (e.g. fix/issue-26-*), the receiver continues on that branch instead of checking out main and recreating it. This supports retrying after a failed or interrupted run:

git checkout fix/issue-26-enhancement-display-app-version-number-o
cursor-event-receiver run-once --issue 26 --force

When resuming, .cursor/event-receiver-state.json changes are ignored for the clean-tree check, and you stay on the fix branch when the run finishes.

Comment feedback loop

After each run, the receiver posts a summary comment on the issue (what it tried, branch name, testing steps). Teammate comments on the issue are scanned on every poll and trigger a resume on the same fix branch.

Flow:

  1. Receiver fixes issue #26 → posts bot comment with testing instructions
  2. You test and comment: "Version still doesn't show on the home screen — check HomeScreen.tsx"
  3. Next poll (or run-once --issue 26) picks up your comment
  4. Agent resumes on fix/issue-26-* with your feedback in the prompt
  5. Receiver posts an updated summary comment

Bot comments are ignored (marked with <!-- cursor-event-receiver -->). Only new human comments since the last processed comment ID trigger a rerun.

Optional config in .cursor/event-receiver.yaml:

comments:
  scan_feedback: true
  feedback_trigger: ""   # empty = any human comment; or e.g. "@fix" to require that text

Example feedback comment:

The build works but the version text is hidden behind the header. Please adjust the layout.

Or with a trigger set to @fix:

@fix The app crashes on launch when checking out this branch — ENOENT on config path.

Agent prompting

Every agent call is built from layered prompts before Agent.prompt() runs:

  1. prompt.preamble — inline rules in yaml (always prepended)
  2. prompt.preamble_file — markdown file merged next (default: .cursor/event-receiver-prompt.md)
  3. Mode instructionsinitial (first fix) or feedback (teammate commented)
  4. Issue body + comment thread
  5. Requirements — stricter on feedback reruns (must change code, don't argue the fix is already correct)

Add to .cursor/event-receiver.yaml:

prompt:
  preamble: |
    This is an Electron desktop app. Run npm run dev to test UI changes.
    Keep diffs minimal. Match existing TypeScript patterns.
  preamble_file: .cursor/event-receiver-prompt.md
  initial: |
    First attempt — locate the root cause before editing.
  feedback: |
    A human tester commented below. Their report is ground truth.
    Do not explain that the fix already works. Change code to address their feedback.

init creates .cursor/event-receiver-prompt.md as an editable template.

Preview the full prompt before running:

cursor-event-receiver print-prompt --issue 26
cursor-event-receiver print-prompt --issue 26 --feedback

Feedback reruns use strong built-in defaults if you leave prompt.feedback empty — tuned so the agent doesn't "correct" the tester and actually edits code.

Commands

# Test one issue manually
cursor-event-receiver run-once --issue 42

# Re-run even if already processed
cursor-event-receiver run-once --issue 42 --force

# Start the 60s poll loop
cursor-event-receiver watch

# Show config + processed issues
cursor-event-receiver status

# Preview agent prompt (debug)
cursor-event-receiver print-prompt --issue 42 --feedback

Multi-project isolation

Run one watcher per Cursor project, each from its own directory:

# Terminal 1
cd ~/projects/frontend && cursor-event-receiver watch

# Terminal 2
cd ~/projects/backend && cursor-event-receiver watch

Each project reads only its own:

  • .cursor/event-receiver.yaml
  • .cursor/event-receiver-state.json

GitHub PAT scopes

For branch push + issue comments:

  • repo (or fine-grained: Contents read/write, Issues read/write, Metadata read)

Requirements

  • Node.js 20+
  • Git repo with origin remote
  • Clean working tree before each issue run (gitignore .cursor/event-receiver-state.json so polling does not dirty the tree)
  • CURSOR_API_KEY from Cursor Dashboard → Integrations
  • Ripgrep for local Cursor agents (bundled automatically via @cursor/sdk-* platform packages)

If you see Ripgrep path not configured, reinstall dependencies or set:

export CURSOR_RIPGREP_PATH=/path/to/rg

License

MIT

About

received github events to your cursor ide. Use it to scan for issues opened and use cursors api to fix them.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors