Get Shit Done, working with AI assistants without chaos
Get Shit Done is a way of working built on a simple observation: since the cost of writing code fell, the bottleneck stopped being writing and became deciding what to write and checking whether what appeared is what was meant.
The name suggests haste, and that is the biggest misconception around this approach. The point is not doing things faster and worse, but removing steps that stopped making sense with assistants and strengthening those that gained importance.
What actually changed
Worth naming the difference concretely, since which habits deserve changing follows from it.
Writing a function used to take twenty minutes and now takes two. Writing a class with tests used to take half a day and now takes an hour. That change is real and measurable.
What did not change is how long understanding somebody else's code takes, how long finding a bug in code nobody read takes, and how much a badly made architectural decision costs.
The conclusion is predictable: since writing gets cheaper while understanding does not, the proportion shifts. Code appearing faster than it can be reviewed is debt rather than progress, and that is this period's main trap.
The right approach therefore consists not of accelerating everything but of accelerating writing while holding the pace of review. A task is sized so the result can be read, not so the tool can handle it.
The task as the unit of work
The first principle concerns division and is the most important on the list.
A task suited to an assistant has three properties. It can be described in two sentences together with a completion criterion. It touches at most a few files. The result can be reviewed in fifteen minutes.
A bad task looks like this: "rewrite the payments module onto the new architecture". The assistant will do something, the change will touch thirty files, and reviewing it will take longer than writing it yourself. In practice nobody reviews that and the result enters the repository on trust.
Splitting such a task into seven smaller ones takes fifteen minutes and pays back immediately. Every step can be checked, every step can be reverted separately, and when the third goes wrong, everything need not be undone.
Note too that smaller tasks give better results in themselves. The model receives narrower context, so it misses less often, and you phrase the instruction more precisely, since it covers one thing.
Phrasing the instruction
The second principle concerns what you write, and it is where the difference in effectiveness is largest.
Describe the outcome and the constraints rather than the steps. The tool decides the order; your job is to set the boundaries.
Cancel an order.
Result: a user can cancel an order in the new or paid status. A cancelled
order refunds the payment and sends a notification.
Constraints:
- the OrderService interface stays unchanged
- add tests in src/orders/orderService.test.ts
- do not touch database migrations, the status column already existsThe constraints list matters more here than the description of the outcome. The tool will usually infer the outcome, while the boundaries it must not cross follow from nothing visible in the code.
Supply context rather than hoping it gets found. A file name, a directory name, or a pasted object shape narrows the search area more effectively than a more precise description of the task itself.
Start with a question on unfamiliar code. Asking how a fragment works before changing it costs pennies and saves reverting changes based on a wrong assumption.
Record instructions that worked. A phrasing after which the tool landed on the first attempt is repeatedly useful in the same repository, and reconstructing it from memory two weeks later usually fails.
## Adding a field to an order
Add a <name> field of type <type> to the order.
Go through every layer: the Prisma schema, a migration, the type in
src/orders/types.ts, validation in src/orders/schema.ts, the form in
src/app/orders/[id]/edit.tsx. Add tests to the existing files.
Do not add new dependencies.A file of such records beside the project guidelines speeds a whole team up more than any setting. Angle brackets in the variable positions are enough to make an instruction reusable without reading it in full.
Verification, the part that gained importance
The third principle concerns checking and is the one most often skipped, since it does not look like progress.
Tests change the whole dynamic of working with an assistant. A tool that runs tests after a change and sees red corrects itself. A tool with no tests reports readiness and leaves the checking to you. That is the cheapest investment in effectiveness this way of working offers.
Type checking and static analysis work the same way: they give immediate feedback the model can use without your involvement.
{
"scripts": {
"verify": "pnpm lint && tsc --noEmit && vitest run --reporter=dot"
}
}One command instead of three matters in practice. A line in the guidelines saying "the task is done when pnpm verify passes" is unambiguous, while a list of three separate commands ends with the first one being run. A project without that layer is not ready for task based work, however good the tool.
Review that is read rather than skimmed is the third element. Generated code looks polished, and that is its most misleading property. Error handling, edge cases, and behaviour on empty data are where appearance and substance diverge most often.
The practical rule: if you have no time to read a change, you have no time to make it. That sounds severe and is the only rule protecting against turning speed into debt.
The size of the change itself tells you whether that rule can still be applied.
git diff --stat
git diff -- '*.test.ts' '*.spec.ts'Run the second command separately, because changes to tests read differently from changes to code. A test fitted to the implementation rather than to the requirement looks exactly like a correct test and passes just as green.
What to keep from older habits
Not everything that worked before lost its meaning, and the distinction matters.
Thinking about architecture before starting stays. Deciding where business logic lives and how layers divide costs the same as before, and a mistake in it costs more, since code built on a wrong assumption now appears in greater volume and faster.
Tests, code review, and version control stay. What changes is their weight: with slow writing they were insurance, with fast writing they are a precondition.
What goes is planning details before the first line. Since writing a draft takes fifteen minutes, discussing an interface's shape divorced from working code costs more than seeing it. That is the part where older rules genuinely stopped fitting.
What also goes is attachment to the first version. Rewriting something that took an hour is cheap, so clinging to a solution known to be poor makes less sense than it used to.
The project guidelines file
The cheapest thing you can do for output quality, and the most often skipped, since it does not look like work.
An assistant sees the code and draws conclusions from it, which works on a coherent project and fails on one with history. A convention departed from over two years will be read as both versions at once, and the result depends on which file it happens to land on.
What belongs there. The libraries in use and those the team deliberately avoids, since a model reaches for the most popular one by default rather than yours. Naming conventions for files and functions. Where tests live and which command runs them, since without that the tool will not run them. The language version and compiler settings. And rules that do not follow from code, such as the service layer never reaching the database directly.
The effect shows from the first task, since the most common category of corrections disappears: code that is technically correct and does not match the rest of the project. Instead of fixing the same thing on every change, you write the rule once.
Treat that file like code: keep it in the repository, review it on changes, and extend it every time you fix something for the second time. A rule added after a second occurrence saves the third and every one after.
Working as a team
Several things change once this way of working belongs to a team rather than one person.
Code review gains importance and loses obviousness. A generated change looks more polished than a hand written one, so a reviewer passes it more easily. Worth naming that in the team, since awareness of the effect suffices to read more carefully.
Agree what enters the repository. Generated code goes through review exactly like hand written code rather than beside it. Without that rule the project gains a layer nobody read, and nobody knows which.
A shared guidelines file matters more here than in solo work, since without one every person receives code in their own style and the project drifts faster than anybody notices.
The last item is expectations. A team accepting that the tool shortens the path to a first version rather than a finished one works more calmly than a team counting on a task assigned in the morning being in production by evening. That second stance leads to shipping unreviewed work, since the deadline was set on an assumption nobody checked.
Tools and their role in this arrangement
| Tool | Form | Strength | Role in this approach |
|---|---|---|---|
| Cursor | A separate editor | Project context, completion | Continuous work on existing code |
| Aider | Command line | Independence, any model | Closed tasks, a commit after each |
| Windsurf | A separate editor | An agent working in tasks | Changes spanning many files |
| Claude | Chat or terminal | Reasoning, long answers | Design decisions and review |
Tool choice is the least consequential decision here and deserves saying plainly, since it consumes the most conversation. All of the above support task based work, and the differences in effectiveness are smaller than the differences arising from how you phrase instructions and whether you have tests.
A sensible arrangement is one tool for continuous work and one for closed tasks, rather than five running at once. Changing tools monthly costs more than it gives, since you rebuild habits every time.
Separating roles does pay, though. A conversation about how to design something and the execution of it are two different tasks, and doing the first before the second usually improves both.
Speed traps
Four things that break most often in this way of working.
The first is code nobody read. It surfaces at the first bug, when it turns out nobody on the team knows how that module works, since it appeared in fifteen minutes and nobody had reason to look inside.
The second is convention drift. Every task done separately produces correct and slightly different code, and after thirty tasks the project holds four naming styles and three ways of handling errors. A project guidelines file solves that most cheaply.
The third is the illusion of progress. The change count grows while the product stands still, since the work goes to things easy to delegate rather than things that matter. Once a week it pays to look at what actually moved forward instead of counting changes made.
The fourth is long sessions. A conversation held over one task for an hour carries the whole context so far, so cost grows while the effectiveness of fixes drops as the tool loses track of its own earlier decisions. Closing a task and starting a new one is often cheaper than continuing to refine.
Common mistakes
The first is tasks touching too many files at once. A change that cannot be reviewed enters the repository unreviewed.
The second is working without tests. An assistant with no feedback from a run cannot correct itself and pushes all checking onto you.
The third is having no project guidelines file. Without one every task produces code that ignores conventions, and you fix the same things repeatedly.
The fourth is running the tool on a dirty working tree. Automatic changes mix with yours and separating them becomes a task of its own.
The fifth is delegating tasks faster done yourself. A one line fix you know how to make takes less time than describing it.
The sixth is confusing speed with progress. Thirty changes a week against a product standing still is a cost rather than a result.
FAQ
Does this approach suit large projects?
Yes, provided task size holds. A large project means more context to convey, so naming files and maintaining a guidelines file matter more there than in a small one. The principle that a task must be reviewable does not depend on scale.
Will AI replace developers in this arrangement?
Not in what this approach reduces to. Writing code gets cheaper, while deciding what to write, judging whether what appeared is what was meant, and carrying responsibility for the result stay with you, and those became the bottleneck.
How do I reconcile speed with quality?
Through task size. A task small enough to review in fifteen minutes gives both. A larger task gives speed at the cost of quality, and that is a trade that turns against you at the first production bug.
Where do I start if the project has no tests?
By adding tests to the part you are working on rather than covering everything. The tool can write them, and you immediately gain a feedback loop in that one place, extendable with each later task.
Which tool should I choose?
The least consequential decision in the set. Cursor, Aider, and Windsurf all support task based work, and the differences between them are smaller than those arising from instruction phrasing and the presence of tests.
A broader treatment of working with models sits in the Anthropic documentation, and terminal based work on the Aider site.