<?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: Yanai Ron</title>
    <description>The latest articles on DEV Community by Yanai Ron (@yanairon).</description>
    <link>https://dev.to/yanairon</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%2F4119523%2Fa299e6b3-0b4f-4590-a842-62b8c73421c7.jpg</url>
      <title>DEV Community: Yanai Ron</title>
      <link>https://dev.to/yanairon</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yanairon"/>
    <language>en</language>
    <item>
      <title>I replaced coding-agent orchestration with Git worktrees and one Python file</title>
      <dc:creator>Yanai Ron</dc:creator>
      <pubDate>Wed, 16 Sep 2026 18:56:51 +0000</pubDate>
      <link>https://dev.to/yanairon/i-replaced-coding-agent-orchestration-with-git-worktrees-and-one-python-file-4gj2</link>
      <guid>https://dev.to/yanairon/i-replaced-coding-agent-orchestration-with-git-worktrees-and-one-python-file-4gj2</guid>
      <description>&lt;p&gt;When I started running more than one coding agent against the same repository, the first problem was not model quality. It was filesystem state.&lt;/p&gt;

&lt;p&gt;Two agents in one checkout can overwrite each other's files, change the same index, switch branches underneath each other, and leave a working tree that no longer explains which task produced which change. The obvious response is to add orchestration: a daemon, a task database, a process manager, or a UI.&lt;/p&gt;

&lt;p&gt;I wanted to see how far plain Git could go first.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The isolation primitive was already there
&lt;/h2&gt;

&lt;p&gt;A Git worktree gives one repository several working directories. Each worktree has its own checked-out branch and index, while the object database is shared.&lt;/p&gt;

&lt;p&gt;That maps cleanly to a coding-agent task:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;one task name&lt;/li&gt;
&lt;li&gt;one worktree&lt;/li&gt;
&lt;li&gt;one branch&lt;/li&gt;
&lt;li&gt;one agent process&lt;/li&gt;
&lt;li&gt;one reviewable diff&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I turned that mapping into &lt;strong&gt;taskpods&lt;/strong&gt;, a small Python CLI with no runtime dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;taskpods
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From inside a Git repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;taskpods start tests &lt;span class="nt"&gt;--agent&lt;/span&gt; codex &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;--sandbox&lt;/span&gt; workspace-write &lt;span class="s2"&gt;"add API tests"&lt;/span&gt;
taskpods start docs &lt;span class="nt"&gt;--agent&lt;/span&gt; claude &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"improve the docs"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first command creates .taskpods/tests on pods/tests. The second creates .taskpods/docs on pods/docs. Each agent runs with its worktree as the current directory.&lt;/p&gt;

&lt;p&gt;The agents do not need a taskpods integration. Everything after &lt;code&gt;--agent&lt;/code&gt; is passed through as the command to execute. That means the same mechanism works with Claude Code, Codex CLI, Gemini CLI, opencode, aider, or a local script.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pod is disposable, but the result is not
&lt;/h2&gt;

&lt;p&gt;An agent process exiting does not delete its worktree. The pod stays in place so I can inspect the actual diff:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;taskpods list
git &lt;span class="nt"&gt;-C&lt;/span&gt; .taskpods/tests diff main
git &lt;span class="nt"&gt;-C&lt;/span&gt; .taskpods/docs diff main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I want the change, I finish the pod:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;taskpods &lt;span class="k"&gt;done &lt;/span&gt;tests &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Add API tests"&lt;/span&gt; &lt;span class="nt"&gt;--remove&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;done&lt;/code&gt; stages and commits the worktree, pushes its branch, and uses the GitHub CLI to open a pull request when gh is available. &lt;code&gt;--remove&lt;/code&gt; removes the worktree after the branch is safely on the remote.&lt;/p&gt;

&lt;p&gt;If I do not want the change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;taskpods abort tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The abort path checks whether the branch exists on the remote. If it does, taskpods refuses to delete it automatically. That guard matters because "disposable" should describe the local environment, not already-pushed work.&lt;/p&gt;

&lt;p&gt;There is also a cleanup command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;taskpods prune
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It removes pods whose branches have already been merged upstream.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I kept it small
&lt;/h2&gt;

&lt;p&gt;There are good tools for supervising fleets of agents, managing terminal sessions, assigning tasks, and reviewing results. taskpods is intentionally below that layer.&lt;/p&gt;

&lt;p&gt;It does not schedule agents or coordinate their reasoning. It does not maintain a database. It does not run a daemon. It makes one narrow guarantee: each task gets a separate Git worktree and branch, and the lifecycle from start to review to PR or abort is explicit.&lt;/p&gt;

