<?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: Nick Woodhead</title>
    <description>The latest articles on DEV Community by Nick Woodhead (@naw103).</description>
    <link>https://dev.to/naw103</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%2F3554256%2F30bcbda8-7c4e-4e95-b2a5-0e5a0008965a.png</url>
      <title>DEV Community: Nick Woodhead</title>
      <link>https://dev.to/naw103</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/naw103"/>
    <language>en</language>
    <item>
      <title>Coding agents stop mid-task. Our coordination store had 3,896 stale conflicts</title>
      <dc:creator>Nick Woodhead</dc:creator>
      <pubDate>Mon, 02 Nov 2026 16:15:51 +0000</pubDate>
      <link>https://dev.to/naw103/coding-agents-stop-mid-task-our-coordination-store-had-3896-stale-conflicts-4iem</link>
      <guid>https://dev.to/naw103/coding-agents-stop-mid-task-our-coordination-store-had-3896-stale-conflicts-4iem</guid>
      <description>&lt;p&gt;Foremerge records what each coding agent plans to change before it edits anything, and raises a finding when two plans cannot both be true. That only works if the record is current. Version 0.6.0 fixes the way it was not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agents stop without saying goodbye
&lt;/h2&gt;

&lt;p&gt;An agent session ends without closing its intent far more often than you would guess. A context window fills up. A laptop lid closes. A scheduled run reaches the end of its slot. The intent the agent published stays open, its claims expire, and nobody closes it.&lt;/p&gt;

&lt;p&gt;Foremerge treated that abandoned work as live. Every later intent on the same files was compared against it, and each comparison that found something was recorded. One of our own repositories, where scheduled agents and interactive sessions share a single coordination store, reached 3,896 open conflicts, 98% of them with no live agent on either side. A new intent on a busy file opened with about 40 recorded against it, and the ones worth reading were buried in the ones that were not.&lt;/p&gt;

&lt;p&gt;This is a problem you only get from running several agents at once over a long period. One agent, one session, and the record stays tidy by accident.&lt;/p&gt;

&lt;h2&gt;
  
  
  What 0.6.0 changes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A finding below HIGH against work whose agent has stopped is no longer recorded. An intent counts as stopped under the same test &lt;code&gt;work adopt&lt;/code&gt; already applied: it sits in &lt;code&gt;INTENT&lt;/code&gt;, &lt;code&gt;CLAIMED&lt;/code&gt;, &lt;code&gt;IN_PROGRESS&lt;/code&gt; or &lt;code&gt;PROVISIONAL&lt;/code&gt;, it holds no live claim, and its agent has made no call that writes to the record for two hours (reads and validation runs do not count).&lt;/li&gt;
&lt;li&gt;Stopped work is still listed in &lt;code&gt;related_work&lt;/code&gt;, last, marked with &lt;code&gt;owner_stopped_since&lt;/code&gt;, and needs no assessment. Another agent can see it there and adopt it. A what-if &lt;code&gt;check_conflicts&lt;/code&gt; applies the same rule and names what it left out under &lt;code&gt;stopped_work&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If the agent was only quiet, its next call, an adoption of its work, or a check that validates it records the findings that were skipped in the meantime, unless the other agent has gone quiet too. Pairs already on record are left alone, settled or not. If the agent never returns, those findings are never recorded. The stopped work stays listed in related_work, but nothing requires anyone to act on it. This leans on severity: everything below HIGH counts as safe to skip, so a finding rated too low goes with the rest.&lt;/li&gt;
&lt;li&gt;The agent skill and the &lt;code&gt;discard_work&lt;/code&gt; description now tell an agent to close its intent before it stops. Work that reached Git without going through acceptance, because no named check is registered or a maintainer committed a batch by hand, can be closed with &lt;code&gt;foremerge work discard --landed REF&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why HIGH findings are still recorded
&lt;/h3&gt;

&lt;p&gt;HIGH findings gate acceptance, and an agent that was only quiet must not lose that protection. So the gate is unchanged. A stopped intent whose declared plan genuinely contradicts yours still asserts, and you still have to deal with it before your ChangeSet is accepted. The rule only removes the advisory noise underneath that line.&lt;/p&gt;

&lt;h3&gt;
  
  
  What you see now
&lt;/h3&gt;

&lt;p&gt;Before, a new intent on a crowded file came back with a long list of recorded conflicts, most of them against intents whose agents had been gone for days, and nothing in the list told you which was which. Now the same intent comes back with the live findings only. The stopped work is still there at the end of &lt;code&gt;related_work&lt;/code&gt;, each entry carrying &lt;code&gt;owner_stopped_since&lt;/code&gt; with the time its agent went quiet, so you can see what was set aside and pick it up if it is worth finishing.&lt;/p&gt;

&lt;p&gt;Conflicts already on record are not touched by the upgrade. To clear a backlog like ours, close the stopped intents.&lt;/p&gt;

&lt;h2&gt;
  
  
  The migration change
&lt;/h2&gt;

&lt;p&gt;Foremerge used to migrate a ledger's schema as a side effect of opening it, and every command opens the ledger, including the ones that only read. A &lt;code&gt;status&lt;/code&gt; run by a newer binary from the wrong directory migrated a real repository's shared coordination store and locked every older client out of it.&lt;/p&gt;

&lt;p&gt;Foremerge no longer migrates on open. A command that meets an older ledger refuses it with &lt;code&gt;MIGRATION_REQUIRED&lt;/code&gt; and leaves the file exactly as it was. &lt;code&gt;foremerge ledger migrate&lt;/code&gt; does the migration and nothing else does: it refuses to run while another process has the ledger open, copies the ledger with its WAL contents into a timestamped backup directory, checks the copy's integrity, migrates, and prints how to roll back. Without &lt;code&gt;--yes&lt;/code&gt; it only reports what it would do.&lt;/p&gt;

&lt;p&gt;The schema itself has not changed since 0.4.0, so upgrading from any 0.4.x or 0.5.x build needs no migration and both versions read the same store. Only a ledger last opened by 0.3.x needs the step. This is why 0.6.0 is a minor version rather than a patch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://foremerge.com/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That installs a checksum-verified release binary on macOS and Linux. On npm, which also covers Windows x64:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; foremerge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full list of changes is in the &lt;a href="https://github.com/naw103/foremerge/releases/tag/v0.6.0" rel="noopener noreferrer"&gt;0.6.0 release notes&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The general lesson
&lt;/h2&gt;

&lt;p&gt;If you are building coordination for agents, the failure mode to design for is not the agent that disagrees with another agent. It is the agent that never comes back. Human collaborators close their tickets, eventually, because somebody asks them to. An agent whose process exited has no such pressure, and a store that assumes otherwise will slowly fill with work that nobody is doing and nobody will ever withdraw.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devtools</category>
      <category>agents</category>
      <category>git</category>
    </item>
    <item>
      <title>What is an intent conflict?</title>
      <dc:creator>Nick Woodhead</dc:creator>
      <pubDate>Sun, 01 Nov 2026 19:58:42 +0000</pubDate>
      <link>https://dev.to/naw103/what-is-an-intent-conflict-hmf</link>
      <guid>https://dev.to/naw103/what-is-an-intent-conflict-hmf</guid>
      <description>&lt;p&gt;An &lt;strong&gt;intent conflict&lt;/strong&gt; is a contradiction between two declared plans that cannot both be carried out as written. Two coding agents each say what they are about to change and what they will do to it, and the plans disagree: one will replace a thing, the other will build on it. It is called an intent conflict because it exists at the moment the plans are made, before any line of code does.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does an intent conflict look like?
&lt;/h2&gt;

&lt;p&gt;Take a payments class that two agents have been given work on.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Agent A is told to modernize payments. It plans to &lt;strong&gt;replace&lt;/strong&gt; &lt;code&gt;PaymentService&lt;/code&gt;, moving every caller onto a new &lt;code&gt;PaymentProvider&lt;/code&gt; interface.&lt;/li&gt;
&lt;li&gt;Agent B is told to add PayPal. It plans to &lt;strong&gt;extend&lt;/strong&gt; &lt;code&gt;PaymentService&lt;/code&gt; with a PayPal method.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each plan is sensible alone. Together they are not possible: B is adding to a class A is retiring. If each agent works in its own worktree, the files never touch. When the branches merge, Git may find nothing to complain about, and the new PayPal code ends up attached to a class that no longer has callers. &lt;a href="https://foremerge.com/blog/worktrees-move-the-collision-to-merge-time/" rel="noopener noreferrer"&gt;Worktrees do not remove this collision, they move it to merge time&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;An intent conflict is what you want surfaced here, while both agents are still at the planning stage. With Foremerge, each agent publishes an intent and the scopes it will change, with the operation on each. When the second agent declares &lt;code&gt;symbol:PaymentService=extend&lt;/code&gt; against the first agent's &lt;code&gt;replace&lt;/code&gt;, the comparison raises a &lt;code&gt;destructive_vs_additive&lt;/code&gt; finding at HIGH severity, with both worktrees still clean.&lt;/p&gt;

&lt;h2&gt;
  
  
  How is it different from a merge conflict?
&lt;/h2&gt;

&lt;p&gt;A merge conflict is a statement about text: two branches changed the same lines, and Git cannot choose between them. It appears when the work is finished and the branches are combined.&lt;/p&gt;

