<?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: Daniel Saadia</title>
    <description>The latest articles on DEV Community by Daniel Saadia (@dyod).</description>
    <link>https://dev.to/dyod</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%2F4086210%2F44495f12-50ef-4cc5-a589-a354ada6520a.jpg</url>
      <title>DEV Community: Daniel Saadia</title>
      <link>https://dev.to/dyod</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dyod"/>
    <language>en</language>
    <item>
      <title>Turn a dupes report into small PRs with Lumpcode</title>
      <dc:creator>Daniel Saadia</dc:creator>
      <pubDate>Thu, 20 Aug 2026 09:44:50 +0000</pubDate>
      <link>https://dev.to/dyod/turn-a-dupes-report-into-small-prs-with-lumpcode-1ome</link>
      <guid>https://dev.to/dyod/turn-a-dupes-report-into-small-prs-with-lumpcode-1ome</guid>
      <description>&lt;p&gt;Lumpcode is a &lt;strong&gt;git-first loop manager&lt;/strong&gt;: a small CLI that runs long agent campaigns over your own repo, in reviewable slices. Git is the gate (one PR at a time) and the source of truth (what is left is read from remote history, not a distant database). You describe the campaign once, merge what is good, and the next tick continues with the rest.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;lump&lt;/strong&gt; is one campaign under &lt;code&gt;.lumpcode/lumps/&amp;lt;name&amp;gt;/&lt;/code&gt;. Each &lt;strong&gt;context&lt;/strong&gt; is one isolated unit of work: one branch, one PR. You can run a tick by hand, or leave a daemon on a machine that stays on.&lt;/p&gt;

&lt;p&gt;This article is one campaign: a scanner finds repeated code; one lump proposes a single abstraction as a plan in git; a second lump implements it, with tests, until green. You merge small PRs; the loop does not finish.&lt;/p&gt;

&lt;p&gt;The argument for why loops should plug into git is &lt;a href="https://github.com/lumpcode/lumpcode/blob/main/articles/04-why-lumpcode/article.md" rel="noopener noreferrer"&gt;Codemods grew a brain. Our tooling didn't.&lt;/a&gt;. If you do not have a Lumpcode project yet, start with the &lt;a href="https://github.com/lumpcode/lumpcode/blob/main/articles/05-hands-on-dedicated-daemon/article.md" rel="noopener noreferrer"&gt;dedicated daemon how-to&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;/lumpcode&lt;/code&gt; in your agent session when you hit a config question (&lt;code&gt;npx skills add lumpcode/skills&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  1. What you are building
&lt;/h2&gt;

&lt;p&gt;Two lumps, one backlog folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.lumpcode/lumps/abstractionFinder/     # scan + write one plan
.lumpcode/lumps/abstractionImplementer/
  backlogItems/
    todo/&amp;lt;utilName&amp;gt;/desc.yml
    todo/&amp;lt;utilName&amp;gt;/requirements.md
    completed/&amp;lt;utilName&amp;gt;/              # after a merged implementer run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Finder:&lt;/strong&gt; one ephemeral context per tick. Reads a dupes report, writes &lt;code&gt;todo/&amp;lt;name&amp;gt;/&lt;/code&gt;, does &lt;strong&gt;not&lt;/strong&gt; implement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implementer:&lt;/strong&gt; one backlog item that already has &lt;code&gt;requirements.md&lt;/code&gt; → implement, refactor call sites, tests, &lt;code&gt;retryUntilGreen&lt;/code&gt; → move to &lt;code&gt;completed/&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cap how many plans sit unmerged (&lt;code&gt;maxPendingAbstractions&lt;/code&gt;, &lt;code&gt;maximumNumberOfConcurrentBranches&lt;/code&gt;) so the finder does not outrun review.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Project deps
&lt;/h2&gt;

&lt;p&gt;On the laptop repo (commit these before the dedicated clone needs them):&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;--save-dev&lt;/span&gt; @lumpcode/cli-utils @lumpcode/recipes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The global CLI does not resolve recipes. If &lt;code&gt;cli-utils&lt;/code&gt; / &lt;code&gt;recipes&lt;/code&gt; are already in &lt;code&gt;package.json&lt;/code&gt; from the daemon how-to, skip this.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Pick a scanner
&lt;/h2&gt;

