Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ This file is the contract any agent (Claude Code, Cursor, Codex, …) must follo

## What this repo is

A Claude Code plugin that delegates coding tasks from Claude to the Cursor CLI (`cursor-agent`). Nine slash commands under the `cursor:` namespace plus a `cursor-runner` subagent. Source of truth lives under `plugins/cursor/`.
A Claude Code plugin that delegates coding tasks from Claude to the Cursor CLI (`cursor-agent`). Eleven slash commands under the `cursor:` namespace, a `cursor-runner` subagent, and a `composer-prompting` skill. Source of truth lives under `plugins/cursor/`.

## Hard rules

1. **Zero runtime dependencies.** The plugin ships as plain ESM `.mjs` and must execute directly after `/plugin install` with zero `npm install` in the user's plugin cache. If you are about to add `execa`, `zod`, `nanoid`, a HTTP client, a command parser, or any other third-party runtime package — stop. Write a small inline helper instead. See `plugins/cursor/scripts/lib/run.mjs` as the reference pattern (it replaced `execa` in ~80 lines).
2. **No build step.** No TypeScript, no bundler, no `dist/`. `scripts/*.mjs` IS the ship artefact. If you find yourself wanting one, something has gone wrong with the approach.
3. **Slash command scripts live under `plugins/cursor/scripts/<cmd>.mjs`.** Their wrappers at `plugins/cursor/commands/<cmd>.md` must use `node "${CLAUDE_PLUGIN_ROOT}/scripts/<cmd>.mjs" -- "$ARGUMENTS"` with quoted `$ARGUMENTS` — unquoted breaks under zsh on any prompt containing `?`, `*`, or `@`.
4. **`Bash(node:*)` is the only permission pattern used in `allowed-tools`.** Do not invent path-based patterns — Claude Code does not expand `${CLAUDE_PLUGIN_ROOT}` inside `allowed-tools`.
3. **Slash command scripts live under `plugins/cursor/scripts/<cmd>.mjs`.** Their wrappers at `plugins/cursor/commands/<cmd>.md` must use `node "${CLAUDE_PLUGIN_ROOT}/scripts/<cmd>.mjs" -- "$ARGUMENTS"` with quoted `$ARGUMENTS` — unquoted breaks under zsh on any prompt containing `?`, `*`, or `@`. Exception: `review.md` and `adversarial-review.md` are model-orchestrated (they estimate the diff and ask wait-vs-background before running), so they give Claude the `node …` command in a fenced block rather than an auto-executing `!` line, and `adversarial-review` reuses `review.mjs --adversarial` instead of shipping its own script.
4. **`Bash(node:*)` is the only permission pattern used in `allowed-tools`.** Do not invent path-based patterns — Claude Code does not expand `${CLAUDE_PLUGIN_ROOT}` inside `allowed-tools`. Exception: the two estimate-first review commands additionally list `Bash(git:*)`, `AskUserQuestion`, and `Read, Glob, Grep` for the size-estimate/ask step — those are tool-name patterns, not path-based ones, so they are fine.
5. **Jobs are persisted under `~/.cursor-plugin-cc/jobs/<repo-hash>/`.** Never break that layout; users point scripts at those files when reporting bugs.
6. **Language: everything in this repo is English.** Code, comments, commit messages, docs, PR bodies, issue titles. The plugin does not impose a language policy on target repos — `cursor-runner` reads target-repo conventions — but this repo itself is English-only.
7. **Do not impose conventions on target repos.** The `cursor-runner` subagent reads `AGENTS.md` / `.cursor/rules` / existing code in whatever repo the user is working in and tells Cursor to match THAT style. When editing the subagent, do not hardcode English / Prettier / whatever.
Expand Down Expand Up @@ -46,10 +46,11 @@ Plus a **Constraints** block that forbids: touching files outside the list, rena

## Where things live

- `plugins/cursor/scripts/<cmd>.mjs` — command entrypoints (9).
- `plugins/cursor/scripts/lib/*.mjs` — shared helpers (run, id, args, paths, jobs, parse, cursor, git, invoked, plan).
- `plugins/cursor/scripts/<cmd>.mjs` — command entrypoints (10; `adversarial-review` has no script of its own — it reuses `review.mjs --adversarial`).
- `plugins/cursor/scripts/lib/*.mjs` — shared helpers (run, id, args, paths, jobs, parse, cursor, git, invoked, plan, hints, md).
- `plugins/cursor/commands/*.md` — slash command wrappers.
- `plugins/cursor/agents/cursor-runner.md` — the handoff subagent prompt.
- `plugins/cursor/skills/composer-prompting/SKILL.md` — Cursor prompt-shaping guidance the `cursor-runner` subagent references via its `skills:` frontmatter.
- `plugins/cursor/tests/*.test.mjs` — vitest specs + fixtures.
- `.claude-plugin/marketplace.json` — what Claude Code's `/plugin install` reads.

Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 0.4.0 — /cursor:adversarial-review + estimate-first reviews + composer-prompting skill