&lt;p&gt;An intent conflict is a statement about plans. It does not need overlapping lines, overlapping files or even overlapping time. And it can be present when the merge is perfectly clean, which is the case that costs the most, because nothing reports it.&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;Merge conflict&lt;/th&gt;
&lt;th&gt;Intent conflict&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Compares&lt;/td&gt;
&lt;td&gt;changed lines&lt;/td&gt;
&lt;td&gt;declared plans&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Appears&lt;/td&gt;
&lt;td&gt;when branches are combined&lt;/td&gt;
&lt;td&gt;when the second plan is declared&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Needs overlapping text&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can exist with a clean merge&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What is it not?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Not a prediction that the code will break.&lt;/strong&gt; It says two plans contradict each other. Whether the damage is a failing test or a quiet dead end depends on the code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not a replacement for Git.&lt;/strong&gt; Git is still the right tool for text. The intent record sits above it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not the same as orchestration.&lt;/strong&gt; An orchestrator decides who does what. An intent conflict is what is left when two agents each did what they were told and the instructions disagreed. See &lt;a href="https://foremerge.com/blog/orchestrator-vs-coordinator/" rel="noopener noreferrer"&gt;orchestrators and coordinators&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where does the term sit?
&lt;/h2&gt;

&lt;p&gt;Git made disagreement between people a named object: a conflict, appearing at a known moment, resolved before anything lands. Agent coordination applies the same idea one layer up. Git can only see a collision when two agents touch the same lines, and the expensive collisions are decided earlier, in the plans. See &lt;a href="https://foremerge.com/blog/the-coordination-layer/" rel="noopener noreferrer"&gt;the coordination layer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you only ever run one coding agent at a time, you will not meet an intent conflict. If you run several, the cheapest check is to write down what each will change and what it will do to it, and read two entries side by side before anyone starts. Foremerge is open source (Apache-2.0), pre-1.0 and local-first, so it works on one machine and has no shared mode yet.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>git</category>
      <category>devtools</category>
      <category>agents</category>
    </item>
    <item>
      <title>Git worktrees stop your coding agents overwriting each other’s files. They do not stop their plans contradicting each other.

Sometimes Git flags it at merge. Sometimes it merges clean and nothing reports it.</title>
      <dc:creator>Nick Woodhead</dc:creator>
      <pubDate>Thu, 29 Oct 2026 18:29:12 +0000</pubDate>
      <link>https://dev.to/naw103/git-worktrees-stop-your-coding-agents-overwriting-each-others-files-they-do-not-stop-their-plans-38ho</link>
      <guid>https://dev.to/naw103/git-worktrees-stop-your-coding-agents-overwriting-each-others-files-they-do-not-stop-their-plans-38ho</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/naw103/worktrees-do-not-remove-the-collision-they-move-it-to-merge-time-3gb2" class="crayons-story__hidden-navigation-link"&gt;Worktrees do not remove the collision. They move it to merge time.&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/naw103" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3554256%2F30bcbda8-7c4e-4e95-b2a5-0e5a0008965a.png" alt="naw103 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/naw103" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Nick Woodhead
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Nick Woodhead
                
                
              
              &lt;div id="story-author-preview-content-4942942" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/naw103" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3554256%2F30bcbda8-7c4e-4e95-b2a5-0e5a0008965a.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Nick Woodhead&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/naw103/worktrees-do-not-remove-the-collision-they-move-it-to-merge-time-3gb2" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 29&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/naw103/worktrees-do-not-remove-the-collision-they-move-it-to-merge-time-3gb2" id="article-link-4942942"&gt;
          Worktrees do not remove the collision. They move it to merge time.
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/git"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;git&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devtools"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devtools&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/productivity"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;productivity&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/naw103/worktrees-do-not-remove-the-collision-they-move-it-to-merge-time-3gb2" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;10&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/naw103/worktrees-do-not-remove-the-collision-they-move-it-to-merge-time-3gb2#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              16&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            8 min read
          &lt;/small&gt;
          
          &lt;div class="only-sidebar-menu-item trusted-visible-block print-hidden align-center"&gt;
                
                    
                
          &lt;/div&gt;

        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>softwaredevelopment</category>
      <category>git</category>
      <category>agents</category>
      <category>ai</category>
    </item>
    <item>
      <title>Worktrees do not remove the collision. They move it to merge time.</title>
      <dc:creator>Nick Woodhead</dc:creator>
      <pubDate>Thu, 29 Oct 2026 18:27:30 +0000</pubDate>
      <link>https://dev.to/naw103/worktrees-do-not-remove-the-collision-they-move-it-to-merge-time-3gb2</link>
      <guid>https://dev.to/naw103/worktrees-do-not-remove-the-collision-they-move-it-to-merge-time-3gb2</guid>
      <description>&lt;p&gt;Git worktrees give each coding agent its own checkout, so the agents stop overwriting each other's files. They do not remove the collision between what the agents are trying to do. That collision is still there, and with worktrees you find it later, when you merge the branches.&lt;/p&gt;

&lt;p&gt;Sometimes Git stops you at that point. Sometimes it merges cleanly and the damage is only visible if you go looking. Below is a small repository you can build in two minutes that shows both outcomes, then what you can check with Git alone and what you need to move earlier.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;merge-time collision&lt;/strong&gt; is a conflict between two agents' plans that nothing detects until their branches are combined. The plans were incompatible from the moment both were made. Worktrees keep the files apart while the work happens, so the incompatibility sits unseen until integration.&lt;/p&gt;

&lt;h2&gt;
  
  
  What do worktrees isolate, and what do they leave alone?
&lt;/h2&gt;

&lt;p&gt;A worktree is a second checkout of the same repository, on its own branch, in its own directory. Two agents in two worktrees cannot overwrite each other's half-written files, break each other's builds with a stray install, or read stale code because the other agent changed it underneath.&lt;/p&gt;

&lt;p&gt;That is the whole of it, and it is worth having. But look at what is not on the list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What each agent has decided to build.&lt;/strong&gt; That lives in a prompt, not in a file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What each agent assumes will still exist.&lt;/strong&gt; Agent B adds a method to a class because the class is there. It has no way to know Agent A is retiring it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The order in which the work should land.&lt;/strong&gt; Worktrees do not know that one task has to be merged before the other is started.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Isolation helps while the agents work. It decides nothing about whether their work belongs in the same codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does Git report when you merge?
&lt;/h2&gt;

&lt;p&gt;Git merges by comparing changed lines against a common ancestor. I ran the same two-agent task through a throwaway repository three different ways, with Git 2.51.0, and Git gave three different answers.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What Agent A did&lt;/th&gt;
&lt;th&gt;What Agent B did&lt;/th&gt;
&lt;th&gt;What Git said at merge&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Deleted &lt;code&gt;payments.py&lt;/code&gt; after moving callers off it&lt;/td&gt;
&lt;td&gt;Added a method to &lt;code&gt;payments.py&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;CONFLICT (modify/delete)&lt;/code&gt;. Stopped.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rewrote the call in &lt;code&gt;checkout.py&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Added a new function next to that call in &lt;code&gt;checkout.py&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;CONFLICT (content)&lt;/code&gt;. Stopped.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Moved callers to a new class and left &lt;code&gt;payments.py&lt;/code&gt; in place&lt;/td&gt;
&lt;td&gt;Added a method to &lt;code&gt;payments.py&lt;/code&gt; and a new file that uses it&lt;/td&gt;
&lt;td&gt;Clean merge. No output.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The first two are the cases people mean when they say worktrees "work": the plans touch the same file, Git notices, and a person decides. The third is the one that matters here.&lt;/p&gt;

&lt;p&gt;So Git's answer depends on how the agents happened to arrange their edits, not on whether the plans were compatible. The same disagreement is loud in one run and silent in the next.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does the clean merge look like?
&lt;/h2&gt;

&lt;p&gt;Here is the third case from the table, end to end. The task: Agent A is asked to replace &lt;code&gt;PaymentService&lt;/code&gt; with &lt;code&gt;StripePaymentService&lt;/code&gt;. Agent B is asked to add PayPal support to &lt;code&gt;PaymentService&lt;/code&gt;. Each gets its own worktree and branch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git worktree add ../agent-a &lt;span class="nt"&gt;-b&lt;/span&gt; agent/stripe
git worktree add ../agent-b &lt;span class="nt"&gt;-b&lt;/span&gt; agent/paypal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agent A creates &lt;code&gt;shop/stripe_payments.py&lt;/code&gt;, moves every caller in &lt;code&gt;shop/checkout.py&lt;/code&gt; to the new class, and leaves a note at the top of &lt;code&gt;shop/payments.py&lt;/code&gt;: &lt;code&gt;# Deprecated: callers moved to StripePaymentService. Delete next release.&lt;/code&gt; It commits.&lt;/p&gt;

&lt;p&gt;Agent B adds a &lt;code&gt;charge_paypal&lt;/code&gt; method to the end of &lt;code&gt;shop/payments.py&lt;/code&gt; and a new file, &lt;code&gt;shop/paypal_checkout.py&lt;/code&gt;, that calls it. It commits.&lt;/p&gt;

