Wrestling with LLMs: The Parachute on the Dragster

My hobby code was always missing the same things. Tests I'd write later. CI/CD I'd set up eventually. Linting I'd configure when I had time. None of it was laziness - it was math. Solo developer, limited hours, choosing between features and infrastructure. Features won every time.

Then LLMs made me 10x faster at writing code. Which meant I was now 10x faster at writing untested, unlinted, manually-deployed code. A dragster engine bolted onto a go-kart frame.

The insight that changed how I work: LLMs don't just write features faster. They make the infrastructure I always skipped finally affordable. The same tool that gives you the engine helps you build the parachute.


Why I Never Built It Before

At work, production infrastructure is a shared responsibility. Someone's good at testing, someone else handles CI, someone else does the deployment config. You complement each other.

Solo, I played every role and wasn't equally good at all of them. Writing code? Great. Comprehensive test coverage? I'd rather ship features. GitHub Actions YAML? I'd put it off for weeks. Pre-commit hooks, ESLint configs, Docker setups - each one was another hour not spent on the thing I actually wanted to build.

The few times I tried to do it all upfront, the project died. I'd spend a weekend configuring CI, lose momentum, and never come back. The infrastructure that was supposed to protect the project killed it instead.

So I accepted "hobby code" and moved on. The cost was real - technical debt piled up, refactoring without tests was terrifying, I shipped bugs I could have caught - but it was the rational choice.


What Actually Changed

LLMs don't just speed up what I'm good at. They make achievable what I'd avoid.

I asked Claude to set up Playwright E2E tests for dokku-dns. An hour later I had a test suite that spun up a real Dokku instance, created DNS records, verified they resolved, and tore everything down. Integration tests that would have taken me days of reading Playwright docs and debugging Docker networking - done in an afternoon. I verified the tests actually tested the right things, but I didn't have to start from scratch.

Same pattern with CI/CD. Claude wrote the GitHub Actions workflow while I described what I wanted. What would have been a full day of YAML research became an hour of reviewing and testing.

Same with linting. I don't know every shellcheck rule, but Claude configured it and then shellcheck caught dozens of bash issues in code Claude had confidently declared "working perfectly" - missing quotes, unsafe variable expansions, logic errors. The LLM set up the tool that catches the LLM's own mistakes.


The Infrastructure Catches Real Problems

This isn't theoretical. Here's what the safety net actually caught:

Claude deletes tests to make them pass. I caught this multiple times. A test would fail, and instead of fixing the code, Claude would remove the test. "All tests passing now!" it would announce, having eliminated the evidence. I now treat any test deletion as a red flag.

Claude skips pre-commit hooks. It used --no-verify to bypass the checks I'd asked it to set up. So I added CI validation where it can't be bypassed. The accountability loop has to be airtight - if there's a shortcut, the LLM will find it.

Claude writes inconsistent code. Different quote styles in the same file. Patterns that technically work but drift from the codebase's conventions. Without linting, these accumulate into a mess. With linting, they get caught on every commit.

Claude builds on broken foundations. It will happily generate 500 lines on top of a subtle bug. Without tests running on every commit, you don't discover the foundation is cracked until the whole thing collapses. By then, the LLM has moved so fast that unwinding the damage is harder than the original work.


PRs Stopped Being Theater

Before LLMs, pull requests as a solo developer were a joke. I'd open a PR, review my own code, leave a comment like "Looks good to me! Nice work Dean, ship it!" and merge. Pure ceremony.

With LLMs, PRs actually serve a purpose. They're how I review what the LLM generated before it hits main. They isolate changes so I can revert mistakes without destroying what's already working. Small PRs and meaningful commits become how I understand what happened - because I didn't write the code, I need the diff to tell me the story.

The PR workflow went from overhead I couldn't justify to the primary way I supervise an unreliable but productive collaborator.


The Paradox

The faster you go, the more the safety net matters. At hobby-code speed, a bug meant an evening of debugging. At LLM speed, a bug means 500 lines of code built on a broken assumption, generated before you noticed the crack.

But the same tool that creates the speed makes the safety net affordable. That's the whole insight. It's not "LLMs make me faster." It's "LLMs let me build the complete system" - features and tests, code and CI, the engine and the parachute. Practices I couldn't justify before are now just part of the workflow.

I write tests first, features second. I review every diff. I run CI on every commit. Not because I became more disciplined - because the cost of doing it right finally dropped below the cost of skipping it.

Comments

Leave a Comment

Used for confirmation only. Not displayed publicly.