<?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>Forem: Amitai Levy</title>
    <description>The latest articles on Forem by Amitai Levy (@amitaile).</description>
    <link>https://forem.com/amitaile</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3769249%2Fa3a4e1af-4edd-489b-8ea4-5731dca93e65.png</url>
      <title>Forem: Amitai Levy</title>
      <link>https://forem.com/amitaile</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/amitaile"/>
    <language>en</language>
    <item>
      <title>Using Claude Code to Post-Mortem Its Own Mistakes</title>
      <dc:creator>Amitai Levy</dc:creator>
      <pubDate>Thu, 05 Mar 2026 10:29:34 +0000</pubDate>
      <link>https://forem.com/amitaile/using-claude-code-to-post-mortem-its-own-mistakes-3ned</link>
      <guid>https://forem.com/amitaile/using-claude-code-to-post-mortem-its-own-mistakes-3ned</guid>
      <description>&lt;p&gt;In a &lt;a href="https://dev.to/amitaile/the-wrong-unit-of-work-what-happened-when-i-built-my-dev-environment-using-claude-code-5a6"&gt;previous post&lt;/a&gt;, I wrote about building a Docker Compose dev environment using Claude Code — and how it took 15 commits across 10+ sessions because the first session produced everything as one intertwined system instead of incrementally. That post told the story. This one is about the process — how I used Claude Code itself to analyze session logs, identify failure patterns, and turn them into targeted fixes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Session Logs Are There
&lt;/h2&gt;

&lt;p&gt;Claude Code stores conversation transcripts as JSONL files in &lt;code&gt;~/.claude/projects/&lt;/code&gt;. Each session is a complete record — every user message, every tool call, every file read and edit. I had months of history across 8 repos, totaling hundreds of sessions.&lt;/p&gt;

&lt;p&gt;I wouldn't want to read through all of that manually. But Claude Code can.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Gather Evidence
&lt;/h2&gt;

&lt;p&gt;I started a new session and pointed Claude at the session log directory. The prompt was roughly: "look at conversation history to see the many iterations it took to get the dev-environment right. Dive into what went wrong."&lt;/p&gt;

&lt;p&gt;It launched parallel agents to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Walk the full git history (15 commits) and summarize what changed in each&lt;/li&gt;
&lt;li&gt;Extract all user messages from the largest session files&lt;/li&gt;
&lt;li&gt;Read CLAUDE.md files across all sibling repos to find related patterns&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;From the session logs, it found concrete evidence: 41 user messages in the main session, at least 7 redirections where I interrupted mid-execution, 5 explicit "stop and simplify" requests. It identified the specific things that were over-engineered (custom shell script, shared Dockerfile, env file layering, port offset arithmetic) and mapped them to the commits where they were eventually removed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Find Cross-Repo Patterns
&lt;/h2&gt;

&lt;p&gt;A single bad session might look like an isolated mistake. So I asked Claude to look across other repos for the same pattern.&lt;/p&gt;

&lt;p&gt;It found it. In a different repo, Claude had delivered a full-stack feature — backend schemas, validation endpoints, frontend wizard, form integration — all in one pass. My response in that session: "This is a very big feature. Perhaps we can iterate implementation a bit, leave parts blank or mock then fill them in? It's hard to plan all the details at once." Same problem, different project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Categorize the Failure Modes
&lt;/h2&gt;

&lt;p&gt;Claude categorized the user messages it extracted — redirections, corrections, explicit rejections, "why does this exist?" questions. This turned vague dissatisfaction into a ranked list of specific, recurring failure modes. Not "Claude is too verbose" but things like "when asked to build X, Claude builds the most thorough version of X instead of the simplest."&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Turn Patterns into Rules
&lt;/h2&gt;

&lt;p&gt;This is where the analysis becomes useful. Each failure mode maps to a specific, implementable fix. The key is to write rules that are concrete behavioral changes, not general principles. "Prefer simplicity" doesn't change behavior. "Propose a sequence of increments, implement the first one, check in before the next" does.&lt;/p&gt;

&lt;p&gt;The rules went into my global &lt;code&gt;CLAUDE.md&lt;/code&gt; — the config file that Claude Code loads into every conversation. They're untested — I don't know yet if they'll change behavior enough. But they're grounded in specific documented patterns, not vibes.&lt;/p&gt;

&lt;h2&gt;
  
  
  If You Want to Try This
&lt;/h2&gt;

&lt;p&gt;The ingredients are simple: the session logs exist, Claude Code can read them, and you probably have enough history to surface patterns. The steps generalize:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Point Claude at session logs for a project where you felt like you fought the tool&lt;/li&gt;
&lt;li&gt;Ask it to find cross-repo patterns, not just single-session issues&lt;/li&gt;
&lt;li&gt;Have it categorize user messages by type (redirections, corrections, rejections)&lt;/li&gt;
&lt;li&gt;For each failure mode, design a specific rule or workflow change — not a general principle&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The output doesn't have to be CLAUDE.md rules. It could be hook scripts, skill definitions, per-repo instructions, or changes to how you prompt. The point is turning accumulated friction into targeted fixes.&lt;/p&gt;