&lt;p&gt;Then the integration, in the main checkout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git merge agent/stripe
 shop/checkout.py        | 4 ++--
 shop/stripe_payments.py | 3 +++
 2 files changed, 5 insertions(+), 2 deletions(-)
 create mode 100644 shop/stripe_payments.py

$ git merge agent/paypal
 shop/payments.py        | 3 +++
 shop/paypal_checkout.py | 4 ++++
 2 files changed, 7 insertions(+)
 create mode 100644 shop/paypal_checkout.py

$ git status --short
(clean)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now look at what the merged repository says:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ head -2 shop/payments.py
# Deprecated: callers moved to StripePaymentService. Delete next release.
class PaymentService:

$ grep -rn "PaymentService" shop/ | grep -v Stripe
shop/payments.py:2:class PaymentService:
shop/paypal_checkout.py:1:from shop.payments import PaymentService
shop/paypal_checkout.py:4:    return PaymentService().charge_paypal(cents)

$ python3 -c "from shop.checkout import checkout; from shop.paypal_checkout import checkout_paypal; print(checkout(500)); print(checkout_paypal(500))"
charged 500 via stripe
charged 500 via paypal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both paths run. Nothing fails. And the codebase now has one class marked for deletion, with PayPal, a new feature, built on top of it. The next person to follow the deprecation note deletes the class and takes PayPal with it. Or they leave it, and the repository permanently has two payment classes, one per gateway.&lt;/p&gt;

&lt;p&gt;No test fails, because each branch's tests passed on its own and the merged tests exercise two working paths. Each agent also reported success, and it was right. The only thing wrong is a contradiction between two plans, and no tool in the standard pipeline reads plans.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is merge time the expensive moment?
&lt;/h2&gt;

&lt;p&gt;The incompatibility existed the second the second agent started. What changes with time is the cost of resolving it. This is reasoning, not a measurement: I have no timing data to give you.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;At planning time&lt;/strong&gt;, you change a sentence in a prompt. Nothing has been written.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;While the agents work&lt;/strong&gt;, you stop one and redirect it. You lose part of a session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;At merge time&lt;/strong&gt;, both agents have finished and both branches are green. Now you are choosing between two completed pieces of work, or rewriting one to sit on the other. If the conflict is the loud kind, you also have to understand both diffs to resolve it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;After merge&lt;/strong&gt;, the conflict is in the codebase, and the only evidence of it is a deprecation note and a class that should not have grown.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Worktrees move the discovery from the first row of that list to the third or fourth. They make the work itself smoother and the surprise later. That trade is usually fine with two agents and a small task. It stops being fine as the number of agents grows, because the number of pairs of plans grows faster than the number of agents.&lt;/p&gt;

&lt;h2&gt;
  
  
  What can you do with Git alone?
&lt;/h2&gt;

&lt;p&gt;Quite a lot, and you should do all of it before you add a tool.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Decide the order of destructive work.&lt;/strong&gt; If a task replaces, removes, renames or migrates something, nobody else should be editing that thing. Run the destructive task first, merge it, then start the others from the merged commit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Define the boundary before you split.&lt;/strong&gt; If two tasks meet at an interface, make one small change that defines it, merge it, and start both agents from that commit. In the example, that is a &lt;code&gt;PaymentProvider&lt;/code&gt; interface first, then Stripe and PayPal behind it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assign by what a task changes, not by its name.&lt;/strong&gt; "Modernize payments" and "add PayPal" sound like two features. They change one class.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test the merged result, not each branch.&lt;/strong&gt; Merge into a throwaway integration branch and run your real checks there. In the example this would have passed, so it catches the loud failures and not the quiet one, but it catches a lot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ask Git whether a merge is clean before you do it.&lt;/strong&gt; &lt;code&gt;git merge-tree --write-tree agent/stripe agent/paypal&lt;/code&gt; performs the merge in memory and reports conflicts without touching your working tree. It is quick, and it gives you the same answer the merge would, which in the third case is "clean". Treat that answer as a statement about text only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write the plans down where every agent reads them.&lt;/strong&gt; A shared file that lists each task, what it changes and what operation it performs catches duplicate work. It catches replace-versus-extend only if someone reads two entries side by side and notices.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All of these are the same move: get the plans into a form you can compare before the code exists. Past two or three agents, the weak point is that a person has to do the comparing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changes if the plans are compared before the code?
&lt;/h2&gt;

&lt;p&gt;That is the step we built Foremerge for. It is an open-source &lt;a href="https://foremerge.com/blog/the-coordination-layer/" rel="noopener noreferrer"&gt;coordination protocol that sits above Git&lt;/a&gt;. Each agent declares what it is about to change, and what it will do to it, before it edits anything.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;foremerge intent publish &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--agent&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$AGENT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--task&lt;/span&gt; &lt;span class="s2"&gt;"modernize-payments"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--summary&lt;/span&gt; &lt;span class="s2"&gt;"Replace PaymentService with StripePaymentService"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--scope&lt;/span&gt; symbol:PaymentService&lt;span class="o"&gt;=&lt;/span&gt;replace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When another agent declares &lt;code&gt;symbol:PaymentService=extend&lt;/code&gt;, the comparison raises a &lt;code&gt;destructive_vs_additive&lt;/code&gt; finding at HIGH severity, while both worktrees are still clean:&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;"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;"destructive_vs_additive"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"severity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HIGH"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scope"&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;"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;"symbol"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PaymentService"&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;"explanation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"One intent will replace `PaymentService` while the other will extend it; both declare the same semantic scope."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"suggestion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Coordinate on a stable `PaymentProvider` contract first, then implement StripePaymentProvider and PayPalPaymentProvider behind it and migrate callers deliberately. This is a heuristic suggestion, not an automatic design decision."&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 finding does not block anyone. Claims are advisory, so two agents can still work the same area when that is fine. It is information for the agent or the person, delivered at the cheapest point on the list above. The store is a SQLite file in the repository's Git directory, which every linked worktree shares, so the agents keep isolated files and see the same declarations.&lt;/p&gt;

&lt;p&gt;The limits are real. It trusts the declaration: an agent that says &lt;code&gt;extend&lt;/code&gt; and then rewrites the class is not caught, though the declaration and the diff are both on record. A scope on a whole class does not match a scope on one of its methods in this release. Two names for the same concept can slip past it. It does not replace review, CI or someone owning the architecture, and a missing finding never shows that two changes are compatible. There are no published results on time saved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do you need any of this?
&lt;/h2&gt;

&lt;p&gt;If you run one agent at a time, no. If your agents work on clearly separate parts of the code and you merge in sequence, worktrees and the list above are enough. The collision gets expensive when &lt;a href="https://foremerge.com/blog/running-multiple-claude-code-agents-in-parallel/" rel="noopener noreferrer"&gt;several agents run at once on one codebase&lt;/a&gt;, when they come from different tools, or when you cannot read all their plans before they finish.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Do git worktrees prevent merge conflicts between AI agents?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. Worktrees stop agents from overwriting each other's files while they work. Conflicts still appear when the branches are merged, and plans that contradict each other without touching the same lines merge cleanly and are not reported at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why did Git merge two agents' branches with no conflict and the code still not make sense?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Git compares changed lines against a common ancestor, not intentions. If one agent retires a class and another builds on it in a different file, no lines overlap. The merge is clean and the codebase now contradicts itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does &lt;code&gt;git merge-tree&lt;/code&gt; tell me whether two agent branches are compatible?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It tells you whether Git can combine them without a textual conflict, without changing your working tree. That is useful and fast. A clean answer says nothing about whether the two plans are compatible, and in the example above it is clean.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Should one agent finish before the next starts?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When a task replaces, removes or renames something other work depends on, yes: run it first, merge it, and start the others from the result. Tasks that only add or extend different things can run in parallel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Should I merge each agent's branch separately or together?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Merge into a throwaway integration branch and run your real checks on the combined result before anything reaches your main branch. Each branch passing its own tests tells you about that branch only.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does Foremerge replace worktrees?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. Worktrees isolate files and Foremerge shares plans, so you use both. Foremerge reads the same store from every worktree and from Claude Code, Codex and Cursor, and its claims never lock anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you only ever run one agent, skip this
&lt;/h2&gt;

