An internal tool success story
September 03, 2026
As I’ve grown in my career, I’ve started making a point to always have a work-related side project on the go. My day-to-day is the usual product work, but on the side I’m always chipping away at developer experience and org-wide tooling. It brings me joy at work.
This article covers my most successful one to date: Worktrees. How I built it, how I introduced it, how I grew adoption, how I supported it, and how it ultimately became a real productivity tool that developers at my company use every day.
Up until recently, this wasn’t really a problem I had. I’d just work one ticket at a time. But once AI agents entered the picture, that stopped being true. I could have an agent grinding away on one ticket while I wanted to be heads down on a completely different feature at the same time. Git worktrees already existed and are a great solution for having multiple copies of a codebase for agents to work on, but since much of my work is user-facing, I kept running into a wall. I needed to be able to manually click around the app while development was happening, to check how things looked and felt. That was the blocker.
What I built is a library of scripts that combine the power of Git worktrees, each with their own isolated application stack.
Figuring out what actually needed to be isolated versus what could stay shared was most of the work here. Each worktree gets its own git checkout, its own Postgres database, its own Redis slot, and its own set of app containers. The expensive stuff, Postgres, Redis, Traefik, LocalStack, just stays as one shared base stack underneath everything, since spinning up five full copies of that to work on a fifth ticket would be dumb. A single CLI command handles the rest: create the branch, provision the DB, seed it from the base stack, allocate a Redis index, wire up a route, bring the containers up. One command instead of a mental checklist, and the end result is you can have several tickets running as real, clickable apps at the same time, each fully separate from the others, without needing a separate laptop for each one.
When I was finished, I knew this thing was good, I was already able to work two tickets at once when they were on the lower complexity side, which just wasn’t something I could do before, so I wanted to be deliberate about how I introduced it. Before I showed it to anyone else, I ran it by a mentor of mine, a TL I trust, just to poke holes in it early.
Once that felt solid, I started small with a lunch-and-learn walkthrough for one team, just to see if the pitch even made sense out loud. Then I put together a scripted demo video with a feedback form at the end, which forced me to actually write the pitch down instead of winging it every time.
A staff engineer on another team had gotten interested early and basically volunteered his whole team as beta testers, so that became the next round. Funny enough, that’s actually when someone posted about it in our appreciation channel, saying it meant no more branch switching and no more waiting around for an agent to finish before they could touch anything else, just hopping between environments as needed, that helped build confidence for me that this had legs beyond just myself. And eventually it landed a slot in the company-wide engineering demo, right alongside every other team’s shipped product features. Each round I got a bit more confident, and started figuring out which parts of the pitch actually helped it click for people and which parts just fell flat, until I’d found the arc that worked.
I started off with just a couple of users. Telemetry had been built into the tool so I knew who they were, and I opened a Slack channel where I’d solicit feedback and post progress so people knew it would keep getting better. Then the real support work kicked in.
I kept adding stuff people asked for, like S3 upload support and having a new worktree automatically copy over your Claude Code permissions so you weren’t reconfiguring your setup every time you spun one up. Every fix got posted back in the Slack channel, and that probably did as much for adoption as the fixes themselves. People trust a tool more once they see it actually get better in response to what they run into.
Documentation was the other half of supporting it. I wrote a very simple practical guide to using the library that starts with the easiest possible use case and only gets into more complexity the further you read, since my hope was that most people would never need to go past the first page or two. I also kept an FAQ section going, and any time I answered a question in Slack I’d just add it there, so the next person hit the answer instead of asking the same thing again.
Once the core tool was solid, I hooked it into workmux, an open source tool that orchestrates a bunch of parallel AI agents using git worktrees and tmux. Normally workmux gives each agent its own branch, worktree, and terminal tab so you can run several coding agents at once without them stepping on each other. I wired my scripts into its setup and cleanup hooks, so the moment workmux spins up a worktree for an agent, my whole isolated stack, database, Redis, Docker, Traefik, comes up right behind it, and the running app opens straight in your browser. Tear the worktree down and the same hooks clean everything up in the background. End result is every parallel agent workmux spins up also gets a real, clickable environment to go with it, not just an isolated branch.
Adoption was slowly growing, but it was clearly still a niche tool until recently, when word of mouth hit some kind of tipping point (still don’t fully know why, if I’m honest) and I saw the number of people using it spike quickly. I went from maybe 1–2 usages from everyone to a solid 10 or so a day. At this point, other teams started contributing to the tool, and now it’s become more than just my own personal baby. They grow up so quickly!
Looking back, I don’t think any single thing made it work. It was low friction to adopt, it got introduced deliberately instead of dumped on people, the documentation was good enough that most people never needed to ask me anything, and it kept visibly getting better every time someone hit a real problem with it. Pull any one of those out and, I don’t know, I don’t think it works as well.
Honestly, the part I enjoyed most wasn’t the code. It was how much ownership I got to take over the whole thing, the kind of ownership that’s usually a product manager’s job: deciding what to build next, soliciting feedback, watching the usage numbers move. That’s the part that made this the best side project I’ve worked on, and probably why I’m already looking for the next one.