&lt;p&gt;The first finder step should be deterministic. For JS/TS, &lt;a href="https://github.com/fallow-rs/fallow" rel="noopener noreferrer"&gt;Fallow&lt;/a&gt; is the example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx fallow dupes &lt;span class="nt"&gt;--mode&lt;/span&gt; semantic &lt;span class="nt"&gt;--format&lt;/span&gt; json &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .lumpcode/dupes.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Point it at the package or tree you care about (&lt;code&gt;-w @your/package&lt;/code&gt; if you use workspaces). Other languages: any tool that writes a report the agent can &lt;code&gt;@&lt;/code&gt;. The lump only needs a file.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Scaffold the two lumps
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lumpcode lump-create abstractionFinder &lt;span class="nt"&gt;--config&lt;/span&gt; ts
lumpcode lump-create abstractionImplementer &lt;span class="nt"&gt;--config&lt;/span&gt; ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the finder config. The shipped &lt;code&gt;abstractionFinder&lt;/code&gt; recipe is a useful skeleton (&lt;code&gt;ephemeralContextListFn&lt;/code&gt;, backlog path). Override &lt;code&gt;steps&lt;/code&gt; so a scanner runs first, and so the prompt is about &lt;strong&gt;your&lt;/strong&gt; tree, not Lumpcode's CLI package (the recipe default still mentions &lt;code&gt;packages/apps/cli&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.lumpcode/lumps/abstractionFinder/config.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;abstractionFinder&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@lumpcode/recipes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;backlogItemsDir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.lumpcode/lumps/abstractionImplementer/backlogItems&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;abstractionFinder&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;maxPendingAbstractions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;scanDirectories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="nx"&gt;backlogItemsDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cursor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;maximumNumberOfConcurrentBranches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;commandFn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;executable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sh&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;-c&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;npx fallow dupes --mode semantic --format json &amp;gt; .lumpcode/dupes.json &amp;lt; /dev/null&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="p"&gt;};&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;promptTemplate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Read @.lumpcode/dupes.json and scan @src for duplicated logic (same pattern, not merely similar file structure).

List existing names under @&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;backlogItemsDir&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/todo/ and @&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;backlogItemsDir&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/completed/. Do not re-propose those names.

Pick exactly one new abstraction:
- A util name matching ^[a-zA-Z0-9_-]+$
- Refactoring all call sites in src/ should reduce net line count (excluding new unit tests)

Create exactly one folder @&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;backlogItemsDir&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/todo/&amp;lt;utilName&amp;gt;/ with:
- desc.yml: name, task, priority (max todo priority + 1, or 1)
- requirements.md: problem, goals and non-goals, proposed API, affected files, acceptance criteria (net reduction + unit tests)

Do not implement product code.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;.lumpcode/lumps/abstractionImplementer/config.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;abstractionBacklog&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@lumpcode/recipes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;abstractionBacklog&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cursor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;configUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;maximumNumberOfConcurrentBranches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;implValidateCommand&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;npm test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change &lt;code&gt;command&lt;/code&gt;, &lt;code&gt;scanDirectories&lt;/code&gt;, the Fallow invocation, and &lt;code&gt;implValidateCommand&lt;/code&gt; (&lt;code&gt;npm test &amp;amp;&amp;amp; npm run build&lt;/code&gt;, a workspace &lt;code&gt;-w&lt;/code&gt;, …). &lt;code&gt;/lumpcode&lt;/code&gt; can reshape paths and prompts.&lt;/p&gt;

&lt;p&gt;The implementer skips items without &lt;code&gt;requirements.md&lt;/code&gt;. &lt;code&gt;configUrl: import.meta.url&lt;/code&gt; is required so the recipe can resolve the project root.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Dry run
&lt;/h2&gt;