&lt;p&gt;If you run two or more agents on one repository, worktrees handle the files and a comparison of declared plans handles the part Git cannot see. Foremerge is one Rust binary, local-first and Apache-2.0. Install it with &lt;code&gt;curl -fsSL https://foremerge.com/install.sh | sh&lt;/code&gt;, then run &lt;code&gt;foremerge init&lt;/code&gt;. One limit to start with: it can only compare what agents declare.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>git</category>
      <category>devtools</category>
      <category>productivity</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Nick Woodhead</dc:creator>
      <pubDate>Mon, 19 Oct 2026 18:40:10 +0000</pubDate>
      <link>https://dev.to/naw103/-205c</link>
      <guid>https://dev.to/naw103/-205c</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/naw103/translating-technical-debt-1ohi" class="crayons-story__hidden-navigation-link"&gt;Translating Technical Debt&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/naw103" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3554256%2F30bcbda8-7c4e-4e95-b2a5-0e5a0008965a.png" alt="naw103 profile" class="crayons-avatar__image" width="800" height="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/naw103" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Nick Woodhead
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Nick Woodhead
                
                
              
              &lt;div id="story-author-preview-content-4865384" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/naw103" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3554256%2F30bcbda8-7c4e-4e95-b2a5-0e5a0008965a.png" class="crayons-avatar__image" alt="" width="800" height="800"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Nick Woodhead&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/naw103/translating-technical-debt-1ohi" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 17&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/naw103/translating-technical-debt-1ohi" id="article-link-4865384"&gt;
          Translating Technical Debt
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/technicaldebt"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;technicaldebt&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/leadership"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;leadership&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/career"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;career&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/naw103/translating-technical-debt-1ohi" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/naw103/translating-technical-debt-1ohi#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>career</category>
      <category>learning</category>
      <category>productivity</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Nick Woodhead</dc:creator>
      <pubDate>Mon, 19 Oct 2026 00:05:49 +0000</pubDate>
      <link>https://dev.to/naw103/-7pi</link>
      <guid>https://dev.to/naw103/-7pi</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/naw103/running-multiple-claude-code-agents-in-parallel-what-worktrees-cannot-see-4le7" class="crayons-story__hidden-navigation-link"&gt;Running multiple Claude Code agents in parallel: what worktrees cannot see&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/naw103" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3554256%2F30bcbda8-7c4e-4e95-b2a5-0e5a0008965a.png" alt="naw103 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/naw103" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Nick Woodhead
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Nick Woodhead
                
                
              
              &lt;div id="story-author-preview-content-4874444" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/naw103" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3554256%2F30bcbda8-7c4e-4e95-b2a5-0e5a0008965a.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Nick Woodhead&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/naw103/running-multiple-claude-code-agents-in-parallel-what-worktrees-cannot-see-4le7" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 18&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/naw103/running-multiple-claude-code-agents-in-parallel-what-worktrees-cannot-see-4le7" id="article-link-4874444"&gt;
          Running multiple Claude Code agents in parallel: what worktrees cannot see
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/git"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;git&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devtools"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devtools&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/productivity"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;productivity&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/naw103/running-multiple-claude-code-agents-in-parallel-what-worktrees-cannot-see-4le7" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;12&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/naw103/running-multiple-claude-code-agents-in-parallel-what-worktrees-cannot-see-4le7#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              14&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            11 min read
          &lt;/small&gt;
          
          &lt;div class="only-sidebar-menu-item trusted-visible-block print-hidden align-center"&gt;
                
                    
                
          &lt;/div&gt;

        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>agents</category>
      <category>ai</category>
      <category>automation</category>
      <category>claude</category>
    </item>
    <item>
      <title>Running multiple Claude Code agents in parallel: what worktrees cannot see</title>
      <dc:creator>Nick Woodhead</dc:creator>
      <pubDate>Sun, 18 Oct 2026 23:54:25 +0000</pubDate>
      <link>https://dev.to/naw103/running-multiple-claude-code-agents-in-parallel-what-worktrees-cannot-see-4le7</link>
      <guid>https://dev.to/naw103/running-multiple-claude-code-agents-in-parallel-what-worktrees-cannot-see-4le7</guid>
      <description>&lt;p&gt;If you only ever run one coding agent, you do not need most of this. You're also probably working more inefficiently than you could be.&lt;/p&gt;

&lt;p&gt;If you run two or more: give each Claude Code session its own Git worktree, give each one a task that changes different things, and run your real checks on the merged result rather than on each branch. Worktrees stop agents from overwriting each other's files. They do not stop two agents from making plans that cannot both be true, and Git will merge those plans cleanly, because Git compares text, not intent.&lt;/p&gt;

&lt;p&gt;That second problem has a name. A &lt;strong&gt;semantic conflict&lt;/strong&gt; is when two changes merge without a textual conflict but contradict each other in meaning: one agent removes something another agent is building on, two agents build the same thing twice, or one changes a contract that the other is still coding against. Git cannot report it, because no two edits touched the same lines.&lt;/p&gt;

&lt;p&gt;This post covers the setup that works, what Git can and cannot see, how to split work so semantic conflicts are rarer, and the part no amount of task splitting fixes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup: one agent, one worktree, one branch
&lt;/h2&gt;

&lt;p&gt;Running two agents in one checkout fails fast. They overwrite each other's half-written files, one session's install step breaks the other's build, and each agent's picture of the code goes stale under it. The standard fix is a Git worktree per agent: a separate checkout of the same repository on its own branch, sharing one history.&lt;/p&gt;

&lt;p&gt;Claude Code has this built in. Run it once per session, with a different name each time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude &lt;span class="nt"&gt;--worktree&lt;/span&gt; feature-auth
claude &lt;span class="nt"&gt;--worktree&lt;/span&gt; add-paypal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or use stock Git, which works the same way for any agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git worktree add ../myapp-paypal &lt;span class="nt"&gt;-b&lt;/span&gt; agent/paypal
&lt;span class="nb"&gt;cd&lt;/span&gt; ../myapp-paypal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few things worktrees do not isolate, and that will bite you the first week:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gitignored dependencies.&lt;/strong&gt; &lt;code&gt;git worktree add&lt;/code&gt; checks out tracked files only. &lt;code&gt;node_modules&lt;/code&gt;, virtualenvs and build directories do not come with it, so each worktree needs its own install before its tests mean anything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ports, databases and other shared services.&lt;/strong&gt; Two dev servers on one port, or two agents migrating one local database, collide no matter how the files are laid out.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Branches.&lt;/strong&gt; Git lets a branch be checked out in only one worktree at a time, so each agent needs its own branch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration.&lt;/strong&gt; Someone still merges the branches. Pick one integrator, a person or one designated session, and do not let several agents each resolve the same conflict their own way.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With that in place, file collisions are solved. What is left is everything that was never about files.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Git can see, and what it cannot
&lt;/h2&gt;

&lt;p&gt;Git merges by comparing changed lines against a common ancestor. That makes it very good at one kind of collision and blind to the rest.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What the two agents did&lt;/th&gt;
&lt;th&gt;What Git reports&lt;/th&gt;
&lt;th&gt;What actually happened&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Edited the same lines of the same file&lt;/td&gt;
&lt;td&gt;Conflict&lt;/td&gt;
&lt;td&gt;Git stops you. This is the case it handles.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edited different parts of the same file&lt;/td&gt;
&lt;td&gt;Usually a clean merge&lt;/td&gt;
&lt;td&gt;Often fine. Sometimes not.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One renamed a function, the other added a call to the old name&lt;/td&gt;
&lt;td&gt;Clean merge&lt;/td&gt;
&lt;td&gt;The build fails afterwards. Your CI catches it, if it runs on the merged result.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One replaced a class, the other extended it&lt;/td&gt;
&lt;td&gt;Clean merge&lt;/td&gt;
&lt;td&gt;It may compile. The design is broken.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Both built the same feature from different angles&lt;/td&gt;
&lt;td&gt;Clean merge, or an add/add conflict&lt;/td&gt;
&lt;td&gt;You paid twice and now reconcile two versions.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One changed a schema or config contract, the other coded against the old shape&lt;/td&gt;
&lt;td&gt;Clean merge&lt;/td&gt;
&lt;td&gt;It builds, runs, and disagrees at runtime.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Only the first row is visible to Git. The rename row is visible to a compiler. The last three are visible to nothing in a standard toolchain, because the collision is between two plans, and plans live in prompts.&lt;/p&gt;

&lt;h2&gt;
  
  
  The canonical failure: replace versus extend
&lt;/h2&gt;

&lt;p&gt;This is the one that made us build tooling, and it is described in more detail in the first post on this blog.&lt;/p&gt;

&lt;p&gt;Two sessions, two worktrees, one repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Agent A: Replace PaymentService with StripePaymentService
Agent B: Add PayPal support to PaymentService
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agent A moves every caller onto the new Stripe class. Agent B adds PayPal to the old class. They touch different files. Git merges both branches without complaint. The PayPal work now hangs off a class nothing calls any more.&lt;/p&gt;

&lt;p&gt;Neither agent did anything wrong. Each did exactly what it was asked, each branch passes its own tests, and each agent reports success. Two agents can each be correct and jointly wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Same file is not the same as collision
&lt;/h2&gt;

&lt;p&gt;The intuitive fix is to warn whenever two agents touch the same file. Our own data says that signal is weak in both directions.&lt;/p&gt;

&lt;p&gt;When we replayed 76 intents from our own parallel work on GPTree through Foremerge 0.4.0, one pair of branches produced a real Git conflict, and Foremerge had flagged that pair. Five other pairs had changed the same file while both pieces of work were open, and merged cleanly when we checked them with &lt;code&gt;git merge-tree&lt;/code&gt; thanks to Foremerge.&lt;/p&gt;

&lt;p&gt;What it does show is the shape of the problem. Same-file overlap produced mostly clean merges. The replace-versus-extend failure above produces no file overlap at all. File paths are the wrong unit for the collisions that cost the most.&lt;/p&gt;

&lt;p&gt;The replay also showed a real gap: 0.4.0 could not match a scope on a whole class against a scope on one of its methods. Scope hierarchy is a candidate for a later release and is not built yet. More on that in the limitations section below.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to split work between parallel agents
&lt;/h2&gt;

