Skip to content
Dylan San GabrielDylan
API reference
Contact

← All work

GET /api/work/agent-fleet

Running a dozen AI coding sessions on one repo

Live · · sole engineer

I use AI helpers to write much of the code, like a chef running a fast kitchen. This is the system of rules and checks that keeps the plates right.How I use AI coding agents at scale without vibe-coding, auto-loading rules, hooks that block the dangerous operations, and proof before calling it done.

  • Claude Code
  • Node.js
  • Git hooks
  • GitHub Actions
  • Jest
  • Markdown
commits in 6 months
14K
parallel sessions
10+
operating docs
300+
GET/api/work/{id}

Parameters

Request

curl "https://dylansg.com/api/work/agent-fleet"
source: src/content/projects/{id}

Response200 OK · 3.6 KB

{
  "id": "agent-fleet",
  "title": "Running a dozen AI coding sessions on one repo",
  "status": "live",
  "year": 2026,
  "category": "work",
  "role": "sole engineer",
  "summary": "How I use AI coding agents at scale without vibe-coding, auto-loading rules, hooks that block the dangerous operations, and proof before calling it done.",
  "summary_plain": "I use AI helpers to write much of the code, like a chef running a fast kitchen. This is the system of rules and checks that keeps the plates right.",
  "stack": [
    "Claude Code",
    "Node.js",
    "Git hooks",
    "GitHub Actions",
    "Jest",
    "Markdown"
  ],
  "metrics": {
    "commits_in_6_months": "14K",
    "parallel_sessions": "10+",
    "operating_docs": "300+"
  },
  "problem": "One engineer, an ERP-sized scope. AI coding agents made that possible, but running several at once against one repository has very specific failure modes: one session sweeps another's staged files into its commit, a broad test run melts the shared machine, a plausible-looking number ships because nobody checked it, and every new session starts with no memory of the rules the last one learned the hard way.",
  "unique": "Guardrails as code, not advice. Hooks run before every tool call and block the operations that can't be undone: broad git adds, skipping the pre-commit gate, full-tree test runs. A coordination layer registers every live session and locks the shared git index while another session is mid-commit. Rule files auto-load when a session touches a matching path. And nothing is called done on reasoning alone: the query, the endpoint's response or the rendered page comes first.",
  "ai": "This one is about the AI. Honest framing: agents write most of the code in the ERP. I write the rules, decide the architecture, and verify the result with queries, curl and screenshots before anything is called done. What follows is the system that makes that division of labour safe rather than reckless.",
  "learned": [
    "A gate that can't fail hasn't passed. Early reviews were rubber stamps. A second model helped for a while, but what held up was a check whose output nobody chose: a query, a test run, a screenshot.",
    "Second-model review went from triggered by diff size, to triggered by what a mistake would cost (2026-08-14), to not blocking a push (2026-09-11), to retired (2026-09-25). Each step followed a cost I could point to, like a three-and-a-half-minute review holding a fix that could be undone in one prompt.",
    "The model isn't the risk, the process is. Every incident in the ledger came from a missing constraint, not a bad suggestion, and every one became a hook or a rule the same day.",
    "Documentation is the multiplier. The 300-plus operating docs are what let a fresh session be useful in its first minute instead of its first hour, and what make my own decisions readable to me six months later."
  ],
  "subsystems": [
    {
      "id": "agent-fleet/daily-workflow",
      "title": "One task per session, a dozen at a time",
      "summary": "The daily loop behind the fleet, one task per session, background sessions watched from one side panel, and a merge-back check that closes every run.",
      "page": "https://dylansg.com/work/agent-fleet/daily-workflow"
    },
    {
      "id": "agent-fleet/tooling",
      "title": "The guardrails, extracted",
      "summary": "The session-lock layer, fleet scripts, context tooling and review-agent configs behind the fleet write-up, lifted out of the private repo and sanitized.",
      "page": "https://dylansg.com/work/agent-fleet/tooling"
    }
  ],
  "page": "https://dylansg.com/work/agent-fleet"
}

Live: this is the answer from this site’s API, not a mock. Send re-runs the request with your parameters; if the answer names a page, it opens.

The problem

One engineer, an ERP-sized scope. AI coding agents made that possible, but running several at once against one repository has very specific failure modes: one session sweeps another's staged files into its commit, a broad test run melts the shared machine, a plausible-looking number ships because nobody checked it, and every new session starts with no memory of the rules the last one learned the hard way.

What was unique