&lt;p&gt;On the laptop (shared mode, checkout untouched):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lumpcode lump-plan abstractionFinder &lt;span class="nt"&gt;--plan&lt;/span&gt; &lt;span class="nt"&gt;--contexts&lt;/span&gt;
lumpcode lump-plan abstractionImplementer &lt;span class="nt"&gt;--plan&lt;/span&gt; &lt;span class="nt"&gt;--contexts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finder should preview a scan + a prompt that writes a folder, not code. Implementer with an empty &lt;code&gt;todo/&lt;/code&gt; is a valid empty plan.&lt;/p&gt;

&lt;p&gt;Optional: run one finder context and review the requirements PR before the implementer is allowed to code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lumpcode run abstractionFinder
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Merge the configs, let the daemon tick
&lt;/h2&gt;

&lt;p&gt;Commit both lumps (and &lt;code&gt;package.json&lt;/code&gt; / lockfile if you added recipes here), push, merge to your primary branch.&lt;/p&gt;

&lt;p&gt;On the dedicated worker, &lt;code&gt;npm install&lt;/code&gt; is already done if recipes were in the first project push. Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lumpcode start &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'abstractionFinder,abstractionImplementer'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or &lt;code&gt;'abstraction*'&lt;/code&gt;. You do not restart for new backlog items. You do restart if you change &lt;code&gt;local.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Default is one context per branch. Merge implementer PRs into primary. If you squash or rebase, keep the &lt;code&gt;LUMP: abstractionImplementer - &amp;lt;name&amp;gt;&lt;/code&gt; line in the commit message. Drop it and Lumpcode treats that item as not done.&lt;/p&gt;

&lt;p&gt;Finder stays eligible: new ephemeral contexts, same campaign.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Disable
&lt;/h2&gt;

&lt;p&gt;In either config (or both):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Push and merge. The next tick soft-skips that lump. The daemon stays up.&lt;/p&gt;

&lt;p&gt;That's all. The loop is public in &lt;a href="https://github.com/lumpcode/lumpcode" rel="noopener noreferrer"&gt;Lumpcode&lt;/a&gt; under &lt;code&gt;.lumpcode/lumps/abstractionFinder/&lt;/code&gt; and &lt;code&gt;abstractionImplementer/&lt;/code&gt;. Follow along at &lt;a href="https://x.com/ddyods" rel="noopener noreferrer"&gt;x.com/ddyods&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>automation</category>
      <category>cli</category>
      <category>git</category>
    </item>
    <item>
      <title>Hands-on: dedicated Lumpcode daemon</title>
      <dc:creator>Daniel Saadia</dc:creator>
      <pubDate>Thu, 20 Aug 2026 09:41:23 +0000</pubDate>
      <link>https://dev.to/dyod/hands-on-dedicated-lumpcode-daemon-5c38</link>
      <guid>https://dev.to/dyod/hands-on-dedicated-lumpcode-daemon-5c38</guid>
      <description>&lt;p&gt;Lumpcode is a &lt;strong&gt;git-first loop manager&lt;/strong&gt;: a small CLI that runs long agent campaigns over your own repo, in reviewable slices. Git is the gate (one PR at a time) and the source of truth (what is left is read from remote history, not a distant database). You describe the campaign once, merge what is good, and the next tick continues with the rest.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;lump&lt;/strong&gt; is one campaign under &lt;code&gt;.lumpcode/lumps/&amp;lt;name&amp;gt;/&lt;/code&gt;. Each &lt;strong&gt;context&lt;/strong&gt; is one isolated unit of work: one branch, one PR. You can run a tick by hand, or leave a daemon on a machine that stays on.&lt;/p&gt;

&lt;p&gt;This article is that dedicated-daemon path. You author on your laptop. A second clone, that you do not develop in, runs the scheduler. When a lump lands on the primary branch, the worker picks it up.&lt;/p&gt;

&lt;p&gt;The argument for why loops should plug into git is &lt;a href="https://x.com/ddyods/status/2087538267235234025" rel="noopener noreferrer"&gt;Codemods grew a brain. Our tooling didn't.&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Requirements
&lt;/h2&gt;

