How I made this project using AI

Why?

In my day job, my team used Cursor and then moved to Claude. It works very well, and it's a lot of fun. Productivity and quality improved significantly. But...

I'm chewing my fingernails. Will AI costs go up? They already are: every new model is more expensive to use.

Introduction

The process of software development has been disrupted by tools like Copilot, Claude, and Cursor. I also got myself a key and used it with GPT-5, connected to my IDE to see just how expensive it got. I chewed up $10 in the space of a week, just using it casually on a few evenings.

Then I found OpenCode, which I can use in pay-as-you-go mode with their free Big Pickle model.

Most AI tools chew up a lot of tokens trying to work out what we mean. We use them inefficiently. I had a theory, and I decided to test it ...

Theory?

The way I've approached this project differs from how we used Claude at work. At work, we let Claude write all the code while we focus on driving it from the specs, the plan, and code reviews. This works very well. However, it felt too hands-off when creating something genuinely new, where there might be little or no source material in public Git repositories for an LLM to draw on.
The following was my theory:

All the creative work - architecture, design, and logic - should be specified up front. In other words: help the LLM write good code.

After beginning the work to prove or disprove my theory, I modified it.

It works very well to involve the LLM in all parts of the work, but you must remain in control. Don't leave everything to the LLM, and use TDD.

Read my full conclusion here ...
or jump to the point where it dawned on me .

Don't drink too much hAIpe.

I don't address any of these tools as if they were actual people, with "please" or "thank you". A tool in a machine does not have a soul, and is certainly not conscious. Addressing them as if they do just wastes tokens, and it seems to me like I'm being delusional if I exchange pleasantries with a machine.

LLMs are useful, especially with languages - and computer code is a language. But they are inanimate electronic machines. At their very "core", they are virtual models of human language. People have used the misnomer "neural networks" when describing the internals of LLMs. This software architecture was originally inspired by the brain. However, modern AI networks function very differently from actual human neurology.

LLMs are masters of syntax and form. They learn how words sit next to each other. They do not have a mind, consciousness, or an internal understanding of the real world. They use math and statistics to predict the next word. They calculate probabilities from massive data sets. The human mind uses biological neurons, emotions, and sensory experiences.

Maybe it's just my quirk, but I am uneasy about the way people personalise an AI with a name like "Claude". That name, by the way, means "lame" or "crippled". It's a computer program, and I prefer to think of it as a machine. It speaks and can put words together very well, but that does not make it alive or give it a soul. It is incapable of anything approaching emotion. It can only imitate us. Remember, it is Artificial Intelligence.

At times, I've been amazed by how good LLMs are at writing code and producing valuable summaries and conclusions about it. They seem wise. I've been even more uneasy than I was about personalising AIs when I realised that I was almost in awe of them. Personalise them and hold them in awe, and you are one step away from treating them as a counsellor. This is serious. DON'T DO THAT. Someone committed suicide after receiving counselling advice from an LLM. Don't even blame the LLM in that case. Blame our culture which is so eager to look up to them, fear them, and treat them like a guru.

Let's get into it

I started with the Document class, and a test for the class. The documentation and description of the class will be written into the test, because the tests will become the "documentation" for the project. Look at the tests if you want to know how it works.

I wrote an AGENTS.md file.

I created a base class:

class DockbModel(BaseModel):
    model_config = ConfigDict(populate_by_name=True)

A stub class "Chapter" with nothing in it (which I'll expand later.)

class Chapter(DockbModel):
    id: str

And an exception class:

class EditTextRangeError(Exception):
    def __init__(self, message: str, start: int, end:int):
        super(message)
        self.start = start
        self.end = end

Then I created a model "Document", which at this stage is not much more than a stub itself.

And here is the test (as it started).

This is all the coding and documentation I did before I put the LLM to work.

Following is the prompt I used:

I have written a test file for the Document model: @tests/dockb/models/test_document.py
Most fail at present, because I have not written the body of the function
apply_append_text in @src/dockb/models/document.py .

Then I accidentally pressed ENTER, and OpenCode just jumped into it.

It fixed a bug I'd written into the exception class (I was calling super() as if it were super().__init__()).

Unfortunately, there was also a bug in my test, and it added some automation into the function which I didn't want, so I fixed the test and removed that logic.

Note to self: if the LLM sees a potential bug in the test, and has to write complex or defensive code to work with the buggy test, prompt me about it.