# I replaced coding-agent orchestration with Git worktrees and one Python file

> Source: <https://dev.to/yanairon/i-replaced-coding-agent-orchestration-with-git-worktrees-and-one-python-file-4gj2>
> Published: 2026-09-16 18:56:51+00:00

When I started running more than one coding agent against the same repository, the first problem was not model quality. It was filesystem state.

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.

I wanted to see how far plain Git could go first.

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.

That maps cleanly to a coding-agent task:

I turned that mapping into **taskpods**, a small Python CLI with no runtime dependencies.

```
pip install taskpods
```

From inside a Git repository:

```
taskpods start tests --agent codex exec --sandbox workspace-write "add API tests"
taskpods start docs --agent claude -p "improve the docs"
```

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.

The agents do not need a taskpods integration. Everything after `--agent` 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.

An agent process exiting does not delete its worktree. The pod stays in place so I can inspect the actual diff:

```
taskpods list
git -C .taskpods/tests diff main
git -C .taskpods/docs diff main
```

If I want the change, I finish the pod:

```
taskpods done tests -m "Add API tests" --remove
```

`done` stages and commits the worktree, pushes its branch, and uses the GitHub CLI to open a pull request when gh is available. `--remove` removes the worktree after the branch is safely on the remote.

If I do not want the change:

```
taskpods abort tests
```

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.

There is also a cleanup command:

```
taskpods prune
```

It removes pods whose branches have already been merged upstream.

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

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.

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

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.

The current release is **v0.4.0**. 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.

The cases I want to learn more about are:

`main`
The code and issue tracker are here:

[https://github.com/yanairon/taskpods](https://github.com/yanairon/taskpods)

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.

If taskpods saves you time, the repository has optional GitHub Sponsors and Ko-fi links.
