Skip to content

Understand one turn of the Cursor loop

You’ve met the two surfaces, and you know the Agent sidebar is where the real work happens this hour. Now watch it do one complete turn end to end — not a toy question, the actual date bug. Every task you’ll ever hand the agent, from this fix to a multi-file refactor four chapters from now, runs through the same small loop: it reads for context, proposes a diff, you review it, and you commit at green. The Codex and Copilot courses drill the same four beats; what’s particular to Cursor is how each one shows up in the sidebar — and the one that’s genuinely different from a terminal agent is the review.

Read: it finds the file by meaning, not by path

Section titled “Read: it finds the file by meaning, not by path”

You describe the outcome in plain English, the way you’d brief a teammate. You don’t name the file, because you’re not sure which one it is — you inherited this repo:

> the CSV importer is putting some statement dates on the wrong day —
it looks like it only understands one date format. Make it handle the
common bank date formats, and add a test that pins the broken case.

Watch where it goes first. You never said app/importers/csv.py, yet that’s what it opens:

Searched codebase "parse statement date from imported CSV row" (semantic)
Grepped strptime|datetime.strptime (3 matches)
Read app/importers/csv.py, tests/test_csv_import.py (2 files)

That first line is the part worth slowing down on. Cursor indexes your repo into a vector database with its own embedding model — each function and class becomes an embedding that captures what the code means, not just the words in it — so a request phrased as “parse statement date from a CSV row” lands on the importer even though your prompt and the code share almost no literal tokens. You don’t pick the search tool; the agent does. Abstract asks like yours trigger semantic search, exact symbols trigger grep, and a real task chains both — semantic search to find the entry point, grep to trace references, then a couple of file reads to build full context.

The reason this matters on day one: on a repo you didn’t write, you don’t know where the date parsing lives either — and the agent finding it by description is exactly the help you’re here for. It read the existing test too, so anything it adds matches the house style instead of inventing its own.

Having read enough, it proposes. On Cursor that proposal isn’t a sentence in a terminal — it’s a set of inline diffs rendered right in the files, red for removed lines and green for added, gathered into a review bar in the Agent sidebar. One task, two files touched:

app/importers/csv.py
- txn_date = datetime.strptime(row["date"], "%m/%d/%Y").date()
+ txn_date = parse_statement_date(row["date"])
+ # parse_statement_date tries the common bank formats in order,
+ # raising ValueError if a row matches none.
tests/test_csv_import.py
+ def test_dmy_statement_date_parses_to_correct_day():
+ # the format that was previously silently mis-parsed
+ ...

Two beats are done — read, then propose — and the diff is sitting in your tree as a proposal you can read line by line before any of it is yours. That’s the same “treat every change as a proposal, not a result” discipline the rest of the course leans on; Cursor just gives you the diff to look at instead of a summary to trust.

Here is the beat that’s distinct from a terminal agent, and the one worth getting right. Cursor’s agent writes its edits to the files as it works, then hands you a review surface to accept or reject them — not a yes/no gate before each write, but a diff you adjudicate after. The review bar gives you Keep and Undo per change (and a Keep All / Undo All for the whole batch), with next-file / previous-file navigation to step through every hunk.

So you read the diff before you keep it — and on inherited code holding your own money, that read is the whole point:

> walk the importer diff — does anything touch how amounts get parsed?

You’re reading for two things: does the change do what I asked, and did it do anything I didn’t ask. For a date fix it’s a thirty-second read, but the time isn’t the point — never skipping it is. Look for the failures this domain breeds: a test that passes because it asserts the wrong day, or a date “fix” that quietly drifts into how an amount gets parsed while it’s in there. (Money in budgetcli is stored as integer cents, and the original author wasn’t consistent about it — so any edit near the money path is the thing to catch.) Satisfied with the importer hunk, you Keep it; the test hunk you read and Keep too. Anything off, you Undo that hunk and re-ask rather than patching a fix on top of the agent’s mistake.

One Cursor-specific habit goes with this: because edits land on disk as the agent works, don’t let a large unreviewed batch pile up. Review in small bites and the red/green diff stays something you can actually hold in your head; let twelve files of changes accumulate and “review” quietly degrades into rubber-stamping. Small turns, reviewed as they land, is how you keep the leash short.

Reviewing only tells you the change is good. It doesn’t make it safe — until you commit, everything you just kept is sitting in your working tree, one bad next prompt away from being tangled or lost. So before you move on, confirm it’s actually green and commit. You can have the agent do both:

> run the importer tests, and if they pass commit with a sensible message
Ran pytest tests/test_csv_import.py (9 passed)
Ran git commit -am "Parse multiple bank date formats in CSV importer"

This is the single most valuable habit in the chapter. Git is the floor that doesn’t vanish. Every time the agent reaches a genuinely working, reviewed state, a commit locks it in — and then the next experiment, however badly it goes, can never cost you more than the work since your last commit. Commit at every green, reviewed checkpoint and you can let the agent take bigger swings later, because the downside is always capped at “go back to the last commit.” On a week-long build in someone else’s codebase, that floor is what lets you move fast without fear.

Before the beats become muscle memory, it’s worth seeing the engine under them once in slow motion. This stepper traces a different small fix through the loop in its generic form — gather is your read beat, each act is an edit that in Cursor would land in the review bar as a red/green hunk waiting for your Keep — and the failed verify in the middle is precisely why the commit waits for green:

Step 1 / 8You hand over a task
> The login test is failing on main. Fix it.
(prompt enters the window)

Your message lands in the context window. The model reads it and decides what it needs first — it can’t fix what it hasn’t seen, so the first move is almost never an edit.

Read, propose, review, commit — you just watched all four close once, by hand, on a real bug. The next lesson is the same loop with the training wheels off: you’ll hand it the date bug and ship the reviewed change start to finish, and from here on every chapter assumes these four beats are muscle memory.