Guardrails as code, not advice. Hooks run before every tool call and block the operations that can't be undone: broad git adds, skipping the pre-commit gate, full-tree test runs. A coordination layer registers every live session and locks the shared git index while another session is mid-commit. Rule files auto-load when a session touches a matching path. And nothing is called done on reasoning alone: the query, the endpoint's response or the rendered page comes first.

Where AI fit in

This one is about the AI. Honest framing: agents write most of the code in the ERP. I write the rules, decide the architecture, and verify the result with queries, curl and screenshots before anything is called done. What follows is the system that makes that division of labour safe rather than reckless.

GET/api/work/{id}

Parameters

Request

curl "https://dylansg.com/api/work/agent-fleet?fields=problem%2Cunique%2Cai"
source: src/content/projects/{id}

Response200 OK · 1.3 KB

{
  "problem": "One engineer, an ERP-sized scope. AI coding agents made that possible, but running several at once against one repository has very specific failure modes: one session sweeps another's staged files into its commit, a broad test run melts the shared machine, a plausible-looking number ships because nobody checked it, and every new session starts with no memory of the rules the last one learned the hard way.",
  "unique": "Guardrails as code, not advice. Hooks run before every tool call and block the operations that can't be undone: broad git adds, skipping the pre-commit gate, full-tree test runs. A coordination layer registers every live session and locks the shared git index while another session is mid-commit. Rule files auto-load when a session touches a matching path. And nothing is called done on reasoning alone: the query, the endpoint's response or the rendered page comes first.",
  "ai": "This one is about the AI. Honest framing: agents write most of the code in the ERP. I write the rules, decide the architecture, and verify the result with queries, curl and screenshots before anything is called done. What follows is the system that makes that division of labour safe rather than reckless.",
  "page": "https://dylansg.com/work/agent-fleet"
}

Live: this is the answer from this site’s API, not a mock. Send re-runs the request with your parameters; if the answer names a page, it opens.

Inside it

  • One task per session, a dozen at a time

    How a normal day goes. Each AI helper gets one job, one list on the side of my screen shows which ones need me, and every split-up job ends with a check that all of it came back.The daily loop behind the fleet, one task per session, background sessions watched from one side panel, and a merge-back check that closes every run.

  • The guardrails, extracted

    The safety system I describe in the fleet write-up, pulled out on its own and stripped of everything company-specific — the actual traffic-cop code, cleaned up and published.The session-lock layer, fleet scripts, context tooling and review-agent configs behind the fleet write-up, lifted out of the private repo and sanitized.

GET/api/work/{id}

Parameters

Request

curl "https://dylansg.com/api/work/agent-fleet?fields=subsystems"
source: src/content/projects/{id}

Response200 OK · 751 B

{
  "subsystems": [
    {
      "id": "agent-fleet/daily-workflow",
      "title": "One task per session, a dozen at a time",
      "summary": "The daily loop behind the fleet, one task per session, background sessions watched from one side panel, and a merge-back check that closes every run.",
      "page": "https://dylansg.com/work/agent-fleet/daily-workflow"
    },
    {
      "id": "agent-fleet/tooling",
      "title": "The guardrails, extracted",
      "summary": "The session-lock layer, fleet scripts, context tooling and review-agent configs behind the fleet write-up, lifted out of the private repo and sanitized.",
      "page": "https://dylansg.com/work/agent-fleet/tooling"
    }
  ],
  "page": "https://dylansg.com/work/agent-fleet"
}

Live: this is the answer from this site’s API, not a mock. Send re-runs the request with your parameters; if the answer names a page, it opens.

The story

Fair question: how does one person build and run a system this size? I use AI coding assistants, heavily, several at once, like a kitchen with multiple line cooks. They’re fast. They’re also confidently wrong sometimes, and if you just accept whatever they produce you’re not an engineer, you’re a spectator.

So the real work is the kitchen, not the cooking. I decide what gets built and how it should behave. Written house rules load on their own so every helper knows things like “never let a website overwrite the product catalog.” The dangerous actions aren’t discouraged, they’re blocked, the way a fryer has a guard rail. For a while a second AI checked anything touching money or the books before it ran. I dropped that in late September: it held up fixes that could be undone in a minute, and it stalled work when that AI hit its usage limit. What stayed is the rule that nothing gets called done until I’ve watched it work: run the numbers, clicked the buttons, seen the result.

Every time something went wrong, it became a new guard rail the same day. The helpers make me fast, the rules keep it safe, and I own everything that ships.

Vibe coding versus engineering

