<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alfredo Perez</title>
    <description>The latest articles on DEV Community by Alfredo Perez (@alfredoperez).</description>
    <link>https://dev.to/alfredoperez</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F165435%2F8c6793dd-5008-434f-9870-d3765c98ff06.jpeg</url>
      <title>DEV Community: Alfredo Perez</title>
      <link>https://dev.to/alfredoperez</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alfredoperez"/>
    <language>en</language>
    <item>
      <title>Living Specs in SpecKit</title>
      <dc:creator>Alfredo Perez</dc:creator>
      <pubDate>Sat, 17 Oct 2026 01:57:15 +0000</pubDate>
      <link>https://dev.to/alfredoperez/living-specs-in-speckit-3a3j</link>
      <guid>https://dev.to/alfredoperez/living-specs-in-speckit-3a3j</guid>
      <description>&lt;p&gt;Nine months ago I started building a &lt;a href="https://alfredo-perez.dev/blog/2026-03-19-what-is-speckit-companion" rel="noopener noreferrer"&gt;VS Code extension&lt;/a&gt; in the open, and I ran every change in it through spec-driven development. A few weeks ago I wrote about &lt;a href="https://alfredo-perez.dev/blog/2026-08-31-i-wrote-238-specs-and-never-read-one-again" rel="noopener noreferrer"&gt;what that left behind&lt;/a&gt;: a specs folder I never opened again, and an agent that never opened it either.&lt;/p&gt;

&lt;p&gt;That piece ended with a promise. I'd cut one feature from it to keep it readable, and I now think that feature, specs you can reuse, holds the whole method together.&lt;/p&gt;

&lt;p&gt;In SpecKit Companion it's called a living spec. Instead of one spec per change that freezes the day it ships, you keep one spec per feature, like billing or auth, that says what the feature must do today. Every run that touches the feature loads it before drafting anything, and rewrites it when the work is done. The rest of this piece hangs off that loop:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0ku7n4w8rf27z62xj5fj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0ku7n4w8rf27z62xj5fj.jpg" alt="A living spec and its parent are loaded before specify, plan, tasks and implement run, and the result folds back into the living spec when the feature ships" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The usual setup has no arrow back, so a spec is written once and every later run starts over from the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a spec is, and where it usually dies
&lt;/h2&gt;

&lt;p&gt;In most agents you can already ask for a plan before any code gets written. Spec-driven development slices that plan into phases: specify what the feature must do, plan how, break it into tasks, then implement. Each phase leaves a markdown file in the repo, and you read each one before the next runs. You get to see whether the implementation is going your way, step by step, with a little more control than letting it run.&lt;/p&gt;

&lt;p&gt;That part works. It's why I ended up with ninety-four of those folders.&lt;/p&gt;

&lt;p&gt;What nobody talks about is what happens to the files after the feature ships. In the usual setup, nothing. Spec-kit gives each feature its own numbered folder, and that folder is finished the day the feature is:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqdvh6xvu55xzvc0z199e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqdvh6xvu55xzvc0z199e.jpg" alt="Spec-kit's specs folder holds one numbered folder per feature, each with spec.md, plan.md and tasks.md, written once and never updated, while the code in src keeps changing with no link back" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code keeps changing after that, and nothing carries the change back, so each folder is only true for the week it was written. That's where three problems start, none of them dramatic, all of them normal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Every spec starts from zero
&lt;/h2&gt;

&lt;p&gt;Every time a spec touches something, say a dialog, the specify and plan phases go and investigate how that dialog works, and they write down what they learn: the data model, the pieces around it, the conventions. That's just normal. It's the phases doing their job.&lt;/p&gt;

&lt;p&gt;The problem is that the next spec that touches the same dialog does the whole investigation again. Nothing from the last time is there to point at. The understanding was real, and it got written down, and then it got filed in a folder the next run doesn't read. So the agent re-derives it, every feature, from the code.&lt;/p&gt;

&lt;p&gt;A living spec is a pointer to that previous understanding. When the next run starts, the agent has more guidance, faster, because the record of how the feature works is already there and already current.&lt;/p&gt;

&lt;h2&gt;
  
  
  You can't find how a feature works
&lt;/h2&gt;

&lt;p&gt;The second problem is the one I felt as a person rather than as an agent. Once a spec exists, it's hard to find out what the feature is supposed to do today.&lt;/p&gt;

&lt;p&gt;Take one thread in my repo: how a task gets marked complete. I iterated on that many times. Each iteration got its own spec, its own requirements, its own record of what I believed at the time. Ask the folder how task completion works today, and this is the shape of the answer:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu0sndjw4vihdbqe2h17z.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu0sndjw4vihdbqe2h17z.jpg" alt="Five task-completion specs from different iterations sit in a folder with no sign of which is current, next to a single living spec that is true today" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Five specs touch it, four are superseded, and none of them says which. A living spec gives that question one place to land.&lt;/p&gt;

&lt;p&gt;It isn't that I filed them badly. A spec is a snapshot of one moment's intent, and snapshots don't update. Stack ninety-four of them and you don't have documentation, you have an archive. There is a name for this in the writing about spec-driven development: &lt;a href="https://medium.com/gitconnected/there-is-no-single-sdd-three-levels-exist-and-most-teams-are-stuck-on-level-one-afb4efb06734" rel="noopener noreferrer"&gt;most teams pay for a spec that stays and get the benefit of a spec written once and forgotten&lt;/a&gt;. That was me.&lt;/p&gt;

&lt;h2&gt;
  
  
  The agent reads what's nearby
&lt;/h2&gt;

&lt;p&gt;The third problem is about where the agent looks. Ask Claude, or any provider, to work on a feature without a spec run, and it reads the code near the thing you named. That's fine. The code sitting right there is real information.&lt;/p&gt;

&lt;p&gt;Two things make it less fine. The neighbor code isn't always what you would consider the standard, so the agent copies a convention nobody endorses. And the specs folder, the one place where the intended behavior is written down, is unfeasible to go through, because it accumulates fast and nothing in it says what is current. So the agent goes around it. It's right to.&lt;/p&gt;

&lt;p&gt;This is the observation that shaped the whole design: a markdown file sitting next to the code it describes gets read, spec run or not, by any provider, in any prompt. The location is the feature. There is research on how &lt;a href="https://research.trychroma.com/context-rot" rel="noopener noreferrer"&gt;models lose what they were told before the conversation ends&lt;/a&gt;, and a file that survives the session is what brings it back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Specs that get a second life
&lt;/h2&gt;

&lt;p&gt;Reading about how other workflows handle this, especially &lt;a href="https://github.com/Fission-AI/OpenSpec" rel="noopener noreferrer"&gt;OpenSpec&lt;/a&gt;, is what inspired the feature. OpenSpec keeps one durable spec per capability and folds each change back into it when the change ships. The specs get a second life. I liked that a lot, because it meant a spec wasn't going to become a dead file in a dead folder. It was going to be documentation I could read later, modify, adjust.&lt;/p&gt;

&lt;p&gt;I also looked at what that looks like in practice, across 788 public repositories using it. Two things stood out. The fold-back step is manual, and skipping it is how the record dies: code keeps moving, the specs sit still, and nobody notices for months. And nobody maintains prose nobody reads. Even mature repos leave the purpose line as a placeholder. Those two things decided what SpecKit Companion would do differently.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a living spec looks like
&lt;/h2&gt;

&lt;p&gt;In Companion, a living spec covers one capability, like checkout, auth or billing. The examples from here on come from Teamboard, the small demo app I use for the extension's screenshots: a team directory where members have profiles, photos and a search box.&lt;/p&gt;

