Skip to content

The daily edit loop

You shipped one reviewed change in the first hour. This chapter is the next forty of them. budgetcli — the self-hosted budgeting API you inherited, the one that imports bank CSVs, tracks accounts, and flags overspend — has a backlog of the small, real, slightly-wrong things you always find in code you didn’t write. Most of them are too small to summon the Agent for and too fiddly to type by hand. The whole day-to-day of working in Cursor lives in that gap, and it lives there because Cursor is an editor and not a CLI. A terminal agent has one surface: the prompt. Cursor has the prompt and the cursor — the blinking one, in a file you’re looking at — and the skill this chapter builds is knowing, without thinking, which one a given edit wants.

That’s the through-line: not new capabilities, but a loop small enough to run dozens of times a day. Read what’s there, propose a change, review the diff it produces, commit when it’s green. You met that loop in the first hour as a one-time ceremony. Here it becomes a reflex, and you learn the four editor gestures that make each turn of it cheap.

Everything you do all day routes to one of two surfaces, and they are not two flavours of the same thing. They’re two different tools for two different moments.

  • Tab — Cursor’s AI-powered autocomplete. As you type, it predicts the next edit and shows it as ghost text; you press Tab to accept it. It is not agentic — there’s no loop, no tool calls, no “it’ll figure it out.” But it’s no longer just finishing the rest of an identifier: Tab predicts multi-line edits, coordinated edits across files, and the next location you’ll want to jump to. It’s the descendant of the autocomplete you already know, grown into something that anticipates the keystrokes you were about to make across more than the line you’re on.
  • The Agent sidebar — the chat panel where you describe a task in English and Cursor runs the read-propose-review loop: it reads files (semantic search across the codebase), proposes and applies edits across however many files it judges relevant, and runs terminal commands. You open it in the sidepane with Cmd+I. This is the surface for the work you’d rather describe than type.

The dividing line is worth saying plainly because getting it wrong is the most common way to be slow in Cursor: Tab is for edits you can already see in your head; the Agent is for edits you’d have to think to write. Renaming a variable you’re already mid-typing, filling in the obvious other half of an if/else, adding the third field to a struct when the first two are right above — that’s Tab. “Make the CSV date parser handle DD/MM as well as MM/DD” is the Agent. Reaching for the Agent to do a Tab-sized edit is like opening a chat to rename a local; reaching for Tab to do an Agent-sized one just means you type the whole thing yourself while ghost text guesses badly at the end of each line.

One habit to set now: Tab predicts, it does not decide. It will confidently suggest a completion that compiles and is wrong — the right shape, the wrong field, a plausible default that isn’t your default. Because accepting is one keystroke, it’s easy to Tab through three suggestions on autopilot and look up to find a function you didn’t write and don’t fully agree with. Read the ghost text before you accept it the same way you’d read a teammate’s suggestion. The cost of a wrong Tab isn’t that it breaks loudly; it’s that it slips in quietly, looking like something you typed.

Tab gets its own section because it’s the gesture you’ll fire more than every other one combined, and because it’s the thing Cursor does that a terminal agent structurally can’t: it lives at the cursor, predicting your keystrokes inside the file you’re already looking at. Per Cursor’s docs it’s “Cursor’s AI-powered autocomplete” that “suggests code as you type, based on your recent edits, surrounding code, and linter errors” — that last clause is the tell. Tab isn’t autocomplete reading a dictionary; it’s reading what you just did and guessing the next thing in that arc.

Four behaviours are worth knowing by name, because each one changes what you stop typing.

Next-edit / jump prediction. Tab doesn’t only complete where your cursor sits — it predicts the next location you’ll want to edit and offers to jump there. Accept a suggestion, and Tab can immediately point you at the next spot (“jump-in-file”): press Tab again and your cursor moves there with the next edit already staged. On budgetcli, rename acct to account in the struct and Tab will walk you through the other use-sites in the function, jump by jump, each one a single keystroke — you’re not searching, you’re confirming.

Multi-line and coordinated edits. A suggestion isn’t capped at finishing the current line. Tab “can modify multiple lines, add missing import statements, and suggest coordinated edits across related code.” Add a field to budgetcli’s Account struct and Tab can propose the matching change in the constructor below and pull in an import you now need — several lines at once, as one ghost-text block you accept or reject whole.

Cross-file completions. When an edit in one file implies an edit in another, Tab predicts it. Per the docs, “Tab predicts cross-file edits when changes in one file need updates in another. When a jump to another file is available, a portal window appears at the bottom of the editor.” Change a function signature in budgetcli’s importer.go and Tab can surface a portal to the call-site in report.go that now needs updating — you jump across the file boundary without leaving the keyboard.

Partial accept. You don’t have to take the whole suggestion. When Tab offers more than you want, accept it word-by-word with Cmd+ (macOS) or Ctrl+ (Windows/Linux), taking the half you agree with and typing over the rest. This is the antidote to the autopilot problem from the last section: when the first few words are right and the tail is a plausible-but-wrong default, partial-accept keeps the good part without committing to the guess.

