After seven months of building a strategy game with Claude Code, a handful of habits have stuck. None of them are profound in isolation. The compounding is what matters.

TDD is king

Every new behavior must go through the red-green approach.

If you do it the other way around, the agent is going to lie to you. It will make fake implementations with TODO, for now, or “temporary” logic, then write a perfectly green test and claim that everything is done.

I do not trust any feature that did not go through a red-green phase.

The agent needs to see the full picture

I found that the horizontal slice approach works much better. Ideally, the full flow should be visible in one place.

Less is more

Because we need to use our precious context as efficiently as possible, we need to find ways to express the same logic with fewer tokens.

One quick win is reducing boilerplate. Some day, I want to research which programming languages are the most concise and how that affects agent intelligence. But for now, I try to use all available syntactic sugar. For example, primary constructors in C# reduce a lot of code. I also try to create as many helpers as I can.

Small tasks

Each session should start with one small goal.

The full implementation must fit inside the “smart zone” and avoid the “dumb zone” by all means. Claude Code already does a great job in plan mode by creating good context for a task, but my job is to limit the scope as much as possible.

There is another trap I keep falling into: losing focus. If I want to design feature A, and the agent asks in the plan, “Do you also want feature B?”, it is very tempting to say yes. We are already in this topic, right? But my experience shows that this usually results in two incomplete and incorrect features.

The same applies to future plans. As software engineers, when building a feature, we often keep future extensions in mind. If we know that the system will later need C and D, we naturally want to design A in a way that supports those extensions.

But do not tell this to your agent. I found that if I say, “We want to add feature A, but keep in mind that later we will need to add C and D, so plan accordingly,” it confuses the agent and leads to suboptimal results.

Everything must be observable

Agents are very bad at finding tricky bugs. Even worse, the agent may read the code, “guess” the bug in the wrong place, and introduce even more bugs while trying to fix it.

What worked well for me was persisting the full state of the application into a SQLite database. This lets the agent inspect mismatches between expected and actual data. It also helps when writing a red test that reproduces the bug.

Code is disposable, tests are the real value

I have rewritten my codebase completely dozens of times. I tried new architectures, refactorings, and different implementation styles. The churn rate of the code is extremely high, and that is fine.

If I have a good test suite, rewriting the code takes minutes. This also led me to a point where I stopped reviewing code carefully, but I do review tests.

The linter is your first line of defense

The linter is your first line of defense for code quality. Invest time into writing rules that set the bar for your project.