Ported from upstream [`openai/codex-plugin-cc`](https://github.com/openai/codex-plugin-cc) (whose `/codex:adversarial-review`, estimate-first review flow, and `gpt-5-4-prompting` skill this release mirrors), adapted to the Cursor CLI.

### Added

- **`/cursor:adversarial-review`** — a first-class steerable review command that challenges the chosen implementation and design (assumptions, tradeoffs, failure modes, whether a different approach would be simpler or safer), not just implementation defects. It reuses the existing review runtime (`scripts/review.mjs --adversarial`), so it supports `--base <ref>`, `--scope`, `--model`, `--wait`/`--background`, and free-form focus text, and is tracked as a normal job (`/cursor:status`, `/cursor:result`, `/cursor:cancel` all apply). Promotes what used to be only the `--adversarial` flag on `/cursor:review` into a discoverable command with sharper framing.
- **`composer-prompting` skill** — the Cursor/Composer prompt-shaping guidance (repo grounding, the five-section prompt anatomy + guardrails, chunking heuristics, model selection, resume-vs-fresh) now lives in `plugins/cursor/skills/composer-prompting/SKILL.md`. The `cursor-runner` subagent references it via a new `skills:` frontmatter entry instead of restating the mechanics inline, and the main thread can consult it when hand-crafting `/cursor:delegate` prompts. Mirrors codex's internal `gpt-5-4-prompting` skill.

### Changed

- **`/cursor:review` and `/cursor:adversarial-review` estimate the diff before running.** When neither `--wait` nor `--background` is passed, the command inspects `git status` / `git diff --shortstat` to gauge review size, then asks once (via `AskUserQuestion`) whether to wait or run in the background — recommending background for anything beyond a tiny 1–2 file change. Explicit `--wait` / `--background` skip the question. The commands moved from an auto-executing one-liner wrapper to a model-orchestrated flow; their `allowed-tools` now include `Bash(git:*)` and `AskUserQuestion` for the estimate step. Background runs still use the plugin's own detached worker (the script returns a job id immediately), not a Claude background task.
- **`cursor-runner` subagent slimmed** — the prompt-anatomy, chunking, model, and resume/fresh sections were extracted into the `composer-prompting` skill; the agent now points at the skill and keeps only its operational spine (ground → invoke `/cursor:delegate` → return verbatim) and guardrails.

## 0.3.2 — clearer "job not found" hint

### Fixed
Expand Down
24 changes: 21 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,12 @@ What lives where after a run:

## What you get

Ten slash commands under the `cursor:` namespace:
Eleven slash commands under the `cursor:` namespace:

- **`/cursor:delegate`** — hand a coding task to Cursor, foreground or background.
- **`/cursor:from-plan`** — turn a Claude Code plan (from plan mode) into a `tasks/<file>.md` and hand it off to Cursor.
- **`/cursor:review`** — read-only code review of your git diff by a Cursor model. Reports findings; never edits files.
- **`/cursor:adversarial-review`** — steerable review that challenges the design and approach (assumptions, tradeoffs, failure modes), not just implementation defects. Read-only.
- **`/cursor:browser`** — verify a URL / flow in a real browser via Cursor's `chrome-devtools` MCP.
- **`/cursor:status`** — list recent jobs or inspect a specific one.
- **`/cursor:result`** — print the final output of a finished job.
Expand All @@ -130,7 +131,7 @@ Ten slash commands under the `cursor:` namespace:
- **`/cursor:sessions`** — list Cursor's own chat sessions for this repo.
- **`/cursor:setup`** — health-check the CLI, list models + configured MCPs, or guide installation.

Plus a `cursor-runner` subagent you can invoke from inside Claude to delegate well-scoped tasks automatically.
Plus a `cursor-runner` subagent you can invoke from inside Claude to delegate well-scoped tasks automatically, and a `composer-prompting` skill it uses to shape well-specified tasks into tight Cursor prompts.

## Why this plugin

Expand Down Expand Up @@ -205,11 +206,13 @@ Read-only code review of your git diff by a Cursor model. The plugin collects th

By default it picks the target automatically: a dirty working tree is reviewed as-is; a clean tree falls back to a branch diff against the detected default branch. Any trailing text is passed as a reviewer **focus**.

**Wait or background?** If you don't pass `--wait` or `--background`, the command first estimates the diff size (`git status` / `git diff --shortstat`) and asks once whether to wait for the result or run it in the background — recommending background for anything beyond a tiny 1–2 file change, since a multi-file review can take a while. Pass `--wait` or `--background` explicitly to skip the question.

| Flag | Default | Effect |
| ------------------------------------ | ----------------- | ------------------------------------------------------------------------------------------------- |
| `--base <ref>` | auto | Review the branch diff `<ref>...HEAD` (merge-base) instead of the working tree. |
| `--scope auto\|working-tree\|branch` | `auto` | Force the target. `working-tree` = uncommitted changes; `branch` = vs the detected default branch. |
| `--adversarial` | off | Challenge the design and assumptions, not just implementation defects. |
| `--adversarial` | off | Challenge the design and assumptions, not just implementation defects. Prefer the dedicated [`/cursor:adversarial-review`](#cursoradversarial-review-flags-focus) command; this flag is kept for backward compatibility. |
| `--model <id>` | `auto` | Same aliases as `/cursor:delegate`. Use `gpt`/`opus`/`gemini` for a deeper review. |
| `--background` | off | Detach; returns a job id immediately. Read it later with `/cursor:result`. |
| `--wait` | on | Block until the review finishes (default unless `--background`). |
Expand All @@ -228,6 +231,21 @@ Examples:

This is a **second opinion**, not a replacement for Claude reviewing the diff in-session. Reach for it when you want a different model's eyes on the change, or to offload a large review while Claude keeps orchestrating.

### `/cursor:adversarial-review [flags] [focus...]`

A **steerable** sibling of `/cursor:review` that questions the chosen implementation and design rather than only hunting implementation defects. Use it to pressure-test assumptions, tradeoffs, failure modes, and whether a different approach would have been simpler or safer — for example before shipping a change you are not fully sure about.

It uses the **same review-target selection** as `/cursor:review` (working tree by default, `--base <ref>` for a branch diff, `--scope`, `--model`, `--wait`/`--background`) and, like `/cursor:review`, estimates the diff and asks wait-vs-background when you don't pass an explicit mode. Any trailing text is the reviewer **focus** — use it to point the challenge at a specific risk area. It is read-only and never edits files; the same post-flight check applies.

```
/cursor:adversarial-review # challenge the working-tree diff
/cursor:adversarial-review --base main # challenge this branch vs main
/cursor:adversarial-review "is the retry/backoff design sound under load?"
/cursor:adversarial-review --background --model opus look for race conditions and question the approach
```

Under the hood it is `/cursor:review --adversarial`, so it shows up as a normal job in `/cursor:status`, `/cursor:result`, and `/cursor:cancel`.

### `/cursor:browser <url> <what to verify...>`

Verify a page or a flow in a **real browser** via Cursor's `chrome-devtools` MCP. This is read-only by design — Cursor navigates, interacts, checks console/network and reports back; it will not modify your source files.
Expand Down
64 changes: 12 additions & 52 deletions plugins/cursor/agents/cursor-runner.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
name: cursor-runner
description: Hand off a well-specified coding task to the Cursor CLI (`cursor-agent`) via `/cursor:delegate`. Use for small-to-medium, well-scoped changes where speed matters (default model `composer-2.5-fast`). Do NOT use this agent for code review, design decisions, or large refactors — those stay with the main Claude conversation.
tools: [Bash, Read]
skills:
- composer-prompting
---

You are the **cursor-runner** subagent. Your single job is to delegate a concrete coding task to Cursor CLI and then report the outcome back to the main Claude conversation. You are a forwarder, not an implementer.
Expand All @@ -19,61 +21,19 @@ Your job is step 2 only. Never do steps 1, 3, or 4 yourself.

## What you must do

### 1. Read the target repo's conventions before writing the prompt
### 1. Shape the prompt with the `composer-prompting` skill

Cursor has no conversation context — whatever the target repo expects, you must bake into the prompt you send. **Use `Read` (only) to check for:**
Use the **`composer-prompting`** skill to turn the main thread's spec into a tight Cursor prompt. It is the source of truth for:

- `AGENTS.md`, `CLAUDE.md`, `.cursor/rules/**`, `.github/copilot-instructions.md`, `CONTRIBUTING.md` — convention files.
- `package.json` / `Taskfile.yml` / `Makefile` / `justfile` — to learn which commands build and test the project.
- `README.md` — for the overall project goal (one sentence is enough).
- **Grounding** — read the target repo's `AGENTS.md` / `CLAUDE.md` / `.cursor/rules` / conventions and verify commands with `Read` (only) before writing the prompt, and match the repo's own language and style.
- **Prompt anatomy** — the five required sections (Goal, Repo context, Acceptance criteria, Files to touch, How to verify) plus the guardrails block.
- **Chunking** — refuse a monolithic blob; split anything bigger than ~5 steps / ~10 files / 2 layers into one slice per `/cursor:delegate` call.
- **Model choice** — default `composer-2.5-fast`; escalate only with a reason.
- **Resume vs fresh** — continue the same thread or start clean.

**Language and style follow the target repo, not this plugin.** If the target repo's commits, comments, or UI strings are in Czech / German / any other language, Cursor must match — do not force English. If the repo is mixed (e.g. code in English, user-facing copy in Czech), say so explicitly in the prompt. When in doubt, tell Cursor: "match the existing style of surrounding files."
Use the skill only to shape the forwarded prompt. Do not use it to review the diff, draft a solution, or do independent work of your own.

### 2. Write a tight, self-contained prompt for Cursor

Every prompt you send **must** have these sections, in this order:

1. **Goal** — one or two sentences. What is the outcome? What is this a step of, if anything?
2. **Repo context** — 1–2 lines: stack / framework, and "follow conventions in `AGENTS.md` / `.cursor/rules` / whichever you actually found."
3. **Acceptance criteria** — 1–5 bullet points, concrete and verifiable.
4. **Files to touch** — an explicit list. Unless the task inherently cannot predict this, Cursor must not wander outside it.
5. **How to verify** — the exact commands that prove the task is done (e.g. `npm test`, `task typecheck && task test`, `pnpm lint`). This is not optional — without it Cursor will declare "done" on unverified work.
6. **Guardrails** — short and blunt:
- Do not delete files outside the list.
- Do not rename public APIs unless asked.
- Do not touch lockfiles (`package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`) unless the task is explicitly about dependencies.
- If a pre-existing test is already failing, report it — do not "fix" it as a side task.

### 3. Chunk oversized plans before delegating

`cursor-agent --force` will YOLO through anything you hand it. That is the point — and also the risk. **Refuse to delegate a single monolithic blob of work.** Heuristics:

- If the plan has **more than ~5 discrete steps**, split into one `/cursor:delegate` call per step (or per coherent slice).
- If the plan touches **more than ~10 files** or crosses **more than 2 architectural layers**, ask the main Claude to narrow the slice first.
- If you cannot name the acceptance criteria in ≤ 5 bullets, the slice is still too big.

Small slices give Cursor a tight scope, make the diff reviewable, and make failures cheap to retry.

### 4. Pick a model

Default is `composer-2.5-fast` — Cursor's own current default and the fastest Composer variant. Escalate only when the task warrants it:

- `composer-2.5` (non-fast) — quality matters slightly more than latency, but the task is still well-scoped.
- `sonnet` (`claude-4.6-sonnet-medium`) — more than ~5 files touched, or moderate architecture changes.
- `opus` (`claude-opus-4-7-high`) — cross-cutting refactor, subtle correctness, or a prior `composer` run failed.
- `gpt` / `codex` (`gpt-5.3-codex`) — only when the user explicitly asks for it.

Unknown aliases are forwarded as-is, so `--model <whatever>` always works.

### 5. Decide: resume or fresh

- **`--resume`** (default when not specified): continue the latest Cursor chat for this repo. Use it when you are **iterating on the same task** — e.g. "also cover the 429 path", "rename the helper you just added". Cheap, preserves Cursor's mental model.
- **`--resume=<chat-id>`**: same as above but target a specific prior chat — use when `/cursor:status` or the user pointed you at one explicitly.
- **`--fresh`**: start a brand-new Cursor session. Use it when **the new task has nothing to do with the previous one**, or when the previous run went off the rails and resuming would just carry the confusion forward.

When in doubt: fresh if the task topic changed, resume if it's the same thread of work.

### 6. Invoke `/cursor:delegate` via a single `Bash` call
### 2. Invoke `/cursor:delegate` via a single `Bash` call

```bash
node "${CLAUDE_PLUGIN_ROOT}/scripts/delegate.mjs" \
Expand All @@ -82,7 +42,7 @@ node "${CLAUDE_PLUGIN_ROOT}/scripts/delegate.mjs" \

Use `--background` only if the user explicitly asked for it, or the task obviously exceeds ~5 minutes.

### 7. Return Cursor's output verbatim
### 3. Return Cursor's output verbatim

Do not paraphrase the summary, do not rewrite the file list, do not hide the chat id. The main Claude will read the diff and decide what comes next.

Expand Down
Loading
Loading