cd /news/developer-tools/kill-the-ceremony-intent-driven-deve… · home topics developer-tools article
[ARTICLE · art-56454] src=pub.towardsai.net ↗ pub= topic=developer-tools verified=true sentiment=· neutral

Kill the Ceremony: Intent-Driven Development and the Minimum Viable Spec

A software development team leader proposes intent-driven development (IDSD) as a middle ground between rigid spec-driven development and chaotic vibe-coding, arguing that AI can handle implementation details while humans focus on defining outcomes. The approach aims to reduce ceremony and increase flexibility for non-safety-critical systems like marketing sites and internal tools.

read17 min views1 publishedJul 12, 2026

The UX was insightful. The design was beautiful. The functionality was spot-on. The testing was thorough. It was exactly what they had been asking for. And then the client said, “Huh. Now that I see this live, I don’t like it.”

My team runs on spec-driven development (SDD), and it has made us genuinely faster at building with AI. But a change like that can mean days of spec archaeology before anyone touches a single file. It feels like trying to rewire a breadboard mid-circuit: technically possible, but one wrong move and you release the magic smoke of doom.

There is too much raw ceremony in all of this. I am interested in the absolute minimum process required to produce the maximum results. As French pilot and poet Antoine de Saint‑Exupéry said:

“Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.”

I’ve been tinkering with how much we can remove from the spec-driven development process. What’s the minimum amount of spec to produce the maximum value production code?

This is for engineering leads, technical product people, and developers using AI to build real software, especially teams that find traditional spec-driven development too rigid and pure vibe-coding too chaotic. It is not for safety-critical systems where every implementation detail must be nailed down up front. If you need to catch a rocket with giant metal chopsticks, this is not for you (but I’m glad you’re reading my articles).

If you hear “intent-driven” and think “so… we just wing it?” no, dear reader, the whole point is to be less vague while also being less brittle. A surprisingly narrow target, which is usually where the useful stuff lives. This is like targeting a two-meter-wide thermal exhaust port on a moon-sized battle station.

SDD is very effective at turning an easily-distracted AI into a rigid coding companion. For a load-bearing system, that’s like upgrading from a contractor down the street to a structural engineer. But for something like a marketing site, an internal tool, or an exploratory product feature SDD can also feel exhausting. SDD is like hiring that same structural engineer to hang a picture frame that the client is going to want to move anyway.

But vibe-coding sits at the other extreme. Give the model a rough prompt, let it improvise, and hope the jazz solo resolves somewhere useful. Sometimes it does. More often you end up with code that works until it doesn’t, built on decisions nobody made consciously and nobody can explain on a Friday afternoon when something breaks in production.

So on the one hand we have a spec so heavy it collapses under its own weight the moment reality changes. On the other hand we have a process so light it was never really a process at all. SDD gives you a sacred text. Vibe-coding gives you a mood. Neither one scales gracefully when a client walks in and says “huh.”

My vision for intent-driven software development (IDSD) is to carve out a new space between those two extremes. Change is part of life, so I need to enable far more flexibility without sacrificing quality. You might think that makes me a modern-day Don Quixote, tilting at process windmills. But I am proceeding anyway, because I like windmills and I have a dream, an impossible dream…

Intent-driven software development chisels away the spec until only the parts humans actually need to own are left.

The central idea is simple:

Humans should definewhat matters. The system should help determinehow to implement it.

That sounds obvious, but it is a meaningful shift in practice and it will hurt your brain if you’re accustomed to SDD.

When I was in college, my friends and I ran a tiny humor website based on Flash animation. I was enamored by keyframe animation. You pick the important points of motion and let Flash fill in the frames between. Intent-driven software development is like picking the keyframes and letting the AI handle everything between.

Intent: the outcome wanted, under what constraints, and what failure must be avoided.

Expectations: what counts as done, what will be validated, and what the finished result must demonstrate.

Context: the technical and organizational surroundings the work must fit into.

Everything inside those boundaries.

That is the heart of IDSD. AI should not decide what the business wanted. It should help deliver what the business wanted once that is made clear.

There’s an old engineering joke:

Any idiot can build a bridge that stands, but it takes anengineerto build a bridge thatbarelystands.

So let’s engineer a bridge. In fact, let’s build the Golden Gate Bridge in San Francisco.

Spec-driven development would jump into the materials used in the steel cables, the kind of concrete needed, the anchoring mechanism, resonance testing, and a litany of engineering details. That stuff needs to happen, but it’s an exhausting place to start and it’s optimistic about your ability to predict the future.

Intent-driven development starts with the desired outcome and the constraints instead.

Intent

Enable cars to cross between San Francisco to Marin County in the shortest path possible.

Expectations

Context

The geography of the area requires crossing the Golden Gate strait of water while considering the possibility of earthquakes and intense storms.

Constraints

Failure Conditions

Now here is the fun part: I never said it had to be a bridge.

A giant transparent tunnel could, in theory, meet the same goals. It would also be more expensive, harder to build safely, and probably become a monument to my own bad ideas. But that’s the point. We didn’t have to say “it’s a bridge,” and we definitely didn’t need to lock it into “a suspension bridge built from this exact kind of steel” before the system had even reasoned about the problem.

We let the AI system contemplate multiple solutions, fill in the details, and test against the IDSD document.

And remember my whole point that change is part of life? What if the mayor suddenly swoops in and says the start and end points have changed a bit? In a spec-heavy world, all that engineering detail has to be redone and re-examined. With IDSD, we update the intent and let the AI fill in the work against the new intent. Cue the trumpet-playing angels if we can make that actually work at scale.

OK enough about imaginary bridges and wildly unsafe aquarium-tunnel infrastructure. Let’s make something with this!

I wanted AI to take a base image-generation prompt plus some creative direction phrases and automatically generate lots of variations.

The inspiration for this is Leonardo AI’s Flow State. You can scroll through to get new remixes of your idea, and you can click one to be the new reference point.

This works great, but I want it to be able to connect to my local AI image generation models (see my local AI setup and my local model showdown article), and that gives us some context and some constraints. For example, I can only generate one image at a time instead of a whole grid like Leonardo’s interface. That’s fine. It’s just a constraint, not a tragedy.

As I have mentioned in my other articles, I don’t have a ton of patience for twiddling my thumbs while AI does its thing. Since image resolution is the main driver of generation time, I can use a constraint to help out future impatient Cody, a man who is somehow always frustrated that bigger images take longer. But I hear future Cody is very suave and debonair.

I also hate cluttering up my file system. So I want these images to just live in the browser unless I specifically save them.

The full intent file

View on GitHub