&lt;p&gt;The dedicated clone is a checkout you do not develop in. Put it on a remote machine if you want it to run forever. Pre-flight hard-resets that tree.&lt;/p&gt;

&lt;p&gt;You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Git &lt;code&gt;origin&lt;/code&gt; with fetch and push&lt;/li&gt;
&lt;li&gt;A coding agent CLI on &lt;code&gt;PATH&lt;/code&gt; (&lt;code&gt;cursor-agent&lt;/code&gt;, &lt;code&gt;copilot&lt;/code&gt;, &lt;code&gt;claude&lt;/code&gt;, …), already logged in&lt;/li&gt;
&lt;li&gt;Node 22+&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing else. No extra service to stand up.&lt;/p&gt;

&lt;p&gt;Install the &lt;code&gt;/lumpcode&lt;/code&gt; skill so your agent has current docs while you set this up and write configs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add lumpcode/skills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use &lt;code&gt;/lumpcode&lt;/code&gt; in the session when you hit a config or CLI question.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Install the CLI
&lt;/h2&gt;

&lt;p&gt;On both machines:&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; @lumpcode/cli
lumpcode &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Laptop: project setup, shared mode
&lt;/h2&gt;

&lt;p&gt;From your day-to-day repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lumpcode project-setup &lt;span class="nt"&gt;--primaryBranch&lt;/span&gt; main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use your real integration branch instead of &lt;code&gt;main&lt;/code&gt; if that is what you merge to.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.lumpcode/local.json&lt;/code&gt; is gitignored and per machine. On the laptop it should be:&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;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shared"&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;Shared mode never touches this checkout. Runs go to &lt;code&gt;~/.lumpcode/project-copies/&amp;lt;projectName&amp;gt;/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Install &lt;code&gt;@lumpcode/cli-utils&lt;/code&gt; and &lt;code&gt;@lumpcode/recipes&lt;/code&gt; into this repo &lt;strong&gt;now&lt;/strong&gt;, before the first push. Later TypeScript lumps import them from the project's &lt;code&gt;node_modules&lt;/code&gt; (the global CLI does not ship them). If they are already in &lt;code&gt;package.json&lt;/code&gt; when the dedicated clone is set up, that machine runs &lt;code&gt;npm install&lt;/code&gt; once and does not need another install when the first lump lands.&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;--save-dev&lt;/span&gt; @lumpcode/cli-utils @lumpcode/recipes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the repo has no &lt;code&gt;package.json&lt;/code&gt; yet, this creates a minimal one. Commit it with the Lumpcode project in the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Push the Lumpcode project
&lt;/h2&gt;

&lt;p&gt;Commit &lt;code&gt;.lumpcode/project.json&lt;/code&gt;, the &lt;code&gt;.gitignore&lt;/code&gt; updates, and &lt;code&gt;package.json&lt;/code&gt; plus the lockfile. Do not commit &lt;code&gt;local.json&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add .lumpcode/project.json .gitignore package.json package-lock.json
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Add Lumpcode project"&lt;/span&gt;
git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Merge that to your primary branch if you are not already on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Dedicated clone: dedicated mode, then start
&lt;/h2&gt;

&lt;p&gt;On the worker, clone (or pull) the same repo. &lt;code&gt;.lumpcode/&lt;/code&gt; is already there, so &lt;code&gt;project-setup&lt;/code&gt; will refuse. Install project deps (this is the &lt;code&gt;npm install&lt;/code&gt; that pulls in &lt;code&gt;cli-utils&lt;/code&gt; and &lt;code&gt;recipes&lt;/code&gt;):&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then write &lt;code&gt;.lumpcode/local.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dedicated"&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;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lumpcode start
lumpcode daemon-status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No lumps yet. That is fine. The default &lt;code&gt;global&lt;/code&gt; daemon ticks every five minutes. When a lump appears on the primary branch, the next tick runs it. You do not restart for new lumps.&lt;/p&gt;

&lt;p&gt;Do not edit product code in this clone.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. First lump (laptop)
&lt;/h2&gt;

