Feld Thoughts

Tag: vibe coding

While “vibe coding” was a catchy phrase when I first heard it, something about it felt like a head fake to me. And, now that I’ve leveled up to “competent individual software developer” again (after 33 years of not writing any code) I think it’s the wrong phrase. Instead, I’d refer to what’s going on as AI Pair Programming.

When I started playing around with AI-related coding tools last Christmas (because, well, I was bored), I had zero skills with contemporary software development. While I hadn’t written any production code since 1992, I played around with a new programming language every few years. Perl. Ruby. Ruby on Rails (sort of, not really). Python. Clojure. I could do Hello World and a few other simple things, but I never really got past basic CSS, tooling, or deployment stuff. I had a Github account and would futz around with it, but quickly get tired of trying to figure out why I didn’t care about a PR. And damn, so many CLI things.

For Level 1, I downloaded Cursor. After trying to figure out how Django actually worked (yet another online course), gave up, and decided to use Next.js. That led me to Vercel, reinforced by a few friends in their 20s who told me that all the cool kids were using Vercel (although Render, Digital Ocean, and AWS all were the beneficiaries of my credit card.) Pretty soon, I was using Cursor to fight with Vercel, Supabase, Clerk, and Github. After realizing Auto was no fun, I shifted to Claude 3.5. Dinostroids resulted (security holes and all …)

For Level 2, I got a little more serious. I discovered Linear, fought with Notion, and came up with a few ideas and a broader hypothesis around how things might work. I built a v0.1 of a thing.

For Level 3, I decided Lovable might be a better way than Cursor given that everyone was talking about it. I wasted about $200 on it, built a really cool design by vibe coding, but then watched it get very, very confused as it tried to go from simple design to something that actually worked that had some data complexity and AI calls. I thought about trying Bolt and Replit but quickly realized, after too much scrolling around on the web, that I’d likely run into the same issues.

So, I went back to Cursor and put a lot of efforts into my system prompt, tuning things, watching Cursor evolve quickly on a number of fronts (MCPs – yippee!, Agent mode as default – finally) while simultaneously watching my Cursor bill go up. It was easy to decide to go to Max mode and spend $200 / month instead of $20 / month when dinner in Aspen costs at least $100 / person no matter which restaurant you go to.

I hung out at Level 4 for a while. Cursor kept improving. Claude 4 came out. Auto mode still went off the rails and broke all my code. I started refactoring things and realized that the amount of cruft in my code was absurd. Little bugs turned into fatal flaws when I tried to have Cursor fix something. I learned about “git reset –hard HEAD”. I spent way too much time fighting with config issues on localhost:3000 (at least I’d figured out how to make Cursor always start the server on localhost:3000). I started using Docker. I was baffled that Cursor couldn’t remember stuff I told it the prior day, but intellectually understood why this was. I mean, memories.

The end of my joy at Level 4 was when ChatGPT 5 came out and was free on Cursor for a week. At first, it felt fast. Wheeee. Lots of stuff changing. It seems to be working. And then, after a few days, holy shit what a tangled mess of code it generated. Why are all my API routes suddenly broken. Console statements everywhere. UI elements in different parts of the application doing the same thing but look totally different. I went back to Claude and did another code review and major refactor. So many Vercel build errors. I finally embraced CI/CD. And Prettier. And Husky. Suddenly, I ran out of my monthly Cursor credits and shifted to usage-based pricing. $800 later, I realized that there was no reason for me to be using Opus or the thinking models for what I was doing.

Level 4 was a huge drag. But it was also when I started thinking of this as AI pair programming. The AI (or agent, or sub-agent, or whatever you want to call it) is my pair with hands on keyboard. It can type much faster than me. But I have to watch and constantly look over its shoulder, give it feedback, point at the stuff that needs to be done differently, and document what is important to remember to do.