&lt;p&gt;In fact — I just started writing blog posts, and I'm writing them with Claude. These two posts took a fair amount of back-and-forth to get right. After a few more, I'll probably have enough session history to use this exact method to write myself a blog-writing skill.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>productivity</category>
      <category>tooling</category>
    </item>
    <item>
      <title>The Wrong Unit of Work: What Happened When I Built My Dev Environment using Claude Code</title>
      <dc:creator>Amitai Levy</dc:creator>
      <pubDate>Tue, 03 Mar 2026 21:11:17 +0000</pubDate>
      <link>https://forem.com/amitaile/the-wrong-unit-of-work-what-happened-when-i-built-my-dev-environment-using-claude-code-5a6</link>
      <guid>https://forem.com/amitaile/the-wrong-unit-of-work-what-happened-when-i-built-my-dev-environment-using-claude-code-5a6</guid>
      <description>&lt;p&gt;I use Claude Code daily for real product engineering. I'm building a clinical trials platform at PhaseV, and Claude Code is my primary coding partner across a multi-repo microservices stack.&lt;/p&gt;

&lt;p&gt;Recently I asked it to set up a local Docker Compose dev environment with multi-instance support. It took 15 commits across 10+ sessions to get there. Not because the problem was hard, but because the first session produced everything as one intertwined system instead of building up to it incrementally.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Asked For
&lt;/h2&gt;

&lt;p&gt;Several backend services, a frontend, and shared infrastructure. Each service in its own repo. I wanted a central repo that orchestrates everything with Docker Compose so a developer can run &lt;code&gt;docker compose up&lt;/code&gt;. I mentioned that multi-instance support would be important — being able to run the stack twice for different feature branches.&lt;/p&gt;

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

&lt;p&gt;The first session produced everything at once:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;compose.yaml&lt;/code&gt; with &lt;code&gt;include&lt;/code&gt;s for each service&lt;/li&gt;
&lt;li&gt;A shared Dockerfile for all Python services&lt;/li&gt;
&lt;li&gt;A custom shell script called &lt;code&gt;pv&lt;/code&gt; with subcommands for managing instances&lt;/li&gt;
&lt;li&gt;Port offset arithmetic and environment file layering for multi-instance support&lt;/li&gt;
&lt;li&gt;Workspace selection logic for choosing which repos to include&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I asked for a compose-based dev environment with multi-instance support. The implementation approach came as a package — one intertwined system. Each piece was defensible in isolation. Together they were complex, fragile, and hard to maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Simplification Marathon
&lt;/h2&gt;

&lt;p&gt;What followed was 10+ sessions of me pulling things back out:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Session 2-3:&lt;/strong&gt; "Why do we need the &lt;code&gt;pv compose&lt;/code&gt; script? Can't we just use &lt;code&gt;docker compose&lt;/code&gt; directly?" Claude explained the benefits. I said drop it. Dropped.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Session 4-5:&lt;/strong&gt; "Why does each service use a shared Dockerfile? Let each repo own its own." Switched to per-repo Dockerfiles with Compose Watch for live reload. Removed the shared &lt;code&gt;Dockerfile&lt;/code&gt;, &lt;code&gt;entrypoint-dev.sh&lt;/code&gt;, and the &lt;code&gt;pv rebuild&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Session 6-7:&lt;/strong&gt; "Why is infrastructure separate from apps? Just put them in the same Compose project." Merged infra into the main compose file. Removed &lt;code&gt;container_name&lt;/code&gt; directives, the shared network, and the separate &lt;code&gt;pv infra&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Session 8:&lt;/strong&gt; "Why do we need port variables for every service? Just let Docker assign random ports." Removed a dozen port variables from &lt;code&gt;.env&lt;/code&gt;. Only the frontend kept a fixed port.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Session 9-10:&lt;/strong&gt; "Why is &lt;code&gt;.env&lt;/code&gt; so big? Most of these values are constants." Moved defaults into each service's compose file. The &lt;code&gt;.env&lt;/code&gt; went from ~30 variables to 2.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final state:&lt;/strong&gt; A 15-line &lt;code&gt;compose.yaml&lt;/code&gt; with &lt;code&gt;include&lt;/code&gt;s, a &lt;code&gt;compose.infra.yaml&lt;/code&gt;, a 2-line &lt;code&gt;.env.example&lt;/code&gt;, and a README. Multi-instance works via Compose project names — no scripts, no port arithmetic.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Happened
&lt;/h2&gt;

&lt;p&gt;I went back and read the session transcripts — not just for this feature, but across other repos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The unit of work is wrong.&lt;/strong&gt; The default behavior is to treat each task as a single delivery — plan, build, present. By the time I saw the full output, the pieces were intertwined and hard to pull apart. If it had delivered a bare compose file first and then added multi-instance support on top, I could have steered the implementation approach early instead of unwinding it after the fact.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'm Trying
&lt;/h2&gt;

&lt;p&gt;After the analysis, I added a rule to my global &lt;code&gt;CLAUDE.md&lt;/code&gt; — the config file that Claude Code loads into every conversation:&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="gu"&gt;## Lead with increments&lt;/span&gt;

For complex features, act as a tech lead managing the process:
&lt;span class="p"&gt;
1.&lt;/span&gt; Propose a sequence of increments — not a detailed plan,
   just the milestones.
&lt;span class="p"&gt;2.&lt;/span&gt; Implement the first increment autonomously. Build the
   smallest complete version that works. Deliver it.
&lt;span class="p"&gt;3.&lt;/span&gt; Check in briefly before the next increment. Let the user
   decide if more is needed. Often the first increment is enough.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is untested. I'm hoping it shifts Claude from "deliver the comprehensive solution" to "deliver the first working version and let the user steer from there." For the dev-environment case, that would have looked like: "Step 1: compose file that starts all services. Step 2: add profiles. Step 3: multi-instance support." By step 3, the basic setup would already be working, and I could have evaluated what multi-instance actually needs — instead of unwinding an over-engineered approach after the fact.&lt;/p&gt;

&lt;p&gt;Whether a CLAUDE.md rule can actually change this behavior, I don't know yet. Discussion welcome.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>docker</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
