This Old, Curmudgeonly Software Engineer Finally Embraces Agentic/Vibe Coding

holmok
This Old, Curmudgeonly Software Engineer Finally Embraces Agentic/Vibe Coding

I have to be honest here. I am old. As one gets older, there is a tendency to become a curmudgeon. As a software engineer, this has been both a superpower (avoiding flash-in-the-pan fads) and a hindrance (being late to the party on things that are actually “the next great thing”).

Let’s face it, it’s a bit early to call the current state of AI and LLMs “the next great thing” in its current state, partly because that state seems to be changing at such a rapid pace: every week, a new model, a new app, a significant update to existing tools.

All the bits of my brain have been telling me to wait for all this to settle, then pick the obvious winner and grab hold. But, to be honest, FOMO is also screaming at me. I decided to watch some videos and research the available tools. Oh boy. It’s a mess.

Everyone has opinions, and content is out of date in less than a month. Folks who have been involved in this since the beginning often discuss things in a language that is almost foreign to me. Now I know how non-technical folks feel when I try to explain the difference between statically typed languages and loosely typed languages. Did I start too late?

The answer is, “nope.” I need to do what I do whenever I want to learn a new language, tech stack, or framework.

  1. Research it.
  2. Get frustrated at all the available content (whether it is lacking or missing, out of date, or just bad).
  3. Throw myself into a project that will force me to use it so I can learn by doing.

Starting A Project and Picking Tools

I have a website. This is the one where you are reading this. Well, this is a fancy new version of it that I technically “vibe-coded.”

With input from the folks I work with and based on some stuff I read, I chose Claude Code. Without getting too deep into the nitty-gritty, here are the bullet points of why I chose it.

  • It does not live in the IDE. I have used CoPilot, and it’s fine. I treat it like a better autocomplete, and I never use the chat. I tried Cursor about three times and stopped using it after about an hour. It was annoying always, and mostly wrong.
  • The models are pretty good. Anthropic is focusing on building models centered on coding rather than general-purpose ones, such as those developed by OpenAI.
  • There are the fewest negative opinions about it. Most of the gripes are about convenience stuff, which I don’t care that much about.
  • The Claude Max subscription looked interesting. All the bandwidth limitations and token and context-related issues were confusing and unnerving. Several folks said that with the big ole subscription on Cluade Max, it was almost impossible to “max out.”

So I threw my credit card at it (luckily, my work helped out a bit so that I could use it at work too). I installed all the necessary components and began a complete rewrite of my website, green fields!

My Starting Strategy

There have been too many videos and articles written about “how to vibe code.” I decided not to follow a prescribed path to set everything up and interact with the coding agent. I selected some high-level topics and developed my own personal strategy for accomplishing this task.

  1. Start with nothing. In my early attempts at agentic/vibe coding, it was hit or miss in actually understanding the context of a large project. I would have to spend the same amount of time explaining what I wanted it to do as it would have taken to write it myself. A clean palette would help it understand the context, because it is building it.
  2. Start vague and add details as you iterate. I decided to act like a product manager I would like to work for: technically proficient, but not prescriptive, and a problem solver.
  3. Have it fix the mistakes. This was a hard one. Even with junior engineers, I tend to say things like, “Never mind, just let me do it.” Which is not good as a mentor, nor is it good with an LLM. They gotta learn.
  4. Shut up and trust it. I always auto-accept. If things get out of hand, there is always the option to roll back in version control. It will go down some dumb paths, and sometimes it’s good to clear history and try again.

So How Did It Go?

So I started my adventure with the following prompt and an empty directory:

I want to create a personal website featuring a blog with articles covering various topics, including technology, coding, photography, and other miscellaneous subjects. It should have an about page, support adding multiple photo galleries, and a section to host multiple web-based utilities for software engineers. The blog will be managed by a directory of Markdown files with front matter, and directories for galleries that contain Markdown files for gallery descriptions and YAML files to organize the photos within the galleries. Use Next.js and TypeScript.

This is a little prescriptive. However, I wanted to build it with tools I was familiar with and knew there was good content for the LLM to use, and I didn’t want to have to deal with databases just yet.

