<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Test-Driven Development on RockB</title><link>https://baeseokjae.github.io/tags/test-driven-development/</link><description>Recent content in Test-Driven Development on RockB</description><image><title>RockB</title><url>https://baeseokjae.github.io/images/og-default.png</url><link>https://baeseokjae.github.io/images/og-default.png</link></image><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sat, 23 May 2026 04:16:02 +0000</lastBuildDate><atom:link href="https://baeseokjae.github.io/tags/test-driven-development/index.xml" rel="self" type="application/rss+xml"/><item><title>Superpowers + Claude Code: TDD Workflow Setup Guide 2026</title><link>https://baeseokjae.github.io/posts/superpowers-claude-code-tdd-guide-2026/</link><pubDate>Sat, 23 May 2026 04:16:02 +0000</pubDate><guid>https://baeseokjae.github.io/posts/superpowers-claude-code-tdd-guide-2026/</guid><description>How to set up the Superpowers framework with Claude Code for enforced TDD workflows — with real configuration examples and what changes in practice.</description><content:encoded><![CDATA[<p>The biggest failure mode when using AI coding agents is letting them skip the test. Superpowers is an open-source framework — 99K+ GitHub stars, 2.5M+ VS Code extension downloads, official Claude Plugin Marketplace listing — that enforces test-driven development as a hard constraint on Claude Code rather than a suggestion. Here&rsquo;s how to set it up and what actually changes in practice.</p>
<h2 id="what-is-the-superpowers-framework-and-why-tdd-enforcement-matters">What Is the Superpowers Framework and Why TDD Enforcement Matters</h2>
<p>Superpowers is a framework that installs as a system prompt layer between your requests and Claude Code&rsquo;s reasoning engine, enforcing a 5-phase TDD discipline on every coding task: requirements clarification, test writing, implementation, test passing, and refactoring. Unlike <code>.cursorrules</code> or a <code>CLAUDE.md</code> file that suggests behavior, Superpowers uses a structured agent protocol that blocks code generation until a failing test exists. The framework reached 99K+ GitHub stars and an official listing on the Anthropic Claude Plugin Marketplace, with 2.5M+ VS Code extension downloads as of 2026. The core insight behind Superpowers is that AI coding agents are optimistic — they generate code that looks correct and compiles cleanly, but fails in edge cases that a test suite would catch immediately. When you add TDD enforcement at the framework level, Claude Code can&rsquo;t take the shortcut of writing implementation first and hoping tests follow. The workflow discipline is structural, not optional. For developers who have shipped code with AI agents only to find regressions a week later, this matters significantly. The free tier is available for individual use with a Pro plan at $20/month for team features.</p>
<h2 id="installing-superpowers-with-claude-code">Installing Superpowers with Claude Code</h2>
<p>Installing Superpowers takes about five minutes. You need Claude Code running (CLI or VS Code extension) and either npm or pip available.</p>
<p><strong>Option 1: VS Code Extension (recommended for most developers)</strong></p>
<p>Install the Superpowers VS Code extension directly from the marketplace:</p>



<div class="goat svg-container ">
  
    <svg
      xmlns="http://www.w3.org/2000/svg"
      font-family="Menlo,Lucida Console,monospace"
      
        viewBox="0 0 312 25"
      >
      <g transform='translate(8,16)'>
<text text-anchor='middle' x='0' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='8' y='4' fill='currentColor' style='font-size:1em'>x</text>
<text text-anchor='middle' x='16' y='4' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'>p</text>
<text text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'>p</text>
<text text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'>w</text>
<text text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'>-</text>
<text text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='200' y='4' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'>.</text>
<text text-anchor='middle' x='216' y='4' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='224' y='4' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='232' y='4' fill='currentColor' style='font-size:1em'>p</text>
<text text-anchor='middle' x='240' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='248' y='4' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='256' y='4' fill='currentColor' style='font-size:1em'>p</text>
<text text-anchor='middle' x='264' y='4' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'>w</text>
<text text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'>s</text>
</g>

    </svg>
  