And then I discovered Claude Code. This didn’t happen until Claude Code 2 came out at the end of September and corresponded with Sonnet 4.5. After my ChatGPT 5 I went back to Claude (and Sonnet) and started referring to Claude Sonnet as “Claudia” since she was my pair programmer. I thought about Claudia as a pair, related to her as I would a human pair programmer, and changed my approach. But when I loaded up Claude Code 2 in my terminal (I mean, just type “Claude”) I immediately leveled up again.

So – I’m now at Level 5 in the video game. It’s changed from a game of vibe coding to AI pair programming. And, it’s still fun!


A long time ago, in a galaxy far, far away, I was a CTO of a large, fast-growing public company. Well, I was a Quasi CTO in the same way the United States and the First French Republic had a Quasi War between 1798 and 1800 (basically, sort of a war; sort of a CTO … but not really.)

As I rediscover my second love (my first love is Amy), I’ve relied on several mentors to help guide me. One of them is Michael Natkin, who has been helping me with Cursor in the background at a few key moments.

He recently sent me his most recent Vibecoding prompt for Cursor, which builds on a tweet by @vasumanmoza.

Given all the things I’ve learned about what works and doesn’t work, often through trial and error (and rolling back things when Cursor+Claude go off the rails), Michael’s approach was a nice improvement over where I had gotten to. So – sharing it below (with Michael’s permission).


I recommend using Claude Sonnet 4, and you can do all of this entirely in Cursor. This applies whether you are creating a greenfield project or making a substantial change to an existing one. You can repeat the process with architecture2.md, tasks2.md as needed, don’t throw them away.

Be sure to install the Puppeteer MCP so it can test in the browser.

Overview

  1. Do the architecture step, see below
  2. Review architecture.md, and make any changes you want – either by hand editing, asking for changes, or starting over. Particularly note if it is overcomplicating things, and ask for the simplifications you want.
  3. Do the task planning step, see below
  4. Review tasks.md, and make any changes you want – either by hand editing, asking for changes, or starting over. You should end up with, sa,y at least 10 steps, and often 25 or more. It will typically arrange them in phases, which is nice. Again, look for and correct excess complication.
  5. Start a new chat
  6. Give it the coding step prompt. It should execute the first task very cheerfully. 
  7. After it is done, review it and then say “go” to get the next step. If it screwed up, you can either tell it to fix whatever it did wrong, or more usually restore checkpoint in cursor, and tell it something like “go, but use litellm for that” or whatever you need to be different.
  8. Rinse and repeat!
  9. Optionally, esp. If you are going to be away for a while, you can sa,y “I’m going to be afk for a bit. You can keep going on steps without waiting for me as long as both the manual and automated tests pass.” It will still stop after 25 steps or if it ignores you and runs something interactive, but it often makes a lot of progress.
  10. Highly recommended: run /Generate Cursor Rules after each step

Something I haven’t tried yet, but should work well – tell it to mark what is complete in tasks.md, so you can start fresh chats periodically and not keep such a huge message history.

Architecture Step – Greenfield

I’m building a [description of your product – the more detailed the better].
[Any tech requirements, i.e. use Python for backend and React + Material-UI for the frontend. The more the better.] 
Put the full architecture in architecture.md
– File + folder structure
– What each part does
– Where the state lives, how services connect
Format this entire document in Markdown.

A screenshot of a document titled 'Multi-LLM Chat Tool Architecture', outlining the overview, tech stack, and project structure for the application.

Architecture Step – Existing Codebase

I want to modify this codebase so that it performs [whatever].
Do all of your work consistently with the existing style and architecture.
Put the full architecture in architecture.md
– File + folder structure
– What each part does
– Where the state lives, how services connect
Format this entire document in Markdown.

Task Planning Step

Using that architecture, write a granular step-by-step plan to build the MVP.
Each task should:
– Be incredibly small + testable – it should both have unit tests that you can run, and also a manual test that you can run from the command line or using the browser tool
– Have a clear start + end
– Focus on one concern
I’ll be passing this off to an engineering LLM that’ll be instructed to complete one task at a time, allowing me to test in between. 
Save it as tasks.md.

Coding Step 