After a while, it actually had a functioning, albeit clunky, website that I could run locally. I gave it some theming advice and preferences. Gave it some pointers on usability, and in a few hours, I had the beginnings of a nice little site that I liked.

After describing some utilities that I had on my original site, it made versions of them that were even slightly better. I had to copy some content to seed the text generator and the random excuse utility. Building out these utilities was, dare I say, fun.

Getting the galleries and blog to work like I wanted them to was a different story. There were a few times it made assumptions that were wildly wrong, and asking it to correct the issues led me to revert code and clear the conversation context. However, there were times when it came up with clever solutions that impressed me.

Overall, I’d say I accomplished a great deal more in significantly less time, with a result that is better than I expected. However, this project contains a substantial amount of code that I have not reviewed. But do I? If it works, it works. If there are bugs, and the coding agent can’t fix them, I can. Also, this is not a bank website.

Things That Were Cool

I was pleasantly surprised by a few things it managed to pull off.

  • It understood my aesthetic, and remembered it. Initially, I took the care to explain how I wanted things to look, and they understood and were able to apply that to new tasks, even when not explicitly told.
  • Vague prompts got more done than expected. Here’s an example. Across the different pages, blogs, galleries, and utilities, there were inconsistencies in layout, navigation, and functionality. I prompted it to fix it by something like: Hey, the titles on the pages, the bread crumbs, and call to actions on pages across the site are a little random. Can you make them more consistent? It built out a task list, executed it, and performed a significant refactor, covering 95% of the issues.
  • It did the stuff I hated to do, and it did it better than I expected. So the coding agent stubbed out the gallery YAML files, and I was planning to write those myself. After I did two of them, I thought, ‘Ew.’ So I asked Claude to do it based on the actual photos, figuring I’d have to update stuff like location and some of the tags. But it mostly knocked it out of the park. It was even able to recognize locations pretty well, especially if there were landmarks like Haystack Rock on Cannon Beach in Oregon.

Stuff That Was Less than Good

It was not perfect, and it burped and vomited a few times. Here are a few examples:

  • It gets stuck in circles. There were a few times when it made some “bad choices.” It noticed them, went to fix them, but in doing so, changed the functionality. It saw this and fixed it, and when it did, it encountered the same error it had prior. It then noticed this and... You get the idea.
  • Abstract things can confuse it. Interestingly, there were a few times that the coding agent did not understand something, and rather than say, “Sorry, I don’t get it,” it mustered some false confidence and barreled through. A humorous example of this is a photo that I initially thought was an aerial view of rice fields, but was an abstract image of trees at night with Christmas lights. After I manually corrected the metadata, the changes were still ignored, and the gallery’s description still included a description of agricultural aerial views.
  • Assumptions it pulls from context can be outdated. After resolving the whole constituency issue that I found and had the coding agent fix, the issue resurfaced after adding a new page. I pointed it out, and it replied with a phrase you will have to get used to: “Oh yes, you are correct. Let me fix that.”

Conclusion

Overall, I enjoyed the experience and will continue to use Claude Code to build and manage this site. I see the value in using a coding agent in the right situation for the right task. Engineering is still the place for the right tool for the right job. It is a new abstraction in writing code. This changes over time. Let’s look back.

  • Up until and through the 60-70s Almost everything was assembler, and if you wrote any code, it included the operating system and drivers.
  • Up until and through the 90s You relied on existing OS and Drivers that exist, but you may need to tweak them, but you mostly wrote app code from scratch.
  • Up until the 10s Frameworks were the basis for most apps (web/mobile/etc) and very few people write app code from scratch.
  • Now You can launch POC/MVP of new applications by spending some time with a coding agent.

We still need people to write operating systems and drivers. There are still people who are creating new frameworks to build applications. I don’t think that will be replaced, but engineers of tomorrow may not know how to code. Still, they will be experts at prompting a coding agent, just as there are web devs today that don’t know the difference between a threaded and event-loop based web server, and framework engineers that don’t understand why poking a value into a device register may trigger an interrupt.

Just a new layer of abstraction that is useful, and sometimes even fun.