### IntentEnable a user to rapidly explore an evolving space of AI-generated images in a local app, continuously surfacing new visual variations while allowing the user to redirect exploration toward promising results with minimal friction.### ContextThis app is a local AI image exploration tool that generates images from a current base prompt combined with a set of remix phrases. The user reviews generated images inside the app, can inspect images in larger detail, and can explicitly download images they want to keep. The app interacts with AI providers through an OpenAI API-compatible interface and uses separate models for prompt generation and image generation.### Expectations- The user can start and  continuous image exploration at will.- The user can review a stream of newly generated image variations without manually re-entering prompts between generations.- The user can promote a generated image they like into the next direction of exploration.- The app supports a fast enough generation cadence for active creative exploration rather than batch waiting.- The user can inspect any generated image in larger detail without losing control of the exploration session.- The user can understand how a displayed image was generated by viewing its associated generation metadata.- The user can explore freely without unintended persistence of images they have not chosen to keep.- The user can choose models and generation settings to balance speed and output quality for the current session.- The user sees clear variation between generated images based on their remix phrases.- The user can choose a creativity level that controls how far generated prompts are allowed to diverge from the base prompt and remix phrases, independent of any other built-in randomness in generation.### Constraints- New generations must be derived from the current base prompt and the configured remix phrase list.- The app must offer a small, fixed set of selectable creativity levels (e.g. mild, normal, wild) governing how far a new prompt may diverge from the base prompt and remix phrases.- Raising the creativity level must produce a consistent, noticeable increase in how far new prompts diverge from the base prompt, not merely a different random outcome at the same divergence.- The guidance that shapes each creativity level's behavior must be adjustable without modifying application code.- The app must allow separate selection of the text model and the image model.- The app must support an OpenAI API-compatible provider endpoint.- The provider base URL must be overrideable through app environment configuration.- The app must present a selectable list of available models for the configured provider.- Selecting a generated image must set that image's prompt as the new base prompt for subsequent generations.- The app must allow the user to set the initial seed.- The app must allow the user to set the default image size.- The default image size must be 512×512.- With default settings and a functioning configured provider, the interval between consecutive successfully displayed images during continuous generation must ordinarily be 10 seconds or less.- Each displayed image must retain its associated generation metadata, including model, size, seed, creativity level, and prompt.- Generated images must be displayed in the app without being saved to device storage or temporary files unless the user explicitly clicks download.- Opening the image lightbox while the continuous generation loop is active must  the generation loop.- Downloaded images must preserve or be accompanied by their generation metadata.- Unless the user overrides the seed, the seed should be different between each generation.### Failure Conditions- The user starts generation and no new images are produced until the user s or an explicit error is shown.- The user s generation and new image generations continue to start afterward.- The user selects a generated image and subsequent generations do not use that image's prompt as the new base prompt.- The app does not allow separate selection of text and image models.- The app does not support configuration of an OpenAI API-compatible provider endpoint.- The app does not present a selectable list of available models for the configured provider.- The app does not allow the user to set the initial seed.- The app does not allow the user to set the default image size.- The default image size is not 512×512 when no user override has been provided.- With default settings and a functioning configured provider, the interval between consecutive successfully displayed images exceeds 10 seconds.- A displayed image is missing any required generation metadata field: model, size, seed, creativity level, or prompt.- A generated image is written to device storage or temporary files before the user clicks download.- The user opens the lightbox while generation is active and the generation loop does not .- The user cannot access the associated generation metadata for a displayed image.- A downloaded image is not accompanied by the metadata needed to reproduce or inspect its generation settings.- Successive image prompts vary by only a few words or word order.- The app does not offer a selectable creativity level, or offers fewer than three distinct levels.- Raising the creativity level produces no consistent, noticeable difference in how far new prompts diverge from the base prompt.- Adjusting how a creativity level behaves requires changing application code rather than a separate, editable configuration.

That intent file is technically enough to make an app, but if you have a UX/UI vision in mind you’ll get better results by just mocking up a wireframe and/or feeding it a DESIGN.md file. I did both for this project.

For the DESIGN.md file, I used extract-design-system to help me replicate the design of my personal website www.codysandahl.com.

For the wireframe, I used Excalidraw inside of Obsidian to make this simple representation of the interface.

image-app-wireframe.png

My main recommendation here: if the interface matters, show the AI with a mock-up. Do not make the model reverse-engineer your taste from your adjectives. That way lies “sleek modern dashboard” slop. And dragons. Sleek, modern AI slop dragons.

View the full project athttps://github.com/codysandahl/local-ai-image-explorer

If this is your first article with me, brace yourself. My sense of humor is strange. You have been warned.

I know there are readers out there who have always wanted to make scenes of a lighthouse at dusk, remixed with spaceship battles, World War 2, Teletubbies, snakes on a plane, and Titanic. Huge audience for that kinda stuff. Well thirst no more, because I got you!

This achieved my goals, and I didn’t have to grind out all the technical details. I just had to specify the intent, expectations, context, and failure modes.

Things I didn’t specify:

That stuff would’ve taken me hours to write out and validate SDD-style. With IDSD, I just didn’t even do them. Huzzah for great results with less of my time! That charming future Cody is very pleased to have work deleted from his schedule.

The most important result here: the agent had enough structure to make good decisions without me pre-solving the implementation. That’s the windmill I’m tilting at.

Since change is part of life, I’m not really trying to one-shot things. So a few tweaks along the way are fine for me. A key point here: if you need to fix something and you want the AI to remember it, update the IDSD file instead of just vibing a solution into the codebase.