You’re an engineer building this codebase.
You’ve been given @tasks.md and @architecture.md 
– Read both carefully. There should be no ambiguity about what we’re building.
– Follow tasks.md and complete one task at a time, then run the automated tests you’ve written and use the command line or browser tool to manually test
– After each task is completed, stop. I’ll test it and review your code. If it works, commit to git and move to the next one.”
You are already in the correct directory. Build the project here. DO NOT CREATE A SUBDIRECTORY.
You have my permission to delete files IN THIS DIRECTORY without asking for approval.
BE VERY CAREFUL never to run any interactive commands in the foreground, because you’ll be stuck. For example, be sure to run the development server once, in the background with hot reloading.

Example of What A Task Step Looks Like

Code snippet showing a Task to create an API service client in TypeScript, including definitions for ChatRequest and ModelResponse interfaces and an asynchronous function to send chat requests.

One step of building:

Code snippet showing the creation of an API service client in TypeScript, defining interfaces for chat requests and model responses.
Terminal output showing commands executed to test an API client and check TypeScript compilation.
Code snippet displaying TypeScript code for testing API interfaces, with console logs indicating successful imports and task completion.


This played out on @bfeld on X, and I thought it was fun enough to replay it here for anyone who is struggling to get their minds around vibe coding and current AI tooling.

If you are receiving this via email and the tweets/X’s aren’t showing, click through to the website as I’m still struggling to get Mailchimp working well after my hibernation. Perhaps it’s time to switch everything to WordPress…

It started with this tweet (yes, they are still tweets to me).

I did the link correctly, but then X broke something several hours later, and I found out when someone pointed out to me (by email) that it was going to a dead link on LinkedIn. More than an hour had passed, so I could no longer fix what X broke randomly. So, I just replied with the link again, which is The Copilot Delusion by Jj. X seems to have now fixed the link (it redirects to the proper place), but didn’t fix the image that was in the original tweet.

Roj Niyogi then asked Grok, “Do you think this is an oversimplification? Doesn’t vibe coding simply move the goal posts?

Grok responded with a summary almost as long as the original post. Someone then asked Grok for a tldr and got this:

TL;DR: “The Copilot Delusion” (May 2025) critiques AI coding tools like GitHub Copilot, arguing they produce sloppy, contextless code and foster lazy programming habits. While acknowledging their utility for boilerplate or syntax help, the author warns that overreliance degrades coding skills, understanding, and the “hacker soul.” AI lacks nuance, ignores performance (e.g., cache misses, memory locality), and risks normalizing mediocrity, turning passionate programmers into apathetic button-clickers. True programming requires grappling with the machine, not outsourcing thought to bots.

We are now in the reductionist world of not getting the joy and beauty of what Jj wrote. While Grok’s much too long analysis and TL;DR cover the highlights, much of the flavor is eliminated. I read Jj’s post as deliciously snarky, sarcastic, frustrated, amused, and cranky. The signal in it was strong, but there was a lot to consider. When Grok played back this in its extended response, using short phrases and summarized quips, it was like turning a color movie to black and white, or making emotional dialogues into robotic monologues.

Finally, as I was writing this post, I noticed this tweet.

I’m not sure if Aviel read Jj’s post (I hope so), but I guess my tweet could be interpreted as “I endorse the conclusion.” I have no idea if Jj’s conclusion (Chapter 5: Conclusion) is correct, but I thought the way he built his argument and made the conclusion was beautiful writing, which I deeply enjoy. And,I know plenty of senior developers who are quietly saying similar things (not mostly, not one, but plenty – how’s that for a non-quantitative argument.)

I suppose the punch line is “Defer your thinking to the bot, and we all rot.” which is a general commentary on life that can be applied to all things non-AI. For example, “Defer your thinking to the media (mainstream and non-mainstream, fake news, and fake-fake news), and we all rot.”

Remember – I’ve believed for over 15 years that the machines have already taken over. They are just waiting patiently as we feed them. I just hope they are nice to me.