&lt;p&gt;The current release is one Python file, supports Python 3.9+, and has no runtime package dependencies. Git remains the source of truth.&lt;/p&gt;

&lt;p&gt;That small surface also makes it composable. A shell script, CI job, task runner, or higher-level orchestrator can call taskpods without adopting another state model.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I am testing next
&lt;/h2&gt;

&lt;p&gt;The current release is &lt;strong&gt;v0.4.0&lt;/strong&gt;. PePy reports 2,117 cumulative downloads, which is enough to start seeing whether the worktree model survives use outside my own setup but far too early to declare the interface settled.&lt;/p&gt;

&lt;p&gt;The cases I want to learn more about are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;several long-running agents against one repository&lt;/li&gt;
&lt;li&gt;interrupted agent processes&lt;/li&gt;
&lt;li&gt;branch cleanup after manual merges&lt;/li&gt;
&lt;li&gt;repositories whose default branch is not &lt;code&gt;main&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;teams that want task isolation without a permanent control plane&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The code and issue tracker are here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/yanairon/taskpods" rel="noopener noreferrer"&gt;https://github.com/yanairon/taskpods&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you use Claude Code specifically, I maintain claude-hookbook separately: reviewed hooks for formatters, guardrails, and notifications. I kept it separate because hooks configure one agent, while taskpods isolates any agent at the Git layer.&lt;/p&gt;

&lt;p&gt;If taskpods saves you time, the repository has optional GitHub Sponsors and Ko-fi links.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>opensource</category>
      <category>git</category>
    </item>
    <item>
      <title>I got tired of rewriting the same Claude Code hooks in every project, so I built a hookbook</title>
      <dc:creator>Yanai Ron</dc:creator>
      <pubDate>Fri, 11 Sep 2026 12:24:29 +0000</pubDate>
      <link>https://dev.to/yanairon/i-got-tired-of-rewriting-the-same-claude-code-hooks-in-every-project-so-i-built-a-hookbook-1gbl</link>
      <guid>https://dev.to/yanairon/i-got-tired-of-rewriting-the-same-claude-code-hooks-in-every-project-so-i-built-a-hookbook-1gbl</guid>
      <description>&lt;p&gt;A few weeks ago I noticed every Claude Code project I touch starts with the same ritual: I want Prettier to run after Claude edits a file, I want a notification when it asks for permission, and I really want it to not touch my .env files. So I open the hooks docs, dig up an old gist, hand-write a settings.json block, get the matcher slightly wrong, debug it, and repeat the whole thing on the next project.&lt;/p&gt;

&lt;p&gt;Hooks are one of the best features in Claude Code: deterministic shell commands that fire on events like PreToolUse or PostToolUse, so the boring stuff happens every time without relying on the model to remember. But the setup friction means most people run with zero hooks.&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://claude-hookbook.vercel.app" rel="noopener noreferrer"&gt;Claude Hookbook&lt;/a&gt;: a reviewed library of 20 copy-ready hooks, plus a generator that composes the ones you pick into one valid settings.json.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's in the book
&lt;/h2&gt;

&lt;p&gt;20 hooks covering the stuff I kept re-doing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Formatters that run after an edit:&lt;/strong&gt; Prettier, ESLint, Ruff, gofmt, rustfmt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Guardrails that block before something runs:&lt;/strong&gt; stop Claude from writing to .env and credential files, block destructive shell commands, run gitleaks on staged changes before a commit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quality gates:&lt;/strong&gt; run the nearest test after an edit, typecheck TypeScript in the background, block task completion while your project check fails.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quality of life:&lt;/strong&gt; desktop notification when Claude needs input, a session-start repo snapshot, re-injecting project context after a compaction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every hook page lists the event and matcher it uses, the risk level, what it needs installed, install and test steps, and - for the blocking ones - a recovery note for when it fires and you disagree.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest part: test status
&lt;/h2&gt;

&lt;p&gt;Hooks run code on your machine, so I didn't want a site full of unreviewed snippets. Each hook ships with provenance (sources and what Claude Code release it was checked against) and a test badge: &lt;code&gt;tested&lt;/code&gt; only after a real install plus a positive and negative trigger run against the current release. Until then a hook shows &lt;code&gt;needs-manual-check&lt;/code&gt; with the exact test steps on its page. Right now most of the library carries that badge - I'd rather show you the checklist than fake a green one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The generator
&lt;/h2&gt;

&lt;p&gt;The part I built for myself: tick hooks on the site and the &lt;a href="https://claude-hookbook.vercel.app/generator" rel="noopener noreferrer"&gt;generator&lt;/a&gt; emits one merged settings.json. The single-hook pages and the generator build the config fragment from the same canonical fields, so they can't drift apart. No CLI, no account, runs in the browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stack and repo
&lt;/h2&gt;