# budgetcli — partial accept in action. Tab offers the whole line;
# the field name is right, the default is wrong (you want 0, not -1):
default := account.OverdraftLimit ← Tab's full suggestion (ghost)
default := account.OverdraftLimit ← Cmd/Ctrl+→ twice: take "default :="
then type your own RHS
result: default := 0

Tab in the terminal. Cursor’s integrated terminal also has a one-chord, natural-language path: press Cmd+K (macOS) / Ctrl+K (Windows/Linux) in the terminal and describe the command in English — “run only the report package tests” — and Cursor drafts the shell command for you to run.

Tab wins whenever the change is already legible in your hands — you know the next keystrokes, you just want them typed for you. The signal is that you’d have started typing anyway: a rename mid-edit, the symmetric half of a branch, the next field in a list, the call-site that obviously follows the signature you just changed. There’s no prompt to write because there’s no instruction to give; Tab reads the trajectory and finishes it.

It loses the moment you’d have to stop and describe the change. If the words “make it…” or “extract…” or “handle the case where…” form in your head, you’ve left Tab’s territory: a described-but-not-typed local edit is Cmd+K inline edit, and a described outcome that has to find its own files and run its own checks is the Agent. Tab also can’t be told anything — it has no prompt box — so any change that needs an instruction, however small, is already a rung up.

The cheap heuristic, course-wide: if your fingers already know the edit, Tab; if your words do, inline edit; if only the outcome does, the Agent. Tab is the floor of that ladder and where most of your day is spent — but only because most edits, on a repo you’re actively reading, are ones your fingers already know.

Between “type it myself with Tab’s help” and “hand it to the Agent” sits the gesture you’ll use more than either: inline edit, opened with Cmd+K on macOS or Ctrl+K on Windows and Linux.

Inline edit is the everyday non-agentic edit gesture. You select the code you want to change (or just place your cursor), press the chord, and a small prompt box opens right there in the file. You type what you want changed — “extract this into a helper”, “add an error return here”, “make this case-insensitive” — and Cursor rewrites the selection in place, showing the result as a diff you accept or reject before it lands.

The reason it’s a distinct gesture and not just “the Agent, smaller” is scope. Inline edit is scoped to what you selected. It isn’t going to wander into four other files, run your tests, and come back with a five-file diff. It does the bounded, local, single-spot change — the kind where you know exactly which lines should change and roughly how, you just don’t want to type the new version by hand. That makes it predictable in a way the Agent deliberately isn’t: you always know the blast radius, because you drew it yourself with the selection.

# Cursor's CSV importer assumes MM/DD. You've selected the parse line
# and pressed Cmd/Ctrl+K:
┌─ edit selection ─────────────────────────────────┐
│ parse this as DD/MM, not MM/DD │
└──────────────────────────────────────────────────┘
- t, _ := time.Parse("01/02/2006", raw)
+ t, _ := time.Parse("02/01/2006", raw)
[✓ keep] [✗ undo]

So you now have three rungs, smallest to largest, and the skill is reaching for the smallest one that fits:

  • Tab — you’re already typing the change; let it finish your keystrokes.
  • Cmd/Ctrl+K inline edit — you know which lines change and roughly how, but don’t want to type the new version. Bounded to your selection.
  • Agent sidebar — you can describe the outcome but not the edit; you want it to find the files, make the changes, and run the checks.

Picking the smallest rung that fits is most of what “fast in Cursor” means. The instinct that takes longest to build is down-shifting — catching yourself about to summon the Agent for something inline edit would do in one bounded pass.

Two characters carry the entire daily-driver grammar of the Agent sidebar, and confusing them is the single most common stumble. Hold one rule and you never confuse them again:

@ attaches context. / runs something.

@ pulls something into the prompt. Type @ in the Agent input and a picker opens; choose a thing and it’s attached as context the agent can see for that turn — a file, a folder, your docs, terminal output, a past chat, a git diff, the browser. It does not do anything. It answers the question “what should the agent be looking at while it works on this?” When you say @importer.go fix the date parsing here, the @importer.go is you handing the agent the file so it doesn’t have to go find it.

/ triggers an action. Type / and the picker lists things the agent can run — your custom commands and skills (for example /write-tests or /summarize). / answers “what procedure do I want to fire?” not “what should it read?”

The test that settles every case: am I telling the agent what to look at, or what to do? “Look at” is @. “Do” is /. A prompt routinely uses both — @billing.go @billing_test.go /add-test cover the negative-balance case attaches two files with @ and fires a custom command with / — and once the rule is in your hands you stop thinking about it. We don’t catalogue every @ target or every / command here; that’s the context chapter’s job. What you need today is the split, because it’s the grammar under every prompt you’ll type for the rest of the course.

The agent doesn’t edit your files behind your back. When it proposes a change — whether from the sidebar, from inline edit, or applied from a chat suggestion — it surfaces as a diff you review before it becomes part of your working tree. Green for added lines, red for removed, laid over the file the way a code review would look. Nothing is real until you accept it.