The difference isn’t whether a model wrote the code. It’s whether anyone can say why the code is the way it is, what was checked before it shipped, and what would’ve stopped it if it were wrong. Everything below exists so one person can own the output at a speed they couldn’t otherwise keep up.

Rules that load themselves

The repo carries a top-level rules file every session reads, plus path-scoped rules that load when a session opens a matching file: touch channel code and the “master is sacred” rule shows up; open a deploy workflow and the pipeline’s gotchas do. Area docs for inventory, shipping, finance and jobs hold the invariants and the incident ledger for that area. A session doesn’t have to remember to read the rules.

Hooks that say no

Advice gets ignored under time pressure, by humans and agents both. So the operations that have caused incidents are blocked, not discouraged:

  • git add -A, git commit -a, --no-verify: blocked by a pre-tool hook. Staging by explicit path is the only path, because the index is shared and a broad add sweeps another session’s work into your commit.
  • Broad Jest runs: blocked. Scoped suites only. The full lanes run in CI on every push, where they can’t take down the machine ten sessions share.
  • A commit while another session is mid-commit in the same checkout: blocked until they finish.

Each block prints the reason and the sanctioned alternative. A subagent that never read the rules gets stopped the same way, which is the point.

Knowing who else is here

A coordination layer registers every session at start, tells it who else is live and whether any of them share the same checkout, and lets a session broadcast a finding to the others. By default a session works in its own git worktree, branched fresh from the integration branch, so parallel work never touches the same index at all. The failure ledger is public inside the repo — every incident, its cost, and the constraint it produced — and reading it is how a new session, or a new engineer, learns why the rules are shaped the way they are.

The review I retired

Until late September a second model reviewed work before it ran. At first the trigger was the size of the change. On 2026-08-14 it became what a mistake would cost: money, the books, bulk writes to production data, writes to a vendor’s API, migrations, permissions, and anything that could be silently wrong. That came after a 3m38s deep review held up a map-rendering fix that could’ve been reverted in one prompt. On 2026-09-11 the review stopped blocking pushes, after usage limits on the reviewer models stalled two sessions in the same hour. On 2026-09-25 I retired it: “we’ll do it ourselves if needed.”

What catches mistakes now is the next rule. The review agents still exist and run when I ask for one. Their configs are in the tooling write-up, kept the way they ran.

Verify before you assert

The one rule I’d keep if I could only keep one. Nothing is “done”, “fixed” or “passing” without the output behind it. Run the query, curl the endpoint, screenshot the page. “It’s probably fine” after five minutes of reasoning is worth less than one command that shows what it really is. That applies to me as much as to the agents.

What I learned

  1. A gate that can't fail hasn't passed. Early reviews were rubber stamps. A second model helped for a while, but what held up was a check whose output nobody chose: a query, a test run, a screenshot.
  2. Second-model review went from triggered by diff size, to triggered by what a mistake would cost (2026-08-14), to not blocking a push (2026-09-11), to retired (2026-09-25). Each step followed a cost I could point to, like a three-and-a-half-minute review holding a fix that could be undone in one prompt.
  3. The model isn't the risk, the process is. Every incident in the ledger came from a missing constraint, not a bad suggestion, and every one became a hook or a rule the same day.
  4. Documentation is the multiplier. The 300-plus operating docs are what let a fresh session be useful in its first minute instead of its first hour, and what make my own decisions readable to me six months later.
GET/api/work/{id}

Parameters

Request

curl "https://dylansg.com/api/work/agent-fleet?fields=learned"
source: src/content/projects/{id}

Response200 OK · 989 B

{
  "learned": [
    "A gate that can't fail hasn't passed. Early reviews were rubber stamps. A second model helped for a while, but what held up was a check whose output nobody chose: a query, a test run, a screenshot.",
    "Second-model review went from triggered by diff size, to triggered by what a mistake would cost (2026-08-14), to not blocking a push (2026-09-11), to retired (2026-09-25). Each step followed a cost I could point to, like a three-and-a-half-minute review holding a fix that could be undone in one prompt.",
    "The model isn't the risk, the process is. Every incident in the ledger came from a missing constraint, not a bad suggestion, and every one became a hook or a rule the same day.",
    "Documentation is the multiplier. The 300-plus operating docs are what let a fresh session be useful in its first minute instead of its first hour, and what make my own decisions readable to me six months later."
  ],
  "page": "https://dylansg.com/work/agent-fleet"
}

Live: this is the answer from this site’s API, not a mock. Send re-runs the request with your parameters; if the answer names a page, it opens.