Jump to content

One worktree, one DDEV site: running parallel AI agents on ProcessWire without sharing a database


Recommended Posts

Posted

For some time now I've been running more than one coding agent at a time in the same project. Parallel work for time savings. It literally pays off 😉
One builds a new feature, another fixes a bug, a third is off refactoring some template I'm scared to touch while I am planning a new feature with my agent in the main checkout. Git worktrees suck in many ways, but they make that easy for the code: each agent gets its own checkout and its own branch, and nobody steps on anybody's files.

Now that covers the code side. What about the database?

Fields, templates, pages, module config, all of that good stuff. Once you have three agents in three worktrees, you have three branches of code all talking to the same database. Agent A adds a field, agent B's branch has never heard of it, agent C runs a migration and now everyone's admin looks... interesting. Half isolated is not isolated and means headaches. For you and your little helpers.

DDEV doesn't really want to help here either. The tracked .ddev/config.yaml names the main project, so running ddev in a worktree either fights with your main project or refuses outright.

So I built a small tool for that: pw-runtime.

https://github.com/gebeer/pw-runtime

Who this is for

  • You build ProcessWire sites with DDEV (would you be reading this otherwise? My agent added this list item. Please bear with the creature, it's in a chatty mood sometimes...)
  • You use git worktrees, or want to (despite the many ways they suck. But this is not the point of this post. Sorry, now I got verbose...)
  • You let AI agents (Pi, Claude Code, whatever you like) work on features (ideally several at once)
  • You'd rather not give those agents your main dev database to play with (because you are the big kid on the block there)

If you work alone on one branch at a time, you don't need this. Your main DDEV project is fine. But you might miss out on efficiency (and that pay off).

What it does

Every git worktree gets its own runtime (fancy word for isolated container environment) that provides its own DDEV project, its own database, its own hostname, its own cache, logs and sessions. Four commands:

pw-runtime guard   # fresh worktree: ProcessWire refuses to boot until a runtime exists
pw-runtime up      # create or reuse this worktree's runtime, prints the URL as JSON
pw-runtime down    # delete this worktree's runtime
pw-runtime gc      # clean up runtimes whose worktree is already gone

On up it:

  • derives everything from your main project: name, hostnames, DB type and version, PHP, add-ons
  • imports a copy of your main dev database into the new runtime
  • runs your project's sanitize.sql on it before ProcessWire may boot (blank mail credentials, API keys, cron triggers, you name it)
  • forces mail to DDEV's Mailpit, so no agent ever emails a real customer from a test run
  • gives the worktree a private copy of site/assets/files (reflinked on btrfs, so it's nearly free)
  • answers 503 until all of the above is done, and only then prints the URL

The site is up in about 40 seconds on my machine in a project with a big DB, others take around 10s. down deletes it again.

The one rule the tool lives by: it never starts, stops, changes or deletes your main DDEV project or its database. If anything looks off, it stops and tells you. Fail closed.

Opting in

Since this tool is not specific to any single project and doesn't automatically run on all projects, a project can opt in with a tracked .pw-runtime/ folder. Only one file is required:

  • sanitize.sql (mandatory): makes the copied database safe to use
  • verify.sql (optional): checks that sanitizing actually worked, must print 0
  • after-up.sh (optional): your own setup steps, e.g. creating an agent admin user
  • copy-from-main (optional): untracked stuff the site needs, like .htaccess or built assets

Projects without .pw-runtime/ are left alone. All those 4 can and should be customized per project. Your helpful assistant will gladly help with that.

Why this is so effing nice with multiple agents

Here's what contributes to the literal pay off I was talking about. Each agent gets:

  • its own branch (git worktree)
  • its own running site with its own URL
  • its own database it can break as much as it likes

An agent can create fields, run migrations, install a module, click through the admin in a browser and smoke test the frontend (I highly recommend https://github.com/anomalyco/browse/releases), all without touching what the other bots are doing or what I'm looking at in my main project. When the work is done and merged, down and the worktree goes away. If I forget, gc cleans up later.

There's an agent skill included that tells the guy how to get a runtime and use it, so in practice I just say "work on X in a new worktree" and it figures out the rest. I also use it with https://herdr.dev, where creating and removing a worktree runs guard and down automatically. That part is optional and very much tied to my setup.

Honest caveats

My agent insisted on adding these. They seem to really love mentioning caveats, don't they.

  • It's a Bash CLI, tested on Linux (Arch, btrfs) with MySQL 8.0, on a real client project
  • macOS: untested, I'm a poor Linux guy and if I spent a fortune on Mac hardware, I'd run Linux on it

What it needs - Prerequisites

  • DDEV, with your main project already running (up won't start it for you)
  • Bash, jq, flock, rsync, curl and GNU cp
  • A project that opted in with .pw-runtime/sanitize.sql (you already know that from above but my agent insisted... you already know that, too)
  • For private files: a copy-on-write filesystem, so cp --reflink works. Tested on btrfs; XFS with reflink support should work too, untested. Your worktrees and ~/.cache must sit on the same filesystem. Without that, site/assets/files is mounted read-only from main, and uploads and new image variations fail in the worktree.

Resource usage
Upfront: the fans of your machine will stay quiet.
Per runtime (estimates based on my setup). On your super-beefy machine this might be different. I'm a poor guy on a mini PC who can't even afford a Windows license.

  • RAM: one web and one database container. On my machine about 120 MB for web and 450 MB for MySQL 8.0 with a big DB (obviously depends on project DB size). The DDEV router is shared.
  • Disk: a full copy of your dev database in its own Docker volume. The files are reflinked, so they take almost no space until something changes.
  • Once per project: a seed copy of site/assets/files in ~/.cache/pw-runtime (7 GB for one of my client projects). Every runtime reflinks from it. That is needed for efficient use of disk resources. You don't want your SSD clogged and die early from too many writes ;-)
  • Time: about 10-40 seconds for up depending on project. The DDEV image build is cached after the first time.

It's still somewhat young, but it has been working very well for me. If you try it, I'd love to hear how it goes, especially on setups that aren't mine (does that last part even make sense??? Oh my, those helpful helpers...).

Robots get their own sandboxes now. My dev database stays mine. 🤖

  • Like 3
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...