<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Workflow on Stephan Michard</title><link>https://www.stephan.michard.io/tags/workflow/</link><description>Recent content in Workflow on Stephan Michard</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Sun, 08 Nov 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://www.stephan.michard.io/tags/workflow/" rel="self" type="application/rss+xml"/><item><title>From Vibe Coding to Spec-Driven Development</title><link>https://www.stephan.michard.io/2026/from-vibe-coding-to-spec-driven-development/</link><pubDate>Sun, 08 Nov 2026 00:00:00 +0000</pubDate><guid>https://www.stephan.michard.io/2026/from-vibe-coding-to-spec-driven-development/</guid><description>&lt;figure&gt;&lt;img
src="https://www.stephan.michard.io/images/posts/post_50/overview_hu_b1a0b471e8ca1973.webp"
srcset="https://www.stephan.michard.io/images/posts/post_50/overview_hu_d64a4bdd869ee077.webp 480w, https://www.stephan.michard.io/images/posts/post_50/overview_hu_18d1f05e963a222f.webp 800w, https://www.stephan.michard.io/images/posts/post_50/overview_hu_b1a0b471e8ca1973.webp 1400w"
sizes="(max-width: 42rem) 100vw, 42rem"
width="1400"
height="781"
alt="OpenSpec, Beads and Worktrunk as one workflow - AI generated"
loading="lazy"
decoding="async" title="OpenSpec, Beads and Worktrunk as one workflow - AI generated"&gt;&lt;figcaption&gt;
&lt;h4&gt;OpenSpec, Beads and Worktrunk as one workflow - AI generated&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="introduction"&gt;Introduction&lt;/h2&gt;
&lt;p&gt;This is the last post in my series on how my development workflow has changed. The previous three posts introduced &lt;a href="https://www.stephan.michard.io/2026/openspec-writing-the-plan-before-the-code/"&gt;OpenSpec&lt;/a&gt;
, &lt;a href="https://www.stephan.michard.io/2026/beads-a-task-memory-for-coding-agents/"&gt;Beads&lt;/a&gt;
and &lt;a href="https://www.stephan.michard.io/2026/worktrunk-one-worktree-per-coding-agent/"&gt;Worktrunk&lt;/a&gt;
one at a time. In this post, I connect them and describe the workflow I follow today, from an empty folder to merged code. First, though, a look at why I changed anything at all.&lt;/p&gt;
&lt;h2 id="where-vibe-coding-stopped-working"&gt;Where Vibe Coding Stopped Working&lt;/h2&gt;
&lt;p&gt;Since the beginning of the year, I have built a number of small software projects with coding agents. At first, that meant what Andrej Karpathy called vibe coding: describe what you want and keep prompting until the result works. Gene Kim and Steve Yegge wrote a whole book about it, and I &lt;a href="https://www.stephan.michard.io/2026/book-review-vibe-coding-by-gene-kim-and-steve-yegge/"&gt;reviewed it in April&lt;/a&gt;
. For small experiments, it works. Over time, though, I ran into the same problems again and again.&lt;/p&gt;
&lt;p&gt;Context was the first thing to go. A session lives in one terminal on one machine. After a reboot or a switch to another machine, the agent started from zero, and I spent the first prompts of each session explaining what we had done and what came next.&lt;/p&gt;
&lt;p&gt;Long sessions caused the opposite problem, a kind of context gridlock. Every turn sends the full history along, so the token count climbs with each prompt. At some point, the agent spends more effort carrying old context than working on the task, and when the session is compacted, details I still needed disappear.&lt;/p&gt;
&lt;p&gt;Even with plan mode, the work lacked structure. Agents pulled in memories that had nothing to do with the task, or proposed new features and fixes for unrelated bugs halfway through the work. Each idea made sense on its own. Together, they turned the plan into a pile of loose ends, which was frustrating.&lt;/p&gt;
&lt;p&gt;My first attempt at a fix was a set of Markdown files that held the plan and the open tasks. They needed constant updates, by me or by the agent, and they still fell behind. A Markdown file does not know that one task blocks another or which agent is working on what.&lt;/p&gt;
&lt;h2 id="one-job-per-tool"&gt;One Job per Tool&lt;/h2&gt;
&lt;p&gt;OpenSpec is where an idea becomes a plan. I describe the idea with the agent in the explore step until it becomes a written proposal with a task list. I leave some aspects open on purpose and decide them later, once there is something to look at.&lt;/p&gt;
&lt;p&gt;The plan then moves into Beads. The tasks become beads, grouped by theme under epics, with priorities and dependencies. Because the Beads database travels with the Git remote, the state of the project survives a reboot or a switch to another machine. A new session starts with the Beads context, which a hook loads automatically, and &lt;code&gt;bd ready&lt;/code&gt; tells the agent what to do next. Beads also helps with the detours. Its instructions tell the agent to create a bead before writing code, so a new idea or a bug found along the way usually ends up as a bead in the backlog instead of an unplanned change in the current task.&lt;/p&gt;
&lt;p&gt;Worktrunk comes into play when several agents work at once. Each agent gets its own worktree on its own branch, so the agents can work through beads in parallel without overwriting each other&amp;rsquo;s files.&lt;/p&gt;
&lt;h2 id="my-workflow"&gt;My Workflow&lt;/h2&gt;
&lt;p&gt;The Chart view I contributed to Beadbox, the desktop app for Beads, was planned this way: six OpenSpec changes with 69 tasks in total, released across Beadbox v0.28.0 to v0.28.2. The steps below are the ones I usually follow when I start a new project.&lt;/p&gt;
&lt;h3 id="setting-up-a-new-project"&gt;Setting Up a New Project&lt;/h3&gt;
&lt;p&gt;Every project starts with an empty folder and &lt;code&gt;git init&lt;/code&gt;. The first file I add is an instruction file for the agent, &lt;code&gt;CLAUDE.md&lt;/code&gt; for Claude Code or &lt;code&gt;AGENTS.md&lt;/code&gt; for Codex. Mine is based on the &lt;code&gt;CLAUDE.md&lt;/code&gt; from the andrej-karpathy-skills repository, a short set of rules derived from Andrej Karpathy&amp;rsquo;s observations on LLM coding pitfalls. Among other things, it asks the agent to state its assumptions before writing code and to keep its changes small.&lt;/p&gt;
&lt;p&gt;Then I initialize Beads, connect the remotes, install the Beads integration for the agent I plan to use and initialize OpenSpec:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git init
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bd init
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bd quickstart
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git remote add origin git@github.com:&amp;lt;user&amp;gt;/&amp;lt;project&amp;gt;.git
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bd dolt push
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bd setup claude &lt;span class="c1"&gt;# or: bd setup codex&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;openspec init
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;bd dolt push&lt;/code&gt; sends the Beads database to the same remote as the code. On the next machine, &lt;code&gt;bd dolt pull&lt;/code&gt; brings it back, which takes care of the machine switch from the beginning of this post.&lt;/p&gt;
&lt;h3 id="from-idea-to-beads"&gt;From Idea to Beads&lt;/h3&gt;
&lt;p&gt;With the project set up, I open a coding agent and run &lt;code&gt;/opsx:explore&lt;/code&gt;. The agent asks questions until the idea is clear enough to write down, and &lt;code&gt;/opsx:propose&lt;/code&gt; then writes the change folder with the proposal and the task list. I read all of it and correct what the agent got wrong. This takes longer than typing a prompt and hoping for the best, and it is the step where I spend most of my time today.&lt;/p&gt;
&lt;p&gt;At the end of the propose step, I ask the agent to create epics and beads from the task list, with the beads grouped by theme under their epics. Then I look at the result in Beadbox, where the Chart view shows each epic as a timeline, and check the list in the terminal:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bd list
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bd ready
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;figure&gt;&lt;img
src="https://www.stephan.michard.io/images/posts/post_50/beadbox_hu_87f0c267c95c644f.webp"
srcset="https://www.stephan.michard.io/images/posts/post_50/beadbox_hu_cba1f99bc7086570.webp 480w, https://www.stephan.michard.io/images/posts/post_50/beadbox_hu_41ce2179f2a868f0.webp 800w, https://www.stephan.michard.io/images/posts/post_50/beadbox_hu_87f0c267c95c644f.webp 1400w"
sizes="(max-width: 42rem) 100vw, 42rem"
width="1400"
height="820"
alt="The Chart view in Beadbox, with beads grouped under their epics and connected by their dependencies"
loading="lazy"
decoding="async" title="The Chart view in Beadbox, with beads grouped under their epics and connected by their dependencies"&gt;&lt;figcaption&gt;
&lt;h4&gt;The Chart view in Beadbox, with beads grouped under their epics and connected by their dependencies&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="handing-out-the-work"&gt;Handing Out the Work&lt;/h3&gt;
&lt;p&gt;For a single agent, the instruction is short: work on bead &lt;code&gt;&amp;lt;id&amp;gt;&lt;/code&gt;, or on a whole epic. Alternatively, &lt;code&gt;/opsx:apply&lt;/code&gt; implements the change directly from its task list.&lt;/p&gt;
&lt;p&gt;When several agents work at the same time, each one gets its own worktree. Worktrunk creates the worktree and starts the agent in it with the prompt. Each line runs in its own terminal pane:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wt switch -x claude -c feature-a -- &lt;span class="s1"&gt;&amp;#39;work on bead &amp;lt;id&amp;gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wt switch -x claude -c feature-b -- &lt;span class="s1"&gt;&amp;#39;work on bead &amp;lt;id&amp;gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This works because Beads finds its database through the repository directory that all worktrees share. Every worktree of a repository reads and writes the same issues, so a bead that one agent claims in its worktree shows up as in progress for all the others.&lt;/p&gt;
&lt;h3 id="watching-and-merging"&gt;Watching and Merging&lt;/h3&gt;
&lt;p&gt;While the agents work, I follow their progress in Beadbox and in Herdr, the terminal multiplexer I &lt;a href="https://www.stephan.michard.io/2026/herdr-panes-for-my-folders-one-place-for-my-agents/"&gt;wrote about earlier this year&lt;/a&gt;
. Herdr gives me one pane per agent and shows which agent is still working and which one is waiting for me. One more pane runs a live view of the beads (on macOS, &lt;code&gt;watch&lt;/code&gt; comes from Homebrew):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;watch -n &lt;span class="m"&gt;1&lt;/span&gt; bd list
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;figure&gt;&lt;img
src="https://www.stephan.michard.io/images/posts/post_50/herdr_hu_7fe1b8ccd2e8720.webp"
srcset="https://www.stephan.michard.io/images/posts/post_50/herdr_hu_c4ae8e0c8149cec4.webp 480w, https://www.stephan.michard.io/images/posts/post_50/herdr_hu_4fe686ab38b732de.webp 800w, https://www.stephan.michard.io/images/posts/post_50/herdr_hu_7fe1b8ccd2e8720.webp 1400w"
sizes="(max-width: 42rem) 100vw, 42rem"
width="1400"
height="820"
alt="Herdr with a live bd list, a shell, Claude Code and Codex in separate panes"
loading="lazy"
decoding="async" title="Herdr with a live bd list, a shell, Claude Code and Codex in separate panes"&gt;&lt;figcaption&gt;
&lt;h4&gt;Herdr with a live bd list, a shell, Claude Code and Codex in separate panes&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;When an agent has closed its bead, I merge its worktree with &lt;code&gt;wt merge&lt;/code&gt;, which squashes and rebases the branch onto the default branch and removes the worktree. Worktrees keep agents from overwriting each other&amp;rsquo;s files while they work. They do not prevent conflicts at merge time. If two beads change the same file, the second merge needs a rebase and sometimes a manual fix.&lt;/p&gt;
&lt;h2 id="what-changed"&gt;What Changed&lt;/h2&gt;
&lt;p&gt;The biggest change is where my time goes. I spend more of it on planning and reviewing proposals and less on fixing code that the agent wrote from a misunderstanding. For small projects, the total time from idea to working software has gone down considerably.&lt;/p&gt;
&lt;p&gt;Token usage went down as well, because each agent session starts with one bead and the matching part of the spec instead of a long conversation history. That is my impression, at least, and I cannot back it with numbers yet. I started sending traces of my Claude Code sessions to a self-hosted MLflow instance in October, and it records token usage and cost per turn. That gives me numbers from now on, but no baseline from before I changed the workflow.&lt;/p&gt;
&lt;h2 id="limits-and-open-ends"&gt;Limits and Open Ends&lt;/h2&gt;
&lt;p&gt;Spec-driven development has critics. Birgitta Böckeler from Thoughtworks looked at Kiro, Spec Kit and Tessl on martinfowler.com and wrote: &amp;ldquo;To be honest, I&amp;rsquo;d rather review code than all these markdown files.&amp;rdquo; She also doubts that one fixed workflow fits a small bug fix as well as a large feature. Both points are fair, and the second matches my experience. For a feature, the full OpenSpec cycle pays off. For a two-line fix, it is too much, and a single bead or a direct prompt does the job.&lt;/p&gt;
&lt;p&gt;OpenSpec and Beads also overlap. Both keep a task list, &lt;code&gt;tasks.md&lt;/code&gt; in the OpenSpec change and the beads in the database. With &lt;code&gt;/opsx:apply&lt;/code&gt;, the agent ticks off &lt;code&gt;tasks.md&lt;/code&gt;. When it works through beads, it closes beads. Mixing both in one change means that one list falls behind the other. The cleaner split is to use OpenSpec for what to build and why, and Beads for the progress.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;At the start of the year, a new project began with a prompt. Today it begins with a conversation about what to build, and the code comes later.&lt;/p&gt;
&lt;p&gt;If you work with coding agents and recognize the problems from the beginning of this post, OpenSpec and Beads are the two tools I would try first. Worktrunk becomes useful once you run more than one agent at a time.&lt;/p&gt;
&lt;h2 id="references"&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Part one of this series: OpenSpec - &lt;a href="https://www.stephan.michard.io/2026/openspec-writing-the-plan-before-the-code/"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Part two of this series: Beads - &lt;a href="https://www.stephan.michard.io/2026/beads-a-task-memory-for-coding-agents/"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Part three of this series: Worktrunk - &lt;a href="https://www.stephan.michard.io/2026/worktrunk-one-worktree-per-coding-agent/"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Herdr: Panes for My Folders, One Place for My Agents - &lt;a href="https://www.stephan.michard.io/2026/herdr-panes-for-my-folders-one-place-for-my-agents/"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Book Review: Vibe Coding by Gene Kim and Steve Yegge - &lt;a href="https://www.stephan.michard.io/2026/book-review-vibe-coding-by-gene-kim-and-steve-yegge/"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;andrej-karpathy-skills: CLAUDE.md - &lt;a href="https://github.com/multica-ai/andrej-karpathy-skills/blob/main/CLAUDE.md" target="_blank" rel="noopener noreferrer"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Birgitta Böckeler: Understanding Spec-Driven-Development: Kiro, spec-kit, and Tessl - &lt;a href="https://martinfowler.com/articles/exploring-gen-ai/sdd-3-tools.html" target="_blank" rel="noopener noreferrer"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Beadbox - &lt;a href="https://beadbox.app/en" target="_blank" rel="noopener noreferrer"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;MLflow: Tracing Claude Code - &lt;a href="https://mlflow.org/docs/latest/genai/tracing/integrations/listing/claude_code/" target="_blank" rel="noopener noreferrer"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>