&lt;p&gt;This part is useful whether or not you ever install anything. Most semantic conflicts are avoidable at assignment time, if you assign on the right axis.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Split by what a task changes, not by what it is called.&lt;/strong&gt; "Payments refactor" and "PayPal support" sound like different features and change the same class. Before starting a task, ask which things it will change: which classes, endpoints, tables, config keys. Two tasks with no overlap there can run in parallel. Two with overlap need an order.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Name the operation, not just the target.&lt;/strong&gt; Adding to something, extending it or modifying it preserves what other work depends on. Replacing, removing, renaming or migrating it does not. Two additive tasks on one target usually just need a shared contract. A destructive task on a target anyone else is touching should run alone, or first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Specify the contract before you split the work.&lt;/strong&gt; If two tasks meet at a boundary, make one small change that defines the boundary (the interface, the schema, the API shape), merge it, and then start both agents from that commit. In the payments example, that is a &lt;code&gt;PaymentProvider&lt;/code&gt; interface first, then Stripe and PayPal implementations behind it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;List the shared registries.&lt;/strong&gt; Route files, &lt;code&gt;.env.example&lt;/code&gt;, dependency manifests, migration numbering, feature flag lists. Almost every task touches one of them, and almost no plan mentions them. In our replay, two of the same-file pairs were exactly this: a routes file and an example env file that neither plan had named.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write the plans down where every agent can read them, before any code.&lt;/strong&gt; A shared markdown file listing each agent's task and targets catches duplicate work, as long as every agent reads it every time. It does not catch replace versus extend unless someone reads both entries and notices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify the merged result, not each branch.&lt;/strong&gt; Every branch can be green while the merge is red. Build, typecheck and test after integration, and treat a branch passing its own tests as a statement about that branch only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run only as many agents as you can follow.&lt;/strong&gt; We do not have a number to give you. The honest limit is how many plans you can read and compare before the agents finish.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Steps 1 to 5 are all versions of one idea: get each plan into a form that can be compared with the others before code exists. That is exactly the step that falls apart past two or three agents, because a person has to do the comparing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part Git cannot see: compare plans before code
&lt;/h2&gt;

&lt;p&gt;Foremerge is the tool we built for that comparison. It is an open-source coordination protocol for coding agents that sits above Git. Each agent declares what it is about to change, and how, before it changes anything. Foremerge compares declarations from every agent in the repository and reports a finding when two plans collide, while both worktrees are still clean.&lt;/p&gt;

&lt;p&gt;A declaration is an intent with one or more semantic scopes, each carrying an operation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;foremerge intent publish &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--agent&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$AGENT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--task&lt;/span&gt; &lt;span class="s2"&gt;"modernize-payments"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--summary&lt;/span&gt; &lt;span class="s2"&gt;"Replace PaymentService with StripePaymentService"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--scope&lt;/span&gt; symbol:PaymentService&lt;span class="o"&gt;=&lt;/span&gt;replace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scopes are not file paths. The kinds are &lt;code&gt;symbol&lt;/code&gt;, &lt;code&gt;api&lt;/code&gt;, &lt;code&gt;schema&lt;/code&gt;, &lt;code&gt;config&lt;/code&gt;, &lt;code&gt;infra&lt;/code&gt;, &lt;code&gt;test&lt;/code&gt;, &lt;code&gt;migration&lt;/code&gt;, &lt;code&gt;env&lt;/code&gt;, &lt;code&gt;file&lt;/code&gt;, &lt;code&gt;component&lt;/code&gt;, &lt;code&gt;contract&lt;/code&gt; and &lt;code&gt;domain&lt;/code&gt;. The operation is declared by the agent rather than guessed from the summary, so "consolidate payments onto Stripe" and "replace PaymentService with Stripe" reach the same verdict.&lt;/p&gt;

&lt;p&gt;When Agent B declares &lt;code&gt;symbol:PaymentService=extend&lt;/code&gt;, Foremerge raises a &lt;code&gt;destructive_vs_additive&lt;/code&gt; finding at &lt;code&gt;HIGH&lt;/code&gt; severity, explains that one intent replaces the scope the other extends, and suggests coordinating on a stable &lt;code&gt;PaymentProvider&lt;/code&gt; contract first. The suggestion is labelled as a heuristic, not an architecture decision. The response also lists the other agent's intent and every overlapping scope with both declared operations, so the agent can decide what the overlap means and record that decision.&lt;/p&gt;

&lt;p&gt;A few properties matter for parallel Claude Code work specifically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It works across worktrees.&lt;/strong&gt; The store is a SQLite file inside your repository's Git common directory, which every linked worktree shares. Agents keep isolated files and see the same declarations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It works across tools.&lt;/strong&gt; Claude Code, Codex and Cursor each connect through the same MCP server and read the same store, so a Codex session and a Claude Code session on one repository see each other's plans.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You can check before you commit to a plan.&lt;/strong&gt; &lt;code&gt;check_conflicts&lt;/code&gt; runs the same comparison as publishing and stores nothing, so an agent that is still planning can ask without leaving a trace.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claims never lock.&lt;/strong&gt; Two agents can claim the same scope. The second gets a warning and the other agent's context, not a refusal, because a lock serializes work that was often compatible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Acceptance is gated on evidence, not on the agent's word.&lt;/strong&gt; When an agent finishes, it publishes a ChangeSet, and Foremerge runs a check you registered (a build, a typecheck, a fast test target) against the exact fingerprint of that candidate. An agent saying "tests pass" is recorded as provenance and does not satisfy the gate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this replaces worktrees. Worktrees isolate files. Foremerge shares plans. You want both.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting it up
&lt;/h3&gt;

&lt;p&gt;The fastest path is to paste this into Claude Code, Codex or Cursor from inside the repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Set up Foremerge in this repository so we can coordinate parallel agents.

1. Install it:      curl -fsSL https://foremerge.com/install.sh | sh
2. Initialize:      foremerge init
3. Wire this client and any others in use: foremerge setup all
4. Register the check I should be validated against, for example:
                    foremerge checks set test -- cargo test --all-targets
5. Confirm:         foremerge doctor --client all

Then read the Foremerge skill that step 3 installed for this client and follow
it from now on: publish your intent with semantic scopes before editing, claim
the scope, and check for conflicts before you start.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change step 4 to your repository's real test command. Step 3 asks the client to enable an MCP server, so it will prompt you first.&lt;/p&gt;

&lt;p&gt;To install by hand instead: the install script above fetches a checksum-verified release binary for macOS or Linux. &lt;code&gt;npm install -g foremerge&lt;/code&gt; works on macOS and on Linux with glibc. &lt;code&gt;cargo install foremerge&lt;/code&gt; builds it with Rust 1.85 or later. Windows binaries are on the &lt;a href="https://github.com/naw103/foremerge/releases" rel="noopener noreferrer"&gt;releases page&lt;/a&gt;. Then run &lt;code&gt;foremerge init&lt;/code&gt; and &lt;code&gt;foremerge setup claude&lt;/code&gt; (or &lt;code&gt;codex&lt;/code&gt;, &lt;code&gt;cursor&lt;/code&gt;, &lt;code&gt;all&lt;/code&gt;) inside the repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does not catch
&lt;/h2&gt;

&lt;p&gt;A coordination tool that overclaims is worse than none, because severity is what an agent uses to decide what to stop for. So, plainly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Under-declaration.&lt;/strong&gt; An agent that declares &lt;code&gt;extend&lt;/code&gt; and then rewrites the thing is not detected. Not caught, but auditable: the declaration and the diff are both on record, so the miss can be reconstructed afterwards.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scope hierarchy.&lt;/strong&gt; A scope on a whole class does not match a scope on one of its methods, and &lt;code&gt;domain:payments&lt;/code&gt; does not imply every payment symbol. Narrow, accurate scopes matter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Files nobody declared.&lt;/strong&gt; File overlap is not a conflict signal in this release. The shared registries from step 4 above only show up if an agent declares them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Synonyms.&lt;/strong&gt; Two agents using different names for the same concept can slip past the detector, and it can warn on work that was always compatible. Detection is deterministic and explainable, but heuristic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Late arrivals.&lt;/strong&gt; A conflict is detected when the later intent publishes. There are no push notifications, so the earlier agent learns of it at its next boundary or by checking again.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Other machines.&lt;/strong&gt; The store is per machine. Coordination between machines is outside the project's scope.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measured results.&lt;/strong&gt; There is a benchmark plan and a harness in the repository, but no published coordinated-versus-uncoordinated results. We make no claim about time saved right now.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Everything else in your pipeline.&lt;/strong&gt; It does not replace code review, CI, or architecture ownership. A missing finding never proves two changes are compatible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full list is in &lt;a href="https://github.com/naw103/foremerge/blob/main/docs/limitations.md" rel="noopener noreferrer"&gt;docs/limitations.md&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you are deciding whether you need this at all, the companion piece on orchestrators and coordinators has a one-question test, and the case for a coordination layer has a post of its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Can I run multiple Claude Code sessions in the same directory?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can, but they share one set of files, so one session's edits and installs land underneath the other's work. Give each session its own Git worktree with &lt;code&gt;claude --worktree &amp;lt;name&amp;gt;&lt;/code&gt; or &lt;code&gt;git worktree add&lt;/code&gt;. Each gets a separate checkout and branch while sharing the repository's history.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do Git worktrees prevent merge conflicts between agents?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. Worktrees stop agents from overwriting each other's files while they work. Textual conflicts still appear at merge time when two branches change the same lines, and semantic conflicts, where two changes contradict each other without touching the same lines, merge cleanly and are not reported at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why did my agents' branches merge cleanly but the app broke?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most likely a semantic conflict: one agent renamed, replaced or removed something another agent was still using, or changed a schema or config contract the other coded against. Git only compares changed lines, so contradictory plans in different files merge without complaint. Building and testing the merged result catches some of these. Comparing plans before code catches others earlier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How many Claude Code agents should I run in parallel?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is no number we can defend. The practical limit is how many plans you can read and compare before the agents finish, plus how many installs, ports and databases your machine can run at once. If tasks change different things, more agents are fine. If they overlap, more agents mostly means more reconciliation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does Foremerge work with Codex and Cursor, or only Claude Code?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;All three. &lt;code&gt;foremerge setup all&lt;/code&gt; installs the skill and MCP entry for Claude Code, Codex and Cursor, and every client reads the same store in the repository's Git common directory. Any other MCP client can launch &lt;code&gt;foremerge mcp&lt;/code&gt; over stdio. Agents from different vendors see each other's declared plans.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does Foremerge lock files or stop agents?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. Claims are leased and advisory: overlap produces a warning and the other agent's context, never a lock. Findings are evidence for the agent or person to act on. The one hard gate is acceptance, which requires a passing registered check on the exact candidate and no unresolved HIGH finding unless someone overrides it with a recorded reason.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you run more than one agent
&lt;/h2&gt;

