I tune Cursor like a workshop, not a slot machine
Max mode on Opus 4.8, Context7 docs attached on every hard task, background agents for the long jobs, and rules I actually enforce in review. The Cursor setup I use when correctness matters more than speed.
I am going to be honest about something. For about three months I used Cursor the lazy way. Tab, tab, accept, accept, and a faint feeling that I was building a house out of cards that someone else had shuffled. The completions were fast and mostly fine, and mostly fine is exactly the problem. Mostly fine code is the most expensive code there is, because you pay for it later, in a review six weeks from now when nobody remembers why the function takes four positional booleans.
So I stopped. I rebuilt the way I use Cursor from the ground up, and I optimized for one thing: I want to trust the diff without re-reading every line. Not speed. Trust. Those are different goals and most setups quietly choose speed. This one chooses quality, and yes, it costs more per task. I will show you the numbers later and you can decide if you are the kind of person who cares.
Opus 4.8 in Max mode, and why I do not flinch at the cost
Cursor lets you pick a model and, for the strong ones, a Max mode that gives the model more room: a larger effective context and the budget to think longer before it answers. People treat Max mode as a luxury. I treat it as the default for any task that has a wrong answer. A typo fix, sure, use the cheap fast path. A change that touches the data layer and three components? That is exactly where a model running out of thinking room produces something that compiles and is still wrong.
My rule is blunt: Max mode on Opus 4.8 for anything I would ask a senior to review. Everything else can use a faster tier. The split is not about saving money, it is about not wasting a careful model on work that does not need care, and not handing careless throughput to work that does.
Rules: the part everyone gets lazy about
Cursor rules are version-controlled Markdown files in .cursor/rules/ with an .mdc extension and a little YAML frontmatter. The frontmatter decides when a rule loads: alwaysApply: true for the standards I never want skipped, or a globs pattern so a rule only attaches when the model touches matching files. This is the single highest-leverage thing in the whole setup and it is the thing people half-do. They write three vague bullet points and wonder why the model still ignores their conventions.
My core rule is always on. It is opinionated on purpose. A rule that says 'write clean code' is worthless. A rule that says exactly which patterns I will reject in review is a contract the model can actually hold itself to.
---
description: Core engineering standards for this repo. Always on.
alwaysApply: true
---
# How we write code here
This is a TypeScript monorepo: a Next.js app, a small Hono API, and a
shared design-system package. pnpm workspaces. I care about quality more
than I care about speed, so behave accordingly.
## Non-negotiable
- TypeScript strict. No `any`. No `as` to silence the compiler. If a
type is hard, that is a design smell, fix the design.
- Reuse before you add. Check packages/ui and packages/lib before pulling
a dependency or writing a new helper. I will notice the duplicate.
- Server components by default in the Next.js app. "use client" only when
the component genuinely needs state or an effect.
- No console.log shipped. Use the logger. No commented-out code committed.
## Before you edit
- Read the file you are about to change, and its tests, first.
- For anything over ~3 files, write a short plan and wait for me. Do not
start refactoring the world because I asked for one button.
## Style I will reject in review
- Premature abstraction. Three call sites, then you abstract, not before.
- Barrel files that re-export everything. Import from the source.
- Magic numbers and one-letter variables outside a tight loop.The second rule only loads when the model edits a .tsx file in the web app. No point spending context on component conventions while it is editing a migration. Scope your rules and they stay sharp.
---
description: Conventions for React components in apps/web
globs: apps/web/**/*.tsx
alwaysApply: false
---
# Component rules (auto-attached for .tsx in the web app)
- One component per file, named the same as the file.
- Props are a named type, not inline. Destructure in the signature.
- Tailwind classes go in source order: layout, box, type, color, state.
Out-of-order class lists get sent back.
- Every interactive element is keyboard reachable and has a visible focus
ring. No `outline-none` without a replacement.
- Pull design tokens from packages/ui/tokens. Never hardcode a hex.Context7: stop the model citing an API that died two versions ago
Here is the failure that pushed me to wire up Context7. Opus is sharp, but its knowledge has a cutoff, and library APIs move. I lost an afternoon to a routing helper the model insisted existed because it had existed, eighteen months ago. That is not a model being dumb. That is me failing to give it current information.
Context7 is an MCP server that pulls up-to-date, version-correct docs for a library on demand. My rule is to attach it for any task that uses a framework feature I am not 100% certain of. In practice I just write use context7 in the prompt, or let the rule remind the Agent to reach for it. Here is my full MCP config.
{
"mcpServers": {
"context7": {
"url": "https://mcp.context7.com/mcp"
},
"github": {
"url": "https://api.githubcopilot.com/mcp/"
},
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": { "DATABASE_URL": "${env:DATABASE_URL}" }
},
"sentry": {
"url": "https://mcp.sentry.dev/mcp"
}
}
}- context7 is the one I would not give up. Current docs for whatever library the task touches, fetched at the moment of need.
- github so the Agent can read the issue I point it at and open a PR when the work is done.
- postgres lets it check the real schema before it writes a query. It kills the whole 'that column does not exist' category of bug.
- sentry for triage. I paste a Sentry issue link and it pulls the real stack and breadcrumbs instead of guessing.
Hooks and a pre-commit gate the model cannot talk its way past
Rules are persuasion. Hooks are enforcement. I do not want my formatter or my safety net to depend on the model being in the mood to follow instructions, so the deterministic stuff lives in hooks that run no matter what. Cursor runs hooks on lifecycle events: I format on every file edit, and I screen shell commands before they run.
{
"version": 1,
"hooks": {
"afterFileEdit": [
{ "command": "pnpm exec prettier --write \"$CURSOR_FILE_PATH\"" }
],
"beforeShellExecution": [
{ "command": ".cursor/hooks/block-destructive.sh" }
]
}
}The real wall, though, is the git pre-commit hook. The Agent runs the same gate I do, and a red gate means no commit. No exceptions, no 'I will fix it in a follow-up.' This is the line that has kept a broken build off my main branch for months.
#!/usr/bin/env bash
# .husky/pre-commit
# The model never commits past a red gate. Neither do I.
set -euo pipefail
echo "› typecheck"
pnpm typecheck
echo "› lint (staged only)"
pnpm exec lint-staged
echo "› tests for changed packages"
pnpm test --filter "...[HEAD]" --runBackground agents for the long, boring work
The piece that genuinely changed my day is the Background Agent. It runs a task in its own environment while I keep working in the editor. I hand it the slow, mechanical jobs: bump a dependency across the monorepo and fix the fallout, write the missing tests for a package, chase down every usage of a deprecated helper. Then I review what it pushed, on my schedule, like a PR from a colleague who never gets tired.
I do not let it merge. Ever. A background agent that can open a PR is a force multiplier. A background agent that can merge to main is a way to get paged at 2am. The gate is human, and it stays human.
A normal task, start to finish
- Frame it in the Agent. I describe the change and, if it is non-trivial, ask for a plan first. I read the plan. I correct the wrong assumption before a line is written.
- Max mode if it has a wrong answer. Anything past a cosmetic tweak runs on Opus 4.8 in Max mode, with Context7 attached when a library is involved.
- Let the hooks do their job. Edits format on save. I watch the diff land clean instead of mentally compiling unformatted code.
- Review like it is a stranger's PR. I read the diff against my own rules. If I would reject it from a human, I reject it from the model.
- Commit through the gate. Typecheck, lint-staged, tests for changed packages. Green or it does not land.
The cost question, answered honestly
Max mode on Opus is not cheap, and I am not going to pretend otherwise. What I will say is that the expensive part of software was never the tokens. It was me, re-reading, re-doing, and shipping the bug. Here is a month of my work before and after I rebuilt this.
| Metric | Tab-and-accept | This build |
|---|---|---|
| Diffs I had to rework by hand | ~50% | ~13% |
| Avg cost per real feature | $0.30 | $0.71 |
| Hours per feature, idea to merge | ~3 hrs | ~1.6 hrs |
| Broken builds I committed / week | 2 to 3 | 0 |
| Times I re-read the whole diff | every time | spot checks |
The cheaper setup felt faster and was slower. I was paying in attention what I thought I was saving in dollars.
28:05If you want the philosophy behind handing more or less autonomy to the editor, this comparison is the clearest I have read. I land firmly on the 'less raw autonomy, more enforced quality' side, but it lays out the trade honestly.
Claude Code vs Cursor: Complete comparison guide in 2026A clear-eyed comparison of the autonomous-agent versus interactive-IDE approaches. Worth reading before you decide how much to let the tool drive.northflank.comTake it, then make it yours
Everything here is in the build. Installing it drops the rule files, the MCP config, the hooks and the pre-commit gate into your repo. Do not copy it and walk away, that is exactly the lazy move I am arguing against. Start with the core rule, rewrite it in your own opinions, point the globs at your real folders, and keep the gate. The gate is the part that makes the rest safe to trust.