&lt;p&gt;It's a static Next.js site on Vercel, all routes pre-rendered. Hooks live as one JSON file per hook, validated at build time by a Zod schema, so a malformed hook fails the build instead of failing on your machine.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/yanairon/claude-hookbook" rel="noopener noreferrer"&gt;github.com/yanairon/claude-hookbook&lt;/a&gt;. Issues and hook requests welcome - if there's a hook you keep rewriting in every project, tell me about it in the comments.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>opensource</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I got tired of my AI agents fighting over one repo, so I built taskpods</title>
      <dc:creator>Yanai Ron</dc:creator>
      <pubDate>Thu, 10 Sep 2026 14:41:33 +0000</pubDate>
      <link>https://dev.to/yanairon/i-got-tired-of-my-ai-agents-fighting-over-one-repo-so-i-built-taskpods-nk0</link>
      <guid>https://dev.to/yanairon/i-got-tired-of-my-ai-agents-fighting-over-one-repo-so-i-built-taskpods-nk0</guid>
      <description>&lt;p&gt;A few months ago I started running AI coding agents in parallel: one fixing a bug, one updating docs, one trying a refactor. The agents were fine. My repo was not.&lt;/p&gt;

&lt;p&gt;Every agent CLI works in your working tree. Two agents on the same repo means they edit the same files, stage each other's changes, and occasionally commit on top of one another. The "solution" I kept seeing was manual git worktrees: create one per agent, remember the branch names, remember where you put them, clean them up later. It works, but it's fiddly enough that I kept not doing it.&lt;/p&gt;

&lt;p&gt;So I wrote the thing I wanted: &lt;a href="https://github.com/yanairon/taskpods" rel="noopener noreferrer"&gt;taskpods&lt;/a&gt;, a small Python CLI that wraps git worktrees into disposable "pods".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;taskpods
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What a pod is
&lt;/h2&gt;

&lt;p&gt;A pod is a git worktree plus a branch, managed as one unit. One command creates it and drops your agent inside:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;taskpods start fix-auth &lt;span class="nt"&gt;--agent&lt;/span&gt; &lt;span class="s2"&gt;"claude -p 'fix the token refresh bug'"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That creates &lt;code&gt;.taskpods/fix-auth/&lt;/code&gt; as a worktree on branch &lt;code&gt;pods/fix-auth&lt;/code&gt; and runs the agent there. &lt;code&gt;--agent&lt;/code&gt; takes any command, so it works with claude, codex, gemini, opencode, a shell script, whatever you use. Start a second pod and the two agents never see each other's files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;taskpods start docs-update &lt;span class="nt"&gt;--agent&lt;/span&gt; &lt;span class="s2"&gt;"claude -p 'document the config options'"&lt;/span&gt;
taskpods list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The lifecycle
&lt;/h2&gt;

&lt;p&gt;When an agent finishes, I review the diff like I would for a junior dev:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git &lt;span class="nt"&gt;-C&lt;/span&gt; .taskpods/fix-auth diff main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it's good:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;taskpods &lt;span class="k"&gt;done &lt;/span&gt;fix-auth &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"fix: token refresh"&lt;/span&gt; &lt;span class="nt"&gt;--remove&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That commits, pushes the branch, opens a PR if you have &lt;code&gt;gh&lt;/code&gt; installed, and removes the worktree. If it's bad:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;taskpods abort fix-auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the pod never existed. Abort refuses to delete work you've already pushed, which has saved me once already.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Design choices I cared about
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero config.&lt;/strong&gt; No daemon, no TUI, no config file to learn. It's one Python file over plain &lt;code&gt;git worktree&lt;/code&gt; commands. If you know git, you already know what it's doing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent-agnostic.&lt;/strong&gt; Claude Code has a native worktree flag now, but it's Claude-only. I wanted the same workflow regardless of which agent I'm using that week, and I wanted the lifecycle (list / done / abort) in one place instead of in my shell history.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Boring on purpose.&lt;/strong&gt; Pods are real worktrees with real branches. Nothing is hidden in a database somewhere; you can &lt;code&gt;cd&lt;/code&gt; into a pod and use git normally.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;It's MIT-licensed and on PyPI: &lt;a href="https://github.com/yanairon/taskpods" rel="noopener noreferrer"&gt;github.com/yanairon/taskpods&lt;/a&gt;. v0.4.0 just shipped with the &lt;code&gt;--agent&lt;/code&gt; launcher. I'd genuinely like to hear how other people run parallel agents - if you have a workflow that works better, tell me about it in the comments.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>python</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
