I woke up Saturday morning to commits I didn’t write. Dozens of them.

Real code. Passing builds, coherent diffs. One batch added Supabase Auth to HydrantMap. Another restructured PermitRadar’s routing from flat municipality paths to nested county/municipality paths. A third bolted on a CSV import pipeline for municipal hydrant data. All pushed between 1am and 7am while I was asleep.

By Sunday night, the total was 215 commits across 4 repos. 72 per day. Roughly 1 commit every 20 minutes, around the clock.

Two months ago, I was copy-pasting code from ChatGPT into my editor at about 7 commits per day in a single repo.

Here’s how I got from there to here, and what I built to make it repeatable.

The ramp-up

It happened in 3 stages over about 2 months.

Stage 1: Chatbot (Jan 3-10). OpenAI Codex through ChatGPT. Copy output, paste into editor, test, fix, commit. 59 commits in 8 days, all in 1 repo. About 7 per day. The commit messages tell you everything: “bugfix”, “fixes”, “dsf”. That last one isn’t a typo. I just didn’t care enough to type a real message because I was already back in the chat window.

Stage 2: Co-pilot (Jan 25 to Feb 19). Switched to Claude Code in interactive mode and stopped shipping product entirely. For almost a month, I built infrastructure: dotfiles, CLAUDE.md context files, project docs, SSH configs, n8n workflows, a React dashboard. 133 commits across 10 repos. About 5 per day. On a PR chart it looked like nothing (0.1 PRs/day) because I was pushing straight to main. But the commits were real. I was onboarding a new hire. The first month is slow. That’s the point.

Stage 3: Delegator (late Feb). Started filing GitHub issues instead of typing instructions into a terminal. Built a label system: claude-ready (backlog), claude-wip (claimed), claude-blocked (stuck). Plus a TODO(@claude) convention for inline micro-tasks. 65 commits across 7 repos. About 4 per day. Still running sessions manually. But the shape of my work changed. I was managing, not building.

Each stage taught me something specific. Stage 1 taught me what AI could write. Stage 2 taught me what context it needed. Stage 3 taught me that issues and labels could replace my voice. By the end of stage 3, I had all the pieces. They just weren’t packaged yet.

The weekend

Friday night I filed a batch of issues across HydrantMap and PermitRadar, set up 5 autonomous /loop commands in Claude Code, and went to bed.

215 commits in 3 days. 72 per day.

HydrantMap went from a static Leaflet map to a full multi-tenant SaaS: Supabase Auth, user profiles, avatars, admin dashboard, verification queue, CSV import, leaderboard, photo capture, dark mode, invite codes, and 45 tests. One weekend.

PermitRadar went from a single-county hardcoded app to multi-county support with restructured routing, a GDB-to-GeoJSON data pipeline, SODA API verification, a CI pipeline, 43 tests, an accessibility sweep, and a visual redesign with percentile charts. 122 commits in 3 days.

My role for the entire weekend: file issues Friday night, review PRs Saturday and Sunday. That’s it.

What I packaged into a repo

After the weekend, I looked at everything I’d wired up by hand across those 2 months: the CLAUDE.md conventions, the loop prompts, the label system, the CI pipelines, the permissions files. It was the same scaffolding every time, just slightly different per project.

So I extracted it into a single script: claude-agent-bootstrap.

One setup.sh that drops into any repo and generates everything an autonomous Claude Code agent fleet needs to start picking up work. The 2 months of trial and error, compressed into one command.

What it generates

Run the script from your project root:

Terminal window
cd your-project
~/claude-agent-bootstrap/setup.sh

It asks 3 questions (model mode, label preferences, loop speed), then generates:

FileWhat it does
CLAUDE.mdAgent instructions, conventions, and rules (appended to existing)
.claude/loops/*.txtIndividual loop prompts for each agent
.claude/settings.jsonPermissions for autonomous operation
start-loops.shtmux launcher to start/stop the fleet
LOOPS.mdLoop docs and manual paste commands
.github/workflows/ci.ymlCI pipeline (if your language supports it)
.claude/bootstrap.confYour saved config for re-runs

It auto-detects your language (Node.js, Python, Go, Rust) and configures the right linter, build command, and test runner. If you don’t want to answer prompts, --defaults runs it non-interactively.

The loops

Once setup.sh finishes, you start the fleet:

Terminal window
./start-loops.sh

This opens tmux sessions with 5 to 7 agent loops, depending on your model mode:

LoopWhat it doesFrequency
TODO WorkerPicks up claude-ready issues, implements them, creates PRsEvery 15 min
Lint GuardianRuns your linter, fixes violations, opens PRsEvery 30 min
Build WatchdogRuns the build, fixes failures, opens PRsEvery 30 min
PR Comment ResponderReads review comments on open PRs, pushes fixesEvery 15 min
Code Quality SweepFinds one code smell per cycle, refactors, opens a PREvery 1 hour
Triage WorkerClassifies new issues by complexity (dual-model mode only)Every 15 min

Model routing

You pick one of 3 modes during setup:

  • Dual (Sonnet + Opus): 2 tmux sessions, 7 loops. A Triage Worker reads each new issue and routes simple tasks to Sonnet, complex ones to Opus. Best for heavy workloads.
  • Single Sonnet: 1 session, 5 loops. Cost-effective. Good for smaller projects.
  • Single Opus: 1 session, 5 loops. Maximum quality for complex codebases.

How you file work

3 ways to give the agents something to do:

GitHub Issues. Add the claude-ready label. The TODO Worker picks it up, creates a branch, implements, opens a PR. In dual mode, you can skip triage by labeling claude-sonnet or claude-opus directly.

Inline TODOs. Drop a comment anywhere in your source:

// TODO(@claude): add input validation for email field

The TODO Worker scans for these, files issues, and opens PRs.

Epics. File an issue titled “Plan: …” and the agent breaks it into sub-tasks automatically.

Managing the fleet

Terminal window
./start-loops.sh # start all sessions
./start-loops.sh stop # kill all sessions
./start-loops.sh --dry-run # print prompts without starting

Sessions expire after about 3 days. To restart: stop and start again. LOOPS.md in your project has the full renewal instructions.

Running setup.sh again in an already-bootstrapped project sources your saved config, regenerates loop files, and skips anything already in place.

What broke

A lot.

Branch sprawl. Lint Guardian created 10 duplicate branches for the same fix. Build Watchdog created 5. Code Quality Sweep created 22. Each loop detected the same issue, didn’t realize another loop already had a PR open, and spun up its own branch. I had to add dedup rules so loops check for existing branches before creating new ones.

The MCP-first lesson. The agent kept generating SQL migration scripts and posting them in PR descriptions with a note saying “run this in Supabase.” It had a Supabase MCP tool that could execute SQL directly. It just… didn’t use it. I had to add explicit rules: you execute, I review. Never insert a human step that the agent can do itself. Every time you write “please run this,” you’ve failed.

Epic branches. The Gloucester County expansion touched routing, data pipelines, UI components, and test fixtures. 15 PRs all targeting main created a merge conflict nightmare. Big features need a parent branch with sub-tasks PRing against it. I learned this the expensive way.

All 3 of these lessons are baked into the bootstrap script now. The generated CLAUDE.md includes branch dedup rules, MCP-first conventions, and epic branch patterns. You get the fixes without hitting the walls first.

The math

PhasePeriodCommits/dayReposMy role
ChatbotJan 3-10~71Builder (copy-paste from chat)
Co-pilotJan 25 - Feb 19~510Pair programmer (direct commits)
DelegatorLate Feb~47Manager (filing issues manually)
FleetMar 7-9724Architect (reviewing PRs)

7 to 72. A 10x increase.

Line chart showing weekly commits from January to March 2026, steady at 5-7 per day then spiking to 72 per day in the final week

But the number that matters more: 133 commits in Phase 2. PRs said 0.1 per day. Commits said 5. All that “invisible” work (dotfiles, project docs, SSH configs, n8n workflows) was real, countable output that didn’t register on a PR chart because I was pushing straight to main.

Without spending a month teaching Claude my conventions, my project architecture, my code style, the autonomous loops would’ve produced garbage. Fast garbage, but garbage.

Try it

I’m a TPM. That’s my day job, and these are personal projects I build on nights and weekends. The reason this worked is that both halves of my skill set finally had something to grab onto. The technical side (writing the bootstrap script, configuring CI, setting up MCP tools) got the system running. The program management side (scoping issues, writing acceptance criteria, structuring epics) kept it producing useful output instead of chaos.

If you’ve already got Claude Code installed and a GitHub repo with some issues to burn through, the bootstrap takes about 2 minutes:

Terminal window
git clone https://github.com/stevedolinsky/claude-agent-bootstrap.git
cd your-project
~/claude-agent-bootstrap/setup.sh
./start-loops.sh

File some issues, label them claude-ready, and go do something else. The agents will start picking them up.

The repo is at github.com/stevedolinsky/claude-agent-bootstrap. MIT licensed. If you try it, I genuinely want to know what breaks for you that didn’t break for me.