&lt;p&gt;Turning it on is one file at the root of the project, and the feature is off until that file exists. Each capability gets a name and the files that belong to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 📃 living-specs.yml&lt;/span&gt;
&lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;capabilities&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;member-profiles&lt;/span&gt;
    &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;src/features/profile/**'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;src/api/members/**'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;directory-search&lt;/span&gt;
    &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;src/features/directory-search/**'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;src/features/directory-search/directory-search.spec.md&lt;/span&gt; &lt;span class="c1"&gt;# 👈 lives next to the code&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;match&lt;/code&gt; globs are how Companion knows which capability a change touches, so it's the part that matters most. The &lt;code&gt;spec&lt;/code&gt; line decides where the file goes. Without it, the spec lives centrally at &lt;code&gt;capabilities/member-profiles/member-profiles.spec.md&lt;/code&gt;, the way OpenSpec does it. With it, the spec sits in the folder of the code it describes. Side by side, the two options look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1yvfm45ajb9726ljnkus.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1yvfm45ajb9726ljnkus.jpg" alt="On the left, member-profiles.spec.md sits in a central capabilities folder away from the profile code; on the right, directory-search.spec.md sits inside the directory-search folder next to the code, where the agent already is" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The difference is who finds the spec without being told where it is. You can pick per capability, and &lt;code&gt;/speckit.companion.living-move&lt;/code&gt; moves a spec between the two later, so nothing here is a commitment.&lt;/p&gt;

&lt;p&gt;Inside, a living spec holds what the capability must do today, as requirements and scenarios, and nothing about how it was built. Here's the start of the one for member profiles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- 📃 capabilities/member-profiles/member-profiles.spec.md --&amp;gt;&lt;/span&gt;
&lt;span class="gh"&gt;# Member Profiles&lt;/span&gt;

&lt;span class="gu"&gt;## Purpose&lt;/span&gt;

Every Teamboard member has one profile: a name, a role, a team and a short bio.
This capability owns who may read a profile, who may change it, and what the
rest of the product is allowed to assume about its fields.

&lt;span class="gu"&gt;## Requirements&lt;/span&gt;

&lt;span class="gu"&gt;### A member edits only their own profile&lt;/span&gt;

A profile update MUST be accepted only from the member it belongs to or from a
workspace admin.

&lt;span class="gu"&gt;#### Scenario: a member opens another member's profile&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="gs"&gt;**WHEN**&lt;/span&gt; the viewer is neither the owner nor an admin
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**THEN**&lt;/span&gt; the profile renders read-only and the update endpoint refuses the change
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's no component name, no endpoint path, no data model in it. That's on purpose: the code can be refactored under it without the spec going stale, and the part that would go stale, how it's built, is the part the agent can always read from the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next to the code, and in a tree
&lt;/h2&gt;

&lt;p&gt;My hypothesis, or the reason I feel it's better this way, is navigation. I made a version of this argument &lt;a href="https://alfredo-perez.dev/blog/2026-06-07-specs-that-move-in-next-to-your-code" rel="noopener noreferrer"&gt;once before&lt;/a&gt;, for an earlier tool, and living in a real repo for a few months has only made it stronger. If every spec lives in a &lt;code&gt;capabilities/&lt;/code&gt; folder, that's already a step forward, because the specs got extracted from the pile. But it also means that when I'm looking at the code, I have to go somewhere else to find out what it's supposed to do. If the spec sits beside the code, I'm already there. And so is the agent.&lt;/p&gt;

&lt;p&gt;The thing that keeps this from turning your source tree into a mess is the sidebar. The Living Specs view shows every capability as a tree, grouped by where it lives:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn3ehpydu3yt4erc9ut9a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn3ehpydu3yt4erc9ut9a.png" alt="The Living Specs sidebar, with capabilities kept in one folder at the top and specs that live next to the code grouped under src below" width="800" height="915"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both kinds sit in the same tree, so putting a spec next to the code doesn't make it harder to find. Other tools don't do this part, and it's the part that made colocated specs practical for me: easy to find, easy to navigate, and opened in a viewer that renders the spec as a page rather than raw markdown.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adopting one area at a time
&lt;/h2&gt;

&lt;p&gt;Owning the location also lets you adopt one domain at a time. Maybe you use spec-driven development and you own a domain, and you don't want to force it on the whole team. You adopt that domain. From then on, everything that touches it uses living specs, and everyone else's workflow is untouched.&lt;/p&gt;

&lt;p&gt;Adopting is one command pointed at one folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/speckit.companion.living-adopt src/features/directory-search
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It reads that area's surface (the routes, the screens, what each one needs before it renders), proposes the capabilities for just that area, and stops to show you the names, the globs and where each spec will live. Once you confirm, it drafts the spec and adds the capability to &lt;code&gt;living-specs.yml&lt;/code&gt;. The draft doesn't pretend to be more than it is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- 📃 src/features/directory-search/directory-search.spec.md --&amp;gt;&lt;/span&gt;
&lt;span class="gh"&gt;# Directory Search&lt;/span&gt;
&lt;span class="gt"&gt;
&amp;gt; [DRAFT] Adopted from the code's surface and the project's conventions. Review before trusting.&lt;/span&gt;

&lt;span class="gu"&gt;## Purpose&lt;/span&gt;

The directory is how a Teamboard member finds a colleague. This capability owns
what a search matches, how results are ordered, and which members a searcher is
allowed to see.

&lt;span class="gu"&gt;## Requirements&lt;/span&gt;

&lt;span class="gu"&gt;### A search matches name, role and team&lt;/span&gt;
...

&lt;span class="gu"&gt;## Uncovered&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each requirement is marked as observed in the code or inferred, anything it couldn't settle carries a &lt;code&gt;[NEEDS CLARIFICATION: …]&lt;/code&gt; that it walks you through one at a time, and rules nobody owns land under &lt;code&gt;## Uncovered&lt;/code&gt;. The banner goes away when the last marker does. On adoption day your job is reading and correcting a draft, and the markers show you which parts nobody has confirmed yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Written as a side effect of shipping
&lt;/h2&gt;

&lt;p&gt;Here's the part that answers the objection I take most seriously, that spec-kit &lt;a href="https://medium.com/gitconnected/vendor-lock-in-in-spec-driven-development-five-dependency-layers-and-how-to-price-them-3eb08b704773" rel="noopener noreferrer"&gt;claims to keep specs alive and delivers specs that freeze&lt;/a&gt;. You don't keep a living spec current by hand. The pipeline does.&lt;/p&gt;

&lt;p&gt;When a spec run starts, the specify phase has a step that finds the living specs for the area you're touching and loads them before it drafts anything. Not only the leaf you named: the parents in the hierarchy too, so the new feature spec starts from what is true across the whole area. Plan works from that. Tasks work from that.&lt;/p&gt;

&lt;p&gt;The rewrite happens at the end. While it finishes the feature, the agent adds a short section to the feature's own spec for each capability the feature changed, saying what changed. For the profile photo feature in the demo, that section looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- 📃 the feature spec for 041-profile-photo-upload --&amp;gt;&lt;/span&gt;
&lt;span class="gu"&gt;## ADDED Requirements&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- capability: member-profiles --&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- 👈 which living spec it goes to --&amp;gt;&lt;/span&gt;

&lt;span class="gu"&gt;### A member sets their own profile photo&lt;/span&gt;

&lt;span class="gu"&gt;#### Scenario: a member uploads a new photo&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; WHEN a member picks a JPEG under 5 MB on their own profile
&lt;span class="p"&gt;-&lt;/span&gt; THEN the photo replaces the previous one
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you mark the feature complete, that section folds into &lt;code&gt;member-profiles.spec.md&lt;/code&gt;: an added requirement is appended, a modified one replaces the old text, a removed one is deleted. There are four kinds (&lt;code&gt;ADDED&lt;/code&gt;, &lt;code&gt;MODIFIED&lt;/code&gt;, &lt;code&gt;REMOVED&lt;/code&gt;, &lt;code&gt;RENAMED&lt;/code&gt;), and a feature that changed two capabilities sends each one only its own section. Because the section is written into the feature's spec, it shows up in the same PR diff as the code, so the change to the living spec gets reviewed instead of applied blindly. If a run loaded a living spec and wrote nothing for it, completion names it and says there was nothing to fold, so a skipped fold-back is visible rather than silent.&lt;/p&gt;

&lt;p&gt;The first real feature I ran this way was a webview rendering change. The ticket said nothing about HTML safety. The living spec for that area did, and the rule traveled through every phase until it became something I could tick:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiaivg6j1grawudqhqmzp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiaivg6j1grawudqhqmzp.jpg" alt="A rule from the living spec becomes a requirement in the spec, an attribute-safety check in the plan, and a checkbox in the tasks, though the ticket never mentioned it" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The rule reached the work because the spec was loaded, not because anyone remembered it.&lt;/p&gt;

&lt;p&gt;What also made me trust this is that it shows its work. The Overview of a finished run lists the living specs it found, with a badge that says whether they folded back:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foaotyocuzckpglbdgl9z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foaotyocuzckpglbdgl9z.png" alt="The Overview of a finished run, with the living specs it loaded marked and the folded-back badge highlighted" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The badge tells me the run found all the relationships, not just the one I pointed at, and that the record is current as of this feature. &lt;a href="https://medium.com/gitconnected/sdd-kent-beck-and-martin-fowler-why-spec-anchored-development-wins-a4c838d5be11" rel="noopener noreferrer"&gt;Kent Beck's objection to spec-driven development&lt;/a&gt; was never that you write things down. It was that you write them down and they freeze while the code moves. Fold-back at completion is the thaw.&lt;/p&gt;

&lt;h2&gt;
  
  
  When you worked outside the pipeline
&lt;/h2&gt;

&lt;p&gt;Sometimes, and this is really normal, I don't use spec-kit at all: big spikes, exploratory features, a quick fix on a Friday. Now imagine a team of dozens, where not everyone runs the same workflow with AI, and that's fine too. The code moves and the living spec sits still, which is exactly the way the records died in those 788 repos. So Companion watches for it, and this is the path back:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7a9q5mxzv5f4obtvvucf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7a9q5mxzv5f4obtvvucf.jpg" alt="A quick fix without a spec run moves the code, a drift badge appears, sync runs, and the spec and code are reviewed together" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nothing blocks the quick fix. Drift is information, not a gate: a flag never stops a run, it just means you know, and you sync when you're ready.&lt;/p&gt;

&lt;p&gt;Each capability whose code changed since its spec was last committed carries a drift badge in the sidebar. From the terminal, it's two commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 👇 what moved, uncommitted work included&lt;/span&gt;
/speckit.companion.living-drift &lt;span class="nt"&gt;--working&lt;/span&gt;

&lt;span class="c"&gt;# 👇 update every affected spec&lt;/span&gt;
/speckit.companion.living-sync
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Drift lists, per capability, the files that changed since its spec was last committed, and says how each one slipped. A &lt;code&gt;tracked&lt;/code&gt; file went through the pipeline but its change never folded back, a missed sync. An &lt;code&gt;unspeced&lt;/code&gt; file changed entirely outside the pipeline, so the living spec never saw it at all, which is the one to look at first.&lt;/p&gt;

&lt;p&gt;Sync then groups your changes by capability, reads what actually changed, and updates each affected spec. It edits rather than regenerates: every requirement and scenario the change didn't touch stays word for word, so a sync never flattens what someone wrote by hand. And it leaves the edits uncommitted, so the code and the spec get reviewed together. The spec page has the same thing as an Update button:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvfr0gb3k3sdtpinrm2gb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvfr0gb3k3sdtpinrm2gb.png" alt="A living spec page showing the drift badge and the Update button, with the code paths the spec covers marked below" width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The covered paths are what drift is measured against, so a spec only flags when its own code moved, not every time someone touches the repo.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it asks of you
&lt;/h2&gt;

&lt;p&gt;It asks for adopting the system: adding domains, organizing as a team, deciding where you want your living specs to live. And it asks for being conscious that you'll need to sync and get rid of drift, because it happens.&lt;/p&gt;

&lt;p&gt;There is also something it doesn't do yet, and I'm still thinking about it. While specify and plan run, they gather a lot: data models, architecture, decisions. Right now the living spec keeps how the feature works and nothing else. I don't know yet whether those other artifacts should be persisted too, whether they add to the understanding of the feature or just add to the context, and whether they would stay maintainable. That's an open question, not a roadmap.&lt;/p&gt;

&lt;p&gt;And to be fair to the other side: there is a good argument that &lt;a href="https://medium.com/gitconnected/stop-writing-specs-start-writing-facts-the-entire-sdd-movement-is-already-obsolete-9045f7061e26" rel="noopener noreferrer"&gt;an executable test is the more durable contract&lt;/a&gt;, because it survives a model upgrade unchanged where prose gets reinterpreted. I think that's right, and I think a living spec holds something a test cannot, which is why the feature exists at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Ninety-four specs nobody opened taught me less than the handful that get loaded every session.&lt;/p&gt;

&lt;p&gt;If you want to try it, the steps below follow the order of this piece, and the &lt;a href="https://speckit-companion.dev/docs/guides/living-specs" rel="noopener noreferrer"&gt;guide&lt;/a&gt; has the rest.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install the &lt;a href="https://alfredo-perez.dev/blog/2026-09-28-give-spec-kit-superpowers" rel="noopener noreferrer"&gt;spec-kit extension&lt;/a&gt;: &lt;code&gt;specify extension add companion --from https://github.com/alfredoperez/speckit-companion/releases/download/companion-latest/companion.zip&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create &lt;code&gt;living-specs.yml&lt;/code&gt; at the root with &lt;code&gt;enabled: true&lt;/code&gt;. Living specs are off until this file exists.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;/speckit.companion.living-adopt src/&amp;lt;area&amp;gt;&lt;/code&gt; on the one area you explain most often, and read the draft.&lt;/li&gt;
&lt;li&gt;Ship a feature through the pipeline and check the Overview for the folded-back badge.&lt;/li&gt;
&lt;li&gt;When the sidebar shows drift, run &lt;code&gt;/speckit.companion.living-sync&lt;/code&gt; and commit the spec edits with the code.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To see it move before you install anything, the &lt;a href="https://speckit-companion.dev" rel="noopener noreferrer"&gt;SpecKit Companion website&lt;/a&gt; has a short video that walks through living specs.&lt;/p&gt;

&lt;p&gt;This is the first of the three threads I cut from &lt;a href="https://alfredo-perez.dev/blog/2026-08-31-i-wrote-238-specs-and-never-read-one-again" rel="noopener noreferrer"&gt;the 238-specs piece&lt;/a&gt;. &lt;a href="https://alfredo-perez.dev/blog/2026-09-28-give-spec-kit-superpowers" rel="noopener noreferrer"&gt;Give Spec Kit Superpowers&lt;/a&gt; introduced the other two, fast mode and auto mode, in a line each. Next up is auto mode properly: planning several features at once and reviewing the whole batch from the sidebar.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Take Your AI's Questions Out of the Terminal</title>
      <dc:creator>Alfredo Perez</dc:creator>
      <pubDate>Wed, 14 Oct 2026 20:33:35 +0000</pubDate>
      <link>https://dev.to/alfredoperez/take-your-ais-questions-out-of-the-terminal-5dp4</link>
      <guid>https://dev.to/alfredoperez/take-your-ais-questions-out-of-the-terminal-5dp4</guid>
      <description>&lt;p&gt;This is a decision page. &lt;a href="https://claude.com/product/claude-code" rel="noopener noreferrer"&gt;Claude Code&lt;/a&gt; wrote it after reading a project's notes, and it shows the detail a chat question leaves out. I answer it in &lt;a href="https://obsidian.md" rel="noopener noreferrer"&gt;Obsidian&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvdaik1dz560vpuz1rtix.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvdaik1dz560vpuz1rtix.png" alt="One question on the Worky decision page in Obsidian: a heading with a " width="800" height="1097"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When an AI asks me to choose, what I get is the question and the options, one line each. The detail that would help me choose is still inside its context, and I can't see it. On this page it's all there: what Claude found while reading the project, a picture of the problem, a table of what could break, and only then the options, with one marked as recommended. I tick a box, type a line if I have one, and tell Claude I'm done.&lt;/p&gt;

&lt;p&gt;The page is plain markdown. Two things make it look like this: a skill that knows which parts a decision page can use, and the vault stylesheet from &lt;a href="https://alfredo-perez.dev/blog/2026-10-01-make-your-vault-look-right" rel="noopener noreferrer"&gt;Make Your Vault Look and Read the Way You Want&lt;/a&gt;, which draws them so I can read the page instead of parsing it. If you haven't set up that stylesheet, start there, because this article builds on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it started
&lt;/h2&gt;

&lt;p&gt;For most choices, the grid Claude Code shows in the chat is all I need. The bigger ones were the problem. One line per option can't hold a picture of the problem or what might break, and once I answer, the question scrolls away, so a month later I can't find what I picked or why.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/mattpocock/skills" rel="noopener noreferrer"&gt;Matt Pocock's grill-me&lt;/a&gt; got me most of the way, and I want to give it proper credit. It's a skill that interviews you about a plan until you and the agent understand it the same way: a round of numbered questions, each with a recommended answer under it. Here's the first round it gave me on the question I use as the example below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2vfnvirdedkl6xk715y7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2vfnvirdedkl6xk715y7.png" alt="Claude Code in a terminal running grill-me on the Worky calendar question: the first numbered question with a recommended answer under it that starts with " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I used it for weeks and kept running out of space, because a terminal gives every question the same few lines, whatever the question needs. So I moved the questions into a document, where a question can carry a picture, a table, or a folded block of code. I ask for a page when the questions need background I haven't read, when there are more than three and they affect each other, or when I've already said "let me think about it". Most choices don't pass that test, and for those the chat grid is still the right shape.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ask for the page
&lt;/h2&gt;

&lt;p&gt;For the examples I'll use Worky, a made-up company that schedules painter crews. It has three screens: a Client Portal where homeowners book and track a job, a Crew App where painters see today's jobs on a phone, and a Dispatch Console where the office moves crews between jobs. The open question was whether the calendar gets built once and shared, or whether each screen builds its own view of the same schedule.&lt;/p&gt;

&lt;p&gt;Here's the kind of thing I said to Claude:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I need to decide whether Worky's three apps share one calendar
or each build their own. Read the Worky notes first, then write
me a decision page I can answer tomorrow. Recommend an answer for
each question, but don't tick anything for me.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude read the project notes and wrote one page into the project's decisions folder. Follow-up rounds go into the same page, so there's one place to look.&lt;/p&gt;

&lt;h2&gt;
  
  
  Put what Claude found beside the question
&lt;/h2&gt;

&lt;p&gt;This is the part a chat round has no room for. Each question on the page carries what Claude found while reading the project, open, right under the heading:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A row of small tags. One says how sure the finding is, for example "seen in all three apps", and one says how big the change would be.&lt;/li&gt;
&lt;li&gt;A one-line summary of the question.&lt;/li&gt;
&lt;li&gt;A picture, when a picture says it faster.&lt;/li&gt;
&lt;li&gt;A short "What I found" list, two or three plain sentences.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The heading carries a tag too, for how heavy the question is: "quick call", "trade-off" or "the debate". The quick calls come first, so I get a few answers down before the hard one.&lt;/p&gt;

&lt;p&gt;This is the second question on the Worky page, about where the shared words live so that "moved" means the same thing on every screen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu2iemw89iezgzp6alj6u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu2iemw89iezgzp6alj6u.png" alt="The top of the second question on the Worky decision page in Obsidian: a row of tags reading " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A sentence can say the three screens use three different words. The picture shows it, and a chat round has nowhere to put one.&lt;/p&gt;

&lt;h2&gt;
  
  
  See what could break before you choose
&lt;/h2&gt;

&lt;p&gt;Under the finding sits a short "what could break" table: the change, what breaks, and how we'd find out. Rows where nothing fails and you only find out late are tinted, so I can spot the dangerous ones without reading every cell.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbxo84rotrd5oji068qcn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbxo84rotrd5oji068qcn.png" alt="The " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The tinted row is the reason the recommendation is a typed package: with the other two options, a wrong word on one screen fails silently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Answer right next to the question
&lt;/h2&gt;

&lt;p&gt;Under the table come the options as checkboxes, with a green Recommended tag on one of them, an empty slot to type in, and a folded block called "Dev details".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fygbxo1jfmovmvevuk76f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fygbxo1jfmovmvevuk76f.png" alt="The end of the second question: three options as cards with a Recommended tag on the first, an empty typing slot, and a folded block named " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The recommendation is marked but never ticked, because a ticked box should always mean I decided. If Claude ticked it for me, I couldn't tell my agreement from my not reading.&lt;/p&gt;

&lt;p&gt;"Dev details" holds the code and the file names: what the package would export, and where each screen keeps its words today. I don't need it to choose, so it stays closed, and whoever wants to check Claude's reading opens it. The rule I ended up with is that what I need to decide is open, and what I'd only need to check is folded.&lt;/p&gt;

&lt;p&gt;There's no plugin and no form to export. The page is the form, so my answers stay as text beside the question they answer.&lt;/p&gt;

&lt;p&gt;When I say I'm done, Claude reads the page in a set order:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The "Talk to me" box at the top first, because that's where I'd say it's asking the wrong question.&lt;/li&gt;
&lt;li&gt;The assumptions it listed, to see if I struck one out.&lt;/li&gt;
&lt;li&gt;Which options I ticked.&lt;/li&gt;
&lt;li&gt;Anything I typed beside a question.&lt;/li&gt;
&lt;li&gt;Questions I left blank, which usually means the question was wrong.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then it tells me what it understood, in one short block, before doing anything. A ticked box with "but only for the Crew App" typed beside it isn't the same answer as a ticked box, and that block is where a misreading gets caught.&lt;/p&gt;

&lt;h2&gt;
  
  
  The skill that writes it and the styles that draw it
&lt;/h2&gt;

&lt;p&gt;I don't build these pages by hand, and Claude doesn't make them up each time either. Two pieces do the work, and they were built together.&lt;/p&gt;

&lt;p&gt;The first is a skill called &lt;code&gt;create-decision&lt;/code&gt;. It knows the parts a decision page can use and when to use each one: the tags, the one-line summary, the "What I found" list, the picture, the "what could break" table, the options, the typing slot and the folded "Dev details". Not every question gets every part. A quick call has no table and no picture, and the debate has all of them. The skill writes each part as plain markdown: a short &lt;code&gt;span&lt;/code&gt; with a class name for a tag, a normal table for what could break, a checkbox list for the options, a callout that starts folded for the code. It also holds the rules from this article: the finding above the options, the code folded below them, never ticking for you, and the read-back order.&lt;/p&gt;

&lt;p&gt;The second is the vault's stylesheet, &lt;code&gt;vault.css&lt;/code&gt;, the one from the &lt;a href="https://alfredo-perez.dev/blog/2026-10-01-make-your-vault-look-right" rel="noopener noreferrer"&gt;first article&lt;/a&gt;. A few lines in it draw each part: the &lt;code&gt;span&lt;/code&gt; becomes a pill, a flag in one table cell tints the whole row, each checkbox becomes a card, and &lt;code&gt;==Recommended==&lt;/code&gt; becomes the green tag. The decision page is the same stylesheet put to work on one kind of note.&lt;/p&gt;

&lt;p&gt;Here are the parts in one picture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdyke1lcdsn11o5gjjhmd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdyke1lcdsn11o5gjjhmd.png" alt="A hand-drawn diagram titled " width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The two pieces know about each other through the &lt;code&gt;obsidian&lt;/code&gt; skill from that first article. It lists the components the vault can draw, with the markdown for each one. &lt;code&gt;create-decision&lt;/code&gt; picks from that list, so when I added the tinted row, I added it in both places: one rule in &lt;code&gt;vault.css&lt;/code&gt;, one line in the component list, and the decision skill could use it the next time.&lt;/p&gt;

&lt;p&gt;That split is why the page survives outside Obsidian. Open it in any editor and the questions, the options and my answers are all still there as text. Only the cards and the colors are gone.&lt;/p&gt;

&lt;p&gt;The parts are the ones I wanted. If you don't want the tags, or you want the code open, or you'd rather have a "what we tried before" list than a table, you say that to Claude and it changes the skill, so every page after that has the parts you chose.&lt;/p&gt;

&lt;p&gt;Both pieces are in the &lt;a href="https://github.com/alfredoperez/obsidian-claude-vault" rel="noopener noreferrer"&gt;obsidian-claude-vault repo&lt;/a&gt;: the skill under &lt;code&gt;.claude/skills/create-decision&lt;/code&gt;, the styles in &lt;code&gt;.obsidian/snippets/vault.css&lt;/code&gt;, and the Worky page at &lt;code&gt;Projects/Worky/decisions/One calendar or three.md&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Watch answered questions fold into phases
&lt;/h2&gt;

&lt;p&gt;Once I answer a question, it becomes a numbered decision, and the decision moves into the phase of work it led to. Here's the whole loop.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fimlz1snybmg9cf3k0e17.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fimlz1snybmg9cf3k0e17.png" alt="A five-step loop of simple blue sketches: doc written by Claude, you answer in the file in Obsidian (highlighted), Claude reads it back, answers become decisions in folders D1 and D2, and a next-round page with one open question that leads back to the start" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the Worky page I answered the first question in round one: three views over one schedule. That's now D1. It sits inside the phase that's in progress, folded, with my reason, the options I didn't pick, and what would make me reopen it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmyzepenuibj4v6gbt0mh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmyzepenuibj4v6gbt0mh.png" alt="The " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As the project moves, finished phases collapse to a single line with a colored status. The page gets shorter as more gets decided. What's left open is at the top, and the history is one click away, filed under the work it produced instead of the order I was asked. The numbers never get reused, because people say "D1" long after the round that made it.&lt;/p&gt;

&lt;p&gt;My first version let these pages expire after a few weeks. I changed my mind, because the answered page turned out to be the most useful note in the project folder. When something changes, I open the decision, read the "revisit if" line, and decide again with the old reasoning in front of me. And before Claude writes a new decision page, it reads the project's decisions folder, so it doesn't ask me something I already settled.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it, then make your own
&lt;/h2&gt;

&lt;p&gt;Pick a decision you've been putting off, the kind where you've said "let me think about it" at least once. Ask Claude to read the notes around it and write you a decision page with a recommendation for each question, then answer it tomorrow with coffee. If you want a working example first, clone &lt;a href="https://github.com/alfredoperez/obsidian-claude-vault" rel="noopener noreferrer"&gt;obsidian-claude-vault&lt;/a&gt; and open the Worky calendar decision. One call is already filed in its phase, and two questions are waiting for you.&lt;/p&gt;

&lt;p&gt;Decisions are only my example. The same two pieces work for any page you answer or read often: a skill that knows which parts the page can use, and a few styles that draw them. It could be a weekly review you tick through, or a bug list with a tag on each item saying how sure the finding is. Tell Claude what you want to see when you open the page and how you want to answer it, then ask it to write the skill and the styles. Mine took a few rounds of "this part looks off" before it settled, and yours will too.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>tutorial</category>
      <category>documentation</category>
    </item>
    <item>
      <title>Make Your Vault Look and Read the Way You Want</title>
      <dc:creator>Alfredo Perez</dc:creator>
      <pubDate>Mon, 05 Oct 2026 13:26:37 +0000</pubDate>
      <link>https://dev.to/alfredoperez/make-your-vault-look-and-read-the-way-you-want-fdk</link>
      <guid>https://dev.to/alfredoperez/make-your-vault-look-and-read-the-way-you-want-fdk</guid>
      <description>&lt;p&gt;I wanted my vault to look right. Not a theme someone else picked, and not the default gray, but a place I'd actually want to open every morning, with notes that tell me where things stand before I read a paragraph. You can get both now by showing Claude a picture of what you like, saying what you want in a sentence, and telling it what's off until it matches.&lt;/p&gt;

&lt;p&gt;For years I had two options: live with the default look, or spend an evening hunting for a theme and then in forum threads guessing which of a hundred settings controlled the sidebar. I never learned the styling side of Obsidian, and I still haven't. What changed is that I stopped trying to write it and started describing the result. Claude does the reading that used to cost the evening.&lt;/p&gt;

&lt;p&gt;This post belongs to a series on keeping your notes in markdown and letting Claude do the parts that used to be expensive. The argument going around is that documentation should move to HTML because it looks better and can do the layout. I'd rather keep the plain files and make them look right, and this post covers both halves of that: how the vault looks, and how the notes inside it read.&lt;/p&gt;

&lt;h2&gt;
  
  
  My taste is only the example
&lt;/h2&gt;

&lt;p&gt;What I liked was &lt;a href="https://bear.app" rel="noopener noreferrer"&gt;Bear&lt;/a&gt;. Its dark sidebar, the calm light page next to it, the way nothing competes with the text. So my example is a Bear-style vault with a dark blue rail in the Tokyo Night palette.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxcptsl965mriq0a2fdtg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxcptsl965mriq0a2fdtg.png" alt="Bear's own picture of its app: a dark list of tags and folders in a sidebar, next to light notes with a table of contents and backlinks." width="688" height="771"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's Bear's picture of itself, from &lt;a href="https://bear.app" rel="noopener noreferrer"&gt;bear.app&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You'll want something else, and that's the point. Maybe it's Craft, or a notebook you used in school, or a screenshot of an app you saw on someone's desk. The method below doesn't care what the target is. It cares that you can point at it and say what's wrong with the first try.&lt;/p&gt;

&lt;h2&gt;
  
  
  Show it, say it, repeat
&lt;/h2&gt;

&lt;p&gt;The whole thing is three moves. I give Claude a screenshot of the look I want, tell it which part of the vault I'm talking about, and ask it to make my vault look like that. Then I switch the change on, compare, and say what's off.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg8r1ck1k6l5r5l8txbbv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg8r1ck1k6l5r5l8txbbv.png" alt="A three-stop loop drawn left to right: a phone outline labeled what I want, a themes folder marked with a small orange Claude logo, and a snippet.css file going into a snippets folder marked with a small purple Obsidian logo, with an arrow from the snippets folder back to the phone labeled compare." width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The arrow back to the screenshot is the part that matters. Claude reads how Obsidian draws each part of the screen and writes a small add-on file for the one piece I named, so I never have to learn what any of it is called. Obsidian lets you switch each of those add-ons on or off in its Appearance settings, which means &lt;strong&gt;every change is one toggle away from undone&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc0mxsg5n7pr54eke62hk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc0mxsg5n7pr54eke62hk.png" alt="Obsidian's Appearance settings with the CSS snippets list open: each add-on has its own switch, and the one for the sidebar is highlighted." width="800" height="845"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The sidebar, start to finish
&lt;/h3&gt;

&lt;p&gt;The sidebar was the hardest part, so I started there. In the example vault it's drawn by a plugin called Notebook Navigator, which ignores most of Obsidian's usual styling. I didn't know that. Claude found it out by reading the plugin's own files, and it found the settings the plugin exposes for its colors.&lt;/p&gt;

&lt;p&gt;My request was close to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Look at the attached Bear screenshot. I want a dark left rail in the
Tokyo Night blue, and everything else should stay light. Only change
the navigation pane. Put it in its own file I can switch off, and
explain the colors in a comment at the top.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I named one surface, the dark rail and nothing else, because "make it look like Bear" is too loose. A change that restyles the sidebar and the editor together ends up repainting the whole app. One surface kept the result small and easy to undo.&lt;/p&gt;

&lt;p&gt;What came back was one small file, and a choice I wouldn't have made on my own. It used two shades of the same blue: a bright one on the dark rail, and a darker twin for links and buttons on the light side. The reason was in the comment it wrote at the top of the file: the bright blue washes out against a white page, so it's hard to read there, and the darker one would disappear on the dark rail. I'd have picked one blue, found half of it unreadable, and blamed the theme.&lt;/p&gt;

&lt;p&gt;The picture shows what's touched and what isn't.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe1h9yehyyh2lm5jx4igb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe1h9yehyyh2lm5jx4igb.png" alt="A simple app window whose narrow left rail is filled solid blue, highlighted in coral, with a tag reading --nn-theme-* and an orange Claude logo pointing at it, while a padlock, a tag reading --background-primary and a check sit on the light editor pane to show it is left alone." width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Only the rail went dark, which is what makes it feel like Bear rather than a dark mode. After that it was a few one-sentence fixes: the selected row is too bright, the counts are hard to read, the icons need to match the blue.&lt;/p&gt;

&lt;p&gt;Here's a note before and after, with every change switched off and then on. I didn't change a word of the note itself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjjh7fs0nwu5wzymfc1so.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjjh7fs0nwu5wzymfc1so.png" alt="The example vault's weekly crew update open with the default sidebar, the default narrow reading column and no heading markers, with every add-on switched off." width="800" height="582"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6ux5cli6biwigwqzmj7j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6ux5cli6biwigwqzmj7j.png" alt="The same note at the same scroll position with the look switched on: a dark blue navigation rail, a wider reading column, small heading level markers in the margin, and the callouts, stats and cards drawn as components." width="800" height="582"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nothing in the note moved, only what draws it. That's why I'm comfortable letting Claude change how the vault looks at all: &lt;strong&gt;the notes stay plain text any editor can open&lt;/strong&gt;, and switching the look off puts you back exactly where you started.&lt;/p&gt;

&lt;p&gt;The smaller asks worked the same way, one sentence each. "Make the reading column wider" took it from Obsidian's default of 700 pixels to 1,000, and Claude's note at the top said it only works with the "Readable line length" option on, which saved me ten confused minutes. "Show me each heading's level in the margin while I edit" added a small muted marker that hides on the line your cursor is on. And "make the Calendar start weeks on Monday" was one change to that plugin's settings. None of them was hard. &lt;strong&gt;The value was not having to find where Obsidian keeps those knobs.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The same method, inside the notes
&lt;/h2&gt;

&lt;p&gt;A vault that looks right still holds notes that read like a wall of bullets. Every time I liked a widget in an HTML doc, I rebuilt it by hand: a two-column compare here, a green, amber and red matrix there, a pipeline with little arrows between the steps. Each one lived in the page that used it, so the next page got a slightly different copy.&lt;/p&gt;

&lt;p&gt;Worse, I couldn't find anything I'd written in them. At one point about 140,000 words of my notes, roughly a tenth of the whole vault, sat inside HTML pages that search couldn't see. A page can look exactly right and still be a dead end: you can't search it, link to it, or stumble on it from another note. Markdown notes stay searchable and linkable, which is why I want the good look inside the notes and not in a separate page.&lt;/p&gt;

&lt;p&gt;So I gave the shapes I kept rebuilding a name, and taught Claude the names. Here's the same weekly update written twice with the same facts. On the left it's what I used to write. On the right it's what I get now when I ask for it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu0vjspdtgntzsk12z1d3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu0vjspdtgntzsk12z1d3.png" alt="Two panes side by side in Obsidian: on the left a weekly crew-scheduling update as plain markdown with headings, bullets and one table; on the right the same update with a one-line thesis box, a row of stat tiles, two tinted cards and a rail of project phases." width="800" height="531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The right-hand version answers "where are we?" before you read a sentence, and it's still the same plain file underneath. My set is cards, phases, a matrix and a handful of others. If you're always writing pros and cons, meeting agendas or reading lists, those are your components.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ask for a comparison, get cards
&lt;/h3&gt;

&lt;p&gt;When two things are being compared, I ask for cards.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Compare the MVP with the full vision as two cards.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What comes back is two boxes side by side, each with a title and a line or two.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feml8ojlx2t9n72runddm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feml8ojlx2t9n72runddm.png" alt="Two side-by-side cards in reading view, the left tinted blue and the right tinted green, each with a short title and one line of text." width="800" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The two colors do the comparing before you read a word. That's on purpose: two matching gray boxes make the reader work out which is which, which defeats the layout. If you'd rather have them in your own colors, or three across instead of two, that's one sentence to Claude.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ask for a plan, get phases
&lt;/h3&gt;

&lt;p&gt;When the work has an order, I ask for phases.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Turn this plan into phases. Phase 1 is in flight, keep only that one open.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm8jfgx1xrdrtbzlpbkqa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm8jfgx1xrdrtbzlpbkqa.png" alt="A phase rail in reading view: five folded phases with done, next, queued and parked chips, and one open phase marked now." width="800" height="541"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every phase is folded except the one being worked on, so the rail reads as a column of status chips with one open block. The states are a small closed set: done, now, next, queued and parked. "Later" is missing on purpose, because it hides why something isn't next. Queued means ready but not prioritized, and parked means blocked by something outside the work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ask for a matrix, see the shape
&lt;/h3&gt;

&lt;p&gt;This is the demo I use to explain why names matter. The example vault gives Claude a short guide to every component: its name, what it's for, and how to write it. Claude reads that guide before it writes any note, and that's how a plain request becomes a finished shape.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flvz6qk17pvkebyksvzk1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flvz6qk17pvkebyksvzk1.png" alt="Four stops left to right: a speech bubble reading a comparison, an open book labeled obsidian skill under an orange Claude logo, a two-row grid with a strip of three boxes labeled matrix + legend, and a sheet labeled vault.css." width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Take a comparison in plain prose: Companion has an in-editor interface and spec-kit doesn't, and for auto-mode it's the reverse, with spec-kit only partial. Read that twice and you have the facts. Now ask for it as a matrix.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Turn this comparison into a capability matrix with a legend.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsea9oc6noln51iwjtoq4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsea9oc6noln51iwjtoq4.png" alt="A two-row capability matrix with green, red and amber cells and a legend of three color swatches directly beneath it." width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The matrix isn't prettier so much as faster. You see the shape of the data instead of holding three clauses in your head. Two rows are a toy, and at ten rows the difference is the whole point.&lt;/p&gt;

&lt;h3&gt;
  
  
  The rules that keep them safe
&lt;/h3&gt;

&lt;p&gt;I cared about three things. Each component is one of Obsidian's built-in boxes for notes and warnings, called callouts, with a name I chose, so nothing has to be installed for the text to make sense. If the look is missing, a set of cards shows up as a plain gray box labelled "Cards", ugly but readable. And a matrix cell says "partial" in words, colored amber, instead of a yellow circle, because you can't search for a circle.&lt;/p&gt;

&lt;p&gt;There's one more rule, and it's the first line of the components page in the example vault: &lt;strong&gt;don't decorate.&lt;/strong&gt; Most notes are prose and a callout or two. A component is for content that has a shape, like a comparison, a sequence or a status.&lt;/p&gt;

&lt;p&gt;The rest of the shelf is smaller: a box for terminal output, a frame for a diagram, a story map, a folder tree, a row of numbers when the numbers are the finding, and a few inline tags.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft4pfgz9r3845juz2kalx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft4pfgz9r3845juz2kalx.png" alt="Eight small blue line drawings in a row above a shelf, labeled callout, cards, ticket, phase, matrix, terminal, story map and tree, with a vault.css sheet hanging below the shelf." width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Eight shapes cover most of what I used to build by hand in HTML&lt;/strong&gt;, and they share one look, so a note from March matches a note from today. The guide also carries my mistakes, which is what makes the corrections stick. The one I remember is a story map that borrowed the matrix's legend and showed colors that appeared nowhere in the map. Nothing errors to tell you a key is lying. Now "the legend uses the same colors as the cells" is written where Claude reads it, so I'm not correcting it in every note.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build your own views: a dashboard, a board and a canvas
&lt;/h2&gt;

&lt;p&gt;Components change how one note reads. Sometimes what I want is a page that looks across many notes: what's in progress, what's stuck, what changed this week. Obsidian has three ways to build that, and I ask Claude for each of them the way I ask for everything else.&lt;/p&gt;

&lt;h3&gt;
  
  
  A dashboard that keeps itself current
&lt;/h3&gt;

&lt;p&gt;The Dataview plugin builds a page from what your notes say about themselves, like a status or a date. Nothing on the page is typed by hand, so it can't go stale. In the example vault it powers a Worky dashboard with the crew-scheduling stories counted by status, the open decisions, and the latest updates and meetings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Make a dashboard page for the Worky project. Show its stories grouped by
status, the decisions that are still open, and the latest updates and meetings.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I adjust. "Make the status a colored chip." "Only show this week." "Put the blocked ones at the top." Each one is a sentence, and the page rebuilds itself when the notes change.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fingtb08me91oo7mhnjuz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fingtb08me91oo7mhnjuz.png" alt="The same Worky dashboard with the styling snippet switched off: the tables are plain, and each status is bare text with no chip." width="696" height="1270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The same page with one snippet switched on. Nothing about the data changed. The statuses became chips, the headers got quieter, and the dates now stay on one line:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpan1bi4k8nrmlrmmb4al.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpan1bi4k8nrmlrmmb4al.png" alt="The Worky dashboard in reading view: a table of stories grouped by status with a colored chip on each status, a table of open decisions with the time left, and a table of the latest updates and meetings." width="696" height="1270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The latest-updates list only works because each note carries a date at the top. I hadn't written one, so I asked Claude to add it to the three notes and to sort the list by it. That's the pattern with a dashboard: if a table can't show something, the notes don't say it yet, and you ask Claude to make them say it.&lt;/p&gt;

&lt;p&gt;The dashboard is a question the vault answers every time you open it, which is why I stopped keeping status lists by hand.&lt;/p&gt;

&lt;h3&gt;
  
  
  A board where cards are notes
&lt;/h3&gt;

&lt;p&gt;Obsidian's Bases feature can show notes as a Kanban board. Each column is one value of a property, like status, and each card is a note. Drag a card to another column and Claude isn't involved at all: Obsidian changes that property in the note for you.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Show the crew-scheduling stories as a Kanban board, one column per status.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That gave me the board.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm48s5vgzvyc9wr1ywtwz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm48s5vgzvyc9wr1ywtwz.png" alt="The board as a Kanban view, with one tinted column per story status and each story as a card with its ID." width="800" height="608"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It has limits, and a good review of it at &lt;a href="https://practicalpkm.com/kanban-review/" rel="noopener noreferrer"&gt;Practical PKM&lt;/a&gt; lays them out. A board groups by one property only, every card has to be its own note, and you can't reorder cards inside a column. As of this writing it's also an early-access feature in Obsidian, so it may not be in your version yet. It isn't the older Kanban plugin, which keeps its cards inside a single file. If you need a plain checklist board in one note, that's a different tool.&lt;/p&gt;

&lt;h3&gt;
  
  
  A canvas for arranging things
&lt;/h3&gt;

&lt;p&gt;A canvas is an open board of cards and arrows, which suits a story map better than a list does. The example vault has one for crew scheduling, with the stories laid out in lanes. I asked for softer cards, and the look came from a snippet, the same as the sidebar. What came back is plain white cards with quiet borders inside tinted lanes, with a yellow card marking the one thing that blocks the rest.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Make the cards on the story map softer: rounded, a pale tint per lane,
and no heavy borders.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F41pykehzxv3sku5d6kl5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F41pykehzxv3sku5d6kl5.png" alt="Part of the crew-scheduling story map on a canvas: a tinted backbone lane above release lanes, plain white cards with their ticket numbers, one yellow card marking a blocker, and arrows between the lanes." width="800" height="743"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The lanes and arrows say where a story sits in the whole plan, which a list of the same stories can't.&lt;/p&gt;

&lt;h3&gt;
  
  
  One idea behind all three
&lt;/h3&gt;

&lt;p&gt;All three read your notes as they are. Nothing about the notes changes to make them show up: they stay plain markdown, with a line at the top saying what they are. &lt;strong&gt;You style the view, not the data.&lt;/strong&gt; So I ask Claude for the view, look at it, and say what to change, and if I ever drop the plugin, the notes are exactly what they were.&lt;/p&gt;

&lt;h2&gt;
  
  
  Good plugins to start with
&lt;/h2&gt;

&lt;p&gt;The example vault switches on six community plugins. Each one is something you can set up by saying what you want, the same way as the sidebar.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://obsidian.md/plugins?id=notebook-navigator" rel="noopener noreferrer"&gt;Notebook Navigator&lt;/a&gt; replaces the file list with a two-pane browser, folders on the left and notes with a short preview on the right. It's the Bear feel. Try: "Show two lines of preview under each note and hide the note that shares its folder's name."&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://obsidian.md/plugins?id=calendar" rel="noopener noreferrer"&gt;Calendar&lt;/a&gt; puts a month view in the right sidebar and opens the note for any day you click. Try: "Add a week column to the Calendar so I can open a note for the whole week."&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://obsidian.md/plugins?id=dataview" rel="noopener noreferrer"&gt;Dataview&lt;/a&gt; turns a question into a list that keeps itself up to date, like every open decision in a project. The example vault's Worky dashboard is built with it, so you can see one at work. Try: "Add a list to this project note of every note tagged decision that isn't done."&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://obsidian.md/plugins?id=obsidian-excalidraw-plugin" rel="noopener noreferrer"&gt;Excalidraw&lt;/a&gt; lets you draw diagrams that live in the vault and stay editable. The skills that write a product spec or a roadmap save their diagrams this way. Try: "Draw this flow as an Excalidraw diagram I can move things around in."&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://obsidian.md/plugins?id=callout-menu" rel="noopener noreferrer"&gt;Callout menu&lt;/a&gt; adds a right-click menu to any box in a note, to change its kind, fold it or copy what's inside. Try: "Add my component names to Callout menu so I can turn a box into cards or phases with a right-click."&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://obsidian.md/plugins?id=obsidian-admonition" rel="noopener noreferrer"&gt;Admonition&lt;/a&gt; is switched on too, but honestly nothing in the example vault needs it, because Obsidian's built-in callouts draw every component. You can skip it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One plugin was removed on purpose: Code Styler restyles the small code-looking tags that the phase and story chips are drawn from, so it breaks them.&lt;/p&gt;

&lt;p&gt;The loop for plugin settings is the same as for the look: you say what you want, Claude changes the plugin's settings, and you reload the plugin.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqs1ocxh3lsyw9z5steee.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqs1ocxh3lsyw9z5steee.png" alt="Three steps left to right: a person says say what you want, a data.json file sits in a folder marked with an orange Claude logo, then a puzzle piece with a circular arrow reads reload the plugin, with a note beneath the folder and a purple Obsidian logo reading quit Obsidian first." width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The coral note is the catch worth knowing before you start. Obsidian keeps some settings in memory and writes them back when it closes, so a change made while it's open can get quietly overwritten. If a change doesn't stick, quit Obsidian, ask again, and reopen.&lt;/p&gt;

&lt;p&gt;Claude will also tell you when you're asking the wrong plugin. I assumed I could point Calendar at a folder for daily notes, and Claude came back and said Calendar has no such option: in the example vault, Notebook Navigator decides where daily notes go. I'd never have found that by clicking through settings panes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping it tidy
&lt;/h2&gt;

&lt;p&gt;I asked Claude to keep each change separate: one for the sidebar, one for the reading width, one for the heading markers, one for the components. When an Obsidian update breaks one thing, I switch off one piece instead of hunting through everything. I also kept the comment Claude writes at the top of each change. It's the only record of why the sidebar uses two blues, and six months from now I won't remember. Because all of this lives inside the vault folder, it travels with the notes to any machine they sync to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Open your vault, take a screenshot of an app whose look you like, and ask Claude for one thing: "make my sidebar look like this, and only the sidebar." Switch it on, say what's off, and go again. Then pick one comparison paragraph you already have and ask Claude to "turn this into two cards." When you catch yourself asking for the same shape twice, ask Claude to give it a name and add it to the guide. The example vault at &lt;a href="https://github.com/alfredoperez/obsidian-claude-vault" rel="noopener noreferrer"&gt;github.com/alfredoperez/obsidian-claude-vault&lt;/a&gt; has my Bear version and my set of components if you'd rather start from something and take it somewhere else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Under the hood
&lt;/h2&gt;

&lt;p&gt;Each change to the look is a CSS snippet, a small file in the vault's &lt;code&gt;.obsidian/snippets&lt;/code&gt; folder that Obsidian lists under Settings, Appearance, CSS snippets: &lt;code&gt;bear-sidebar.css&lt;/code&gt;, &lt;code&gt;line-width.css&lt;/code&gt; and &lt;code&gt;heading-levels.css&lt;/code&gt;. One stylesheet, &lt;code&gt;vault.css&lt;/code&gt;, draws every component, keyed off each callout's name so plugins don't break it. The guide Claude reads is the &lt;code&gt;obsidian&lt;/code&gt; skill in &lt;code&gt;.claude/skills&lt;/code&gt;, and &lt;code&gt;Reference/Components.md&lt;/code&gt; shows every component. A small stylesheet, &lt;code&gt;views.css&lt;/code&gt;, gives the dashboard and the canvas their look, and the board is a &lt;code&gt;.base&lt;/code&gt; file next to the stories it shows. Plugin settings live in each plugin's own folder, and &lt;code&gt;.obsidian/README.md&lt;/code&gt; lists the six plugins and why each is there. All of it is in the &lt;a href="https://github.com/alfredoperez/obsidian-claude-vault" rel="noopener noreferrer"&gt;example vault&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>tutorial</category>
      <category>documentation</category>
    </item>
    <item>
      <title>Build Log 4: Your Pipeline, as Nodes</title>
      <dc:creator>Alfredo Perez</dc:creator>
      <pubDate>Mon, 05 Oct 2026 13:26:06 +0000</pubDate>
      <link>https://dev.to/alfredoperez/build-log-4-your-pipeline-as-nodes-42j9</link>
      <guid>https://dev.to/alfredoperez/build-log-4-your-pipeline-as-nodes-42j9</guid>
      <description>&lt;p&gt;How many settings should it take to answer one question?&lt;/p&gt;

&lt;p&gt;The question was simple: how much ceremony do you want for this change? But SpecKit Companion had grown &lt;strong&gt;three&lt;/strong&gt; different knobs to answer it. There was Template Profile (&lt;code&gt;standard&lt;/code&gt; / &lt;code&gt;turbo&lt;/code&gt; / &lt;code&gt;off&lt;/code&gt;). There was a Turbo Workflow Picker. There was a Complexity Fast Path toggle. Each one earned its place honestly, shipped for a real reason in its own build log. That is the part worth saying out loud: none of them was a mistake on its own.&lt;/p&gt;

&lt;p&gt;But stacked together, they were a maze. I built them, and even I had to stop and think about which combination did what.&lt;/p&gt;

&lt;p&gt;That is the smell of a design problem. When the controls for one decision multiply, the decision is the thing that needs fixing, not the controls.&lt;/p&gt;

&lt;p&gt;So this wave replaced all three with one idea: your pipeline is now a plain list of steps you can read, reorder, and add to, instead of a fixed sequence buried in code. Three toggles collapse into one picker, and when the list finishes it marks the spec done on its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  The knobs were patches on something deeper
&lt;/h2&gt;

&lt;p&gt;Here's the thing the toggles were quietly admitting: the pipeline underneath was &lt;strong&gt;hardcoded&lt;/strong&gt;. It was always the same fixed sequence, specify then plan then tasks then implement, baked into the code. The settings couldn't reshape that sequence. All they could do was nudge it from the outside, trimming a template here, skipping a step there. Three knobs, all working around the same limitation.&lt;/p&gt;

&lt;p&gt;You can see the cost up close in one file. The &lt;code&gt;specify&lt;/code&gt; command was 142 lines doing seven different jobs back to back, and three of those jobs were copy-pasted to live somewhere else too. The logic that sizes a change as small or large sat inside &lt;code&gt;specify&lt;/code&gt;, &lt;em&gt;and&lt;/em&gt; inside a standalone &lt;code&gt;classify&lt;/code&gt; command, &lt;em&gt;and&lt;/em&gt; described a third time in the workflow file. So "change how we decide a change is small" meant editing the same idea in three places and hoping they stayed in sync. There was even a parity checker whose entire job was to catch them drifting apart. When you need a robot to babysit your copies, the copies are the problem.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fudf6embs1jz81xlspdfi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fudf6embs1jz81xlspdfi.jpg" alt="A specify.md file crammed with seven jobs, with classify and route tagged copied in 3 places, becoming a clean numbered list of nodes where each job has a single home" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the left: one file doing seven jobs, the sizing logic tagged in all three places it got copied. On the right: that same idea collapsed into a single node. Everything in this wave is the move from left to right.&lt;/p&gt;

&lt;p&gt;So the real fix was never "remove a setting." It was to change what the pipeline &lt;em&gt;is&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your pipeline is now a list of nodes
&lt;/h2&gt;

&lt;p&gt;Stop treating the pipeline as code. Treat it as &lt;strong&gt;data&lt;/strong&gt;. A workflow is just an ordered list of nodes, and now it literally is one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 📃 speckit-companion.workflow.yml&lt;/span&gt;
&lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;specify&lt;/span&gt; &lt;span class="c1"&gt;# 👇 writes the spec&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;classify&lt;/span&gt; &lt;span class="c1"&gt;# 👇 sizes the change: small | normal | oversized&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;route&lt;/span&gt; &lt;span class="c1"&gt;# 👇 the fork: less ceremony for small, full pipeline otherwise&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mark-complete&lt;/span&gt; &lt;span class="c1"&gt;# 👇 the last node: writes status: completed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So what &lt;em&gt;is&lt;/em&gt; a node? It's just a named step with a job, and there are only four jobs it can have. Here they are, side by side:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzx7k1uwegia140rr5775.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzx7k1uwegia140rr5775.jpg" alt="The four kinds of node: investigate, author, gate, and control, each drawn as a card with an icon and a one-line description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A node either &lt;strong&gt;investigates&lt;/strong&gt; (reads the request and the code, gathers understanding, writes no document), &lt;strong&gt;authors&lt;/strong&gt; (writes one specific file or section, like &lt;code&gt;specify&lt;/code&gt; producing the spec), &lt;strong&gt;gates&lt;/strong&gt; (a check or review pause), or &lt;strong&gt;controls&lt;/strong&gt; (routes or finishes, like &lt;code&gt;route&lt;/code&gt; and &lt;code&gt;mark-complete&lt;/code&gt;). Notice there's no fifth kind. That constraint is the trick: because a node can only do one of four things, the workflow reads like a sentence instead of a program. Write the spec, size it, fork on the size, finish. That's all a pipeline is now.&lt;/p&gt;

&lt;p&gt;(Today these are whole commands lined up. The next step is finer grained, letting the &lt;em&gt;sections inside&lt;/em&gt; a command be nodes too, so you could pick exactly which parts of a spec get written. That's still being built; the grammar above is what it'll be built on.)&lt;/p&gt;

&lt;p&gt;This is the whole point of the wave, so it is worth sitting on. Once the pipeline is a list, the things the old toggles fought for stop being toggles and become &lt;strong&gt;nodes in the list&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;"Less ceremony for a small change" used to be the Complexity Fast Path setting. Now it is the &lt;code&gt;route&lt;/code&gt; node. It reads the size from &lt;code&gt;classify&lt;/code&gt; and picks a path: a small change runs plan and tasks without the review-gate pauses, anything normal runs the full gated pipeline, and an oversized change warns out loud and then runs the full pipeline anyway. The safe default is always the full path, so an unclear size never silently drops a step.&lt;/p&gt;

&lt;p&gt;"Mark the spec done when it's actually done" used to be a manual click. Now it is the terminal node. When the list finishes, the spec lands at &lt;code&gt;completed&lt;/code&gt; on its own.&lt;/p&gt;

&lt;p&gt;Put it together and the fork you used to toggle is right there in the list:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr3cby3t0kur5d2efo7vq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr3cby3t0kur5d2efo7vq.jpg" alt="A pipeline drawn as four numbered nodes: specify, classify, route, mark-complete, where the route node forks into small, normal, and oversized paths" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The diamond is &lt;code&gt;route&lt;/code&gt;, reading the size and picking a path. The mint check is the terminal node closing the spec. What used to be two hidden toggles is now two visible nodes you can point at.&lt;/p&gt;

&lt;p&gt;Nothing here is a new setting. The behavior moved &lt;em&gt;into&lt;/em&gt; the workflow, where you can see it and reshape it, instead of living in a pile of checkboxes that hide it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you actually see today: one picker
&lt;/h2&gt;

&lt;p&gt;The structural change is large. The visible change is small, and that's fine. The three Beta toggles are gone, replaced by one setting with exactly two values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json-doc"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 📃 settings.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"speckit.defaultWorkflow"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"companion"&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// 👈 or "speckit". That's the whole menu.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Create Spec picker pre-selects your choice. Pick &lt;strong&gt;SpecKit&lt;/strong&gt; and you get the stock pipeline, untouched. Pick &lt;strong&gt;SpecKit Companion&lt;/strong&gt; and you get the leaner one, right-sizing built in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjxh3b5y481tcang04l8e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjxh3b5y481tcang04l8e.png" alt="The Create Spec page showing a single picker to choose between SpecKit and SpecKit Companion" width="800" height="695"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One dropdown, two values. That is the entire visible surface of everything above: all the node machinery, reduced to a single choice at the top of the page.&lt;/p&gt;

&lt;p&gt;And because deleting settings is its own kind of risk, the extension migrates on activation. It drops the three retired keys at every scope and coerces the old values, so a leftover entry in someone's &lt;code&gt;settings.json&lt;/code&gt; does not break activation. That bug bit me once with a renamed provider. Not again.&lt;/p&gt;

&lt;p&gt;Now the honest part, because build-in-public is worthless if it only shows the wins. Since the draft, the commands learned to read the list and walk it themselves. In an agentic CLI like Claude Code, you run &lt;code&gt;specify&lt;/code&gt; and it advances to the next node on its own, with the terminal node wired to mark the spec complete. That self-advance is real and shipped.&lt;/p&gt;

&lt;p&gt;The finish line used to be the catch. A panel run would get most of the way and then stick at &lt;code&gt;implementing&lt;/code&gt;, because two writers raced on the same status file. That one is fixed now: status only ever moves forward, so a late or duplicate write can't drag a spec backward, and the terminal node lands it at &lt;code&gt;completed&lt;/code&gt; on its own.&lt;/p&gt;

&lt;p&gt;What's left is cosmetic. One of the close paths can still write a duplicate "done" line into the history, and there's a ticket open for it. The completion itself is solid.&lt;/p&gt;

&lt;p&gt;Two ways to walk the same list, stacked:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4yueozwdmry4gs2hcjlv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4yueozwdmry4gs2hcjlv.jpg" alt="Two lanes: GUI today where you click each step yourself, and self-advancing where the same commands flow on their own to a completed check" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Same nodes, same commands underneath. The only thing that changes between the lanes is who presses next: you, clicking through in a one-shot chat, or the agent walking the list on its own in a CLI that keeps going.&lt;/p&gt;

&lt;h2&gt;
  
  
  The receipt: I shipped this wave's own ticket through it
&lt;/h2&gt;

&lt;p&gt;The right-sizing is already real, and I have the receipt. I built one of this wave's own tickets through the Companion workflow: the Create Spec polish, the very page that picker lives on. It's a small change, a few CSS tweaks and some placeholder copy, so the workflow sized it &lt;code&gt;small&lt;/code&gt; and folded the plan and tasks steps. Those two steps, which on a real feature take minutes of generation, finished in about &lt;strong&gt;80 milliseconds each&lt;/strong&gt;. For a small change there's nothing heavy to write. The plan file came out 204 bytes. Seven tasks, the full suite green (998 tests), and the spec closed out completed. The fold isn't a someday promise. It already runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  When the plan met reality
&lt;/h2&gt;

&lt;p&gt;The best part of this wave was the part that went wrong on paper first.&lt;/p&gt;

&lt;p&gt;My ticket confidently described how to build the workflow, and it was wrong in three specific ways. I only found out because I checked against the actually-installed spec-kit before writing a line of YAML. The routing step I planned didn't exist under that name. Workflows turned out not to register through the extension manifest at all; they live in their own catalog. And my version floor quietly excluded the exact pre-release builds the install produces.&lt;/p&gt;

&lt;p&gt;Three assumptions, three corrections, zero wasted implementation. That is the whole argument for a pre-flight pass. An hour reading the tool you actually have beats a day building against the tool you imagined.&lt;/p&gt;

&lt;h2&gt;
  
  
  The engine I almost rode
&lt;/h2&gt;

&lt;p&gt;The tempting version of this is to write my own runner: a loop that walks the nodes, handles the gates, manages pause and resume. That's a lot of code, so my first instinct was to dodge it entirely. Spec-kit ships its own workflow engine, and on paper it does everything: steps, gates, conditional routing, pause and resume from the exact node you stopped on. Ride that, I figured, and Companion gets a real runner for free.&lt;/p&gt;

&lt;p&gt;Then I actually checked. That engine is genuinely capable, but in this project nothing had wired it up yet: the Companion workflow wasn't registered with it, and every spec I'd shipped, mine and the demos, had run the way people actually run them, one command at a time. Hanging the whole roadmap on a runner that nothing here had ever connected to meant building for a tool I imagined instead of the one in front of me. So I asked a smaller question: where does the self-advance actually need to live?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F16iwwsj43f76m9bnv09k.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F16iwwsj43f76m9bnv09k.jpg" alt="A specify command with gears turning inside it, the flow self-advancing through the nodes to a done check, captioned no separate runner to wire up" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The picture is the answer: the gears live inside the command you already run, not in a separate box you have to start first. &lt;strong&gt;Instead&lt;/strong&gt; of a standalone runner, the command does its own node, then reads the list, finds the next node, and keeps going. Nothing extra to invoke. Running &lt;code&gt;specify&lt;/code&gt; &lt;em&gt;is&lt;/em&gt; running the first node of the engine. The decision that changed this wave was &lt;em&gt;where the engine goes&lt;/em&gt;, and the answer turned out to be "the thing you already run."&lt;/p&gt;

&lt;p&gt;Two honest limits, because this is the part that bites if you don't say it out loud. First, "keep going on your own" needs an agent that keeps acting after a step. So ask one question before you lean on self-advance: does your tool keep acting after a reply, or stop dead after one? Claude Code and the agentic CLIs keep going. Some one-shot IDE chats stop, and there the fallback is you, or the GUI button, firing the next step. The rule the commands carry is "continue if you can." Second, "read the list and run the next node" is the model following instructions, not a bulletproof loop. The bulletproof version is exactly &lt;code&gt;specify workflow run&lt;/code&gt; from a terminal, and that's the command nobody wants to type. So this is a deliberate trade: self-advance that works in your everyday flow with zero special commands, leaning on the agent instead of a hard engine, with the terminal runner still there for anyone who wants the guaranteed version.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this wave taught me
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;When one decision needs three toggles, fix the decision, not the toggles.&lt;/strong&gt; Multiplying controls is the smell; the rigid thing underneath is the real bug.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make the pipeline data, not code.&lt;/strong&gt; A workflow you can read as a list is one you can reorder and extend without editing a command.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check the tool you actually have before you build against it.&lt;/strong&gt; An hour reading the installed spec-kit caught three wrong assumptions and saved a day of rework.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Put the engine in the thing you already run.&lt;/strong&gt; Self-advance lives in the command, so there's no separate runner to wire up.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Here is the part this was all for, and it is no longer a someday promise. The pipeline being a list means you grow it by adding to the list, and the first real addition already runs. A Companion run now ends &lt;em&gt;reviewed and PR'd&lt;/em&gt; instead of as raw code: right before it marks the spec complete, it reviews its own diff against the project's conventions, runs a simplifier pass, and opens a pull request, stopping before merge. None of that is new code in the extension. It is a handful of lines in a &lt;code&gt;.specify/companion.yml&lt;/code&gt; file that the command reads at run time and slots in at the right moment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnd6ftny2r7po395mag3y.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnd6ftny2r7po395mag3y.jpg" alt="A node list with a new review, simplify, open PR node being slotted in by hand just before mark-complete" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice what does not change in that picture. The new node (marigold) drops in one slot before the finish, and every command around it stays exactly as it was. That is what "grow it by adding to the list" actually looks like.&lt;/p&gt;

&lt;p&gt;That is the whole shape of it: because it's just entries in a list, you add your own without rewriting any command. Drop in a security review, pick the exact author steps your team wants, skip the rest. None of it is a new toggle.&lt;/p&gt;

&lt;p&gt;What's genuinely still ahead is making it effortless: a hands-off auto mode that runs the whole list start to finish without anyone pressing next. That has since shipped too, so the next build log is its story.&lt;/p&gt;

&lt;p&gt;Same pipeline. Next time, it drives itself.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Build Log 3: Turbo Mode and the Fast Path</title>
      <dc:creator>Alfredo Perez</dc:creator>
      <pubDate>Mon, 05 Oct 2026 13:25:48 +0000</pubDate>
      <link>https://dev.to/alfredoperez/build-log-3-turbo-mode-and-the-fast-path-1gko</link>
      <guid>https://dev.to/alfredoperez/build-log-3-turbo-mode-and-the-fast-path-1gko</guid>
      <description>&lt;p&gt;spec-kit treats a typo fix and a brand new auth system exactly the same way. Same eight files in the spec folder. Same user-story scaffolding. Same heavy pipeline, whether the change earns it or not.&lt;/p&gt;

&lt;p&gt;For most of what I ship, that is ceremony I never read. A User Scenarios block, a separate &lt;code&gt;checklists/requirements.md&lt;/code&gt; gate, a &lt;code&gt;quickstart.md&lt;/code&gt;, a dual-option Project Structure tree. All of it generated, none of it touched.&lt;/p&gt;

&lt;p&gt;I had already built a leaner shape into &lt;a href="https://dev.to/blog/2026-05-26-build-log-0-rebuilding-sdd-in-public"&gt;SDD&lt;/a&gt;: about three files instead of eight, a short Overview instead of user stories. So this step had two goals. Give spec-kit that same shape without forking it. Then go one further and stop making a one-line change walk the whole pipeline at all.&lt;/p&gt;

&lt;p&gt;That turned into two features, and a week of churn before they settled into a shape I would actually ship.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I shipped
&lt;/h2&gt;

&lt;p&gt;Two features came out of this, and they solve the same problem from two different angles: a typo fix and a new auth system should not cost the same ceremony.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Turbo mode&lt;/strong&gt; changes the &lt;em&gt;shape&lt;/em&gt; of a spec. Same seven commands, but leaner output: no user stories, tasks grouped by the files they touch, side documents written only when they help. A smaller spec folder.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fast Path&lt;/strong&gt; changes the &lt;em&gt;flow&lt;/em&gt;. When a change is genuinely small, it short-circuits the pipeline. No separate plan and tasks stages. It goes straight from specify to implement, in a single run.&lt;/p&gt;

&lt;p&gt;Turbo stands on its own. The Fast Path builds on it, because skipping plan and tasks only makes sense once the shape is already lean, so it fires only when turbo is on. In settings they are two independent switches: &lt;code&gt;speckit.companion.templateProfile&lt;/code&gt; for turbo, &lt;code&gt;speckit.companion.complexityFastPath&lt;/code&gt; for the Fast Path. Both ship opt-in beta. The next two sections take each one in turn: what it is, how to turn it on, and exactly how it compares.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turbo mode
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it is.&lt;/strong&gt; A second shape for the same seven spec-kit commands. &lt;code&gt;companion-standard&lt;/code&gt; is the stock commands, unchanged, with honest timing added. &lt;code&gt;companion-turbo&lt;/code&gt; keeps those same commands but trims the heavy parts: the user stories collapse into a three-line Overview, tasks group by files and dependencies, and the side documents get written only when they actually help. A third value, &lt;code&gt;off&lt;/code&gt;, means plain upstream spec-kit with no overrides at all.&lt;/p&gt;

&lt;p&gt;A quick honesty note on the name. This shipped as &lt;code&gt;lean&lt;/code&gt; first. I renamed it to &lt;code&gt;turbo&lt;/code&gt; before any release, with no alias and no migration. "Lean" sold the wrong thing. The point is not fewer files. The point is that it is faster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to enable it.&lt;/strong&gt; Set the project default &lt;code&gt;speckit.companion.templateProfile&lt;/code&gt; to &lt;code&gt;turbo&lt;/code&gt;. It defaults to &lt;code&gt;off&lt;/code&gt;, so this is opt-in.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 📃 .specify/companion.yml  (machine-local, gitignored)&lt;/span&gt;
&lt;span class="na"&gt;templateProfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;turbo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each spec then carries its own profile pin in &lt;code&gt;.spec-context.json&lt;/code&gt;, so the choice holds all the way through plan, tasks, and implement. Why that pin matters is its own story, below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it differs from standard.&lt;/strong&gt; Here is the full per-file breakdown:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;standard&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;turbo&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;spec.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;User Scenarios / user stories&lt;/td&gt;
&lt;td&gt;a 1-3 line &lt;strong&gt;Overview&lt;/strong&gt;, no user stories&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;tasks.md&lt;/code&gt; axis&lt;/td&gt;
&lt;td&gt;grouped by user story, &lt;code&gt;[US#]&lt;/code&gt; labels, MVP framing&lt;/td&gt;
&lt;td&gt;grouped by &lt;strong&gt;files and dependencies&lt;/strong&gt;, strict &lt;code&gt;[Tn] [P?] + path&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;plan.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;dual-option Project Structure + Complexity Tracking&lt;/td&gt;
&lt;td&gt;a turbo &lt;strong&gt;Approach and Structure&lt;/strong&gt; (files/deps) + Out of Scope&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;requirements.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;full checklist, including acceptance scenarios&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;lean&lt;/strong&gt; self-check, no user-story items&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;research&lt;/code&gt; / &lt;code&gt;data-model&lt;/code&gt; / &lt;code&gt;contracts/&lt;/code&gt; / &lt;code&gt;quickstart&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;written by default&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;on demand&lt;/strong&gt; only, when they help &lt;em&gt;that&lt;/em&gt; change&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Net spec folder&lt;/td&gt;
&lt;td&gt;about 8 files&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;&lt;code&gt;spec.md&lt;/code&gt; + &lt;code&gt;plan.md&lt;/code&gt; + &lt;code&gt;tasks.md&lt;/code&gt; + &lt;code&gt;requirements.md&lt;/code&gt;&lt;/strong&gt;, side files on demand&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Timing fidelity&lt;/td&gt;
&lt;td&gt;honest finish-only&lt;/td&gt;
&lt;td&gt;honest finish-only (identical)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The same split is easier to see stacked side by side.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj5jbpqqrhfq78p1d02ya.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj5jbpqqrhfq78p1d02ya.jpg" alt="A standard eight-file spec folder with a struck-out User Scenarios block beside a lean turbo folder of spec, plan, tasks and a lean requirements checklist, with research, data-model, contracts and quickstart marked on-demand" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Turbo keeps four files where standard keeps eight, and the user stories are the one block it drops outright.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fast Path
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it is.&lt;/strong&gt; The Fast Path lets a small change skip the middle of the pipeline. Under the hood it is a classify step at the end of turbo's &lt;code&gt;specify&lt;/code&gt; command: it reads the spec you just drafted, returns one of two verdicts, &lt;code&gt;simple&lt;/code&gt; or &lt;code&gt;normal&lt;/code&gt;, and then either short-circuits straight to implement or runs the full pipeline. It is best-effort, and it deliberately errs toward &lt;code&gt;normal&lt;/code&gt;. A change never gets under-planned by accident.&lt;/p&gt;

&lt;p&gt;It decides on four inputs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;What it reads&lt;/th&gt;
&lt;th&gt;Pushes toward&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fastPathEnabled&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the &lt;code&gt;complexityFastPath&lt;/code&gt; flag&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;simple&lt;/code&gt; only if &lt;code&gt;true&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;projectedFiles&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;files the change will touch, vs a &lt;strong&gt;5-file&lt;/strong&gt; ceiling&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;normal&lt;/code&gt; if over&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;projectedTasks&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;tasks projected, vs a &lt;strong&gt;10-task&lt;/strong&gt; ceiling&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;normal&lt;/code&gt; if over&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;scopeSignal&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;scope phrases (&lt;code&gt;rewrite&lt;/code&gt;/&lt;code&gt;overhaul&lt;/code&gt;/&lt;code&gt;new system&lt;/code&gt; vs &lt;code&gt;one-line&lt;/code&gt;/&lt;code&gt;rename&lt;/code&gt;/&lt;code&gt;typo&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;larger&lt;/code&gt; forces &lt;code&gt;normal&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A spec is &lt;code&gt;simple&lt;/code&gt; only when the flag is on, both projections sit at or under the ceiling, and the scope signal is not &lt;code&gt;larger&lt;/code&gt;. Anything else is &lt;code&gt;normal&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to enable it.&lt;/strong&gt; Set &lt;code&gt;speckit.companion.complexityFastPath&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;. Like turbo, it defaults to &lt;code&gt;false&lt;/code&gt;, and it only does anything in turbo mode.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 📃 .specify/companion.yml&lt;/span&gt;
&lt;span class="na"&gt;templateProfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;turbo&lt;/span&gt;
&lt;span class="na"&gt;complexityFastPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;# 👇 small changes now fast-track to implement&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If both the project file and the editor setting are present, the project file wins, and the resolved value is mirrored back so the command body reads a single source of truth.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it compares.&lt;/strong&gt; The two branches:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;simple&lt;/code&gt; (Fast Path)&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;normal&lt;/code&gt; (full pipeline)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;When&lt;/td&gt;
&lt;td&gt;flag on, 5 or fewer files, 10 or fewer tasks, no "rewrite" scope&lt;/td&gt;
&lt;td&gt;anything larger, or flag off&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Artifacts&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;one combined &lt;code&gt;spec.md&lt;/code&gt;&lt;/strong&gt; (Approach + Implementation Tasks inline) + &lt;code&gt;requirements.md&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;spec.md&lt;/code&gt;, then &lt;code&gt;plan.md&lt;/code&gt;, then &lt;code&gt;tasks.md&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stages&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;specify&lt;/code&gt; straight to &lt;code&gt;implement&lt;/code&gt; (plan/tasks &lt;strong&gt;folded&lt;/strong&gt;)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;specify&lt;/code&gt;, &lt;code&gt;plan&lt;/code&gt;, &lt;code&gt;tasks&lt;/code&gt;, &lt;code&gt;implement&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lands at&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;ready-to-implement&lt;/code&gt; in &lt;strong&gt;one run&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;each step run on its own&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Over the guardrail&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;warns&lt;/strong&gt;, never a silent fast-track&lt;/td&gt;
&lt;td&gt;not applicable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When the change crosses the guardrail (more than 5 files or 10 tasks, or a "rewrite"-class scope word), the body prints a warning and runs the full pipeline instead. It never silently fast-tracks something big.&lt;/p&gt;

&lt;p&gt;The fold is real, not cosmetic. After specify self-closes, the command writes the folded plan and tasks entries itself, the last one marking the spec &lt;code&gt;ready-to-implement&lt;/code&gt;. So the Companion viewer reads plan and tasks as satisfied, not missing, and the spec lands ready for implement in a single run. The final completed gate stays a human action.&lt;/p&gt;

&lt;p&gt;The whole routing decision reads more clearly as one picture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7wh8bbu7iq4gyyn0e2wl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7wh8bbu7iq4gyyn0e2wl.jpg" alt="A flow where a spec hits a classify step: the simple branch runs specify straight to implement with plan and tasks folded in, the normal branch runs the full specify-plan-tasks-implement pipeline, and a guardrail warns past five files or ten tasks" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A simple change takes the short express arrow to implement, while anything past the guardrail drops back onto the full four-stage line.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does it work?
&lt;/h2&gt;

&lt;p&gt;I ran the same feature, on the same codebase, through both shapes. Turbo finished the full pipeline in 12.4 minutes against standard's 21.3, a 42% drop, and produced 3 spec artifacts instead of 8.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Standard&lt;/th&gt;
&lt;th&gt;Turbo&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Total pipeline&lt;/td&gt;
&lt;td&gt;21.3m&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;12.4m (42% faster)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;specify / plan / tasks / implement&lt;/td&gt;
&lt;td&gt;5.2 / 5.9 / 2.5 / 5.2m&lt;/td&gt;
&lt;td&gt;1.3 / 2.6 / 1.0 / 6.2m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spec artifacts&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Source files touched&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tasks&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Now the honest part. Turbo's implement step was actually slower, 6.2 minutes against 5.2, despite having fewer tasks. That is one run, so it is noise, not evidence that scaffolding speeds up implementation. The lever here is choosing the right profile, not bloating turbo to chase a number. I am calling it out because the tempting conclusion, that more upfront design makes implementation faster, is exactly the one this data does not support.&lt;/p&gt;

&lt;p&gt;The Fast Path got its own proof on a real spec. A small install-URL fix, run in turbo with the Fast Path on, emitted one combined &lt;code&gt;spec.md&lt;/code&gt;, an Overview plus an inline Approach, and landed at implement in a single shot. After specify self-closed, the command wrote the folded plan and tasks entries itself, with real timestamps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;📃&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;specs/&lt;/span&gt;&lt;span class="mi"&gt;159&lt;/span&gt;&lt;span class="err"&gt;-inline-install-stable-url/.spec-context.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;history&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;two&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;folded&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;entries&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(abridged)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"step"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"plan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"substep"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fast-path"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"complete"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"by"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ai"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-06-13T01:31:19.217Z"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"step"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tasks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"substep"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fast-path"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"complete"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"by"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ai"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-06-13T01:31:19.425Z"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The eval asserts those folds carry real timestamps and that the spec reaches &lt;code&gt;ready-to-implement&lt;/code&gt;, and it stays silent on a normal spec.&lt;/p&gt;

&lt;p&gt;Underneath all of it, the timing finally stayed honest. Back in &lt;a href="https://dev.to/blog/2026-06-08-build-log-2-capturing-the-whole-lifecycle-and-shipping-v1"&gt;Build Log 2&lt;/a&gt;, the eval caught the timing lying. Finish-only journaling is the fix that stuck: it logs one &lt;code&gt;complete&lt;/code&gt; event per task and derives every duration from the gaps between finishes. Lap times, not stopwatches. The zero-second ticks, the phantom gaps between tasks, the bursts where a dozen substeps share one timestamp: all gone. The eval runs 13 pass, 0 fail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the shape lives in commands, not templates
&lt;/h2&gt;

&lt;p&gt;The obvious way to reshape a spec is to override the document template, &lt;code&gt;spec-template.md&lt;/code&gt;, with a lean one. I built it that way first. It silently did nothing.&lt;/p&gt;

&lt;p&gt;The reason is mechanical, not stylistic. A spec-kit preset can override two kinds of file: the command (the prompt the agent runs) and the template (the document scaffold). Template overrides only resolve when a setup script walks the override stack.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;plan&lt;/code&gt; and &lt;code&gt;tasks&lt;/code&gt; go through &lt;code&gt;setup-plan.sh&lt;/code&gt; and &lt;code&gt;setup-tasks.sh&lt;/code&gt;, which do walk the stack. A template override there takes effect.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;specify&lt;/code&gt; copies &lt;code&gt;templates/spec-template.md&lt;/code&gt; by literal path and never runs the resolver. A lean &lt;code&gt;spec-template.md&lt;/code&gt; is simply never read.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So template overrides are mixed: they work for plan and tasks, and no-op for specify. Command overrides apply uniformly to all seven commands. The only reliable single mechanism is to carry the shape in the command bodies, so that is where it lives. The accepted tradeoff: in turbo mode the on-disk &lt;code&gt;spec-template.md&lt;/code&gt; still shows the stock shape. Turbo just does not read it.&lt;/p&gt;

&lt;p&gt;The two code paths make the mismatch obvious.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqpp3p4p6yefg9lc21i5t.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqpp3p4p6yefg9lc21i5t.jpg" alt="Two lanes: plan and tasks run a setup script that walks the override resolver so a template override applies, while specify copies the template by literal path and bypasses the resolver so the override is ignored" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Plan and tasks honor a template override, specify copies the file by literal path and walks right past the resolver, so the shape has to live in the command body to reach all seven commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why modes route, not swap
&lt;/h2&gt;

&lt;p&gt;Once the shape lives in command bodies, the next obvious move is to swap them. Switch to turbo, uninstall the standard commands, install the turbo ones. My first cut did exactly that. The moment you switched mid-pipeline, &lt;code&gt;/speckit-plan&lt;/code&gt; failed with "Unknown command."&lt;/p&gt;

&lt;p&gt;The fix was to stop deleting things. Keep both command sets installed, and route each command to its &lt;code&gt;/speckit.companion.*&lt;/code&gt; twin based on the spec's pinned profile. Nothing gets removed, so switching modes can never strand you. An add-only "ensure standard" runs on activation to re-materialize the stock family on a fresh checkout, and it never removes anything.&lt;/p&gt;

&lt;p&gt;The pin also has to be durable. Turbo used to run for &lt;code&gt;specify&lt;/code&gt; and then quietly revert to stock for everything after it. The capture script writes &lt;code&gt;.spec-context.json&lt;/code&gt; with no profile, and the extension only pinned the profile when it created that file itself. The command always got there first, so the pin was never written. The fix back-fills the pin from the project default on the first lifecycle write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;📃&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;specs/&lt;/span&gt;&lt;span class="mi"&gt;159&lt;/span&gt;&lt;span class="err"&gt;-inline-install-stable-url/.spec-context.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"workflow"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"speckit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"profile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"turbo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;pinned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;specify&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;carried&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;completed&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"currentStep"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"implement"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"completed"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the shape carries the whole way through, and existing un-pinned specs heal themselves on their next write.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it landed
&lt;/h2&gt;

&lt;p&gt;This is the part a clean changelog hides.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The rename.&lt;/strong&gt; It shipped as &lt;code&gt;lean&lt;/code&gt;, then became &lt;code&gt;turbo&lt;/code&gt; before release. No alias, no migration, the old value just gone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The reversal.&lt;/strong&gt; I planned all of this to ship on by default, opt-out. It landed opt-in, grouped under a "Beta Features" settings section, both toggles defaulting to off. A half-proven feature does not get to reshape everyone's pipeline by default. Capture and status/resume, the parts that just track your work, stay always-on. They are the v1 core, not a beta.&lt;/p&gt;

&lt;p&gt;Here is where the two switches actually surface.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flk4ficiqay6kjv9pjaps.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flk4ficiqay6kjv9pjaps.png" alt="VS Code Settings showing the SpecKit Companion Beta Features section, with Template Profile set to turbo and a Complexity Fast Path toggle, both opt-in beta and off by default" width="800" height="742"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both live under Beta Features, defaulting to off, so nothing changes until you opt in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two housekeeping wins that say more than they look.&lt;/strong&gt; The published &lt;code&gt;.vsix&lt;/code&gt; had bloated to 66.6 MB because it was shipping my entire dev workspace: example sandboxes, caches, spec fixtures. Trimming it to 1.17 MB, roughly 60 times smaller, is just the principle that installing the extension should ship the extension, not my workspace. And &lt;code&gt;.specify/companion.yml&lt;/code&gt; is now machine-local and gitignored, so one developer's profile default no longer leaks into everyone else's checkout.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;The Fast Path just merged, so everything this log describes is shipped, opt-in beta for now. Both graduate to on-by-default only after they have proven themselves on enough real specs to earn the trust that capture and resume already have.&lt;/p&gt;

&lt;p&gt;Then Build Log 4: giving the pipeline an ending. Today it stops at implement, and the review, the commit, the PR, the mark-complete all still live in my head. Next I make them part of the workflow itself, recorded and on screen. That is also what finally makes auto mode worth having.&lt;/p&gt;

&lt;p&gt;The public backlog tracks every step as it merges. &lt;a href="https://github.com/alfredoperez/speckit-companion" rel="noopener noreferrer"&gt;Star the repo&lt;/a&gt; to follow along, and I will see you at Build Log 4.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Build Your Own SDD Workflow</title>
      <dc:creator>Alfredo Perez</dc:creator>
      <pubDate>Mon, 05 Oct 2026 13:25:08 +0000</pubDate>
      <link>https://dev.to/alfredoperez/build-your-own-sdd-workflow-5g9k</link>
      <guid>https://dev.to/alfredoperez/build-your-own-sdd-workflow-5g9k</guid>
      <description>&lt;p&gt;Spec-driven development works. Planning before you code catches bad assumptions early, keeps scope honest, and gives the AI enough context to write code you'd actually ship. That's not the problem.&lt;/p&gt;

&lt;p&gt;The problem is ceremony. &lt;a href="https://github.com/github/spec-kit" rel="noopener noreferrer"&gt;GitHub spec-kit&lt;/a&gt; gives you seven steps, multiple checkpoints, and templates designed for large teams coordinating across repos. When you're adding a component or fixing a bug, that's a lot of overhead for a Tuesday afternoon.&lt;/p&gt;

&lt;p&gt;And it's not like there's a shortage of alternatives. New AI workflow repos show up weekly. Everyone's got an opinion on the "right" way to structure AI-assisted development.&lt;/p&gt;

&lt;p&gt;Here's the thing. What if you just built the one that fits how &lt;em&gt;you&lt;/em&gt; think?&lt;/p&gt;

&lt;p&gt;That's what this article is. We'll build a 4-step SDD workflow from scratch and wire it into &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt; so you can see and run each phase visually. Four commands, four files, zero ceremony.&lt;/p&gt;




&lt;h2&gt;
  
  
  What We Kept
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/github/spec-kit" rel="noopener noreferrer"&gt;GitHub spec-kit&lt;/a&gt; gives you seven steps: constitution, clarify, specification, plan, tasks, implement, review. I only needed four.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dropped:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Constitution:&lt;/strong&gt; coding rules belong in CLAUDE.md once, not re-checked per feature&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clarify:&lt;/strong&gt; draft first, iterate. Stop asking questions before you've seen anything&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review:&lt;/strong&gt; add it back as an enhancement when you need it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Kept:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Specify:&lt;/strong&gt; defines what you're building&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan:&lt;/strong&gt; designs how to build it&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tasks:&lt;/strong&gt; breaks the plan into executable steps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implement:&lt;/strong&gt; executes the work&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the pipeline looks like this: &lt;code&gt;specify&lt;/code&gt; → &lt;code&gt;plan&lt;/code&gt; → &lt;code&gt;tasks&lt;/code&gt; → &lt;code&gt;implement&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Specify&lt;/strong&gt; → &lt;code&gt;sdd.specify&lt;/code&gt; → &lt;code&gt;spec.md&lt;/code&gt;. Explores the codebase, defines &lt;em&gt;what&lt;/em&gt; and &lt;em&gt;why&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan&lt;/strong&gt; → &lt;code&gt;sdd.plan&lt;/code&gt; → &lt;code&gt;plan.md&lt;/code&gt;. Reads the spec, designs &lt;em&gt;how&lt;/em&gt; to build it&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tasks&lt;/strong&gt; → &lt;code&gt;sdd.tasks&lt;/code&gt; → &lt;code&gt;tasks.md&lt;/code&gt;. Breaks the plan into ordered, verifiable tasks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implement&lt;/strong&gt; → &lt;code&gt;sdd.implement&lt;/code&gt; → Code + PR. Executes tasks one by one, commits, opens a PR&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All four map to &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt; phases. The first three produce markdown files. Implement runs the &lt;code&gt;sdd.implement&lt;/code&gt; command. It doesn't produce a file, it executes the work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnngnxruvgxzu24qy6tg3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnngnxruvgxzu24qy6tg3.png" alt="SDD pipeline diagram showing specify, plan, tasks, and implement steps" width="800" height="604"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Get the Files
&lt;/h2&gt;

&lt;p&gt;Here's what goes into your project. Seven files: four commands that tell the AI what to do, three templates that define what the output looks like.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Commands&lt;/strong&gt; (&lt;code&gt;.claude/commands/&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sdd.specify.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sdd.plan.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sdd.tasks.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sdd.implement.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Templates&lt;/strong&gt; (&lt;code&gt;.claude/templates/&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sdd-spec.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sdd-plan.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sdd-tasks.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://gist.github.com/alfredoperez/9b952315f4dd6bc2718fa1e259275109" rel="noopener noreferrer"&gt;Grab the SDD Starter Files (Gist)&lt;/a&gt;.&lt;/strong&gt; Drop them in the folders above and you're ready.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why SpecKit Companion
&lt;/h2&gt;

&lt;p&gt;You could run these commands from the terminal and call it a day. But &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt; gives you something the terminal doesn't: you can see where you are. Each phase shows up in the sidebar, you click to advance, and you always know what's done and what's next. It turns a set of markdown commands into an actual workflow you can follow.&lt;/p&gt;

&lt;p&gt;Here's the config. Add this to &lt;code&gt;.vscode/settings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"speckit.customWorkflows"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sdd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"displayName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SDD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Lean 4-step SDD workflow: specify, plan, tasks, implement"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"steps"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"specify"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Specify"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sdd.specify"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"spec.md"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"plan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Plan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sdd.plan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"plan.md"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tasks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Tasks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sdd.tasks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tasks.md"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"implement"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Implement"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sdd.implement"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"actionOnly"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"speckit.defaultWorkflow"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sdd"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Four steps. The first three produce markdown files. Implement runs the command but doesn't produce a file; it executes the work.&lt;/p&gt;




&lt;h2&gt;
  
  
  Walking Through a Feature
&lt;/h2&gt;

&lt;p&gt;Let me walk you through a real feature. We're adding a home page and navigation bar to an empty application, enough to see every phase in action.&lt;/p&gt;

&lt;h3&gt;
  
  
  Specify
&lt;/h3&gt;

&lt;p&gt;Click &lt;strong&gt;"+"&lt;/strong&gt; in the &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt; sidebar, describe what you want ("Add a home page with a navigation bar"), and select the SDD workflow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8kron73suxnc7f9qviko.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8kron73suxnc7f9qviko.png" alt="SpecKit Companion workflow selector showing the SDD option with a feature description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the specification finishes, the new spec appears in the sidebar. Open it and you'll see what we're building. Under the hood, the AI explored two or three relevant files, figured out the scope of the change, and wrote &lt;code&gt;spec.md&lt;/code&gt;: summary, requirements with Given/When/Then scenarios, and what's out of scope.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fozyxmb2hyh1ezlgl0v5j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fozyxmb2hyh1ezlgl0v5j.png" alt="Specify phase complete in the sidebar with the generated spec showing requirements" width="800" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Plan
&lt;/h3&gt;

&lt;p&gt;Hit &lt;strong&gt;Plan&lt;/strong&gt; at the bottom of the Specify phase. The command reads &lt;code&gt;spec.md&lt;/code&gt;, researches existing patterns in your repo, and writes &lt;code&gt;plan.md&lt;/code&gt;: the approach, files to create or modify, and risks.&lt;/p&gt;

&lt;p&gt;Here's the part I like: it stops and shows you the plan before anything moves forward. You approve, edit, or reject. No guessing, no "let me just refactor this real quick" surprises.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8c578ks94l79v60ljhv4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8c578ks94l79v60ljhv4.png" alt="Plan phase showing the generated plan with approach and files to change" width="800" height="857"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Tasks
&lt;/h3&gt;

&lt;p&gt;Click &lt;strong&gt;Tasks&lt;/strong&gt;. The command reads both &lt;code&gt;spec.md&lt;/code&gt; and &lt;code&gt;plan.md&lt;/code&gt;, then breaks the plan into phased, verifiable tasks. Each task gets a Do/Verify pair: what to build and how to confirm it works. Phase 1 runs in order. Phase 2 tasks are tagged for parallel execution (tests, docs, cleanup that can run as separate agents).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feau6bd5ic9h4pzs3tz9u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feau6bd5ic9h4pzs3tz9u.png" alt="Tasks phase showing phased tasks with Do and Verify pairs and an Implement button" width="800" height="861"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Implement
&lt;/h3&gt;

&lt;p&gt;Drop to the terminal, run &lt;code&gt;/sdd.implement&lt;/code&gt;. This is where the AI actually writes code. It reads all three files, executes Phase 1 tasks sequentially, auto-fixes small issues like import errors, but stops for anything architectural. Phase 2 agents launch in parallel. It commits and optionally opens a PR.&lt;/p&gt;

&lt;p&gt;Implement lives in the terminal because that's where code belongs. &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt; handles planning. The terminal handles execution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd575y6e5kawt9sfmmgqu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd575y6e5kawt9sfmmgqu.png" alt="Terminal showing sdd.implement completing all tasks and committing the result" width="799" height="471"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Enhance Your Workflow
&lt;/h2&gt;

&lt;p&gt;That worked great for a full feature. But now imagine you need to add a title to the nav bar, a one-line change. The same four steps still run: the AI explores the codebase, researches architecture, writes a multi-file plan, breaks it into phased tasks. That's a lot of machinery for something you could describe in a sentence. Since this is &lt;em&gt;your&lt;/em&gt; workflow, you can fix that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fast Mode
&lt;/h3&gt;

&lt;p&gt;Open &lt;code&gt;sdd.specify.md&lt;/code&gt;. After the AI explores the codebase, add a step that classifies the change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;📃 .claude/commands/sdd.specify.md

&lt;span class="gu"&gt;### 4. Detect Complexity&lt;/span&gt;

Based on what you found in Explore, classify the change:

| Signal                                            | Mode        |
| ------------------------------------------------- | ----------- |
| Touches 1 existing file, change is &amp;lt;10 lines      | &lt;span class="gs"&gt;**minimal**&lt;/span&gt; |
| Pure style or config tweak                        | &lt;span class="gs"&gt;**minimal**&lt;/span&gt; |
| Touches 2+ files, or adds a new component/service | &lt;span class="gs"&gt;**normal**&lt;/span&gt;  |

If unclear, default to &lt;span class="gs"&gt;**normal**&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add a step that only runs in minimal mode. Instead of handing off to &lt;code&gt;/sdd.plan&lt;/code&gt; and &lt;code&gt;/sdd.tasks&lt;/code&gt;, it generates all three files in one pass:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;📃 .claude/commands/sdd.specify.md

&lt;span class="gu"&gt;### 6. Minimal Mode — Write `plan.md` + `tasks.md`&lt;/span&gt;

Skip this step if mode is &lt;span class="gs"&gt;**normal**&lt;/span&gt;.

Write &lt;span class="sb"&gt;`specs/{NNN}-{slug}/plan.md`&lt;/span&gt;:
&lt;span class="p"&gt;
-&lt;/span&gt; Approach (1-2 sentences)
&lt;span class="p"&gt;-&lt;/span&gt; Files to change
&lt;span class="p"&gt;-&lt;/span&gt; Phase 1 tasks with Do/Verify pairs

Write &lt;span class="sb"&gt;`specs/{NNN}-{slug}/tasks.md`&lt;/span&gt;:
&lt;span class="p"&gt;
-&lt;/span&gt; Single phase task list matching the plan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try it: run &lt;code&gt;/sdd.specify add a title to the nav bar&lt;/code&gt;. The command sees it's a single-file fix and collapses three steps into one. All the artifacts, none of the ceremony.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkti4m6d29iw7b75gj7ju.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkti4m6d29iw7b75gj7ju.png" alt="Fast Mode output showing all three files generated in a single pass" width="800" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One command, and you're ready to implement.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Checkpoint
&lt;/h3&gt;

&lt;p&gt;Open &lt;code&gt;sdd.implement.md&lt;/code&gt;. After the AI executes all tasks, add a checkpoint that presents the results for review before pushing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;📃 .claude/commands/sdd.implement.md

&lt;span class="gu"&gt;### 5. Checkpoint — Commit + PR&lt;/span&gt;

Display exactly this format, then use &lt;span class="gs"&gt;**AskUserQuestion**&lt;/span&gt;:

--- CP: Commit &amp;amp; PR ---
Commit: {type}({scope}): {short description}

PR title: {type}({scope}): {short description}
PR body: ## What - [bullet from spec]&lt;span class="sb"&gt;

    ## Why
    [one sentence from spec]

    ## Testing
    - [verify step from tasks]

&lt;/span&gt;Options:
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="gs"&gt;**Approve**&lt;/span&gt; — proceed to commit and PR
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Edit**&lt;/span&gt; — user provides notes; apply changes, redisplay
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;/sdd.implement&lt;/code&gt;. The AI creates a branch, executes the task, and then stops. Before anything gets pushed, it shows you exactly what changed, the commit message, and the PR body. You approve, edit, or reject. Nothing leaves your machine without your sign-off.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcwvfmirycqjx4kiw1u6c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcwvfmirycqjx4kiw1u6c.png" alt="Checkpoint showing the commit message and PR body for approval before pushing" width="800" height="618"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Two interactions total. Full traceability. And if you don't like the PR title, you fix it right there.&lt;/p&gt;




&lt;h2&gt;
  
  
  Make It Yours
&lt;/h2&gt;

&lt;p&gt;You just saw two customizations in action: a complexity check in &lt;code&gt;sdd.specify.md&lt;/code&gt; and a checkpoint in &lt;code&gt;sdd.implement.md&lt;/code&gt;. Both are just markdown rules you can tune or remove.&lt;/p&gt;

&lt;p&gt;Every step works the same way. Want "Security Considerations" in every spec? Add one line to &lt;code&gt;sdd.specify.md&lt;/code&gt;. Want conventional commits? Add a rule to &lt;code&gt;sdd.implement.md&lt;/code&gt;. Want TDD enforced? Add "write tests before implementation" to &lt;code&gt;sdd.tasks.md&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And the workflow commands are just the first layer. Add rules in CLAUDE.md, build a pattern library, wire in specialized agents. Each layer makes the next one better.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Layer 1: Workflow commands.&lt;/strong&gt; &lt;code&gt;sdd.specify.md&lt;/code&gt;, &lt;code&gt;sdd.plan.md&lt;/code&gt;, &lt;code&gt;sdd.tasks.md&lt;/code&gt;, &lt;code&gt;sdd.implement.md&lt;/code&gt;. The structure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Layer 2: Rules.&lt;/strong&gt; CLAUDE.md / AGENTS.md. Naming, testing, commit standards. Written once, applied to every feature.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Layer 3: Pattern library.&lt;/strong&gt; "Here's how we do X." Component templates, API patterns. The AI matches your codebase instead of guessing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Layer 4: Skills and agents.&lt;/strong&gt; Specialized tools called during steps. Route TypeScript to a code reviewer, HTML to an accessibility expert.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's all markdown. Improving it is trivial.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg7bqdrrbb9vfu3x1ueon.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg7bqdrrbb9vfu3x1ueon.png" alt="Diagram showing the four layers of files that compound: workflow commands, rules, pattern library, and skills" width="800" height="561"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://gist.github.com/alfredoperez/9b952315f4dd6bc2718fa1e259275109" rel="noopener noreferrer"&gt;Grab the SDD Starter Files (Gist)&lt;/a&gt;:&lt;/strong&gt; 4 commands + 3 templates&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configure &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt;:&lt;/strong&gt; copy the settings.json snippet above&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/alfredoperez/custom-ai-workflow-demo" rel="noopener noreferrer"&gt;Demo repo&lt;/a&gt;:&lt;/strong&gt; the project from this walkthrough, with all commands and config ready to clone&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evolving version:&lt;/strong&gt; I'm building on this at &lt;strong&gt;&lt;a href="https://github.com/alfredoperez/sdd" rel="noopener noreferrer"&gt;alfredoperez/sdd&lt;/a&gt;&lt;/strong&gt;, a Claude Code plugin incorporating the best patterns from 8+ open-source AI workflows&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Install &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt; from the VS Code Marketplace, drop the files, and start shipping. Next up: how to scale this across a team with shared specs and conventions.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Custom Workflows in SpecKit Companion</title>
      <dc:creator>Alfredo Perez</dc:creator>
      <pubDate>Mon, 05 Oct 2026 13:24:57 +0000</pubDate>
      <link>https://dev.to/alfredoperez/custom-workflows-in-speckit-companion-2bbj</link>
      <guid>https://dev.to/alfredoperez/custom-workflows-in-speckit-companion-2bbj</guid>
      <description>&lt;p&gt;You might think &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt; only works with GitHub's &lt;a href="https://github.com/github/spec-kit" rel="noopener noreferrer"&gt;spec-kit&lt;/a&gt;. It doesn't. Spec-driven development is exploding right now — there are dozens of workflows and methodologies emerging across the community — and &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt; can work with any of them.&lt;/p&gt;

&lt;p&gt;One that caught my attention is &lt;a href="https://github.com/Gentleman-Programming/gentle-ai" rel="noopener noreferrer"&gt;Gentle AI&lt;/a&gt; by &lt;a href="https://github.com/Gentleman-Programming" rel="noopener noreferrer"&gt;Gentleman Programming&lt;/a&gt;. It's an ecosystem configurator that transforms AI coding agents into comprehensive development systems. It takes a different approach to SDD: instead of one AI doing everything, it delegates to specialized sub-agents for each phase — explore, specify, design, implement, verify. One command sets up the entire workflow, and it pairs perfectly with &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt;'s visual interface.&lt;/p&gt;

&lt;p&gt;Let me show you how to set it up and run through a quick feature build.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Are Custom Workflows?
&lt;/h2&gt;

&lt;p&gt;By default, &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt; uses GitHub spec-kit's commands — &lt;code&gt;speckit.specify&lt;/code&gt;, &lt;code&gt;speckit.plan&lt;/code&gt;, &lt;code&gt;speckit.tasks&lt;/code&gt;, &lt;code&gt;speckit.implement&lt;/code&gt;. A custom workflow lets you swap those out for commands from a different SDD methodology.&lt;/p&gt;

&lt;p&gt;You define the steps, the commands they run, and the files they produce. &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt; handles the rest — sidebar navigation, phase tracking, progress indicators — all working with &lt;em&gt;your&lt;/em&gt; workflow instead of the default.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting Up Gentle AI
&lt;/h2&gt;

&lt;p&gt;Before configuring the custom workflow, you need to install Gentle AI. Run &lt;code&gt;gentle-ai install&lt;/code&gt; in the terminal — the interactive TUI lets you select your agent (Claude Code, Cursor, etc.) and components (SDD, Engram memory, skills). This bootstraps the SDD commands and file structure in your project.&lt;/p&gt;

&lt;p&gt;Once initialized, you need to add the &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt; configuration to &lt;code&gt;.vscode/settings.json&lt;/code&gt; — Gentle AI doesn't do this for you. Here's what the workflow configuration looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;📃&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;.vscode/settings.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"speckit.customWorkflows"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gentle-ai"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"displayName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Gentle AI (SDD)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Multi-agent SDD workflow using gentle-ai"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"steps"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"specify"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Spec"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sdd-spec"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"spec.md"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"subDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"specs"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"plan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Design"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sdd-design"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"design.md"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"includeRelatedDocs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tasks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Tasks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sdd-tasks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tasks.md"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"speckit.defaultWorkflow"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gentle-ai"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"speckit.specDirectories"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"specs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"openspec/changes/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"openspec/changes/archive/*"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"speckit.customCommands"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"verify"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Verify"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/sdd-verify"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"step"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tasks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"tooltip"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Validate implementation matches specs"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"archive"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Archive"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/sdd-archive"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"step"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tasks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"tooltip"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Archive completed change"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;customCommands&lt;/code&gt; section adds &lt;strong&gt;Verify&lt;/strong&gt; and &lt;strong&gt;Archive&lt;/strong&gt; buttons to the Tasks phase — these aren't workflow steps, but actions you can trigger once implementation is done. Verify validates that the code matches the specs, and Archive moves the completed change to the archive directory.&lt;/p&gt;

&lt;p&gt;Notice the labels are different from the default workflow — &lt;strong&gt;Spec, Design, Tasks&lt;/strong&gt; instead of Specify, Plan, Tasks. &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt; adapts to whatever naming your workflow uses.&lt;/p&gt;




&lt;h2&gt;
  
  
  Running Through the Workflow
&lt;/h2&gt;

&lt;p&gt;To test this out, I'll add a header navigation bar to an empty Angular app — a quick demo to show the full cycle.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating the Spec
&lt;/h3&gt;

&lt;p&gt;Click the &lt;strong&gt;"+"&lt;/strong&gt; button in the &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt; sidebar and you'll see a workflow selector — the default GitHub spec-kit workflow &lt;em&gt;and&lt;/em&gt; Gentle AI are both available. Select &lt;strong&gt;Gentle AI (SDD)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftn86xzb4k9x2hvt15tpb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftn86xzb4k9x2hvt15tpb.png" alt="Create New Spec dialog showing workflow selector with Gentle AI option" width="800" height="790"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Describe what you want to build, select the workflow that we just added, add any images that can give more context and hit submit. The &lt;code&gt;sdd-spec&lt;/code&gt; command runs and generates the specification.&lt;/p&gt;

&lt;p&gt;Once you click submit, the terminal opens with a command like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/sdd-spec Add a navigation bar and a home page
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Gentle AI creates two specs — one for each feature (the navbar and the home page). You can see both listed in the &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt; sidebar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F430pvyln26zokvjef4vk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F430pvyln26zokvjef4vk.png" alt="Workflow Editor showing the Spec phase with both specs listed in the sidebar" width="730" height="558"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Spec → Design → Tasks
&lt;/h3&gt;

&lt;p&gt;From here, the experience is the same visual flow you're used to — but with Gentle AI's three phases:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spec&lt;/strong&gt; — The specification defines what we're building. In Gentle AI, this follows their Given/When/Then scenario format with one spec per feature. The sidebar shows all the specs created under this change.&lt;/p&gt;

&lt;p&gt;Notice the &lt;code&gt;subDir&lt;/code&gt; setting in the config — this tells &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt; that specs live in their own subfolder, which is how both specs get grouped under the same change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;👇&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Specs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;get&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;their&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;own&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;subfolder&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"specify"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Spec"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sdd-spec"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"spec.md"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"subDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"specs"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiqsdcwwvj4fnxpi2gexn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiqsdcwwvj4fnxpi2gexn.png" alt="Workflow Editor showing the Spec phase with Gentle AI spec content" width="800" height="603"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click the &lt;strong&gt;Design&lt;/strong&gt; button at the bottom to move to the next phase. This executes a command like &lt;code&gt;/sdd-design &amp;lt;change-path&amp;gt;&lt;/code&gt; in the terminal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Design&lt;/strong&gt; — Instead of a single plan file, Gentle AI generates a design document with architecture decisions and rationale. The &lt;code&gt;includeRelatedDocs&lt;/code&gt; flag tells &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt; to display related files (like the spec files from the previous step) in an expandable sub-tree, giving you context without leaving the Design phase:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;👇&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Shows&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;spec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;files&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;context&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;sub-tree&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"plan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Design"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sdd-design"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"design.md"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"includeRelatedDocs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftwyh3ltk1oxxbhu7q2jm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftwyh3ltk1oxxbhu7q2jm.png" alt="Workflow Editor showing the Design phase with Tasks button at the bottom" width="800" height="851"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click the &lt;strong&gt;Tasks&lt;/strong&gt; button at the bottom to move to the final phase. This runs &lt;code&gt;/sdd-tasks &amp;lt;change-path&amp;gt;&lt;/code&gt; and creates the implementation tasks for both specifications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tasks&lt;/strong&gt; — The implementation breakdown. Each task is phased and ordered. You'll also see &lt;strong&gt;Verify&lt;/strong&gt; and &lt;strong&gt;Archive&lt;/strong&gt; buttons — these are custom commands, not workflow steps. Once you implement the tasks with &lt;code&gt;sdd-apply&lt;/code&gt;, use them to validate and archive the completed spec.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv9smpqp9iy7b2oybkpng.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv9smpqp9iy7b2oybkpng.png" alt="Workflow Editor showing the Tasks phase with verify and archive buttons" width="799" height="617"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once all tasks are done, the top navigation bar shows an indicator that the spec is completed. From here you can either verify or archive. In our case, we'll go directly to archive.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvbwtgqvkir9eh45j899o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvbwtgqvkir9eh45j899o.png" alt="Workflow Editor showing the completed spec" width="800" height="68"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The progress bar at the top tracks you through all three phases, and when the last one completes, the spec is marked as done — same visual feedback, different workflow underneath.&lt;/p&gt;

&lt;h3&gt;
  
  
  Archiving with Custom Commands
&lt;/h3&gt;

&lt;p&gt;Let's try the &lt;strong&gt;Archive&lt;/strong&gt; button — this is a custom command we defined in &lt;code&gt;settings.json&lt;/code&gt;, not a workflow step. Clicking it runs &lt;code&gt;/sdd-archive&lt;/code&gt; and moves the completed change to the &lt;code&gt;openspec/changes/archive/&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;Two settings work together here. The custom command adds the button to the Tasks phase:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;👇&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Adds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Archive&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;button&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Tasks&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;step&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"archive"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Archive"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/sdd-archive"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"step"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tasks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tooltip"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Archive completed change"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the &lt;code&gt;specDirectories&lt;/code&gt; setting keeps archived specs visible in the sidebar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;👇&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Archive&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;folder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;included&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;so&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;past&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;specs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;stay&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;browsable&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"speckit.specDirectories"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"specs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"openspec/changes/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"openspec/changes/archive/*"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The archived spec doesn't disappear — you can browse past changes without digging through folders.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuety2gdqaer6mno0uak2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuety2gdqaer6mno0uak2.png" alt="Sidebar showing archived spec still visible" width="748" height="540"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  When to Use Custom Workflows
&lt;/h2&gt;

&lt;p&gt;Two main use cases:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Try another existing SDD workflow.&lt;/strong&gt; Gentle AI is just one example. Any methodology that uses commands and produces markdown files can be plugged into &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt;. Found a workflow you like on GitHub? Configure it in settings.json and you have a visual interface for it immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Create your own workflow for your team.&lt;/strong&gt; Maybe you don't like how &lt;code&gt;speckit.plan&lt;/code&gt; works — you want something leaner. Or more sophisticated. Or you want to add a review step between plan and tasks. Custom workflows let you define exactly the phases and commands your team needs.&lt;/p&gt;

&lt;p&gt;We'll dig deep into option 2 in the next article.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;Now that you know &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt; works with any SDD workflow, the next question is: what if none of the existing ones are exactly what you need? In the next article, we'll walk through stripping spec-driven development down to a lean 3-step pipeline tailored to your project.&lt;/p&gt;

&lt;p&gt;Give it a try — install &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion from the VS Code Marketplace&lt;/a&gt; and plug in the SDD workflow that fits your team.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuftltjcs5tow511yxrq4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuftltjcs5tow511yxrq4.png" alt="SpecKit Companion extension homepage" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>SpecKit Companion</title>
      <dc:creator>Alfredo Perez</dc:creator>
      <pubDate>Mon, 05 Oct 2026 13:24:36 +0000</pubDate>
      <link>https://dev.to/alfredoperez/speckit-companion-503e</link>
      <guid>https://dev.to/alfredoperez/speckit-companion-503e</guid>
      <description>&lt;p&gt;GitHub's &lt;a href="https://github.com/github/spec-kit" rel="noopener noreferrer"&gt;spec-kit&lt;/a&gt; has been gaining serious traction — 46.7k stars and counting — and for good reason. It brings a solid methodology for using spec-driven development with the AI coding tool of your choice.&lt;/p&gt;

&lt;p&gt;But you might be asking: what &lt;em&gt;is&lt;/em&gt; spec-driven development? It's the practice of defining &lt;strong&gt;what&lt;/strong&gt; you want to build and &lt;strong&gt;why&lt;/strong&gt; before asking AI to write code. Instead of vague prompts and hoping for the best, you write explicit specifications that become the AI's roadmap. Fewer misunderstandings, fewer iterations, better results. (If you want the full breakdown, check out &lt;a href="https://medium.com/ngconf/spec-driven-development-stop-vibe-coding-c42a1f948b26" rel="noopener noreferrer"&gt;Spec-Driven Development: Stop Vibe Coding&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;Here's where &lt;strong&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt;&lt;/strong&gt; enters. It's a VS Code extension that gives you a visual interface for spec-driven development — browse specs, track workflow progress, and manage your AI configuration, all without leaving your editor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft8y6iv2pevs3pr5j54gm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft8y6iv2pevs3pr5j54gm.png" alt="SpecKit Companion extension homepage" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why a Visual Interface?
&lt;/h2&gt;

&lt;p&gt;When &lt;a href="https://kiro.dev/" rel="noopener noreferrer"&gt;Kiro&lt;/a&gt; launched their IDE built around spec-driven development, something clicked for me. Seeing your specs, plans, and tasks laid out visually — not buried in markdown files — changes how you interact with them. It's easier to navigate. Easier to spot what's wrong. Easier to give feedback.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl73mxsd422f2uxpoqznh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl73mxsd422f2uxpoqznh.png" alt="Kiro IDE showing spec-driven development workflow" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Think about it: once you're working with specifications and plans, you want to &lt;em&gt;see&lt;/em&gt; them. You want to add a comment on line 12 of a spec where the requirement is unclear. You want to look at the plan and say "this part doesn't match what I had in mind" and regenerate just that section. You want to view diagrams inline instead of switching to a markdown preview.&lt;br&gt;
&lt;strong&gt;That feedback loop — review, comment, regenerate — is what turns spec-driven development from a process into a conversation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Even creating a spec is better with a visual interface. You can write a detailed description, point to existing files for context, and attach screenshots — all in one place.&lt;/p&gt;

&lt;p&gt;But Kiro is a full IDE. I wanted that same visual experience for &lt;em&gt;any&lt;/em&gt; AI coding assistant — Claude Code, GitHub Copilot, Gemini CLI — without leaving VS Code. &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt; was born from that gap: a lightweight extension that adds the visual layer Kiro pioneered, but works with the tools you already use.&lt;/p&gt;




&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;Three steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open VS Code Extensions (&lt;code&gt;Cmd+Shift+X&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Search for &lt;strong&gt;"SpecKit Companion"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Install&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Or go directly to the &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;VS Code Marketplace&lt;/a&gt;. Supports macOS, Linux, and WSL.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Sidebar
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgrhgjyrlem5sae37trc4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgrhgjyrlem5sae37trc4.png" alt="SpecKit Companion sidebar showing Specs, Steering, Agents, Skills, and Hooks sections" width="355" height="674"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The sidebar has two main areas:&lt;/p&gt;

&lt;h3&gt;
  
  
  Specs — Your Workflow Hub
&lt;/h3&gt;

&lt;p&gt;This is where you spend most of your time. Every specification you create shows up here with its current phase: &lt;strong&gt;Specify → Plan → Tasks → Done&lt;/strong&gt;. Click any spec to open it in the Workflow Editor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F188t537qmiw1birhf45i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F188t537qmiw1birhf45i.png" alt="Specs section of the sidebar showing specs at different workflow phases" width="356" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At a glance, you can see how far along each spec is — which ones are still being defined, which have plans ready, and which are fully tasked out and ready for implementation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuration — Steering, Agents, Skills &amp;amp; Hooks
&lt;/h3&gt;

&lt;p&gt;The rest of the sidebar is about &lt;strong&gt;context and configuration&lt;/strong&gt; — everything that shapes how the AI works during your spec-driven workflow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Steering&lt;/strong&gt; — Your project rules, constitution, and shared scripts. The guardrails that keep the AI aligned with your codebase conventions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agents&lt;/strong&gt; — Personal and project-level AI personas for specific tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skills&lt;/strong&gt; — MCP Servers that extend what the AI can do.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hooks&lt;/strong&gt; — Automations triggered by events (Claude Code only).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of this area as the control panel. The specs are &lt;em&gt;what&lt;/em&gt; you're building. The configuration is &lt;em&gt;how&lt;/em&gt; the AI should behave while building it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Workflow Editor
&lt;/h2&gt;

&lt;p&gt;The Workflow Editor is where specs come to life. A progress bar at the top shows exactly where you are in the workflow — and a special indicator lets you know when a spec is complete.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a Spec
&lt;/h3&gt;

&lt;p&gt;Hit the &lt;strong&gt;"+"&lt;/strong&gt; button in the sidebar and you're in. Write a detailed description, point to existing files for context, attach screenshots or mockups — whatever helps the AI understand what you're building.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk4hb2jpcvi9p32y9eja5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk4hb2jpcvi9p32y9eja5.png" alt="Create New Spec dialog with description text and attached image" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Reviewing with Inline Comments
&lt;/h3&gt;

&lt;p&gt;Here's where the visual interface really pays off. Once a spec or plan is generated, you can add &lt;strong&gt;review comments on individual lines&lt;/strong&gt; — just like a code review. Disagree with a requirement? Comment on it. Think the plan missed something? Flag that specific line.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fko4x1hmch25x3uk7swy1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fko4x1hmch25x3uk7swy1.png" alt="Adding inline review comments on a specification file" width="767" height="169"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6l9ena550c5uy0vtnl7k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6l9ena550c5uy0vtnl7k.png" alt="Specification file with inline review comments on specific lines" width="771" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Based on your comments, you can regenerate the file — the AI uses your feedback to improve that specific section. It's a much faster feedback loop than re-prompting from scratch.&lt;/p&gt;

&lt;h3&gt;
  
  
  Navigating the Phases
&lt;/h3&gt;

&lt;p&gt;Each phase has its own view. The progress bar at the top highlights where you are, and you advance by clicking the action button at the bottom of each step.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Specify&lt;/strong&gt; — Your requirements. The &lt;em&gt;what&lt;/em&gt; and &lt;em&gt;why&lt;/em&gt;. This is the first phase — it activates when you create a new spec. When you're happy with your requirements, click &lt;strong&gt;"Generate Plan"&lt;/strong&gt; to move forward.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu45erme073ssttr2ref3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu45erme073ssttr2ref3.png" alt="Workflow Editor showing the Specify phase with spec content" width="797" height="650"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Plan&lt;/strong&gt; — The technical strategy. In &lt;a href="https://github.com/github/spec-kit" rel="noopener noreferrer"&gt;spec-kit&lt;/a&gt;, this isn't a single file — you get the plan itself, plus research, data models, and a quickstart reference. The editor gives you tabs to navigate between them and can even show you diagrams. When the plan looks right, click &lt;strong&gt;"Generate Tasks"&lt;/strong&gt; to advance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F699c01bho4uwff2ygeff.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F699c01bho4uwff2ygeff.png" alt="Workflow Editor showing the Plan phase with an architecture diagram" width="799" height="647"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tasks&lt;/strong&gt; — The implementation breakdown. Each task is tracked, and you can see exactly how far along the implementation is. When you're ready, click &lt;strong&gt;"Implement Tasks"&lt;/strong&gt; to kick off implementation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbn3qwzpatndgv1l5apax.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbn3qwzpatndgv1l5apax.png" alt="Workflow Editor showing the Tasks phase with task list and progress" width="791" height="636"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Done&lt;/strong&gt; — All phases complete. The progress bar shows four filled circles and the spec is marked as finished.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F74l01ctz580cgeh9h7kv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F74l01ctz580cgeh9h7kv.png" alt="Workflow Editor showing the Done phase with all progress circles filled" width="789" height="649"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Beyond the Defaults: Custom Commands &amp;amp; Workflows
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt; works great with GitHub &lt;a href="https://github.com/github/spec-kit" rel="noopener noreferrer"&gt;spec-kit&lt;/a&gt;'s built-in workflow. But you're not limited to it.&lt;/p&gt;

&lt;p&gt;You can add &lt;strong&gt;custom commands&lt;/strong&gt; that run in any phase of the spec-driven workflow — extending what the defaults offer. And you can create &lt;strong&gt;entirely custom workflows&lt;/strong&gt; for spec-driven development that aren't tied to GitHub &lt;a href="https://github.com/github/spec-kit" rel="noopener noreferrer"&gt;spec-kit&lt;/a&gt; at all.&lt;/p&gt;

&lt;p&gt;This is a deep topic, so I'm covering it separately in other articles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom Workflows in &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt; — We'll demonstrate how to use another SDD AI workflow with &lt;a href="https://github.com/Gentleman-Programming/agent-teams-lite" rel="noopener noreferrer"&gt;Agent Teams Lite&lt;/a&gt; by &lt;a href="https://github.com/Gentleman-Programming" rel="noopener noreferrer"&gt;Gentleman Programming&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Build Your Own SDD Workflow — We'll create and customize our own workflow that adapts to our needs.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;New to spec-driven development? &lt;a href="https://medium.com/ngconf/spec-driven-development-stop-vibe-coding-c42a1f948b26" rel="noopener noreferrer"&gt;Stop Vibe Coding, Start Shipping&lt;/a&gt; covers the full workflow from zero.&lt;/p&gt;

&lt;p&gt;Already using &lt;a href="https://github.com/github/spec-kit" rel="noopener noreferrer"&gt;spec-kit&lt;/a&gt;? Install &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt; and open the sidebar — your existing &lt;code&gt;.specify/&lt;/code&gt; specs will show up automatically.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Links:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion on Marketplace&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/alfredoperez/speckit-companion" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/github/spec-kit" rel="noopener noreferrer"&gt;spec-kit CLI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Build Log 2: Capturing the Whole Lifecycle, and Shipping v1</title>
      <dc:creator>Alfredo Perez</dc:creator>
      <pubDate>Mon, 05 Oct 2026 13:24:10 +0000</pubDate>
      <link>https://dev.to/alfredoperez/build-log-2-capturing-the-whole-lifecycle-and-shipping-v1-ca</link>
      <guid>https://dev.to/alfredoperez/build-log-2-capturing-the-whole-lifecycle-and-shipping-v1-ca</guid>
      <description>&lt;p&gt;&lt;a href="https://www.alfredo-perez.dev/blog/2026-06-07-build-log-1-proving-the-riskiest-assumption" rel="noopener noreferrer"&gt;Build Log 1&lt;/a&gt; proved one link in the chain: a spec-kit &lt;code&gt;after_specify&lt;/code&gt; hook writes my state file, and the SpecKit Companion GUI lights up from it. One write. That's a spike, not a product.&lt;/p&gt;

&lt;p&gt;The problem shows up the second you do anything past specify. Plan, tasks, implement, none of them are captured, so the moment you move forward, the GUI is showing a half-truth. And it gets worse: spec-kit hooks are agent-mediated. They fire only if the agent runs them. Skip a command, run one out of band, open an old project that never had the extension, and the hook never fires at all. The GUI doesn't just go stale. It goes blind.&lt;/p&gt;

&lt;p&gt;So this log has one job: capture the &lt;em&gt;whole&lt;/em&gt; lifecycle, and never lie about state, even when a hook didn't fire. When that holds, &lt;strong&gt;v1 ships&lt;/strong&gt;, tracking and resume on any spec-kit project, with zero template changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;Three things stacked on each other: the rest of the capture chain, a safety net for when a hook doesn't fire, and the two commands that finally make the captured state useful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The lifecycle hooks.&lt;/strong&gt; Build Log 1 had one hook. Now there are four, each backed by a per-step capture command that reuses the same &lt;code&gt;write-context.py&lt;/code&gt; writer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 📃 speckit-extension/extension.yml&lt;/span&gt;
&lt;span class="na"&gt;hooks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;after_specify&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;speckit.companion.capture&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;optional&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;false&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;after_plan&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;speckit.companion.capture-plan&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;optional&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;false&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# 👈 new&lt;/span&gt;
  &lt;span class="na"&gt;after_tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;speckit.companion.capture-tasks&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;optional&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;false&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# 👈 new&lt;/span&gt;
  &lt;span class="na"&gt;after_implement&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;speckit.companion.capture-implement&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;optional&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;false&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# 👈 new&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each one appends an entry to &lt;code&gt;history[]&lt;/code&gt;, the canonical event journal, and advances &lt;code&gt;currentStep&lt;/code&gt; and &lt;code&gt;status&lt;/code&gt;. (The old name &lt;code&gt;transitions[]&lt;/code&gt; is gone. One journal, one name.) Inside implement, each completed &lt;code&gt;- [x] **T###**&lt;/code&gt; task gets its own entry, recorded as a &lt;strong&gt;substep&lt;/strong&gt; so the viewer never mistakes a single task for the whole step finishing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The derive-from-files fallback.&lt;/strong&gt; This is the part that earns "never lie." &lt;code&gt;derive-from-files.py&lt;/code&gt; is a stdlib reader that reconstructs &lt;code&gt;history[]&lt;/code&gt; from the artifacts already on disk, &lt;code&gt;spec.md&lt;/code&gt;, &lt;code&gt;plan.md&lt;/code&gt;, &lt;code&gt;tasks.md&lt;/code&gt;, and which task markers are checked, plus git history, when no hook ever fired. Same no-backward-clobber guard as the live path, tagged &lt;code&gt;by: "derive"&lt;/code&gt; so you can tell reconstructed state from captured state. Delete the state file, or run on a project that never touched the extension, and the GUI still reflects reality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Status and resume.&lt;/strong&gt; Two commands turn all that captured state into something you actually use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/speckit.companion.status&lt;/code&gt; reads the canonical file (or derives it on a miss) and prints the current step, status, recorded decisions, and the next action.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/speckit.companion.resume&lt;/code&gt; picks up at the next unchecked task, carries the recorded &lt;code&gt;decisions[]&lt;/code&gt; back into scope, and dispatches the next &lt;code&gt;/speckit.*&lt;/code&gt; command.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Companion sidebar surfaces the same data: the SPECS tree lists every active spec with its current step, refreshed live by the watcher that was already there.&lt;/p&gt;

&lt;p&gt;Here's that tree in the sidebar:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc80ic78oznvsilyoka35.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc80ic78oznvsilyoka35.png" alt="The SpecKit Companion SPECS sidebar tree, with the active spec 131 expanded to its Specification, Plan, and Tasks rows" width="638" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Spec 131 sits expanded to its three finished steps, updated by the watcher without a manual refresh.&lt;/p&gt;

&lt;p&gt;That's v1. Tracking plus resume on any spec-kit project, no template change. Open a tracked spec and the whole journal renders: each phase with its real duration, every task with the one-line summary it wrote as it landed.&lt;/p&gt;

&lt;p&gt;Here's that full render for spec 131:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Farwfakfiewz4k2gcy1wv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Farwfakfiewz4k2gcy1wv.png" alt="The SpecKit Companion spec viewer showing the four phases (Specify, Plan, Tasks, Implement) with durations, plus the per-task T001 to T004 substeps and their DONE summaries" width="800" height="901"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Four phases with their real durations up top, then the T001 through T004 substeps below, each carrying the one-line summary it wrote as it finished.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does it actually work?
&lt;/h2&gt;

&lt;p&gt;Start with the easy half: the deterministic tests. The capture layer ships 12 stdlib tests, append-only history, no-backward-clobber, unknown-key preservation, per-task idempotency, a full derive round-trip. Status and resume add 25 more Python resolver tests and 354 green Jest tests on the GUI side. All passing.&lt;/p&gt;

&lt;p&gt;The interesting part is that I wrote an eval, and the eval caught capture lying.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;eval-speckit-extension&lt;/code&gt; is a re-runnable checker: it asserts the journal is well-formed, the timestamps are monotonic and not backfilled, and the per-task substeps line up with &lt;code&gt;tasks.md&lt;/code&gt;. It also prints a timing breakdown, and that breakdown is what blew the whistle. Here's one of my own specs after a full implement run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 👇 spec 130 — every task stamped at the same instant, by the hook
implement T001 … T024   by: extension   at: 2026-06-07T23:27:31.648Z
  cadence: BURST — 24 task substeps, 0ms span   ✗
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Twenty-four tasks, one timestamp, all written &lt;code&gt;by: extension&lt;/code&gt;. The capture &lt;em&gt;said&lt;/em&gt; all 24 ran, but with zero time between them. The journal looked complete and was quietly meaningless. The root cause is structural: the &lt;code&gt;after_implement&lt;/code&gt; hook fires once, at the end of the step. A hook physically cannot produce cadence &lt;em&gt;inside&lt;/em&gt; a step it only sees the end of.&lt;/p&gt;

&lt;p&gt;So the fix moves the cadence source out of the hook and into the &lt;strong&gt;implement preamble&lt;/strong&gt;. The idea: have the AI journal each task the moment it finishes, authored &lt;code&gt;by: "ai"&lt;/code&gt; with a real timestamp, instead of letting one hook stamp them all at the end.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;📃&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;.spec-context.json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;—&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;live&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;per-task&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;entry,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;now&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;written&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;AI&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(spec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;131&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"step"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"implement"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"substep"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"T004"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"task"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"T004"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"by"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ai"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-06-08T11:29:35Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because each live entry carries its &lt;code&gt;task&lt;/code&gt; id, the old hook's task-sync &lt;strong&gt;dedupes against them and degrades to a no-op backstop&lt;/strong&gt;. If the AI skips the journaling, the hook still records everything. Strictly better, never worse.&lt;/p&gt;

&lt;p&gt;Here's the honest part: it isn't fixed yet. I re-ran the eval on the next spec, and it refused to sign off:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✗ [FAIL] timestamps-real: 10/16 look hand-typed (round ms) — capture may be backfilled, not live
✓ [PASS] per-task-substeps: 4 task events; substep==task: True
· [INFO] task-cadence: 4 tasks; gaps 0ms, 0ms, 39.0s
→ 12 pass / 1 fail / 4 info
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The entries are &lt;code&gt;by: "ai"&lt;/code&gt; now, which is the structural win. But on a small, fast spec the AI still batched three of them at one timestamp, and those round-second stamps look backfilled, not live. The burst isn't gone. It's smaller.&lt;/p&gt;

&lt;p&gt;And that's the actual point of this beat. I shipped the capture, the fallback, &lt;em&gt;and&lt;/em&gt; an eval whose entire job is to refuse the story I want to tell. It caught the original 24-task 0ms burst, and it's still catching the residual one. The cadence quality is a known bug, tracked in the backlog, not hand-waved away in the journal. A state engine that lies confidently is worse than one that admits it isn't done.&lt;/p&gt;

&lt;p&gt;Here's what the eval saw before and after the fix:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6mbk4u8s7j5e0170z8e0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6mbk4u8s7j5e0170z8e0.jpg" alt="Before and after: on the left a dense stack of two dozen task markers collapsed onto one instant (a 0ms burst); on the right the markers journaled by an AI and spread along a timeline, except three still stacked at one point and caught under a magnifier with a red X" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the left, all 24 tasks pile onto one instant; on the right the AI-authored entries spread out, but three still stack up, and the eval circles exactly those.&lt;/p&gt;

&lt;p&gt;The other two proofs are quieter but matter just as much. Delete &lt;code&gt;.spec-context.json&lt;/code&gt; on a real spec and &lt;code&gt;derive-from-files.py&lt;/code&gt; rebuilds the right step and status from the artifacts and git alone. And &lt;code&gt;/speckit.companion.status&lt;/code&gt; reads that journal, or the derived one, and tells you exactly where a spec sits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ /speckit.companion.status
Spec: Fix Opencode Prompt Flag   (source: state)
Step: implement   Status: implemented
Decisions: (none recorded)
Next: Pipeline complete  →  —
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Its sibling, &lt;code&gt;/speckit.companion.resume&lt;/code&gt;, reads that same resolved state, carries the recorded &lt;code&gt;decisions[]&lt;/code&gt; into scope, and dispatches the next &lt;code&gt;/speckit.*&lt;/code&gt; command, or refuses to invent one when the pipeline is already done. I pointed it at the spec above, which had finished every step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ /speckit.companion.resume
The resolution is complete: true.
Pipeline complete — nothing to resume.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the terminal branch doing exactly the right thing: read the journal, resolve &lt;code&gt;complete: true&lt;/code&gt;, dispatch nothing. It's the unglamorous half of resume, but it's the half that keeps the command from running a finished spec off a cliff. The interesting half, resume re-entering a half-done pipeline and firing the next command, is covered by the 25 resolver tests today, and it earns a proper walkthrough rather than a footnote here. So that gets its own log.&lt;/p&gt;

&lt;p&gt;And the final proof is the one I'd been putting off: installing it the way a stranger would. Not the dev symlink I'd been dogfooding all along, but the real thing, &lt;code&gt;specify extension add companion --from &amp;lt;release.zip&amp;gt;&lt;/code&gt; off a public GitHub release. Then I ran &lt;code&gt;/speckit.specify&lt;/code&gt; on a fresh feature and watched the release-installed hook write the file itself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;📃&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;specs/&lt;/span&gt;&lt;span class="mi"&gt;131&lt;/span&gt;&lt;span class="err"&gt;-fix-opencode-prompt-flag/.spec-context.json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;—&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;written&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;release-installed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;extension&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"step"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"specify"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"from"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"step"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"by"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"extension"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-06-08T02:09:08.437Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;by: "extension"&lt;/code&gt; means the hook fired, not a manual write; the ms-precision timestamp means it fired &lt;em&gt;live&lt;/em&gt;, at the moment specify ran, not backfilled later. The same canonical &lt;code&gt;history[]&lt;/code&gt;, the same writer, but emitted by a copy of the extension that came down the wire from a release archive. That's the line between "works on my machine" and "works." v1 ships.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I built it this way
&lt;/h2&gt;

&lt;p&gt;A few choices I'd defend to anyone copying this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reuse the hook mechanism for every lifecycle event.&lt;/strong&gt; No daemon, no file watcher polling for changes. It rides spec-kit's own prompt-driven execution, the same machinery Build Log 1 already proved.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Derive-from-files is a first-class capture path, not a gap-filler.&lt;/strong&gt; Hooks are best-effort by design. The fallback means the GUI reflects reality even on a project that never ran the extension. State you can't trust is worse than no state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Status and resume are thin readers&lt;/strong&gt; over the one canonical file. No second source of truth to drift out of sync.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resume dispatches the already-installed &lt;code&gt;/speckit.*&lt;/code&gt; commands, not a &lt;code&gt;specify workflow resume&lt;/code&gt; CLI.&lt;/strong&gt; The backlog assumed a &lt;code&gt;&amp;gt;=0.8.5&lt;/code&gt; subcommand, but my workspace runs &lt;code&gt;0.7.4.dev0&lt;/code&gt;. Binding resume to a subcommand that might not exist would break on exactly the stock installs v1 is supposed to support. Dispatching what's already there works everywhere.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Capture and status/resume stay always-on.&lt;/strong&gt; They're the v1 core the GUI reads from. The differentiator features, the lean preset, complexity, drift, auto mode, agent teams, all come later and ship opt-out. The thing that &lt;em&gt;tracks your work&lt;/em&gt; shouldn't be a setting.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;v1 is the boundary this log climbs to: install the Companion on any spec-kit project and get tracking plus resume on your existing flow, no template change. From here the posts stop being plumbing and start being the SDD opinion.&lt;/p&gt;

&lt;p&gt;Two things I'm deliberately carrying forward. The cadence still bursts on fast specs, and the eval won't let me forget it. And resume deserves to be &lt;em&gt;shown&lt;/em&gt; re-entering a live pipeline, not described. Both get their own treatment next, alongside Build Log 3: the SDD shape, the &lt;code&gt;sdd-lean&lt;/code&gt; preset that overrides the templates, and a complexity fast-path that right-sizes the ceremony so a one-line change doesn't drag the full pipeline behind it.&lt;/p&gt;

&lt;p&gt;The public backlog tracks every step as it merges. Watch the repo, and I'll see you at the next one.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Angular Best Practices for AI</title>
      <dc:creator>Alfredo Perez</dc:creator>
      <pubDate>Mon, 05 Oct 2026 13:23:38 +0000</pubDate>
      <link>https://dev.to/alfredoperez/angular-best-practices-for-ai-27m0</link>
      <guid>https://dev.to/alfredoperez/angular-best-practices-for-ai-27m0</guid>
      <description>&lt;p&gt;If you've been using AI to write Angular code, you've probably noticed a pattern. Your agent keeps making the same mistakes. It writes sequential async calls that create request waterfalls. It eagerly loads routes that should be lazy. It misuses signals in ways that thrash change detection. The code compiles, it runs, but it's not how you'd write it.&lt;/p&gt;

&lt;p&gt;AI agents are great at Angular syntax, but they don't have the context of what "good" Angular looks like in production. They're missing the best practices that experienced developers carry around in their heads.&lt;/p&gt;

&lt;p&gt;When I saw &lt;a href="https://vercel.com/blog/introducing-react-best-practices" rel="noopener noreferrer"&gt;Vercel's react-best-practices announcement&lt;/a&gt;, I realized this is exactly what Angular needs. A curated set of rules you can share with your AI agent and with other developers. But I also wanted something the community could contribute to and make better over time, not just a static list that one person maintains.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;Angular Best Practices&lt;/strong&gt;, a curated rules package that teaches your AI coding agent how to write better Angular code. It works with Claude Code, Cursor, Codex, VS Code Copilot, and 30+ more agents.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add alfredoperez/angular-best-practices
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What Is It?
&lt;/h2&gt;

&lt;p&gt;Angular Best Practices is a skills package built on the &lt;a href="https://agentskills.io/" rel="noopener noreferrer"&gt;Agent Skills specification&lt;/a&gt;. You install it, and your AI agent immediately gets access to curated Angular rules covering everything from eliminating request waterfalls and bundle optimization to signals, RxJS patterns, change detection, SSR, testing, and architecture.&lt;/p&gt;

&lt;p&gt;One thing I noticed when rules are AI-generated: they tend to include &lt;em&gt;long code examples with poor context&lt;/em&gt;. That wastes tokens and bloats your agent's context window. Every rule in this package is &lt;strong&gt;human-reviewed&lt;/strong&gt; for accuracy and token efficiency. Each rule is &lt;strong&gt;under 50 lines&lt;/strong&gt; with one to three line code examples. Every rule shows a clear &lt;strong&gt;incorrect vs correct pattern&lt;/strong&gt; so the AI knows exactly what to change, not just what to aim for. They're &lt;strong&gt;tagged by impact&lt;/strong&gt; (CRITICAL, HIGH, MEDIUM, or LOW) so the most important ones get applied first.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F92333g73lqn31s0mdv04.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F92333g73lqn31s0mdv04.png" alt="Screenshot of the web app showing rule categories" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pick What You Need
&lt;/h2&gt;

&lt;p&gt;I didn't want to split every little aspect of Angular into its own package. If you look at the &lt;code&gt;rules/&lt;/code&gt; folder in the repo, you'll see every rule divided by topic: signals, components, RxJS, change detection, and so on. But when you install the core package, it all comes together as a single file. If you use Angular, this is the one you want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add alfredoperez/angular-best-practices
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where it does make sense to split is at the library level. State management libraries, component libraries, testing libraries—these are different for every project. My plan is to have best practices for each one as a separate package, so you just pick whatever you actually have installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add alfredoperez/angular-best-practices-ngrx
npx skills add alfredoperez/angular-best-practices-signalstore
npx skills add alfredoperez/angular-best-practices-tanstack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxs8ffkg25w3q1772lbg8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxs8ffkg25w3q1772lbg8.png" alt="Screenshot showing manual installation options" width="800" height="655"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you prefer manual installation, copy the &lt;code&gt;AGENTS.md&lt;/code&gt; file directly into your project: &lt;code&gt;.claude/AGENTS.md&lt;/code&gt; for Claude Code, &lt;code&gt;.cursor/rules/angular.md&lt;/code&gt; for Cursor, or &lt;code&gt;.github/copilot-instructions.md&lt;/code&gt; for VS Code Copilot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Explore the Rules
&lt;/h2&gt;

&lt;p&gt;Before installing anything, browse all the rules on the web app at &lt;a href="https://angular-best-practices-web.vercel.app/" rel="noopener noreferrer"&gt;angular-best-practices-web.vercel.app&lt;/a&gt;. Check out the categories, read through the code examples, and see if there's something you'd want to use right away—or if there's a rule you think is missing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxx8hajx5ihn2kq2fnr5v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxx8hajx5ihn2kq2fnr5v.png" alt="Screenshot of web app showing a specific rule page" width="800" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Want a Rule Added?
&lt;/h2&gt;

&lt;p&gt;This is an open source project. If you want a rule added, &lt;a href="https://github.com/alfredoperez/angular-best-practices/issues" rel="noopener noreferrer"&gt;create a request&lt;/a&gt; on GitHub—that's it. Rules follow a simple template: a short description, an incorrect pattern, and the correct one, all under 50 lines. Every submission gets human-reviewed for accuracy and token efficiency before it's merged.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fccjfbarfnxhqvok76t8e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fccjfbarfnxhqvok76t8e.png" alt="Screenshot of GitHub issue template" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add alfredoperez/angular-best-practices
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check out the &lt;a href="https://github.com/alfredoperez/angular-best-practices" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;, browse the rules at &lt;a href="https://angular-best-practices-web.vercel.app/" rel="noopener noreferrer"&gt;angular-best-practices-web.vercel.app&lt;/a&gt;, and let me know what you think. Next time your AI agent tries to nest three subscriptions deep, it'll know better.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>ai</category>
      <category>agentskills</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Give Spec Kit Superpowers</title>
      <dc:creator>Alfredo Perez</dc:creator>
      <pubDate>Mon, 05 Oct 2026 13:23:13 +0000</pubDate>
      <link>https://dev.to/alfredoperez/give-spec-kit-superpowers-1pp9</link>
      <guid>https://dev.to/alfredoperez/give-spec-kit-superpowers-1pp9</guid>
      <description>&lt;p&gt;Spec-driven development is the habit of making the AI agent write down what it's going to build before it builds it. &lt;a href="https://github.com/github/spec-kit" rel="noopener noreferrer"&gt;GitHub's Spec Kit&lt;/a&gt; is the tool a lot of people use for that: one command per phase, specify, plan, tasks, implement, and each phase lands as a markdown file in your repo.&lt;/p&gt;

&lt;p&gt;If you've run a feature or two through it, you know the part that's hard to hold in your head. Here's what a single run leaves behind, phase by phase, with the side commands you can call in between.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fua17zy5tyii5jn7xgu9x.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fua17zy5tyii5jn7xgu9x.jpg" alt="Four phases, seven files, and the optional commands that attach to each phase" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When it finishes, you're the one who has to work out which of those files says what actually happened. The files are all there, but nothing puts them together for you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kiro.dev" rel="noopener noreferrer"&gt;Kiro&lt;/a&gt; showed that putting the specs in a panel beside the code, instead of in a folder you open by hand, makes the whole thing easier to follow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcw2or594fqw7zru7ojeb.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcw2or594fqw7zru7ojeb.webp" alt="Kiro with a spec open: requirements, design, and task list as phases above the document, and the agent beside it" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Image: Kiro's launch post.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Spec Kit deserves the same, and that's what &lt;a href="https://speckit-companion.dev" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt; is. It's a VS Code extension that reads what Spec Kit writes and turns it into one page per spec: what the run was for, what it checked, what it decided, and what's left. It also changes the run itself, with a shorter pipeline for small changes, specs that stay current after a feature ships, and a pipeline you can rearrange.&lt;/p&gt;

&lt;p&gt;The files never stop being markdown, and that's what makes this work: the agent creates and edits them fast because they're plain text, and Companion is a better way to read the same files.&lt;/p&gt;


&lt;h2&gt;
  
  
  Install both halves
&lt;/h2&gt;

&lt;p&gt;Companion comes in two parts, and it helps to know which is which before you install. The VS Code extension is the part you look at. The spec-kit extension installs into Spec Kit itself and runs on the command line: it records the run, sizes the pipeline to the change, and keeps living specs up to date. The VS Code side reads what the command-line side writes to a plain &lt;code&gt;.spec-context.json&lt;/code&gt; in each spec folder. Neither needs the other, but the tour below assumes both.&lt;/p&gt;

&lt;p&gt;The VS Code extension comes from the &lt;a href="https://marketplace.visualstudio.com/items?itemName=alfredoperez.speckit-companion" rel="noopener noreferrer"&gt;Marketplace&lt;/a&gt;: search for SpecKit Companion in VS Code and install it. The spec-kit extension is a separate step, and it's the one that turns on traceability, fast mode, auto mode, living specs, and custom workflows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;specify extension add companion &lt;span class="nt"&gt;--from&lt;/span&gt; https://github.com/alfredoperez/speckit-companion/releases/download/companion-latest/companion.zip &lt;span class="nt"&gt;--force&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Spec Kit asks you to confirm before it installs from a URL instead of its catalog, so answer &lt;code&gt;y&lt;/code&gt; at the prompt. Here's what both halves look like once they're in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8uhu3lqkg82xed4cpebj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8uhu3lqkg82xed4cpebj.png" alt="The VS Code extension in the Extensions view, and the spec-kit extension installed from the terminal" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open a repo that already has a &lt;code&gt;.specify&lt;/code&gt; folder and the sidebar fills in.&lt;/p&gt;




&lt;h2&gt;
  
  
  Start on the Overview
&lt;/h2&gt;

&lt;p&gt;The first thing Companion gives you is the Overview. Every spec with recorded activity gets one page that says what the run was for and what it actually did, and that's where the spec opens.&lt;/p&gt;

&lt;p&gt;Here's why it matters. A run in stock Spec Kit produces seven artifacts across four phases. To know whether any of it happened the way you intended, you read all of them, and in practice nobody does.&lt;/p&gt;

&lt;p&gt;I'll use one finished spec, a profile photo upload, for every screenshot below, so you're never decoding a new feature between sections. Here is what the page holds, top to bottom, and why each part earned its place.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why the spec exists, and how the run went
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwttevcfz24wbhq83lnpb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwttevcfz24wbhq83lnpb.png" alt="The reason in one sentence, then how long each phase took, then which living specs the run folded back into" width="800" height="670"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first thing you read is the reason the spec exists, written as a sentence rather than a feature name. Under it sits the run rail with the four phases, how long each took, and the total, and then a card with the approach in two lines, the area of the codebase it worked in, the size verdict that decided how much pipeline it got, and the living specs it loaded and folded back into.&lt;/p&gt;

&lt;p&gt;This block is the answer to "what is this spec and is it relevant to me". When I come back months later, that's the whole question, and it takes a few seconds here instead of four files.&lt;/p&gt;

&lt;h3&gt;
  
  
  The fence around the work
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe72a95qkwauorce3nyym.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe72a95qkwauorce3nyym.png" alt="What must stay true, and what was deliberately left out" width="800" height="620"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This part is two lists: what must stay true no matter how the feature is built, and what was deliberately put out of scope. The second list is the one that saves arguments later. When someone asks why the uploader doesn't crop, the answer is on the page, dated, and it was a choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  What was checked, and what happened
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F809bvjszo82c96ra6cbk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F809bvjszo82c96ra6cbk.png" alt="Four checks the pipeline ran, each with its exit code and time, then one the run only reported" width="800" height="740"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is every check the run made, split in two. On top are the checks the pipeline ran itself: the command, the exit code, and how long it took. Below them is anything the run only reported, like a manual pass on a phone, shown quieter so it can't pass for proof. If a check failed, it sits here with its exit code, not buried in a terminal scrollback that closed with the session.&lt;/p&gt;

&lt;p&gt;This is the part I trust most. A spec can describe anything, and so can an agent summarizing its own work. A row with an exit code is harder to be wrong about.&lt;/p&gt;

&lt;h3&gt;
  
  
  Choices future work should not have to rediscover
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz2e8lop6q0dvcdy9rkpn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz2e8lop6q0dvcdy9rkpn.png" alt="Each decision carries its reason and the alternative it rejected" width="800" height="700"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The rejected alternatives are more important than they sound. A decision alone tells you what was decided. A decision with what it rejected tells you the consequences were considered, and it stops the next person, or the next agent, from proposing the rejected option as if it were new.&lt;/p&gt;

&lt;h3&gt;
  
  
  Requirement to task to test
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjibd21w9vzwnancsg7yu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjibd21w9vzwnancsg7yu.png" alt="One row per requirement: which tasks delivered it and how many tests cover it" width="800" height="580"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A requirement with no test shows up as a gap, which is the cheapest moment to notice. The run log and the per-task records fold away under it for when you want the blow-by-blow.&lt;/p&gt;

&lt;h3&gt;
  
  
  And while it runs
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fec9a5iwwticebnzb041h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fec9a5iwwticebnzb041h.png" alt="Mid-run, two phases in. The pipeline across the top ticks each document as it lands and times the phase in flight" width="800" height="676"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The same spec is what I watch while a run is going. The pipeline across the top unlocks phase by phase, tasks tick over while implement runs, and one button always offers the next step. When it settles, the Overview above is what's left behind.&lt;/p&gt;




&lt;h2&gt;
  
  
  Read the spec, not the markdown
&lt;/h2&gt;

&lt;p&gt;Click into any artifact and the viewer takes the plain markdown the agent wrote and renders it as something you can scan: user stories become cards, requirements become labeled rows, acceptance scenarios read as Given, When, Then lines, tasks sit under their phase with a badge for their state, and Mermaid diagrams render inline. The file underneath doesn't change. What changes is that you can find the one requirement you care about without reading the ones around it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fokmdjr3wavkmgwm3ijj0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fokmdjr3wavkmgwm3ijj0.png" alt="A user story as a card with its scenarios, then each requirement as a labeled row" width="800" height="925"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Two things make this more than pretty markdown. The first is that any file the spec mentions is a link. When the plan says the route lives in &lt;code&gt;avatar.ts&lt;/code&gt;, you click it and the file opens beside the plan.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhj11u1597zk254avne6x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhj11u1597zk254avne6x.png" alt="The plan names the route file, and one click opens it in the editor next to it" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The second is that you're in VS Code, so the spec sits beside the code it describes and the git changes the run produced. With the diff next to it, you read the plan against what actually changed instead of on its own, and that's where a plan that says one thing while the code does another shows up.&lt;/p&gt;




&lt;h2&gt;
  
  
  Review the spec where it is written
&lt;/h2&gt;

&lt;p&gt;The part I use most is that you can review the artifacts and talk to the spec right there, without going back to the chat to prompt each correction. Every rendered row takes a comment, the way a line in a pull request does.&lt;/p&gt;

&lt;p&gt;Here's what those comments usually catch. The agent reads the code near where it's working, picks up a pattern that lives there, and treats it as the house style, when it's often a shortcut someone took in March. The plan proposes a component that's fine for this feature and not reusable for the next one. Or it read a requirement wrong. In the raw markdown those lines look like every other line. In the viewer they're rows you can point at.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd0qfc9mtf1ztwjryh04l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd0qfc9mtf1ztwjryh04l.png" alt="A comment sits under the line it is about. One is pending, one was already applied, a third is being written" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The alternative is what I did first: type the correction into the chat. "The service in the plan, around the middle, should use the shared client, and the component should not be one-off." Then hope the model finds the lines you meant, and fixes both without touching anything else. Two corrections in one prompt is already a coin flip.&lt;/p&gt;

&lt;p&gt;I comment on each thing, exactly like a pull request review, then hit Refine once. Here's what the agent receives when I do.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fytdoknq1vk5pzgcrd78w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fytdoknq1vk5pzgcrd78w.png" alt="Two pending comments on the plan, one click on Run refinement, and Claude Code editing the plan in the terminal" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each comment arrives with the exact line it's about, and the instruction is to edit the file in place rather than regenerate it. The spec comes back corrected, and often with tasks added: a step that applies the pattern I actually want, or a check that keeps the mistake from coming back. The model decides the extent. A one-word comment reworks a sentence, and a paragraph reconsiders the section.&lt;/p&gt;

&lt;p&gt;Comments are saved as you type and committed with the repo, so a review you abandon on Friday is still there on Monday, or on the other machine. Some comments never go to the agent at all. They stay as notes for whoever reads the spec next.&lt;/p&gt;




&lt;h2&gt;
  
  
  Work from the sidebar
&lt;/h2&gt;

&lt;p&gt;The sidebar has three areas, and each one answers a different question.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fag5eiw8okrxu31h1xyie.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fag5eiw8okrxu31h1xyie.png" alt="Specs, Living Specs, and Steering, each with what it's for" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Specs are grouped by lifecycle, with live status per document. You can sort, filter by status, and mark specs complete or archived so only the open ones show.&lt;/p&gt;

&lt;p&gt;I don't like working several features at once, so most days that filter shows one or two. What it's built for is the other mode: plan several features, let them run in auto mode, and come back to review all of them from one list. Hover a spec and it offers to resume where it left off.&lt;/p&gt;




&lt;h2&gt;
  
  
  See what stays true
&lt;/h2&gt;

&lt;p&gt;Feature specs describe one change and then go quiet. Living specs are one per capability, like checkout, auth, or billing. They're loaded into the agent's context when a feature touches that area and brought up to date when the feature ships. I wrote up why in &lt;a href="https://alfredo-perez.dev/blog/2026-08-31-i-wrote-238-specs-and-never-read-one-again" rel="noopener noreferrer"&gt;I Wrote 238 Specs and Never Read One Again&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The sidebar's Living Specs area opens each one as a list of requirements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8s6syumr8babax9mjr7z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8s6syumr8babax9mjr7z.png" alt="The living specs tree with coverage per capability, and Photo Storage open on its requirements, flagged for drift" width="799" height="552"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A living spec holds what the capability must do, as requirements with scenarios, plus the paths it covers. When a feature run touches that area, the spec is loaded before the agent reads code, and when the feature ships, what changed is folded back into it. The feature spec stays as the record of the run, and the living spec is the record of what is true.&lt;/p&gt;

&lt;p&gt;Each requirement is a card, and its left edge tells you where it stands: confirmed, adopted and waiting for you to confirm it, or drifted because the code changed. Each capability shows its test coverage, and the drift flag appears the moment its source files change without the spec following. Comments and Refine work here the same way they do on a feature spec. Open any source file and the status bar says how many living specs describe it, one click from the requirement. That's the answer to the question a folder of feature specs can't answer: is this still true?&lt;/p&gt;




&lt;h2&gt;
  
  
  See the pipeline your project runs
&lt;/h2&gt;

&lt;p&gt;Spec-driven development only works for a team if the workflow fits the team. Yours might want a security review after the plan, a different task template, or no checklist at all. When the pipeline can't bend, people route around it, and then the specs stop meaning anything. So Companion lets you change the pipeline, and the Pipeline Builder is where you see what you changed.&lt;/p&gt;

&lt;p&gt;The steps are columns in run order. Inside each step you see its phases, the nodes in them, and the hooks your project attached before or after.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbtu2ws4tzr65nv2f2vkn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbtu2ws4tzr65nv2f2vkn.png" alt="Four steps as columns. The hooks under before and after, marked as this project's own, are the customization" width="800" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Anything your project changed carries the same color: a hook you added, a node you rewrote, a template section you replaced. Nothing else gets that color, so when someone asks what your team does differently, you can answer by looking. You can build from the same panel too, and if &lt;code&gt;companion.yml&lt;/code&gt; is newer than the commands built from it, the header tells you.&lt;/p&gt;




&lt;h2&gt;
  
  
  What changes in the run itself
&lt;/h2&gt;

&lt;p&gt;Companion isn't only a better way to look at the files. It also adds new ways to run Spec Kit, so the workflow fits how you actually work. Each of these gets its own piece:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast mode reads the size of a change and folds the pipeline for small ones, so a renamed button doesn't get the full ceremony.&lt;/li&gt;
&lt;li&gt;Auto mode runs specify to implement without stopping, which is how I plan several features and review them together.&lt;/li&gt;
&lt;li&gt;Living specs, adopted on a repo you already have, with drift detection and sync.&lt;/li&gt;
&lt;li&gt;Custom workflows: your own steps, hooks, and node order, from one file. The earlier versions of that idea are in &lt;a href="https://alfredo-perez.dev/blog/2026-03-21-build-your-own-sdd-workflow" rel="noopener noreferrer"&gt;Build Your Own SDD Workflow&lt;/a&gt; and &lt;a href="https://alfredo-perez.dev/blog/2026-03-20-custom-workflows-in-speckit-companion" rel="noopener noreferrer"&gt;Custom Workflows in SpecKit Companion&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Install the VS Code extension from the Marketplace, and the spec-kit extension with the command above.&lt;/li&gt;
&lt;li&gt;Open a repo with a &lt;code&gt;.specify&lt;/code&gt; folder.&lt;/li&gt;
&lt;li&gt;Read the Overview before anything else.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Docs and install links are at &lt;a href="https://speckit-companion.dev" rel="noopener noreferrer"&gt;speckit-companion.dev&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Next up: how I plan several features at once, run them in auto mode, and review the whole batch from the sidebar.&lt;/p&gt;

</description>
      <category>specdrivendevelopment</category>
      <category>speckit</category>
      <category>speckitcompanion</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>I Wrote 238 Specs and Never Read One Again</title>
      <dc:creator>Alfredo Perez</dc:creator>
      <pubDate>Fri, 11 Sep 2026 15:02:05 +0000</pubDate>
      <link>https://dev.to/alfredoperez/i-wrote-238-specs-and-never-read-one-again-5705</link>
      <guid>https://dev.to/alfredoperez/i-wrote-238-specs-and-never-read-one-again-5705</guid>
      <description>&lt;p&gt;Nine months ago I started building a &lt;a href="https://alfredo-perez.dev/blog/2026-03-19-what-is-speckit-companion" rel="noopener noreferrer"&gt;VS Code extension&lt;/a&gt; in the open, and I ran every change in it through spec-driven development.&lt;/p&gt;

&lt;p&gt;The tool underneath is &lt;a href="https://github.com/github/spec-kit" rel="noopener noreferrer"&gt;GitHub's spec-kit&lt;/a&gt;. The idea is simple: before the AI agent writes any code, you make it write down what it's building. A feature moves through four phases, specify, plan, tasks, and implement, and each one lands as a markdown file committed to the repo. You review the spec instead of reviewing the two hundred lines of code that would have come out of misreading it.&lt;/p&gt;

&lt;p&gt;My project is &lt;a href="https://github.com/alfredoperez/speckit-companion" rel="noopener noreferrer"&gt;SpecKit Companion&lt;/a&gt;. It sits on top of spec-kit and shows you those specs while they're being written, so you can catch a wrong requirement before it becomes a wrong implementation.&lt;/p&gt;

&lt;p&gt;The repo now contains 94 spec folders, 238 markdown files, and 15,225 lines of specification.&lt;/p&gt;

&lt;p&gt;I haven't reopened a single one since it was marked complete.&lt;/p&gt;

&lt;p&gt;That's not laziness. It's the honest result of doing spec-driven development on something real for long enough. I stopped believing the folder had answers in it somewhere around spec forty, and I never went back. The specs folder had become a write-only place: somewhere things go, not somewhere anyone reads.&lt;/p&gt;

&lt;p&gt;Spec-driven development is what created that problem. It shouldn't be that way.&lt;/p&gt;

&lt;h2&gt;
  
  
  What spec-kit gets right
&lt;/h2&gt;

&lt;p&gt;Give GitHub's spec-kit its due, because the part it owns is the hard part.&lt;/p&gt;

&lt;p&gt;It forces the decision onto paper before the code exists. I wrote up that whole loop in &lt;a href="https://alfredo-perez.dev/blog/2026-01-02-stop-vibe-coding-start-shipping" rel="noopener noreferrer"&gt;Stop Vibe Coding, Start Shipping&lt;/a&gt;. Specify, plan, tasks, implement, and each phase pulls something out of your head that you would otherwise leave implicit and find it later, usually while debugging. A vague requirement dies at the specify step, rather than becoming two hundred lines of wrong implementation.&lt;/p&gt;

&lt;p&gt;That worked. That is why there are 94 of them.&lt;/p&gt;

&lt;p&gt;What no one talks about is what 94 completed specs do to a repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Specs don't just accumulate. They start to lie.
&lt;/h2&gt;

&lt;p&gt;Developing SpecKit Companion was not a straightforward series of new features. It was rewrites, refactors, and reversals: decisions I made in March and undid in June.&lt;/p&gt;

&lt;p&gt;Let's take one concrete thread, how a task gets marked complete, how the time it took gets tracked. I've iterated that many many times. Each iteration had its own spec, its own acceptance criteria, its own functional requirements, its own record of what I believed at the time.&lt;/p&gt;

&lt;p&gt;So when I go looking for "how does task completion actually work", there's no answer in that folder. Five specs touch it. Four are superseded. None of them says which.&lt;/p&gt;

&lt;p&gt;That's the piece that is lost when people talk about spec-driven development. A spec is a moment's snapshot of intent. Snapshots don't update. Put 94 of them in a folder and you don't have documentation, you have an archaeological site, and every layer contradicts the one above it.&lt;/p&gt;

&lt;p&gt;The first fix was the obvious one: pull out the durable parts into &lt;code&gt;docs/&lt;/code&gt;. That worked for a month or so. Then the docs drifted too, because a hand-maintained abstraction has exactly the same problem plus a second place to look. Now I'm moving away from that.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part I got wrong
&lt;/h2&gt;

&lt;p&gt;I figured the problem of all this was mine. I couldn't find things, so I stopped looking, and I treated that as a personal organization issue.&lt;/p&gt;

&lt;p&gt;Then I looked at what my agent was doing.&lt;/p&gt;

&lt;p&gt;Before living specs, when I asked Claude to work on a feature, it read the codebase. Not the specs. The code, plus whatever scattered documents it could find, reconstructing intent from implementation every single session. 94 specs sat right there in the repo, describing exactly what it was working out from scratch, and it went around them.&lt;/p&gt;

&lt;p&gt;Of course it did. I would have done the same. Faced with 238 files, which ones are current? You don't know. The rational move is to read the code.&lt;/p&gt;

&lt;p&gt;So the folder wasn't just unread by me. It was unread by the machine that wrote it.&lt;/p&gt;

&lt;p&gt;Here's the line I'd put on a wall: a spec that nothing reads isn't documentation, it's exhaust.&lt;/p&gt;

&lt;p&gt;Once I saw it that way, the question had a different shape. It moved from "how do I organize my specs" to "what does the agent load before it starts."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdawdzg8bmgdz0q39xrgm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdawdzg8bmgdz0q39xrgm.jpg" alt="Before and after: on the left an agent sweeps past a grid of closed spec cards and reads the whole codebase, on the right three living specs load first and a thin line continues to the code marked locate only" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  There are two extensions, and only one of them is a GUI
&lt;/h2&gt;

&lt;p&gt;Before we get to the mechanism, a clarification is needed, as this is the single most common misunderstanding about SpecKit Companion, and it matters for everything below.&lt;/p&gt;

&lt;p&gt;It reads as a VS Code thing. It isn't.&lt;/p&gt;

&lt;p&gt;The VS Code extension is the GUI. The sidebar, per-spec status, the pipeline rail, the Resume button, inline review. It's the half you look at.&lt;/p&gt;

&lt;p&gt;The spec-kit extension installs into spec-kit itself and runs on the command line. It records the lifecycle, right-sizes the pipeline, assembles commands from nodes, and extracts living specs. There's no editor involved.&lt;/p&gt;

&lt;p&gt;Neither half depends on the other. The command-line half writes a plain &lt;code&gt;.spec-context.json&lt;/code&gt; into each spec directory, and the GUI reads that. That file is the entire handoff, and it's an ordinary JSON, so anything else can read it too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjuuudan1zcawx970jyl3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjuuudan1zcawx970jyl3.jpg" alt="Two panels, the spec-kit extension on the command line and the VS Code extension GUI, connected only through a dot spec-context dot json file between them" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Which means: the command-line part generates living specs, drift detection, and the run record. And if you never open VS Code, you get all of them.&lt;/p&gt;

&lt;p&gt;I'll take the blame for the confusion. I started with the GUI and the product outgrew it, and the naming is still a reflection of that history. While we are here, one asymmetry is worth stating plainly: the GUI doesn't support every AI provider yet. The spec-kit extension does, matching stock spec-kit's set.&lt;/p&gt;

&lt;h2&gt;
  
  
  Living specs invert the read order
&lt;/h2&gt;

&lt;p&gt;A living spec is one spec per capability, not one spec per change. Checkout. Auth. Billing. In this repo: core, spec viewer, AI providers, and eleven more. 238 files and 15,225 lines of feature specs become 14 files and 3,112 lines.&lt;/p&gt;

&lt;p&gt;The feature specs went nowhere. They got relegated. They're the artifacts of the work now, the record of what happened during a run, not the record of what's true. That distinction is the whole point.&lt;/p&gt;

&lt;p&gt;The extraction step is what makes it work, and it isn't a copy. When a feature ships, the extraction compares the living spec to the code and reconciles both, so what lands is what the code actually does, not what the feature spec hoped it would do.&lt;/p&gt;

&lt;p&gt;Then the read order reverses. The agent loads the living spec first, and reads code only to discover where the capability lives, not to discover what it does.&lt;/p&gt;

&lt;p&gt;Here's the portable version of that: when I build the next feature without any spec-kit, in a plain prompt, the living specs still answer what the capability needs. They are not tied to the workflow that created them.&lt;/p&gt;

&lt;p&gt;You can store them centrally in a capabilities folder, or colocated with the code they describe. One reversible command lets you flip between them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1rf5nb8yjcjcczp0pb4p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1rf5nb8yjcjcczp0pb4p.png" alt="The Living Specs sidebar showing per-capability test coverage and drift flags, beside the viewer open on one capability" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Four questions that follow
&lt;/h2&gt;

&lt;p&gt;Once specs are readable again, four things you couldn't ask before become askable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Are they still true?
&lt;/h3&gt;

&lt;p&gt;Companion commands update living specs. Work done outside Companion, a quick fix in a plain prompt on a Friday, leaves requirements that nothing recorded.&lt;/p&gt;

&lt;p&gt;That's where drift detection comes in. It flags which capability's source files have been changed since its spec was last committed. Then the repair command rereads the actual code changes, compares them to the living spec and adjusts it.&lt;/p&gt;

&lt;p&gt;You turn it on repo by repo, it just adds to a spec, and a flag never stops a run. Drift is information, not a gate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I verify one run?
&lt;/h3&gt;

&lt;p&gt;The intent, approach, decisions and requirements are distributed across seven artifacts and four phases. You have to read all of them to know if any of it was ever fulfilled. Nobody does.&lt;/p&gt;

&lt;p&gt;The Overview is a single page that answers why the spec exists, its constraints, the decisions made and alternatives rejected, each verified check and the command that proves it, and a requirement-to-test coverage table.&lt;/p&gt;

&lt;p&gt;The rejected alternatives are more important than they sound. A decision tells you only what was decided. A decision with its rejected alternatives tells you the consequences were considered.&lt;/p&gt;

&lt;p&gt;Months later, this is the page that tells you in about ten seconds if a spec is even relevant to what you're looking for.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1pi8qg7yyst1irexg8ze.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1pi8qg7yyst1irexg8ze.webp" alt="The Overview page scrolling from intent through per-phase timing, verified checks with the commands that prove them, decisions with rejected alternatives, and the coverage table" width="760" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I correct one?
&lt;/h3&gt;

&lt;p&gt;The old way was to type out the correction: "Remember that new service to use, at about line forty, that should be different". Then hope the model gets the line you meant and good luck trying to fix multiple things at the same time.&lt;/p&gt;

&lt;p&gt;Inline review comments are the pull request review you already know. Read the artifact, comment on the specific line, hit refine, and the pending comments go to AI as an in-place edit of the source. The model determines the extent: reword the artifact or reconsider that one line.&lt;/p&gt;

&lt;p&gt;There is a second use which I did not design, which came from a user. Some comments aren't even directed at the AI. These are notes of why a decision was taken, left for the next person reading the spec. They never leave.&lt;/p&gt;

&lt;p&gt;I am more likely to give up on reviews halfway than to finish them. Comments are saved as you type and committed with the repo. Next session, the half-done one is still there or on the other machine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9f4yuegab6crn2xxp984.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9f4yuegab6crn2xxp984.png" alt="A spec with three comment states: one pending, one applied, and the composer open on line four showing how a comment is added" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Does a renamed button need all of this?
&lt;/h3&gt;

&lt;p&gt;Here's stock spec-kit's honest failure. Every change goes through the full pipeline, so every change is a decision to use spec-kit or not. You touch two files, and go for a simple prompt.&lt;/p&gt;

&lt;p&gt;I run into this all the time with little things. Moving a button in the sidebar. Adding a context menu item. Renaming something.&lt;/p&gt;

&lt;p&gt;Fast mode detects the change and folds the pipeline for the small ones. But the reason I'm still running the pipeline for a renamed button isn't what you'd think. My workflow is already review, open the PR, wait for it, merge. Not doing the pipeline means hand-prompting all four of those over and over.&lt;/p&gt;

&lt;p&gt;It composes with auto mode. For a small change I don't need to review the spec, the plan, and the design. It goes from issue link to PR without stopping, and fast mode makes it quick, not ceremonial.&lt;/p&gt;

&lt;p&gt;The measured version, from a benchmark across both workflows: Companion specs are approximately 60 to 68% leaner and write no throw-away side files at any size. Correctness was tied, with every cell in both workflows shipping a passing build against an all-green regression suite and scored 5.0 out of 5 on an independent-judge rubric. Ceremony is the variable, not whether the feature works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it still loses
&lt;/h2&gt;

&lt;p&gt;The two-extension confusion above is the real adoption cost, and I haven't solved it, only explained it.&lt;/p&gt;

&lt;p&gt;Living specs adoption on an existing codebase is the part I'm least sure of. There's a brownfield adoption path, but it needs more feedback than it's had. Usage is nowhere near &lt;a href="https://github.com/Fission-AI/OpenSpec" rel="noopener noreferrer"&gt;OpenSpec&lt;/a&gt;'s, and I don't have enough signal yet to know which parts of it are wrong.&lt;/p&gt;

&lt;p&gt;The customization claim needs an honest edge too. Every part of the process is configurable: the steps, the templates, the artifacts, the hooks, which skills attach where. I built that deliberately, because every SDD framework I tried boxed me into its own commands, and I walked through building one from scratch in &lt;a href="https://alfredo-perez.dev/blog/2026-03-21-build-your-own-sdd-workflow" rel="noopener noreferrer"&gt;Build Your Own SDD Workflow&lt;/a&gt; and &lt;a href="https://alfredo-perez.dev/blog/2026-03-20-custom-workflows-in-speckit-companion" rel="noopener noreferrer"&gt;Custom Workflows&lt;/a&gt;. But everything being configurable means there's more to configure, and the default path has to be good enough that most people never touch it. I'm not certain it is yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd take from this
&lt;/h2&gt;

&lt;p&gt;The useful question in spec-driven development is not how much spec you write. It's what gets read later, and by whom.&lt;/p&gt;

&lt;p&gt;94 specs nobody opened taught me less than 14 that get loaded every session.&lt;/p&gt;

&lt;p&gt;Both halves are useful, and they work better together, and the docs are at &lt;a href="https://speckit-companion.dev" rel="noopener noreferrer"&gt;speckit-companion.dev&lt;/a&gt;, if you want to try them out in your own repo.&lt;/p&gt;

&lt;p&gt;I cut three threads to keep this one readable: adopting living specs on an existing codebase, what the fast-mode short circuit actually decides, and running auto mode end to end. Each is a separate piece and I'll write them up next.&lt;/p&gt;

</description>
      <category>specdrivendevelopment</category>
      <category>aicoding</category>
      <category>speckitcompanion</category>
      <category>livingspecs</category>
    </item>
  </channel>
</rss>