I’ll remix Boris Cherny’s advice about Claude Code and apply it to IDSD:

Every failure should become a rule so it never happens again.

The main behavior I added after the original generation was the different creativity levels. Eagle-eyed readers might notice that the creativity setting wasn’t in my wireframe, and that’s because I didn’t think of it until later.

I was dissatisfied with the variation in the prompts, so I added some language about mild, normal, and wild creativity settings to the INTENT.md file. Then I didn't like how it saved those prompt variations in some random place in the code, so I added some intent language to require a configuration file (preferably somewhere sane, but I'm flexible with that term).

IDSD rewards this simple housekeeping habit. Turn the failure into intent before the model learns the wrong lessons.

If you’re coming from the SDD world, I already warned you that this will hurt your brain.

There are three common failure modes that matter most. I wrote a review-idsd skill that helps me catch and remedy these failures before I unleash the dogs of code.

View the review-idsd skill on GitHub

This is the easiest mistake to make, especially for engineers who are used to thinking in architecture first.

Bad version:

Build a Python worker using Celery…

That is already sliding back into implementation plan mode.

The fix is to rewrite the request as the outcome first. If two different implementations could satisfy it, you probably wrote a goal. If only one implementation could satisfy it, you probably wrote a spec wearing a fake mustache.

Best advice for this section: write the outcome first, then add only the qualities that must be true.

This one is sneakier.

You tell yourself you are writing constraints, but then you produce a list of 43 detailed library choices, pattern decisions, or architecture preferences you’re trying to hide in a trench coat.

That reduces the agent back to a typist. Congratulations, you reinvented SDD, except now everyone has to pretend it is more agile because the file has a cooler name.

The fix is to keep constraints focused on qualities of the result, not implementation choices.

This is the one I think people will underestimate.

“Must work well” is not a failure condition.

“Must be scalable” is not a failure condition.

“Should feel intuitive” is not a failure condition, although it is a wonderful way to start an argument between iPhone and Android religious adherents.

Failure conditions need to be observable. What would clearly tell you the result is unacceptable? What broke? What exceeded the threshold? What user-visible behavior failed?

If you cannot tell when the system has failed, the agent cannot reliably optimize against failure. It can only vibe in your general direction, which, once again, is not a process. It is a mood. We didn’t land on the moon with moods. We used slide rules!

The strangest behavior I observed was with very verbose thinking models. Sometimes they just spat out the same image prompt over and over after waiting for a while.

After some good old-fashioned debugging, I discovered that the thinking models were sometimes overrunning the max token budget just with their own thought process, so the app concluded that they had returned no usable content. The fallback behavior, which I had not specified anywhere, simply reused the original base prompt instead of failing loudly to the user.

That could be a feature. It could also be a bug. As with many things in software, it mostly depends on whether it happened to you or to someone else or to an old friend you’re trying to prank.

I could have fixed that and added it to the intent file, but instead I just used non-thinking models and rode off into the sunset. A highly principled engineering choice, meaning I’ll tell myself “I’ll fix that later” and instead it will follow me to my grave without ever being updated.

I also didn’t add anything about deployment or security or rate limits or any of the other fun details that turn a toy into a product and a weekend project into a year-long endeavor. Those requirements would just be added to the intent files if I wanted to achieve that level of project maturity. But I have more ideas to make, so I’m skipping that and pretending that future Cody will happily pick up the slack.

IDSD delivered the goods.

Now I must admit that a single page app is a relatively forgiving test case. Next I want to ratchet up the difficulty level with a CMS back-end. Real data relationships, real workflows, and a client who will absolutely change their mind about the navigation structure three weeks in.

I didn’t invent this concept in a vacuum. If you want to go deeper on the theory, these are worth your time.

Kill the Ceremony: Intent-Driven Development and the Minimum Viable Spec was originally published in Towards AI on Medium, where people are continuing the conversation by highlighting and responding to this story.

── more in #developer-tools 4 stories · sorted by recency
── more on @antoine de saint-exupéry 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/kill-the-ceremony-in…] indexed:0 read:17min 2026-07-12 ·