I Refactored 8 Files in 20 Minutes with Cursor — Here's What Actually Works
I Refactored 8 Files in 20 Minutes with Cursor — Here's What Actually Works
Last Thursday at 10pm, I rewrote an entire payment module with Cursor. Eight files. Four hundred lines of changes. Twenty minutes flat.
Seriously. Twenty minutes.
Six months ago, that same task would've kept me up until 2am, probably with a sad Deliveroo order somewhere around midnight. Today I want to talk about Cursor's multi-file editing — not the sanitised version from the docs, but the stuff I've learned by breaking things repeatedly.
Let Me Tell You How I Screwed Up First
Three months ago, I tried Cursor's Composer for the first time. I was confident. Selected six auth-related files, typed one innocent sentence: "Replace all console.log with unified logger calls."
What happened?
Cursor did exactly what I asked. It also nuked console.log('token expired', token) from my middleware — the one line I'd deliberately left in for production debugging. I just stared at the screen. That log was my lifeline when things went sideways.
The next day? Production issue. Me? Staring at empty logs like an idiot.
The lesson's obvious now. Before any batch edit, search first. Know exactly how many matches exist and which ones are sacred. Composer's context understanding is impressive, but it can't distinguish between "temporary debug code I need" and "debug code I forgot to delete."
Actually, let me correct myself — it's not that it can't distinguish. It's that it defaults to assuming all console.log statements are rubbish. It lacks that gut feeling of "this code is ugly but necessary."
Now I've built a habit: Cmd+Shift+F first, get the lay of the land, then decide whether to batch-edit everything or handle certain files manually.
Tip 1: Use Composer for Cross-File Refactoring, But Don't Let It "Guess"
Cursor's Composer mode (Cmd+I) is the nuclear option for multi-file editing. Select your files or folders, describe what you want, and it analyses the relationships, proposing changes across everything.
Real example: Last month I converted an Express project's error handling from callback style to async/await. Five route files, two middleware files, one utility function.
Here's the exact prompt I used:
Convert all error handling in these 8 files to async/await pattern. Wrap with try/catch, use next(error) to pass to error middleware. Keep existing business logic unchanged. Do NOT touch any code unrelated to error handling.
That last sentence is everything. Being explicit about what NOT to change matters more than describing what TO change. Without it, Composer might "optimise" your variable names or restructure functions — changes that are technically improvements but make your code reviewer ask "who wrote this and why doesn't it match the spec?"
The result? Seven files passed on the first go. One route file had return res.json() incorrectly changed to return next() — I fixed it manually in ten seconds.
Time saved? At least three hours. Probably more, because honestly, I used to postpone this kind of refactoring to weekends.
Tip 2: Batch Renaming — F2 Isn't Enough
F2 for symbol renaming is basic stuff. But plenty of scenarios laugh at it.
Case in point: I recently renamed avatar_url to avatar in a user table. The blast radius was painful:
- Backend ORM model definition (1 file)
- SQL queries scattered across 4 service files
- Frontend API type definitions (2 files)
- Field references in components (3 files)
This is tricky because it's not just variable names — SQL column names, TypeScript types, API response fields, they all need to change together. Doing it with F2 one by one? I'd still be there.
My approach: dragged all relevant files into Composer and wrote:
Rename avatar_url to avatar across all files. This includes variable names, SQL column names, TypeScript type definitions, and API response fields. If any comments mention this field, update those too.
Cursor scanned everything and proposed 23 changes. I reviewed each diff. All correct.
One nuance worth emphasising: when batch-renaming, split frontend and backend into two separate operations. Round one: backend only, verify API responses actually changed, run your tests. Round two: frontend. Throw too many files in at once and Composer tends to miss things. From what I've seen, version 0.34.x (March 2024) was particularly prone to this — the 0.36 update improved it significantly.
Tip 3: Use Rules Files to Put Guardrails on Batch Editing
This one comes from genuine pain.
I once batch-edited 10 files and discovered afterwards that three of them had their indentation changed from 2 spaces to 4. I was baffled — turns out Composer had referenced some legacy code style in the project. Code written by a previous developer that I'd been slowly cleaning up. Composer assumed it was "the project standard."
Since then, I've kept a .cursor/rules file in my project root. It looks roughly like this:
You are a professional full-stack developer. When modifying code, follow these rules:
- Maintain existing indentation style (2 spaces). Do NOT change it.
- Do NOT modify code unrelated to the task, including but not limited to: variable naming, comment formatting, import ordering
- If uncertain about a change, mark it with // TODO: instead of forcing it
- Do NOT change quote styles for table names and field names in SQL queries
This file affects both Composer and Chat modes. Since adding it, "collateral damage" from batch edits has dropped by over 80%.
Eighty percent is an estimate. But genuinely — I no longer worry about indentation getting scrambled, and my code reviews aren't cluttered with unrelated "optimisations." Peace of mind restored.
Tip 4: Batch Processing + Git Staging
This workflow evolved from Pieter Levels' "ship fast" philosophy. His core idea is rapid iteration, small steps.
Applied to Cursor batch editing, it means: never modify more than 5 files at once.
My workflow is now rigid:
- Select 3-5 related files, edit with Composer
git add -pto review changes chunk by chunk, stage when verified- Run tests or manually walk through critical paths
- Only then move to the next batch
The beauty of this: if a round goes wrong, git reset only affects that batch. No need to scrap everything.
Last month I was refactoring a legacy project with dependency webs like actual spaghetti. Honestly, a complete mess. I split 18 files across 4 rounds using this method — no major disasters. One round did go sideways (Composer referenced a deprecated function), but since I'd only touched 4 files, I found and reverted the issue in five minutes.
Tip 5: Batch Generating Boilerplate Code
Multi-file editing isn't just about modifying — the real power move is generation.
Say you're adding a CRUD module to an API project. You typically need: route file, controller, service, validation schema, TypeScript types. At least five files.
Here's what I do: in an existing module file, write out the requirements as comments.
// Reference the order module structure to generate a product module
// Files needed: product.route.ts, product.controller.ts, product.service.ts, product.schema.ts, product.types.ts
// Fields: id, name, price, category, stock, created_at
// Endpoints: GET /products, GET /products/:id, POST /products, PUT /products/:id, DELETE /products/:id
Then in Composer, select this file and the comment. Cursor generates all files and automatically wires up the references.
Last week I used this to generate an entire notification module — 6 files, 270 lines of code. Manually, that's half a day. Cursor took 15 minutes, I spent 20 minutes reviewing and tweaking.
Time saved? I'd planned to do it on Saturday. Finished Friday afternoon instead. Went hiking on the weekend.
I Actually Tracked the Time Savings
I dug through my Git history from the past month and roughly calculated:
| Task Type | Files | Traditional Time | Cursor Time | Saved |
|---|
| Field rename | 8 | 45 min | 8 min | 82% |
|---|
| Error handling refactor | 7 | 3 hours | 25 min | 86% |
|---|
| Batch module generation | 6 | 4 hours | 35 min | 85% |
|---|
| Code style unification | 12 | 1.5 hours | 15 min | 83% |
|---|
Cael Lee
Full-stack developer with 8+ years of experience. Currently building AI-powered developer tools. I've tested 20+ AI API providers and coding assistants.