</div>
<p>After installation, open VS Code settings and configure your Claude API key:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;superpowers.apiKey&#34;</span>: <span style="color:#e6db74">&#34;sk-ant-your-key-here&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;superpowers.tddMode&#34;</span>: <span style="color:#e6db74">&#34;strict&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;superpowers.testFramework&#34;</span>: <span style="color:#e6db74">&#34;auto&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Set <code>tddMode</code> to <code>strict</code> to block code generation before tests. <code>auto</code> detects your test framework from <code>package.json</code>, <code>pyproject.toml</code>, or <code>Cargo.toml</code>.</p>
<p><strong>Option 2: Claude Code CLI plugin</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>claude plugin install superpowers
</span></span><span style="display:flex;"><span>claude plugin configure superpowers --tdd-mode strict
</span></span></code></pre></div><p><strong>Option 3: Manual CLAUDE.md integration</strong></p>
<p>If you prefer not to use the extension, you can bootstrap Superpowers behavior by adding the framework&rsquo;s system prompt to your project&rsquo;s <code>CLAUDE.md</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>curl -o CLAUDE.md https://raw.githubusercontent.com/obra/superpowers/main/prompts/strict-tdd.md
</span></span></code></pre></div><p>The manual approach gives you full control over the prompt but loses the extension&rsquo;s IDE integrations (test status bar, coverage overlays).</p>
<h2 id="configuring-the-tdd-workflow">Configuring the TDD Workflow</h2>
<p>The 5-phase Superpowers discipline maps onto Claude Code as a structured conversation pattern. Each phase produces a checkpoint that Superpowers tracks before allowing the next:</p>
<p><strong>Phase 1: Requirements Clarification.</strong> Claude asks clarifying questions before writing any code. This prevents the &ldquo;build the wrong thing&rdquo; failure mode that&rsquo;s common with AI agents. Superpowers forces at least one clarification round on ambiguous requests.</p>
<p><strong>Phase 2: Test Writing.</strong> Before any implementation code, Claude writes failing tests that describe the expected behavior. These tests must actually fail (Superpowers verifies this by running your test suite).</p>
<p><strong>Phase 3: Implementation.</strong> Implementation code is written to make the failing tests pass. Nothing more.</p>
<p><strong>Phase 4: Test Passing.</strong> Superpowers runs your test suite and verifies all target tests pass before marking the phase complete.</p>
<p><strong>Phase 5: Refactoring.</strong> With a passing test suite as a safety net, Claude refactors implementation code for clarity and performance without changing behavior.</p>
<p>Configure the phases in <code>.superpowers/config.json</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;phases&#34;</span>: {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;clarification&#34;</span>: { <span style="color:#f92672">&#34;required&#34;</span>: <span style="color:#66d9ef">true</span>, <span style="color:#f92672">&#34;min_questions&#34;</span>: <span style="color:#ae81ff">1</span> },
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;test_first&#34;</span>: { <span style="color:#f92672">&#34;required&#34;</span>: <span style="color:#66d9ef">true</span>, <span style="color:#f92672">&#34;verify_failure&#34;</span>: <span style="color:#66d9ef">true</span> },
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;implementation&#34;</span>: { <span style="color:#f92672">&#34;max_lines_per_commit&#34;</span>: <span style="color:#ae81ff">200</span> },
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;verify_passing&#34;</span>: { <span style="color:#f92672">&#34;required&#34;</span>: <span style="color:#66d9ef">true</span>, <span style="color:#f92672">&#34;fail_on_error&#34;</span>: <span style="color:#66d9ef">true</span> },
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;refactor&#34;</span>: { <span style="color:#f92672">&#34;enabled&#34;</span>: <span style="color:#66d9ef">true</span>, <span style="color:#f92672">&#34;lint_check&#34;</span>: <span style="color:#66d9ef">true</span> }
</span></span><span style="display:flex;"><span>  },
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;test_command&#34;</span>: <span style="color:#e6db74">&#34;npm test&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;coverage_minimum&#34;</span>: <span style="color:#ae81ff">80</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="writing-a-test-first-what-it-looks-like-in-practice">Writing a Test First: What It Looks Like in Practice</h2>
<p>Here&rsquo;s what the Superpowers workflow looks like on a real task — adding a rate limiter to an API endpoint.</p>
<p>You prompt Claude: &ldquo;Add rate limiting to the <code>/api/generate</code> endpoint. Limit to 10 requests per minute per user.&rdquo;</p>
<p>With Superpowers in strict mode, Claude&rsquo;s response starts with clarification:</p>
<blockquote>
<p>Before writing code: should the rate limit reset at the start of each minute (fixed window) or slide as requests arrive (sliding window)? What should happen when the limit is exceeded — return a 429 with retry-after, or silently drop? Are authenticated and anonymous users limited separately?</p></blockquote>
<p>After clarification, Claude writes the test:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-typescript" data-lang="typescript"><span style="display:flex;"><span><span style="color:#a6e22e">describe</span>(<span style="color:#e6db74">&#39;Rate limiter&#39;</span>, () <span style="color:#f92672">=&gt;</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">it</span>(<span style="color:#e6db74">&#39;allows 10 requests per minute per user&#39;</span>, <span style="color:#66d9ef">async</span> () <span style="color:#f92672">=&gt;</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">userId</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;test-user-1&#39;</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">10</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">res</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">request</span>(<span style="color:#a6e22e">app</span>).<span style="color:#a6e22e">post</span>(<span style="color:#e6db74">&#39;/api/generate&#39;</span>).<span style="color:#66d9ef">set</span>(<span style="color:#e6db74">&#39;x-user-id&#39;</span>, <span style="color:#a6e22e">userId</span>);
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">expect</span>(<span style="color:#a6e22e">res</span>.<span style="color:#a6e22e">status</span>).<span style="color:#a6e22e">not</span>.<span style="color:#a6e22e">toBe</span>(<span style="color:#ae81ff">429</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">res</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">request</span>(<span style="color:#a6e22e">app</span>).<span style="color:#a6e22e">post</span>(<span style="color:#e6db74">&#39;/api/generate&#39;</span>).<span style="color:#66d9ef">set</span>(<span style="color:#e6db74">&#39;x-user-id&#39;</span>, <span style="color:#a6e22e">userId</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">expect</span>(<span style="color:#a6e22e">res</span>.<span style="color:#a6e22e">status</span>).<span style="color:#a6e22e">toBe</span>(<span style="color:#ae81ff">429</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">expect</span>(<span style="color:#a6e22e">res</span>.<span style="color:#a6e22e">headers</span>[<span style="color:#e6db74">&#39;retry-after&#39;</span>]).<span style="color:#a6e22e">toBeDefined</span>();
</span></span><span style="display:flex;"><span>  });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">it</span>(<span style="color:#e6db74">&#39;tracks limits independently per user&#39;</span>, <span style="color:#66d9ef">async</span> () <span style="color:#f92672">=&gt;</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">10</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">request</span>(<span style="color:#a6e22e">app</span>).<span style="color:#a6e22e">post</span>(<span style="color:#e6db74">&#39;/api/generate&#39;</span>).<span style="color:#66d9ef">set</span>(<span style="color:#e6db74">&#39;x-user-id&#39;</span>, <span style="color:#e6db74">&#39;user-a&#39;</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">res</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">request</span>(<span style="color:#a6e22e">app</span>).<span style="color:#a6e22e">post</span>(<span style="color:#e6db74">&#39;/api/generate&#39;</span>).<span style="color:#66d9ef">set</span>(<span style="color:#e6db74">&#39;x-user-id&#39;</span>, <span style="color:#e6db74">&#39;user-b&#39;</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">expect</span>(<span style="color:#a6e22e">res</span>.<span style="color:#a6e22e">status</span>).<span style="color:#a6e22e">not</span>.<span style="color:#a6e22e">toBe</span>(<span style="color:#ae81ff">429</span>);
</span></span><span style="display:flex;"><span>  });
</span></span><span style="display:flex;"><span>});
</span></span></code></pre></div><p>Superpowers runs <code>npm test</code> and verifies these tests fail (they do — the endpoint doesn&rsquo;t have rate limiting yet). Only then does Claude write the implementation. This workflow catches the most common AI coding failure: writing an implementation that passes its own tests but misses edge cases.</p>
<h2 id="performance-improvements-in-practice">Performance Improvements in Practice</h2>
<p>Superpowers TDD enforcement has measurable effects on code quality, review speed, and production reliability. Teams using Superpowers consistently report fewer regression bugs per sprint — the verify_failure checkpoint catches behavior changes that would otherwise pass CI and ship. Code review is faster because reviewers see tests alongside implementation, giving them a spec to evaluate the code against rather than inferring intent. Production debugging time decreases because the test suite documents expected behavior and makes it easier to pinpoint where behavior diverged. The specific impact varies by team and project, but the direction is consistent: more upfront time per task, less time fixing problems after merge. Enterprise case studies from Superpowers&rsquo; ROI reports show teams reducing post-release bug reports by 30–45% after adopting the framework, with the heaviest benefits in API and business logic layers where edge cases are most costly.</p>
<p>The tradeoff is speed on individual tasks: initial task completion takes 20–30% longer with Superpowers because clarification and test-writing phases add round trips before implementation starts. For prototyping or spike work where correctness is less critical, this friction is real. Most teams configure a <code>--fast</code> flag that disables strict TDD for exploratory branches and enables it automatically on branches targeting <code>main</code>.</p>
<h2 id="best-practices-and-patterns">Best Practices and Patterns</h2>
<p><strong>Commit tests separately from implementation.</strong> This makes code review easier and preserves the test-first intent in your git history. Superpowers can enforce this with a pre-commit hook: <code>superpowers hook install --require-test-commit</code>.</p>
<p><strong>Use coverage minimums per feature area, not globally.</strong> A 90% global coverage target hides coverage gaps in critical paths. Configure Superpowers to enforce 100% coverage on your API layer and lower thresholds for UI components.</p>
<p><strong>Combine with TypeScript strict mode.</strong> The type safety and test enforcement layers complement each other — TypeScript catches type errors at build time that tests catch at runtime. Running both eliminates a broad class of bugs before review.</p>
<p><strong>Don&rsquo;t enforce TDD on data migration scripts.</strong> One-shot scripts that run once and then become dead code don&rsquo;t benefit from TDD investment. Configure Superpowers to skip enforcement in a <code>scripts/</code> or <code>migrations/</code> directory with:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;exclude_paths&#34;</span>: [<span style="color:#e6db74">&#34;scripts/&#34;</span>, <span style="color:#e6db74">&#34;migrations/&#34;</span>, <span style="color:#e6db74">&#34;*.seed.ts&#34;</span>]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="faq">FAQ</h2>
<p><strong>Q: Does Superpowers work with test frameworks other than Jest?</strong>
Yes — Superpowers has built-in support for Jest, Vitest, Mocha, pytest, RSpec, Cargo test, and Go test. The <code>testFramework: &quot;auto&quot;</code> setting detects your framework from project config files. You can also configure a custom test command in <code>.superpowers/config.json</code> if you use an unusual test runner.</p>
<p><strong>Q: Can I use Superpowers with Cursor or Windsurf instead of Claude Code?</strong>
Superpowers was built for Claude Code and works best with Claude models. Cursor and Windsurf have partial support through the VS Code extension API, but some phase enforcement features (verify_failure step, inter-phase blocking) require the Claude Code execution environment to work reliably.</p>
<p><strong>Q: What happens if Claude generates code before the test in strict mode?</strong>
Superpowers intercepts the response and returns an error to Claude&rsquo;s context: &ldquo;Implementation code detected before test. Please write failing tests first.&rdquo; Claude then backtracks and writes the test before implementation. In practice, after a few interactions Claude adapts to the expected workflow without prompting.</p>
<p><strong>Q: Does the Pro plan ($20/month) add meaningful features for solo developers?</strong>
The free tier includes all TDD enforcement features. Pro adds team coverage dashboards, shared configuration management across a team, CI integration for coverage reporting, and priority support. For solo developers, the free tier is sufficient for most workflows.</p>
<p><strong>Q: How does Superpowers handle test generation for UI components?</strong>
UI component testing is the weakest area. Superpowers can generate Jest + Testing Library tests for React/Vue components, but visual correctness testing (screenshot comparison, visual regression) is outside its scope. For UI-heavy projects, pair Superpowers with a visual testing tool like Chromatic or Percy for full coverage.</p>
]]></content:encoded></item></channel></rss>