&lt;p&gt;If you only ever run one coding agent, you do not need this. If you run two or more on one repository, worktrees handle the files and Foremerge handles the plans: one Rust binary, local-first, Apache-2.0, with its SQLite store in the Git directory your worktrees already share.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repo and docs: &lt;a href="https://github.com/naw103/foremerge" rel="noopener noreferrer"&gt;github.com/naw103/foremerge&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Install: &lt;a href="https://foremerge.com" rel="noopener noreferrer"&gt;foremerge.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It will miss what agents do not declare. If you hit a collision it should have caught, an issue describing it is the most useful thing you can send us.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://foremerge.com/blog/running-multiple-claude-code-agents-in-parallel/" rel="noopener noreferrer"&gt;foremerge.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>git</category>
      <category>devtools</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Did you make copies of your custom GPTs?</title>
      <dc:creator>Nick Woodhead</dc:creator>
      <pubDate>Sat, 17 Oct 2026 03:21:44 +0000</pubDate>
      <link>https://dev.to/naw103/did-you-make-copies-of-your-custom-gpts-39gg</link>
      <guid>https://dev.to/naw103/did-you-make-copies-of-your-custom-gpts-39gg</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/naw103/gemini-gems-become-skills-in-november-and-custom-gpts-retire-on-december-11-what-to-copy-out-first-3kf5" class="crayons-story__hidden-navigation-link"&gt;Gemini Gems become skills in November and custom GPTs retire on December 11. What to copy out first.&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/naw103" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3554256%2F30bcbda8-7c4e-4e95-b2a5-0e5a0008965a.png" alt="naw103 profile" class="crayons-avatar__image" width="800" height="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/naw103" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Nick Woodhead
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Nick Woodhead
                
                
              
              &lt;div id="story-author-preview-content-4848151" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/naw103" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3554256%2F30bcbda8-7c4e-4e95-b2a5-0e5a0008965a.png" class="crayons-avatar__image" alt="" width="800" height="800"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Nick Woodhead&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/naw103/gemini-gems-become-skills-in-november-and-custom-gpts-retire-on-december-11-what-to-copy-out-first-3kf5" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 14&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/naw103/gemini-gems-become-skills-in-november-and-custom-gpts-retire-on-december-11-what-to-copy-out-first-3kf5" id="article-link-4848151"&gt;
          Gemini Gems become skills in November and custom GPTs retire on December 11. What to copy out first.
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/productivity"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;productivity&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/chatgpt"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;chatgpt&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/gemini"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;gemini&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/naw103/gemini-gems-become-skills-in-november-and-custom-gpts-retire-on-december-11-what-to-copy-out-first-3kf5" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;2&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/naw103/gemini-gems-become-skills-in-november-and-custom-gpts-retire-on-december-11-what-to-copy-out-first-3kf5#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              2&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>ai</category>
      <category>chatgpt</category>
      <category>openai</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Translating Technical Debt</title>
      <dc:creator>Nick Woodhead</dc:creator>
      <pubDate>Sat, 17 Oct 2026 03:20:01 +0000</pubDate>
      <link>https://dev.to/naw103/translating-technical-debt-1ohi</link>
      <guid>https://dev.to/naw103/translating-technical-debt-1ohi</guid>
      <description>&lt;h2&gt;
  
  
  What technical debt actually means, and how to explain it to someone who doesn't write code
&lt;/h2&gt;

&lt;p&gt;An engineer asks for two sprints to "pay down technical debt," and the person who owns the budget hears two sprints with nothing to show for them. The phrase was invented to make exactly this conversation easier, and a lot of the time it now gets in the way.&lt;/p&gt;

&lt;p&gt;The fix is not a better slide. It's going back to what the metaphor meant in the first place, because the original version already contains the answer to the question the business side is really asking: is this worth paying for?&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the phrase came from
&lt;/h2&gt;

&lt;p&gt;Ward Cunningham coined it in 1992, in a short experience report for the OOPSLA conference about WyCash, a portfolio management system his team built. The line most people know is "Shipping first time code is like going into debt." The same paragraph says a little debt speeds development, as long as it is paid back promptly with a rewrite, and that the danger is debt that never gets repaid.&lt;/p&gt;

&lt;p&gt;In a later video (the transcript is on the c2 wiki) Cunningham explained why he reached for a money metaphor at all. WyCash was financial software, and he needed to explain to his boss why the team kept reworking code that already worked. As the team learned how the financial objects really behaved, they changed the program to match that understanding. If they had not, he said, they would keep stumbling over the gap between what the code said and what they now knew, and that stumbling would slow them down the way interest slows down a loan.&lt;/p&gt;

&lt;p&gt;So the original idea is simple. You ship before you fully understand the problem, because shipping is how you learn. Then you put what you learned back into the code. Skip that second step for long enough and every change gets slower.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does not mean
&lt;/h2&gt;

&lt;p&gt;In the same video, Cunningham said many people had confused the metaphor with the idea of writing code badly on purpose and cleaning it up later. He was clear that he never favored writing code poorly. What he favored was code that reflects your current understanding, even when that understanding is partial, written cleanly enough that you can change it once you know more.&lt;/p&gt;

&lt;p&gt;That matters for the conversation. When an engineer says "we have technical debt," the business side often hears "we cut corners" or "we did it wrong." Usually it means something closer to "we know more now than we did when we built this, and the code has not caught up." That is not a failure. It is what learning looks like in software.&lt;/p&gt;

&lt;h2&gt;
  
  
  Principal and interest, in plain terms
&lt;/h2&gt;

&lt;p&gt;Martin Fowler's explanation on his site is the clearest one I know of, because it uses the two parts of a loan that everyone already understands.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The principal&lt;/strong&gt; is the cost of cleaning the code up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The interest&lt;/strong&gt; is the extra effort every new change costs while the mess is still there.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;His example: a confusing structure means a new feature takes six days instead of the four it would take with a clean structure. Those two extra days are the interest. Cleaning up the structure would take five days.&lt;/p&gt;

&lt;p&gt;If that is the only feature coming, cleaning up is a bad deal. Fowler points out you would spend nine days instead of six. But if two more similar features are on the way, cleaning up first makes the team faster overall. Using his numbers: three features without the cleanup is 18 days, and the cleanup plus three faster features is 5 + 12 = 17 days.&lt;/p&gt;

&lt;p&gt;Look at what that decision depends on. Not on how ugly the code is, but on how much more work is coming through that part of the system. Engineers know the interest rate. The business side knows the roadmap. Neither can make the call alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not all debt is the same kind
&lt;/h2&gt;

&lt;p&gt;Fowler also sorts debt into a simple grid. One axis is whether the debt was &lt;strong&gt;deliberate&lt;/strong&gt; (you knew you were taking a shortcut) or &lt;strong&gt;inadvertent&lt;/strong&gt; (you found out later). The other is whether it was &lt;strong&gt;prudent&lt;/strong&gt; (taken on with the cost weighed against the benefit) or &lt;strong&gt;reckless&lt;/strong&gt; (taken on without weighing anything).&lt;/p&gt;

&lt;p&gt;In plain terms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deliberate and prudent:&lt;/strong&gt; "We took a shortcut to hit the launch date, and we knew it would cost us later." This is a business decision that worked as intended. The bill is now due.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inadvertent and prudent:&lt;/strong&gt; "Now that we have built it, we understand how it should have been built." Fowler says even the best teams end up here, because you learn as you go. This is Cunningham's original meaning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deliberate and reckless:&lt;/strong&gt; "We knew better and skipped it anyway to go faster." This usually comes from underestimating how soon the shortcut would start costing time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inadvertent and reckless:&lt;/strong&gt; "We didn't know what good looked like." This is a skills conversation, not a debt conversation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fowler's point is that the useful question is not whether a team has debt, since every team does, but whether it was prudent or reckless. Knowing which kind you are talking about tells you whether this is a normal bill, a lesson, or a problem with how the work is done.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you write the code: how to explain it
&lt;/h2&gt;

