How to use Cursor AI effectively on a real repo

Table of Contents
Table of Contents
People ask me how to use Cursor AI effectively, then they show me a greenfield demo. That is the easy case.
The hard case is a client repo. A monorepo. Three package managers in the git history. A folder nobody is allowed to touch because billing lives there. Conventions that exist in the code but not in a README.
I’m Aris Setiawan. Senior full-stack, first Cursor Ambassador in Indonesia. I ship client work in Cursor every week. Effective does not mean the agent wrote a lot. Effective means the PR looks like it belongs here, a month later.
If you want the full production loop, I already wrote it: How to use Cursor AI to ship faster without wrecking the codebase. If you are still getting oriented, start with the Cursor AI tutorial for beginners. This post is the messy-repo version.
Real repos are messy on purpose
A real client repo is not a tutorial app. It has leftover names. It has a package that everyone imports and nobody wants to edit. It has a “temp” folder from 2023 that is now load-bearing.
Three things I assume before I open Cursor:
It might be a monorepo. Apps share packages. Packages drifted. The invoice app does not follow the same folder rules as the admin app. If you @ the whole workspace, Cursor will helpfully apply one pattern everywhere.
Conventions live in nearby files. Not in a style guide. The way this team names loaders, the way they shape API errors, the way they put tests next to the module: that is in the code. I open a sibling file first. Then I tell Cursor to match it.
Some paths are off-limits. Auth. Billing. Migrations. The public API. That vendor folder with a frozen contract. I say the off-limits list out loud in the prompt. If I do not, the agent will tidy something that was frozen for a reason.
Cursor does not know any of this until you say it. “Add export to invoices” with the whole repo in context is how you get a new helper in the wrong package, a rename in the shared UI kit, and a 40-file diff for a button.
That is not the model failing. That is you handing it a city and asking for a door handle.
Scope before you generate

This habit changed my results more than any model switch.
Before I generate, I do three things:
- Open the files I actually expect to change.
@those paths, and only those paths.- Name the blast radius: what I can touch, what I cannot.
A prompt I actually use:
Add a CSV export on the invoices list. Touch
apps/web/app/invoicesandpackages/export. Do not touchpackages/billingor the webhook handlers. Reuse the existing CSV helper if one exists. Match the error shape in the nearby list route.
Open files matter because Cursor weights what you are looking at. @ paths matter because they are the map. Blast radius matters because agents are helpful. Helpful without a fence is how Friday’s PR becomes Monday’s revert.
If the task needs a shared utility, I say so. I do not let it invent utils2.ts next to the helper we already have. If I cannot name the folders in one sentence, I am not ready to generate. I ask in chat first: where does this kind of change live here?
I also stop the agent if it opens a file I did not name. That is how a small export turns into a shared-package rewrite. A teammate should finish the diff in one sitting. If they cannot, I split the work.
Rules that fit on half a page
Project rules help. A 2,000-word constitution does not.
What I put in a client repo, and I stop there:
- Stack and package manager, whatever is true here
- Where features live, using the real path in this repo
- Prefer existing UI primitives
- Ask before schema, payments, or login changes
- No drive-by refactors
Half a page. If I need more, I put it next to the code, not in a manifesto the model will half-read.
When I am unsure where something lives, I @ the module and ask in chat. Pointing Cursor at the right folder beats a long prompt that guesses architecture. Docs get pulled in when the task hits payments, login, or a data model. Not every ticket needs the wiki.
Good rules stop random creativity. They do not make Cursor brilliant. You still have to scope the ticket.
Review like a senior
I treat every AI diff as guilty until I have read it. The author is me. “Cursor wrote it” is not a defense when a client pings late.
The checklist I actually run:
- Does this match the plan, and only the plan?
- Did it wander into off-limits files?
- A new dependency I did not ask for?
- A duplicate of something already in the repo?
- Error handling that matches nearby modules?
- Env values or logs that should not ship?
- Names that match the domain language we already use?
I read the diff file by file. I do not accept the whole thing because the summary sounded sure. Confidence is cheap. Correctness is not.
If it drifted, I do not say “also fix that.” I drop the extra, tighten the scope, and run again. One clean pass beats five follow-ups that re-read a huge context and keep adding files.
Tests are useful and incomplete. Cursor is good at tests that assert what it already wrote. I add one case that would fail if the behavior is wrong. Empty list. Permission denied. The timezone that bit us last quarter. Then I still click the happy path.
What effective looks like a month later
A week of “effective” can look like a lot of green PRs. A month later you can tell if it was real.
On client work I look for this:
- PRs stayed small. Reviewers did not need a weekend.
- The same helper was not invented three times.
- Off-limits folders stayed off-limits.
- Commit messages read like a human who knew the change.
- Reverts did not spike.
- A new teammate can find where a feature lives without asking which agent invented the folder.
If velocity is up and reviews hurt more, you got faster at making mess. That is the opposite of how to use Cursor AI effectively.
Effective is boring diffs. The feature is there. The repo still looks like your repo. The next person, human or not, can keep going without archaeology.
Keep the repo looking like yours
Scope first. Keep rules short. Review like you own the on-call.
That is the whole method. The model will keep getting better. The repo will stay messy. Your job is the fence and the taste.
If you want the production loop in full, use the workflow I run on real code. If you need first-week orientation, use the beginner tutorial. Then come back to this: client-repo habits, not demo habits.
If you want help installing that on your team, that is Level up. I sit with the actual repo, not a toy app.
Ship the ticket. Leave the monorepo boring.