This is the load-bearing half of the loop, and the one beginners skip. Two things to internalise:

  • Keep and undo are per-change, not all-or-nothing. A multi-file proposal isn’t a single yes/no. Cursor surfaces per-change Keep / Undo controls (plus Keep All / Undo All for the whole run), so you can keep the edit in importer.go, undo the one in report.go because it changed behaviour you didn’t ask for, and re-prompt for just that file. Reviewing a diff means reading it, change by change, the same as you’d review a colleague’s PR — not skimming for red and clicking keep.
  • Undo is a real answer, not a failure. When a proposal is wrong, undoing it and re-prompting with a sharper instruction is faster than keeping it and hand-fixing the mess. The diff is your veto, and using it freely is what keeps the agent’s latitude from becoming your liability. On budgetcli — code with your own money flowing through it — an undone diff costs you ten seconds; a kept-then-wrong one costs you a debugging session.

The mental model: the agent proposes, you dispose. It never gets to merge into your reality without your read.

Reviewing each diff protects you from the next edit. Checkpoints protect you from the last several. As the agent works through a task, Cursor records checkpoints at each significant change you can roll back to — restore returns your files to how they stood at that point, undoing the edits that came after. Your chat history stays intact; restore reverts the files, not the conversation, so you keep the thread of what you asked for and can re-prompt from where you left off.

Why this matters next to git: a single agent turn can touch several files before you’ve decided whether you like the direction. Git’s smallest safety net is a commit, and you don’t want to commit a half-finished, possibly-wrong agent run just to have an undo. Checkpoints give you a finer-grained, run-aware undo inside an un-committed run — let the agent go three edits down a path, decide at edit three that edit one took the wrong fork, restore your files to before edit one, and re-prompt. It’s the undo that understands “the agent’s last three steps” as a unit, which plain editor undo doesn’t.

Checkpoints don’t replace git; they sit under it. The rhythm is: explore with checkpoints while the work is still molten, commit with git once it’s green and reviewed. Which is the whole loop, so let’s name it.

The loop: read → propose → review → commit

Section titled “The loop: read → propose → review → commit”

Every one of the gestures above is a move inside one repeating rhythm. Worn in, it’s four beats:

  1. Read. Understand what’s there before you change it — yourself, or by handing the agent the files with @ and asking what’s going on. On inherited code you don’t trust, this beat is not optional; it’s the one that stops you from confidently fixing the wrong thing.
  2. Propose. Make the change with the smallest gesture that fits — Tab for the keystrokes you’d type anyway, Cmd/Ctrl+K for a bounded local edit, the Agent for a described outcome. The proposal is the agent’s, or yours; either way it arrives as a diff, not a fait accompli.
  3. Review. Read the diff change by change. Keep what’s right, undo what isn’t, re-prompt for the gap. Lean on checkpoints to back out a run that wandered. Nothing lands unread.
  4. Commit. The moment a change is green — tests pass, you’ve read it, it does what the ticket said — commit it. A reviewed, green, committed change is a save point you can build the next change on without fear.
# One turn of the loop on budgetcli — the date bug's quieter cousin:
# negative balances render without a sign in the overspend report.
read → @report.go @report_test.go where does the report format
a balance? does it ever drop the minus sign?
→ balances format via fmtMoney(); for values < 0 it strips
the sign before the currency symbol. report_test.go has
no negative-balance case.
propose → (Agent) fix fmtMoney so negatives keep their sign, and add
a report_test case for an overspent account.
⏵ Edit report.go → preserve sign in fmtMoney
⏵ Edit report_test.go → add negative-balance case
⏵ Run go test ./report/...
review → diff: fmtMoney change is right — keep. test case asserts
"-$40.00" — correct, keep. go test → ok.
commit → git commit -m "fix: keep minus sign on negative balances"

That’s the day. Not one heroic prompt, but the same four beats run forty times, each one cheap because you reached for the right-sized gesture and never let an edit land unread.

The loop’s read beat has its own gesture — when you can’t yet name the change, drop the agent into a read-only posture before you escalate to one that can edit — but that dial belongs to the modes chapter, which owns the Ask → Agent escalation and the Shift+Tab chord that cycles postures.

The daily loop isn’t five features to memorize. It’s one rhythm — read → propose → review → commit — run with the smallest gesture each beat allows:

  • Tab finishes keystrokes you were already making. Read its guesses; don’t autopilot.
  • Cmd/Ctrl+K does the bounded local edit you can scope with a selection.
  • The Agent sidebar does the outcome you can describe but not type.
  • @ attaches, / runs — the grammar under every prompt.
  • Diffs are your veto; keep and undo per change, never unread.
  • Checkpoints are your fine-grained undo inside an un-committed run; git is your save point once it’s green.

The person who’s merely installed Cursor types into the Agent for everything and accepts whatever diff comes back. The person who’s good with it feels which rung each edit wants before they touch the keyboard, reads every diff like a review, and commits the second a change is green — so the next one starts from solid ground.

Next, learn to switch posture deliberately with modes →