&lt;p&gt;Back on the day-to-day repo. This example is a React → Vue migration, one component per context, with tests retried until green. &lt;code&gt;cli-utils&lt;/code&gt; and &lt;code&gt;recipes&lt;/code&gt; are already in the project from step 3.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lumpcode lump-create reactToVue &lt;span class="nt"&gt;--config&lt;/span&gt; ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;.lumpcode/lumps/reactToVue/config.ts&lt;/code&gt; (adjust paths and &lt;code&gt;command&lt;/code&gt; to your repo and agent):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@lumpcode/cli-utils&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;retryUntilGreen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;shellCommand&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@lumpcode/recipes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cursor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;contextListJson&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;FOLDER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/components/{COMPONENT_NAME}/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;COMPONENT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/components/{COMPONENT_NAME}/{COMPONENT_NAME}.tsx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;TEST&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/components/{COMPONENT_NAME}/{COMPONENT_NAME}.test.tsx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;retryUntilGreen&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;promptTemplate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Port @{COMPONENT} to Vue 3 &amp;lt;script setup&amp;gt; as {COMPONENT_NAME}.vue in @{FOLDER}. Port @{TEST} to Vitest + @vue/test-utils. Keep behavior identical.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;validationCommandFn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;shellCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;npm test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;/lumpcode&lt;/code&gt; can help you reshape discovery and prompts.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Dry run, optional shared run
&lt;/h2&gt;

&lt;p&gt;Still on the laptop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lumpcode lump-plan reactToVue &lt;span class="nt"&gt;--plan&lt;/span&gt; &lt;span class="nt"&gt;--contexts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That loads the config, lists contexts, and previews the tick. It does not run the agent, branch, or push. Add &lt;code&gt;--contextName Button&lt;/code&gt; to inspect one context.&lt;/p&gt;

&lt;p&gt;If you want a real tick on one context, shared mode keeps your checkout untouched:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lumpcode run reactToVue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Default is one context per branch (the next eligible one). Review the pushed &lt;code&gt;lump/reactToVue/…&lt;/code&gt; branch before you let the daemon loose.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Merge the lump to primary
&lt;/h2&gt;

&lt;p&gt;When the plan (and optional shared run) look right, commit the lump, push, and merge to your primary branch.&lt;/p&gt;

&lt;p&gt;The dedicated daemon fetches that branch on the next tick and starts. Recipes are already installed there from step 5.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Merge work branches
&lt;/h2&gt;

&lt;p&gt;Each finished context is a branch &lt;code&gt;lump/reactToVue/&amp;lt;contextName&amp;gt;&lt;/code&gt; with commit subject &lt;code&gt;LUMP: reactToVue - &amp;lt;contextName&amp;gt;&lt;/code&gt;. Open a PR into the primary branch and merge as usual; if you squash or rebase, keep that &lt;code&gt;LUMP: …&lt;/code&gt; line (drop it and Lumpcode treats the context as not done). Git is the record: Lumpcode scans remote history for that marker, so &lt;strong&gt;toDo&lt;/strong&gt; means it is not on any remote ref, &lt;strong&gt;branchPushed&lt;/strong&gt; means it is on a work branch, and &lt;strong&gt;finished&lt;/strong&gt; means the marker is an ancestor of &lt;code&gt;origin/&amp;lt;primaryBranch&amp;gt;&lt;/code&gt;. Merge the PR; the next tick skips that context and picks another.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Disable the lump
&lt;/h2&gt;

&lt;p&gt;In the lump config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Push and merge. The next tick soft-skips it. The daemon stays up.&lt;/p&gt;

&lt;p&gt;That's all. Once the worker is up, a next campaign is &lt;a href="https://github.com/lumpcode/lumpcode/blob/main/articles/07-setup-abstraction-campaign/article.md" rel="noopener noreferrer"&gt;turning a dupes report into small PRs&lt;/a&gt;. Follow along at &lt;a href="https://x.com/ddyods" rel="noopener noreferrer"&gt;x.com/ddyods&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>automation</category>
      <category>cli</category>
      <category>git</category>
    </item>
  </channel>
</rss>