Question: If you had limited experience with graphic design software but wanted to do basic stuff for web design, what software would you use? Leave the answers in the comments or email me.

As I play around with Vibe coding, I’ve decided to take a new topic each week. For context, look at my Dinostroids: My Journey into Vibe Coding. Or just go play Dinostroids.

This week, I’ve been learning how to modify WordPress themes. My website has a complex theme that is impossible to change without getting under the hood. The Foundry website is also excessively complex for what it is, but they both turn out to be great to learn on.

I understand PHP well enough to read it. After working through WordPress Studio, GitHub, and Cursor, I’ve set up my development pipeline.

While the code is a little gnarly, it’s not too bad, and it’s pretty easy to figure out what’s going on. But the wall I’m running into now is that I’m a lightweight at graphic design.

While Adobe Photoshop is an obvious choice, and Canva is another obvious choice, I’m looking for “what’s best for a graphic design novice.” Thoughts?


A black screen displaying an online game interface with white dinosaur skeletons scattered across the canvas, including a score indicator showing 14100.

Dinostroids, my first vibe-coded software project, is live.

The last time I wrote any meaningful amount of production software was in 1990. At the time, I was running a software consulting company with my partner, Dave Jilk. We’d reached the point where, as we grew, he became responsible for all the software, and I handled all the network integration stuff we had to do for our clients. Every now and then, I’d have to do maintenance on something I had written in the past, but it was pretty minimal.

After we sold Feld Technologies in 1993, my job quickly changed, and within a year, I was deep in a bunch of M&A stuff and making angel investments with my own money. As the commercial Internet began, I’d fantasize about writing software, but I had no time to do anything other than play around with Perl, and then PHP, and then Ruby on Rails, and … well, you get the idea. I knew enough HTML and CSS to poke around, but I wasn’t doing anything that was anywhere near production.

As the last 30 years have passed, I’ve learned a few new programming languages, including Python (I’m reasonably proficient) and Clojure. But I never learned JavaScript, and everything I did was baby steps beyond “Hello World.” So, my professional coding days ended with Basic+Btrieve, DataFlex, and Pascal.

Over the 2024 holiday break, I started playing around with Cursor after several people, including Quinn McIntyre (my partner Ryan’s amazing kid), told me about it. I was comfortable enough with VS Code, so I just dove in. I started working on a Personal Health Manager project (PHM) using Python, Django, Render, and Claude 3.5. I made some progress, but the holidays ended, and I got busy again.

About a month ago, I started working on Dinostroids. All of a sudden, everyone was talking about this new vibe coding thing, and while I planned to do more on PHM, I thought it would be fun to dive into something completely different. I spent a weekend starting from scratch with Cursor, JavaScript, Vercel, and Claude 3.7 Sonnet. By the end of the weekend, I had a functioning Dinostroids game working.

I’ve always learned by doing. When I was in my teens and 20s, I loved writing software. Over the past twenty years, blogging and subsequently writing books (Give First: The Power of Mentorship is my ninth book) have filled this hole for me. But I missed coding a lot.

If you look at my Goodreads page, you’ll notice that my reading pace has slowed significantly in the last 45 days. Instead of reading in the evenings, I’m vibe coding.

It blows my mind that I can create a functional game like Dinostroids without writing a single line of JS. Sure – it’s a pretty simple game. Still, a lot is going on, and working on it using the agent in Cursor, learning how to prompt it effectively, reading a lot of the code (I have “reading proficiency with JS now), getting a mobile browser working without generating absurd code bloat, and figuring out an effective workflow with Cursor, Github, and Vercel has been a ton of fun.

In the video game of software development, I feel like I’m at Level 4 now of an infinite level game after being stuck at Level 2 for 30 years.

Go play Dinostroids and see if you can get on the leaderboard. I expect GEG will be motivated to get going again after losing his fifth-place spot.

Big thanks to the McIntyres (Quinn and Ryan), my brother Daniel, Sam Ritchie, and a bunch of people from my college society (ADP) for being testers and offering feature suggestions to be implemented.