Pair programming with Cursor's agent
Pair programming with Cursor’s agent is a session in which a developer and the agent split driver and navigator roles across one feature. Plan Mode settles the design, Agent mode builds one test-first slice at a time, and debugging starts from a failing test. The developer owns the acceptance criteria and the evidence; the agent does most of the typing.
This page is for developers who already use Cursor’s agent for single tasks (see Agent chat in Cursor) and now want it on a whole feature. The situation: you are building notification preferences with per-channel settings, organization defaults that users override, and timezone-aware delivery windows. The happy path is an afternoon. The edge cases are where it goes wrong, and one long “build the whole thing” prompt returns 600 lines you cannot check.
What you’ll walk away with from a pairing session in Cursor
Section titled “What you’ll walk away with from a pairing session in Cursor”- A role table that says who drives in each phase and which piece of evidence closes it
- Four copy-paste prompts: a design session, a read-only design fork, a test-first build slice, and an evidence-first debugging detour
- A per-step check (red test, green test, diff inside the plan, one commit) that replaces reading every line
- A way to stop the same correction from coming back, and a way to carry the session into a new chat
- Recovery steps for the six ways a pairing session goes wrong
Who drives when you pair with Cursor’s agent?
Section titled “Who drives when you pair with Cursor’s agent?”In human pair programming, the driver types and the navigator watches direction. With an agent, the agent drives almost every keystroke, so your job moves to the navigator’s seat full-time: you set the direction, define “done” for each step, and check the evidence. The table is the whole method; the sections below fill it in.
| Phase | The agent drives | You navigate | Evidence that closes the phase |
|---|---|---|---|
| Design | Reads the code, proposes a plan, asks questions | Answer the questions, choose at every fork, cut scope | A saved plan: numbered slices, a file list, one test per acceptance criterion |
| Build a slice | Writes the test, then the code, then runs the checks | Name the slice, the files, and what must not change | The new test failed first and passes now; the verify command is green; the diff stays inside the file list |
| Debug detour | Reproduces the bug in a test, proposes hypotheses, adds logging | Pick the hypothesis to test; refuse fixes before proof | A failing test or log line that confirms one cause |
| Handoff | Writes a short state note | Check the note in 30 seconds | A note with decisions, done slices and the next step |
| Pull request | Summarises what changed and why | Read the tests and any file the evidence flags | CI green, review comments resolved |
The one rule behind the table: no slice ends on the agent’s word. Each one ends on a command you or CI can re-run.
Set up the session before the first prompt
Section titled “Set up the session before the first prompt”Five minutes of setup makes every later step checkable.
- Start a branch from a clean tree:
git switch -c feat/notification-prefs. Keep one terminal of your own open for checks; the agent’s terminal output is its report, not your evidence. - Know your verify command, the one CI runs: for example
npm run verifywrapping type check, lint and tests. If the repository has none, write one before you pair, because every slice below ends on it. - Write the acceptance criteria down before the agent sees the task, in plain sentences you could turn into tests: “A user with no preferences receives the organization default for every channel.” If you cannot write them yet, the design session below is where they come from. Executable acceptance criteria shows the format.
- Check that your project rules cover logging, error handling and data access, so you do not correct the same pattern in every slice. Project rules in Cursor covers the file location and load modes.
Agree the design in Plan Mode
Section titled “Agree the design in Plan Mode”Plan Mode, in Cursor’s words, “creates detailed implementation plans before writing any code” (Plan Mode docs, verified 28 August 2026). That is the navigator’s first job: agree the route before anyone drives. Open a new chat, start the chat in Plan Mode, and paste the prompt.
Push back on the plan the way you would with a colleague. Cut a slice that exists only “for future flexibility”. Ask why a new table is needed if an existing one could carry a column. When a question has two reasonable answers, do not let the agent choose silently: ask for a comparison in which it may not edit anything.
You make the call, and the plan file records it. If your Cursor build offers a read-only Ask mode, it suits this prompt; the “do not edit” line keeps the prompt safe in any mode. Cursor agent modes covers when to use each mode in more depth.
When the plan is final, commit it in your own terminal and tag the base that every scope check compares against. A tag, unlike a shell variable, is still there when you reopen the terminal or pick the work up in a new chat:
git add docs/plans && git commit -m "docs: notification preferences plan"git tag -f plan-base # durable base; survives a closed terminalBuild one slice at a time in Agent mode
Section titled “Build one slice at a time in Agent mode”Switch to Agent mode and hand over one slice. A slice ends with one new test passing and a green verify command, which keeps each diff small enough for the per-step check below to be meaningful.
The stop after the failing test is the most valuable pause in the session. A test that fails for the right reason proves it tests something; a test written after the code often passes whatever the code does. Read the test, not the implementation: it is 20 lines, and it is the specification the code will be held to.
When the agent reports green, check the evidence yourself before the next slice:
# Run in your terminal, not the agent's.npm run verify # the same gate CI runsgit add -A # stage everything, new files includedgit diff --cached --stat # size and spread of the changegit diff --cached --name-only plan-base -- . ':!docs/plans' ':!docs/handoff' \ | grep -vxF -f docs/plans/notification-preferences.filesgit commit -m "feat(prefs): slice 1 - preferences model"Empty output from the grep line means every changed file is on the plan. The two :! pathspecs leave out the plan and handoff files themselves, so adding a gap to the plan or writing a handoff note later does not show up as drift. The .files list covers the whole feature, so this check proves the change stays inside the plan, not inside slice 1; compare the --stat output with the plan’s slice 1 section for that. A printed path is either a real gap, which you add to the plan file, or drift, which you unstage and revert with git restore --staged --worktree PATH (or git rm --cached PATH and delete it, for a new file). Commit every green slice: each commit is a known-good point you can return to, and it keeps the next slice’s diff separate. If your Cursor build keeps its own checkpoints, Checkpoints and branching explains how they fit alongside these commits.
If something is wrong, say exactly what and why, in one message:
The migration stores delivery_window_start as a timestamp with timezone.Use a plain time column, because the timezone lives in its own column.Add a unique constraint on (scope_type, scope_id, channel). Re-run theslice 1 test and npm run verify, and change nothing else.Keep the agent on your architecture
Section titled “Keep the agent on your architecture”An agent that drives most of the keystrokes drifts in predictable ways: a new date library, a second logging style, a query the plan never mentioned. Three habits keep it on your road.
Fence each slice with what must not happen. Negative constraints are cheap and easy for the agent to follow:
Implement the delivery-window check in src/services/preferences.ts. Do NOT:- add a date library; use the helpers in src/lib/time.ts- add a database query; use the preferences already loaded by the caller- change the signature of isWithinDeliveryWindow()Point at an example, do not describe one. Follow the error handling in @src/services/orders.ts beats a paragraph about your error classes. Context management in Cursor covers choosing that one canonical file.
Promote a repeated correction into a rule. The second time you type “use the logger from src/lib/logger.ts, not console.log”, stop pairing for two minutes and ask the agent to draft a project rule with that line. Review it, commit it, and the correction stops recurring in this chat and in your colleagues’ chats. Project rules in Cursor shows how to prove with a probe task that the rule loads.
Take a debugging detour without losing the thread
Section titled “Take a debugging detour without losing the thread”Bugs surface mid-feature. The trap is letting the agent “try a fix” on a guess: it will produce plausible changes until one happens to pass, and the session loses its plan. Make the detour evidence-first and fence it.
Once the evidence confirms a cause, say “fix it”, and the failing test becomes the proof of the fix. Ask the agent to remove the temporary logging, then run the verify command and commit the fix as its own commit before you return to slice 5. If your Cursor build offers Debug Mode, it runs a similar hypothesis-and-logging loop; the prompt above works in Agent mode either way. Bug hunting in Cursor covers longer investigations.
Carry a long session across chats
Section titled “Carry a long session across chats”A feature can take longer than one chat stays useful. The signs: the agent repeats a mistake you already corrected, or forgets a decision from an hour ago. Do not argue with a long history. Close the chat with a handoff note and continue in a new one, following the handoff prompt in Context management in Cursor. The plan file, the committed slices and the note carry the state, so the new chat starts with:
Read @docs/plans/notification-preferences.md and @docs/handoff/notification-prefs.md.Slices 1-4 are committed (see git log). Continue with slice 5 exactly as planned,test first, and stop after showing me the failing test.Because every finished slice is a commit with a green verify command, you lose nothing when a chat ends.
How do you verify a pairing session without reading every line?
Section titled “How do you verify a pairing session without reading every line?”You read three things closely: the plan, each new test, and any file that the scope check flags. Everything else is covered by commands that do not depend on the agent’s report.
| Check | When | What it proves | Who signs off |
|---|---|---|---|
| Test fails before the code exists | Every slice | The test checks the behaviour, not just the code that was written | You |
npm run verify in your own terminal | Every slice, and in CI | Types, lint and the whole suite pass, not only the new test | You, then CI |
| Scope check against the plan’s file list | Every slice | The agent changed nothing it was not asked to | You |
| One commit per green slice | Every slice | Each step is reversible on its own | You |
| Criteria-to-test map in the PR description | Pull request | Every acceptance criterion has a named test | The reviewer, who reads the map and the tests |
| Bugbot or another review agent on the PR | Pull request | A second reader for bugs and security issues across the whole diff | The reviewer decides what to act on |
Bugbot reviews pull requests for bugs, security issues and code quality problems, and Code review in Cursor shows how to layer it with a human reviewer. For the wider argument that reviewers should read evidence instead of whole diffs, see evidence, not diffs and the evidence bundle for agent pull requests.
What breaks when you pair with Cursor’s agent?
Section titled “What breaks when you pair with Cursor’s agent?”| Symptom | Likely cause | Recovery |
|---|---|---|
| The agent improvises beyond the plan | The plan file is not in the chat, or the slice was vague | @-mention the plan in every build prompt and name the slice by number. Revert extra tracked files with git restore --staged --worktree PATH; delete extra new files (after git rm --cached PATH if they are staged) |
| You asked for the model and got the model, routes and tests | No stop condition in the prompt | Add “Do not create routes, services or UI” and a STOP marker. Keep only the slice’s files, then commit |
| Corrections stop sticking | The chat history carries old attempts that compete with your corrections | Write a handoff note and start a new chat; turn the correction into a project rule |
| Three prompts in, the approach is wrong | The design fork was settled by the agent, not by you | Discard the uncommitted slice with git restore --staged --worktree ., then git clean -n to preview and git clean -f to remove any untracked files that are left, go back to the design-fork prompt, and update the plan before rebuilding |
| Tests pass, but the feature is wrong | An acceptance criterion had no test, or the test was written after the code | Add the missing criterion to the plan, write its test and watch it fail, then fix |
| The agent says “all tests pass”, CI disagrees | The agent ran a subset or read stale output | Treat only your own terminal and CI as evidence. Ask the agent to run the exact verify command and paste its output |