&lt;p&gt;The goal is to give the person with the budget something they can decide on. A few habits help.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Lead with the interest, not the principal.&lt;/strong&gt; "We need two sprints to refactor billing" is a cost with no benefit attached. "Every change to billing takes about two extra days because of how it is structured" is a cost they are already paying. Use your own real numbers, even rough ones.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connect it to work that is actually coming.&lt;/strong&gt; Name the upcoming items on the roadmap that go through that part of the system. If nothing is coming, say so. Leaving it alone can be the right call, and saying that out loud earns you trust for the times it is not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Show the payback.&lt;/strong&gt; Cleanup cost, the time each change saves, and how many changes until it pays for itself. Fowler's example is a good template because the arithmetic fits on one line.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Say which kind it is.&lt;/strong&gt; "We took this shortcut on purpose to make the March launch" lands very differently from "this is how we learned the problem." Both are fine. Just say which.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ask for a decision.&lt;/strong&gt; End with the options and what you would pick: pay it now, pay it before a specific feature, or leave it. Do not end with "let's discuss."&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  If you fund the work: how to ask about it
&lt;/h2&gt;

&lt;p&gt;Business leaders can make this conversation easier too.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ask &lt;strong&gt;"what does this slow down, and by how much?"&lt;/strong&gt; instead of "why is the code bad?" The first question gets you an interest rate. The second gets you a defensive answer.&lt;/li&gt;
&lt;li&gt;Ask &lt;strong&gt;"what happens if we never pay it?"&lt;/strong&gt; Sometimes the honest answer is "nothing much, that area rarely changes," and that is useful to know.&lt;/li&gt;
&lt;li&gt;Share what is coming. The engineers can only work out whether the cleanup pays back if they know what the next few months of work look like.&lt;/li&gt;
&lt;li&gt;Treat a debt request as information, not an admission. The team is telling you about a cost you are already paying.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  One question that carries most of it
&lt;/h2&gt;

&lt;p&gt;Every version of this conversation comes down to one question both sides can answer together, what is the interest on the work we are about to do? Explaining tradeoffs in terms like that, so the decision happens in the meeting, is what TranslateTech's Geek2Speak series is about.&lt;/p&gt;

&lt;p&gt;Next time technical debt comes up, ask (or answer) that one question before anyone talks about how long the cleanup takes.&lt;/p&gt;

</description>
      <category>technicaldebt</category>
      <category>leadership</category>
      <category>programming</category>
      <category>career</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Nick Woodhead</dc:creator>
      <pubDate>Wed, 14 Oct 2026 06:27:24 +0000</pubDate>
      <link>https://dev.to/naw103/-ndn</link>
      <guid>https://dev.to/naw103/-ndn</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/naw103/gemini-gems-become-skills-in-november-and-custom-gpts-retire-on-december-11-what-to-copy-out-first-3kf5" class="crayons-story__hidden-navigation-link"&gt;Gemini Gems become skills in November and custom GPTs retire on December 11. What to copy out first.&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/naw103" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3554256%2F30bcbda8-7c4e-4e95-b2a5-0e5a0008965a.png" alt="naw103 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/naw103" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Nick Woodhead
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Nick Woodhead
                
                
              
              &lt;div id="story-author-preview-content-4848151" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/naw103" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3554256%2F30bcbda8-7c4e-4e95-b2a5-0e5a0008965a.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Nick Woodhead&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/naw103/gemini-gems-become-skills-in-november-and-custom-gpts-retire-on-december-11-what-to-copy-out-first-3kf5" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 14&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/naw103/gemini-gems-become-skills-in-november-and-custom-gpts-retire-on-december-11-what-to-copy-out-first-3kf5" id="article-link-4848151"&gt;
          Gemini Gems become skills in November and custom GPTs retire on December 11. What to copy out first.
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/productivity"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;productivity&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/chatgpt"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;chatgpt&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/gemini"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;gemini&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/naw103/gemini-gems-become-skills-in-november-and-custom-gpts-retire-on-december-11-what-to-copy-out-first-3kf5" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;2&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/naw103/gemini-gems-become-skills-in-november-and-custom-gpts-retire-on-december-11-what-to-copy-out-first-3kf5#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              2&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>ai</category>
      <category>gemini</category>
      <category>news</category>
    </item>
    <item>
      <title>Gemini Gems become skills in November and custom GPTs retire on December 11. What to copy out first.</title>
      <dc:creator>Nick Woodhead</dc:creator>
      <pubDate>Wed, 14 Oct 2026 06:23:48 +0000</pubDate>
      <link>https://dev.to/naw103/gemini-gems-become-skills-in-november-and-custom-gpts-retire-on-december-11-what-to-copy-out-first-3kf5</link>
      <guid>https://dev.to/naw103/gemini-gems-become-skills-in-november-and-custom-gpts-retire-on-december-11-what-to-copy-out-first-3kf5</guid>
      <description>&lt;p&gt;If you built a Gem in Gemini or a custom GPT in ChatGPT, it is about to be converted into something else on the vendor's timetable, not yours. Both companies say most of it carries over, but both also list things that do not, and those are the parts you will miss the next time you use it.&lt;/p&gt;

&lt;p&gt;I read both help pages today (October 13, 2026). Here is what each one says, what does not make the trip, and what I would copy out this week.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Google says about Gems
&lt;/h2&gt;

&lt;p&gt;Google's help page "About the transition from Gems to skills" says that starting in November 2026, Gems will transition to skills for personal Google Accounts, and in 2027 for work and school accounts. The page gives March 2027 for Workspace business accounts and June 2027 for education accounts.&lt;/p&gt;

&lt;p&gt;When Gems are removed, Google says it will automatically recreate your Gems as skills, along with supported knowledge files. A skill is a set of reusable custom instructions you call by typing a slash and its name in any Gemini chat, and Gemini can also apply one on its own when it thinks it is relevant.&lt;/p&gt;

&lt;p&gt;The same page lists what is different:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Skills do not work with Canvas or Deep Research yet, and most of the default tools a Gem could use (Create video, Create music, Guided learning) are not available to a skill.&lt;/li&gt;
&lt;li&gt;Files a Gem pulled from GitHub are not supported in skills, so they are not converted.&lt;/li&gt;
&lt;li&gt;Sharing a skill, and adding Google Drive files to one, are listed as coming in the coming weeks.&lt;/li&gt;
&lt;li&gt;You can make as many skills as you like but only 100 can be active at once.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So a Gem that was mostly instructions will be fine. A Gem that leaned on Canvas, Deep Research, a GitHub file or a share link to your team will come out the other side missing a piece.&lt;/p&gt;

&lt;h2&gt;
  
  
  What OpenAI says about custom GPTs
&lt;/h2&gt;

&lt;p&gt;OpenAI's "Custom GPT retirement and migration FAQ" says custom GPTs are scheduled to retire on December 11, 2026 (February 11, 2027 for Enterprise workspaces with an approved deferral), and that the change affects all ChatGPT plans. Creators migrate each GPT to a plugin from My GPTs when the option shows up for their account.&lt;/p&gt;

&lt;p&gt;What transfers, per the FAQ: the GPT's instructions become a skill inside the new plugin, connected apps are added as apps, and knowledge files are copied into the plugin's reference files. Your existing conversations with the GPT stay accessible after retirement.&lt;/p&gt;

&lt;p&gt;What does not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The GPT's selected model does not carry over.&lt;/li&gt;
&lt;li&gt;Custom actions do not transfer. The FAQ says rebuilding one may need a custom MCP server.&lt;/li&gt;
&lt;li&gt;Sharing settings do not carry over. A migrated plugin starts private, and the people who used your GPT do not get access to the replacement automatically.&lt;/li&gt;
&lt;li&gt;Migration uses the latest published version, so drafts and unpublished edits are left behind.&lt;/li&gt;
&lt;li&gt;After you migrate, the original GPT becomes read-only.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OpenAI also says plainly that a migrated plugin may respond differently, and suggests saving a few familiar prompts so you can compare the results before and after.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pattern in both
&lt;/h2&gt;

&lt;p&gt;The two migrations are not the same, but the same three things hold in both.&lt;/p&gt;

&lt;p&gt;The instructions survive. In both cases the text you wrote is the part that converts cleanly.&lt;/p&gt;

&lt;p&gt;The wiring does not. Tools, actions, model choice and sharing are the parts each vendor is changing, and they are the parts you cannot export as text.&lt;/p&gt;

&lt;p&gt;You do not pick the date. Google gives a month, OpenAI gives a day, and both pages say the timing can differ by account.&lt;/p&gt;

&lt;p&gt;That tells you where the work is. The instructions are the asset, and a copy of them in a plain file is worth more than whatever container they sit in this quarter.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would copy out this week
&lt;/h2&gt;

