Last week Anthropic released a tool called Claude Code (CC), which at first glance seemed pretty powerful. So I tried it for a bit, and it’s clearly not there yet when working on larger projects. At least for me.

Jumping in blindly

I have been working on a little game for a while, and naively I figured CC would be great for iterating on it quickly. After some prompts, and about $5, the codebase turned into a pile of rubble.

Code generated by CC seemed very verbose to me. So much so that I got the feeling it wasn’t implementing what I asked it to generate, but that it was explaining to me how I could implement it in some ideal fantasy world. Whenever I develop something, I know I’m producing soon-to-be-legacy code, so I try to minimize the amount of work done to fit the features I want.

I could still launch the game by the way, but everything that was added by CC felt entirely disconnected from the rest of the codebase. I discarded it, and quickly discovered I should have executed /init to make it a bit more aware of the project.

Rookie mistake on my part, I guess. It would have been nice to show some examples here. Oh well, hindsight.

Reassessing my approach

One of my friends is also pretty smitten with AI tech, so it didn’t take long until we discussed CC over lunch. We talked about my findings with CC. One of the things I mentioned was that it felt to me like CC was generating tutorials to me, the code being too verbose for a 15k-line project. I mentioned that the generated code contained too much context, any developer would split things up in multiple files, maybe only to match the rest of the codebase that was written earlier.

Mentioning the tutorials, my friend told me that could make sense. The models could be trained on tutorial data, and it could be interesting to write a blog on that topic. There was a slight issue though.

I didn’t have a blog, yet

Inspired by the chat I had earlier that day, I figured I should get started on a blog, which I didn’t have yet.

After some browsing I discovered Hugo to be a neat framework for building this blog, which I would develop with CC. I use CC as lazily as possible, accepting pretty much any change. I know it’s possible to intervene, but I didn’t.

In an empty directory, I ran git init, followed by claude. Then I started prompting.

Prompt: I want you to create a blog for me that I can self-host in Docker Compose. I found Hugo to be a fitting framework for this.

This generated the following files:

Makefile
README.md
blog/
blog/config.toml
blog/content/
blog/content/about/
blog/content/about/index.md
blog/content/posts/
blog/content/posts/first-post.md
blog/data/
blog/layouts/
blog/static/
blog/static/images/
blog/themes/
docker-compose.prod.yml
docker-compose.yml

Not too bad at first glance. But when I looked into the project I found stuff like this:

❯ cat Makefile
.PHONY: dev build prod clean

# Development server
dev:
    docker-compose up -d

# Install Ananke theme
install-theme:
    docker-compose exec hugo sh -c "cd /src && hugo mod get github.com/theNewDynamic/gohugo-theme-ananke"

# Create a new post
new-post:
    docker-compose exec hugo sh -c "cd /src && hugo new posts/$(title).md"

# Build static files
build:
    docker-compose exec hugo sh -c "cd /src && hugo --minify"

# Run production environment
prod:
    docker-compose -f docker-compose.prod.yml up -d

# Stop containers
stop:
    docker-compose down

# Stop production containers
stop-prod:
    docker-compose -f docker-compose.prod.yml down

# Clean generated files
clean:
    rm -rf blog/public
    rm -rf blog/resources

It had so many extra options in there already. Same in README.md. For some reason it already required a theme. However, I told myself that it’s not a big deal. I was confident I could fix that with CC.

I don’t like depending on a third-party Docker image (Hugo doesn’t offer their own as far as I know), so I’d want to replace that with some logic to build my own image. It would need a .gitlab-ci.yml as well. I fired CC up again, then ran /init as there was something to work with for CC.

Prompt: I don’t need a theme just yet. I also want to have my own Dockerfile, so I can generate a new image when I want. Also, please add a .gitlab-ci.yml to do that automatically.

This removed the theme, adds a Dockerfile, .gitlab-ci.yml, and expands the Makefile. That looks like what I requested, but I had to verify. When I checked Makefile I saw it now had docker-build and docker-run which both did not use docker-compose, quite strange. This is where I realized that CC hadn’t updated any of the docker-compose*.yml files either.

Hopefully the Dockerfile is better:

FROM klakegg/hugo:0.101.0-ext-alpine as builder

WORKDIR /src
COPY ./blog /src

RUN hugo --minify

FROM nginx:alpine

COPY --from=builder /src/public /usr/share/nginx/html

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

Well… that’s still the same image, but it just added the results to NGINX.

The .gitlab-ci.yml was okay, but definitely not great. It wanted to use Docker-in-Docker (dind), but I prefer kaniko right now. I figured it would be weird to expect CC to guess that based off my prompt.

At this stage I already looked around the Hugo docs for information on how to run it to get it sorted like I actually wanted it. Quite difficult to get that right in a quick prompt. I had more features I want to add to the project, but I didn’t want to overwhelm CC either. So, I kept it to a couple of small tasks again.

Prompt: I don’t want to use that Hugo image, nor do I want to use NGINX. Let’s make sure to fetch the latest version of Hugo in the Dockerfile. Also, I want to use kaniko instead of dind.

This removed the dependency on a third-party image and tried to build everything in the repository onto an alpine:latest image, then copy the public files to a scratch image. However, it didn’t copy an executable that would be able to serve the files over HTTP.

I iterated over this for a while, copying the Hugo CLI commands’ help into CC, explaining I want to load documents separately from building the image (so the hugo executable had to be running with --watch or --poll).

Overall, this part was quite tough for CC. Eventually I got it to a point where I could use a Docker volume to update the blog without needing to rebuild the image. But it took significantly more time than it would have if I had made this myself. Plus, CC snacked on a lot of Anthropic credits, money which I could have used for snacks myself.

But! There is a part where it did work out well for me.

I don’t enjoy front-end work

I work mostly in the area of DevOps and Software Engineering, so occasionally I have to create some front-end stuff. This is where CC shined for me. It was good enough to interpret my prompts for formatting RSS properly, give the blog a general simple and minimalist style. I barely had to correct CC to get what I wanted (or at least close enough, did I mention I don’t enjoy front-end work?), even for a mobile view.

/Ramble

I rambled enough on what I went through. Overall, my experience with Claude Code was a mixed bag. For targeted front-end tasks where I lack expertise and interest, it proved to be a valuable assistant that saved me time and frustration.

However, for architecture decisions, Docker configuration, and working with existing codebases, CC still has significant limitations in my opinion. The tool seems best suited for standalone components, simple scripts, or helping developers work in unfamiliar domains - not for complex system design or maintaining large projects.

For now, I’ll keep using CC for the stuff I feel it’s good at for me, like the frontend stuff. It may get better after a while, after a few iterations from Anthropic. CC is a neat assistant but definitely not a replacement for actually knowing what you’re doing. At least I got a blog out of it!

Maybe I’ll write something on the relationship between tutorials and AI-generated code in the future. I still think there is something worth exploring between how these models generate verbose, tutorial-like code and what they’re trained on. Until then, I’ll be tweaking my blog and trying not to blow more credits on CC-written Docker configs