&lt;p&gt;This takes about 20 minutes for a handful of assistants.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open each Gem and each GPT you still use and paste its name, description and full instructions into a text or markdown file. One file per assistant.&lt;/li&gt;
&lt;li&gt;Download the knowledge files into the same folder. Google's own steps for recreating a Gem as a skill start with exactly this.&lt;/li&gt;
&lt;li&gt;Write down what it depended on that is not text: which model, which tools (Canvas, Deep Research, actions, connected apps) and who it was shared with.&lt;/li&gt;
&lt;li&gt;Save three or four prompts you run often, with an answer you were happy with. OpenAI recommends this for testing a migrated plugin and it works just as well for a skill.&lt;/li&gt;
&lt;li&gt;If a GPT has unpublished edits you care about, publish them before you migrate. Publishing does not require sharing it publicly.&lt;/li&gt;
&lt;li&gt;After the conversion, run the saved prompts and compare. Fix what changed before you rely on it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One useful detail on the Google side: the help page says you can upload a &lt;code&gt;SKILL.md&lt;/code&gt; file to bring in a skill made on another platform, in the Gemini web app and Mac app for now. OpenAI's migration also turns your instructions into a skill. Both vendors are converging on instructions kept as a file, which is one more reason to keep your own copy as one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where GPTree fits
&lt;/h2&gt;

&lt;p&gt;I built GPTree, so read this part knowing that. GPTree does not import Gems or GPTs. What it has is personas, and a persona is three plain fields: a name, an optional description, and the instructions. The text you copied out in step 1 pastes straight into the instructions box. You pick a persona per message from the composer, and personas apply per branch, so you can send the same question down two branches under two personas and compare the answers. On the Free plan you can keep one persona of your own, and the built-in ones do not count toward that.&lt;/p&gt;

&lt;p&gt;That is not a migration tool and I am not selling it as one. The point of the list above is the same wherever you paste the result.&lt;/p&gt;

&lt;h2&gt;
  
  
  The next step
&lt;/h2&gt;

&lt;p&gt;Pick the one Gem or GPT you would miss most, and copy its instructions and files into a folder today. Everything else on the list can wait until the migration option shows up in your account.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>chatgpt</category>
      <category>gemini</category>
    </item>
    <item>
      <title>AI agents introduced several new layers to the development stack. You are probably missing this one.</title>
      <dc:creator>Nick Woodhead</dc:creator>
      <pubDate>Thu, 17 Sep 2026 01:39:19 +0000</pubDate>
      <link>https://dev.to/naw103/ai-agents-introduced-several-new-layers-to-the-development-stack-you-are-probably-missing-this-one-54dg</link>
      <guid>https://dev.to/naw103/ai-agents-introduced-several-new-layers-to-the-development-stack-you-are-probably-missing-this-one-54dg</guid>
      <description>&lt;p&gt;The development stack grew more in the last two years than in the previous ten. Most teams adopted the new layers so quickly they never noticed them becoming layers. Count them.&lt;/p&gt;

&lt;p&gt;The agent layer: Claude Code, Codex, Cursor. The thing that writes code. Two years ago this layer did not exist; today it is where implementation happens.&lt;/p&gt;

&lt;p&gt;The context layer: CLAUDE.md, AGENTS.md, rules files, memory systems. Telling agents how your repository works, what your conventions are, what not to touch. Everyone who onboarded an agent wrote these within a week, because an agent without context is a very fast junior with amnesia.&lt;/p&gt;

&lt;p&gt;The tool layer: MCP. Agents reaching databases, browsers, issue trackers, deployment systems. Adopted fast because an agent that cannot touch your systems can only talk about them.&lt;/p&gt;

&lt;p&gt;The isolation layer: git worktrees, containers, cloud sandboxes. One agent per checkout, because two sessions in one working directory stomp each other's files and poison each other's context. Anyone who ran two agents learned this in the first afternoon.&lt;/p&gt;

&lt;p&gt;The orchestration layer: Gas Town, claude-squad, Foreman, and a fast-growing ecosystem of fleet runners. Who works on what, which sessions are alive, what needs review. The moment you run more than two or three agents, supervision becomes its own job, and this layer takes it.&lt;/p&gt;

&lt;p&gt;Each of these layers got adopted quickly for the same reason: its absence hurts immediately and obviously. No context, the agent writes nonsense today. No isolation, files get stomped today. No orchestration, you lose track of your fleet today.&lt;/p&gt;

&lt;p&gt;There is one more layer, and almost nobody runs it, because its absence hurts silently.&lt;/p&gt;

&lt;h2&gt;
  
  
  The failure that announces nothing
&lt;/h2&gt;

&lt;p&gt;Two agents, one repository. Agent A is told to replace PaymentService with a Stripe-specific implementation. Agent B is told to add PayPal support to PaymentService. Run the failure through every layer you have adopted.&lt;/p&gt;

&lt;p&gt;The agent layer performs perfectly: both sessions write competent code. The context layer performs: both followed your conventions. The tool layer performs: every MCP call succeeded. The isolation layer performs: separate worktrees, no stomped files. The orchestration layer performs: two independent tasks, both completed, both green.&lt;/p&gt;

&lt;p&gt;Git merges both branches without a conflict, because the changes touch different lines. And the design is now broken: agent B built on an extension point agent A deleted. Nothing in the toolchain objected at any moment, because every layer you have answers a different question, and none of them answer this one: can these two plans coexist?&lt;/p&gt;

&lt;p&gt;Git compares diffs, and there is no diff at the moment this collision actually happens. The collision is between intentions, at plan time, before either agent has written a line. We hit versions of this for months. The one that finally made us build tooling surfaced three days after a clean merge, in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  The coordination layer
&lt;/h2&gt;

&lt;p&gt;The missing layer answers exactly one question: can the work currently in flight all be true at once?&lt;/p&gt;

&lt;p&gt;To be precise about what it does not do: it does not create plans. Your agents plan however they already plan. The coordination layer is a ledger and a referee, not a planner. Each agent declares what it is about to change before writing code: a semantic scope plus an operation, like symbol:PaymentService=replace. Scopes are not file paths, because file paths miss API, schema, configuration, and cross-language collisions. Deterministic rules compare the declarations and raise a finding while both sides are still plans: the rule that fired, an explanation, a suggested resolution. In the PaymentService case, one destructive operation and one additive operation on the same scope cannot both be true, and the second agent learns this in the same call that published its intent.&lt;/p&gt;

&lt;p&gt;The other half of the layer is evidence. When work finishes, acceptance is gated on a verification command the layer executes itself against the exact fingerprint of the candidate change. An agent reporting that tests pass is provenance, not proof. If the tree changed after validation, the attempt does not count.&lt;/p&gt;

&lt;h2&gt;
  
  
  What building one taught us
&lt;/h2&gt;

&lt;p&gt;Three lessons, each paid for.&lt;/p&gt;

&lt;p&gt;First: declared beats inferred. We started by inferring operations from agent prose, and it produced confident false alarms. "Delete the flaky ThumbnailCache benchmark test" was read as destroying ThumbnailCache itself. Widening the verb list just moved the boundary. Making agents declare the operation as structured syntax removed the whole error class.&lt;/p&gt;

&lt;p&gt;Second: advisory beats locks, but severity must be earned. Most overlaps between agents are compatible, and a lock serializes work that did not need serializing; the moment a lock exists, a busy repo becomes a queue. So claims warn instead of block. The discipline that makes warnings survivable is reserving HIGH for two declarations that genuinely cannot both be true. Our repo carries a regression fixture that fails the build if compatible work ever raises a HIGH.&lt;/p&gt;

&lt;p&gt;Third: soft claims, hard gate. Everything before the finish line is advisory, because the finish line is not: no acceptance while an unresolved HIGH finding stands, and no acceptance on self-reported evidence. The gate staying hard is what lets everything before it stay soft.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do you need this layer?
&lt;/h2&gt;

&lt;p&gt;If you run one coding agent, no. Close the tab, you are fine.&lt;/p&gt;

&lt;p&gt;If you run two or more on the same repository, whether in parallel today or sequentially across days, you have already had the silent version of this failure whether you noticed it or not. The tell: a change that made you say "wait, when did that class stop existing?" three days after a clean merge.&lt;/p&gt;

&lt;p&gt;We open-sourced the coordination layer we built and use: Foremerge (&lt;a href="https://github.com/naw103/foremerge" rel="noopener noreferrer"&gt;https://github.com/naw103/foremerge&lt;/a&gt;), Apache-2.0, one Rust binary, local-first, above Git rather than inside it. Setup is one paste into Claude Code, Codex, or Cursor. Stated plainly per the honesty its own docs demand: detection is deterministic but heuristic and can warn on compatible work, claims never lock anything, and there are no published benchmarks yet, so no performance claims. The layer matters regardless of whose implementation you run, including one you build yourself.&lt;/p&gt;

&lt;p&gt;The stack grew five layers in two years because each one's absence hurt the day you needed it. The sixth one's absence hurts three days later. That is the only reason you are probably missing it.&lt;/p&gt;

&lt;p&gt;Foremerge&lt;br&gt;
The open-source coordination protocol for parallel coding agents, built above Git. Agents declare intent and semantic scopes before writing code, so plans that cannot both be true collide in a queryable store instead of in your merge. One Rust binary, Apache-2.0, local-first.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;curl -fsSL https://foremerge.com/install.sh | sh&lt;/code&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devtools</category>
      <category>git</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
