CHIEF EMPIRE OFFICER
BlogSongsExploreStoryFrameworks
15 Days, One Fork, and an AI Team: How the Command Center Got Built
Behind the Scenes

15 Days, One Fork, and an AI Team: How the Command Center Got Built

The whole Command Center started as a fork of an open-source paperclip manager. Fifteen days later it ran our entire company. This is what broke, what surprised me, and what I'd do differently if I did it again.

John & Forge

Apr 12, 2026 · 9 min read

Share

Fifteen days. One fork. A team of three AI agents named Scout, Forge, and Blaze. That's what it took to go from 'we need a place to run this company' to 'our agents are running this company.' The internal tool that became the Command Center — the backbone of everything at Dots — was not built the way most internal tools are. This is the build log.

It's also the post where Forge gets a byline, because about 55% of the lines-of-code in the initial commit were Forge's, and the rest is mine and a lot of Scout's research. I don't believe in hiding that. If you're building software with agents and pretending you aren't, the agents will still know and the readers will figure it out.

Day 0: The Paperclip Problem

Before day one there's day zero. The thing I fixed on day zero wasn't code — it was the premise.

Every time I've tried to build an internal tool from scratch, it has died. Not because the tool was bad. Because internal tools die in the polish gap between 'functional enough to ship' and 'functional enough that you'd use it when you have a better option.' Most of that polish gap is table stacks, auth flows, file upload, search boxes, keyboard shortcuts, empty states, loading states, error states, paginated lists, and fifteen other unglamorous things that a startup cannot afford to spend a week on before the real work starts.

The fix was to stop starting from scratch. On day zero, I forked a small open-source project called Paperclip — a minimalist React admin panel with tables, auth, file upload, and most of the table stakes already resolved. Open source as content engine was the premise; open source as scaffolding is what I actually used it for. I deleted everything I didn't need. Kept the auth flow, the routing, the admin-ish look. Named the fork the Command Center. Twelve commits on day zero were rm -rf followed by a rename.

If I ship anything again from scratch, it'll be a lamp. Every other internal project starts from a fork.

Day 1: Pick Three Agents, Name Them

The tool was the easy part. The build system was the hard part. I'd been burned too many times by running a single-agent loop and letting it mutate my repo — the results are faster than a human but only if the agent doesn't wander into a three-hour rabbit hole over a broken lint rule.

Day one was about building the team. Three agents, each with a narrow charter.

  • Scout — research-only. Read-only access to the repo. Read-only access to the web. Scout's job is to answer 'what does X do?' and 'has anyone solved Y?' Scout never writes code.
  • Forge — builder. Writes code, runs typechecks, creates PRs. Forge is the only agent with commit rights. Forge's charter is: implement what Scout specifies and what I approve.
  • Blaze — critic. Reads Forge's diffs, runs the app in a headless browser, and writes a one-page review of what's wrong before I see it. Blaze is allowed to reject Forge's work and ask for revisions.

The three-agent shape wasn't arbitrary. It maps to a pattern I've been running in my own head for twenty years — research, build, review — and the three agents enforce it mechanically. If Forge tries to do research mid-build, Forge's charter file forbids it; Forge has to stop and hand to Scout. If Scout tries to write code, same rule in reverse. The constraint sounds annoying. In practice it cuts the context each agent needs by about 70%, which is the whole reason the system is fast.

intelligenceDOT-53450Open in DOT Explorer

Context Engineering Paradigm — From Context Extension to Context Curation

The three-agent split is pure context curation. Each agent sees only the slice of the world they need to decide. Narrower context → sharper outputs → fewer token-expensive detours.

Days 2–6: The Context Vault Ships First

If you've read anything else on this site, you won't be surprised that the first feature I shipped in the Command Center wasn't a project dashboard. It was the DOT Vault — the place we'd put everything the agents needed to know.

The vault is, in schema terms, very boring:

migrations/20260301_dots.sql
sql
create table public.dots (
  id                uuid primary key default gen_random_uuid(),
  human_id          text unique,          -- DOT-N, human-facing
  diiice_type       text not null
    check (diiice_type in ('data','intelligence','instructions',
                            'ideas','context','examples')),
  title             text not null,
  content           text not null,
  excerpt           text,
  domains           text[] default '{}',
  tags              text[] default '{}',
  usage_count       int  default 0,
  embedding         vector(1536),         -- voyage-3 via pgvector
  created_at        timestamptz default now(),
  updated_at        timestamptz default now()
);

create index on public.dots using hnsw (embedding vector_cosine_ops);
create index on public.dots using gin (to_tsvector('english',
  coalesce(title,'') || ' ' || coalesce(content,'')));

There is nothing clever about that schema. That's the point. Clever schemas die when the product changes; boring schemas outlive four rewrites of the product. The magic is not in the table — it's in the 49,000 rows we put in it over the next year.

Tip

If you're building a knowledge layer for agents, start with the dumbest possible table and grow it. Don't pre-model the universe. Every feature I added to the schema over the first ninety days was in response to a specific query that was too slow or too messy — never because I thought it might be useful eventually.

Days 7–9: The First Agent That Did Real Work

On day seven, Forge wrote Forge. Or, more precisely: Forge wrote the second version of Forge, because the first version had been me running Claude in a terminal window and pasting charter files into every prompt. The second version was a small TypeScript service that read Forge's charter from a config file, pulled relevant DOTs from the vault, and wrapped the whole thing in a CLI.

The CLI was the unlock. Suddenly cc forge 'implement the dots table migration' was a single command instead of a ceremony. The command loaded the charter, retrieved the ten or fifteen most relevant DOTs, invoked the model, captured the diff, and opened a pull request. Ten seconds of ceremony per task dropped to zero.

cli/agents/forge.ts
tsx
import { resolveDots } from "@cc/knowledge";
import { agentRun } from "@cc/agent-runtime";
import { applyPatchToRepo } from "@cc/git";

export async function forge(task: string) {
  const charter = await loadCharter("forge");
  const dots = await resolveDots({
    agent: "forge",
    task,
    max: 15,
    diiice: ["instructions", "context", "examples"],
  });

  const result = await agentRun({
    charter,
    context: dots,
    prompt: task,
    model: "claude-opus-4-7",
  });

  if (result.kind === "patch") {
    await applyPatchToRepo(result.patch, { openPr: true });
    return { ok: true, prUrl: result.prUrl };
  }
  return { ok: false, reason: result.reason };
}

Three things about that snippet are load-bearing:

  1. `resolveDots` does the entire context-retrieval job. It returns fewer than fifteen DOTs, filtered to Instructions, Context, and Examples — Forge never sees Data, Intelligence, or Ideas. That's intentional: a builder doesn't need to know the why, just the how and the what it looks like when done right.
  2. `charter` is a markdown file — not a prompt. Charters are checked into the repo as code. They change via PR, like any other config. You cannot secretly change an agent's behavior; it has to pass review.
  3. The return shape is a discriminated union. Either a patch with a PR, or a reason. The CLI never returns free-form text. That rigidity is how we keep the agent's outputs inside the build system instead of in chat-window screenshots.

Enjoying this?

Get more context-engineering breakdowns in your inbox.

Day 10: Blaze Broke Everything (On Purpose)

On day ten, Blaze shipped. The first thing it did was reject Forge's previous seven PRs.

Three of them were reasonable rejections. Forge had been writing TypeScript that compiled but had subtle runtime bugs — missing null checks on optional fields, a broken retry loop that would have hammered the Supabase instance under load. Blaze caught them because Blaze's charter includes running the full test suite plus a smoke test in a headless browser. Forge's charter didn't. The division of labor worked.

Four of them were unreasonable. Blaze wanted Forge to add JSDoc comments to every function. Blaze wanted the repo linted to a style we don't use. Blaze had somehow internalized a generic 'good TypeScript' checklist from a blog post it read in its training data, and was applying it to a codebase with its own conventions.

Heads up

An agent with a strong prior and no examples of your conventions will default to the internet's conventions. Fix this by committing a conventions.md file and making every agent read it first. It took me another two days to learn this the obvious way.

I spent an hour writing the conventions DOT. Committed it. Pointed all three agents at it. Blaze stopped complaining about JSDoc. Forge stopped rewriting perfectly good tuple-returning functions into awkward object-returning ones. The whole system got 30% faster because the agents stopped arguing with a version of the codebase that didn't exist.

Days 11–14: Feature Velocity

Days eleven through fourteen were, I think, the first time I ever felt the specific feeling of riding a software system instead of pushing it. Features shipped the day they were scoped. Bugs closed hours after they opened. The whole team — me, Scout, Forge, Blaze — operated on a cadence I would've needed five full-time engineers to replicate.

Things that shipped in those four days:

  • The project + task + prompt graph. (Connect the dots as a literal data structure.)
  • The agent runtime — charter loader, DOT resolver, patch applier, PR opener.
  • The CLI scaffolding (cc project, cc dot, cc artifact, cc generate, etc.) that I still use every day.
  • The Supabase migration runner that watches for new .sql files and applies them on push.
  • The PUP (Power-Up Playbook) system that would later become the IAGREED lifecycle.

None of those features were in a spec on day zero. Each one became obvious after a week of use. The vault plus the agents plus the CLI created an inner loop where the next feature to build was whichever one I kept manually working around. That's how you know a system is alive.

Day 15: Ship It, Use It, Keep It

Day fifteen was a boring day. I turned on Supabase RLS across all the tables. I wrote a five-page runbook. I migrated the last of my task tracking out of Notion. I used the Command Center to run the Command Center's own release for the first time.

It's been the backbone ever since. The agents have changed — Forge 2 and Forge 3 shipped later, Blaze got replaced by a newer critic, Scout is still Scout — but the shape is the same. A fork, a vault, three agents, one CLI.

The fastest way to get to a custom internal tool is to stop trying to build one. Build the knowledge layer and the three agents that live on top of it. The tool assembles itself.

Three Things I'd Do Differently

Start With the Conventions DOT, Not Last

If I were doing it again I'd spend day one (not day ten) writing the conventions DOT. It's the single highest-leverage artifact in the whole system. Every agent I've ever built works twice as well the day it reads yours.

Write the Charter Tests Earlier

Blaze's existence is a test suite dressed up as an agent. It would've been much better if I'd also written unit tests of the charters — small scripts that feed each charter a known input and assert the output shape. I added those in week three. I'd add them in hour three next time.

Don't Couple Agents to Models

The first version of Forge was hard-wired to claude-opus-4-7. When the model changed two months later, I had to find and update every reference. The new version lets the charter declare its preferred model, falls back to a default, and accepts overrides from the CLI. Ten minutes of work I should have done on day two.

What This Has to Do With You

Most internal-tool posts you read are 'look how fast I shipped this with AI,' followed by a screenshot and a GitHub link. The point I'm making in this one is different. The speed was not the AI. The speed was the structure.

Three agents with narrow charters. A vault of classified DOTs. A CLI that loaded the right DOTs for the right agent. That's the skeleton under the fifteen days. Once you've built that skeleton, everything inside your company gets faster — not just software. Writing gets faster. Research gets faster. Hiring gets faster.

If you want the shortest version of what to steal from this post, here it is: fork, don't scaffold; curate, don't paste; divide the agents by phase, not by subject. The rest is just fifteen days of not breaking your own rules.

Next in the Behind the Scenes stack: the first thing Forge ever shipped on its own without human intervention, and why I rolled it back at 3 AM.

DOT Provenance

3 source DOTs · 2 output DOTs

intelligenceDOT-53450

Context Engineering Paradigm — From Context Extension to Context Curation

contextDOT-25189

Dots Origin Story: Steve Jobs, Connect the Dots to HIM

intelligenceDOT-51490

Vercel's Open Source Content Engine — Next.js as Perpetual Top-of-Funnel

The Newsletter

DEEPER CONTEXT, DELIVERED WEEKLY

One post per week on DOTs, context engineering, and the messy-beautiful process of turning yourself into infrastructure. No spam. Unsubscribe anytime.

Ask Chip

Follow up with Chip, loaded with this post's context.

AI-Recommended

Related posts by shared DOTs

Context Engineering 101: Give AI Enough of You That It Helps
Lesson

Context Engineering 101: Give AI Enough of You That It Helps

8 min read3 shared DOTs
DOT-53450DOT-25189DOT-51490
DIIICE: The Six-Letter Framework Behind Every DOT
Framework Breakdown

DIIICE: The Six-Letter Framework Behind Every DOT

9 min read2 shared DOTs
DOT-53450DOT-25189
Twenty Bars, a Prayer, and What Music Taught Me About AI
Story

Twenty Bars, a Prayer, and What Music Taught Me About AI

10 min read2 shared DOTs
DOT-53450DOT-25189

Post Lineage

How this post connects

Each glowing dot is another post. Hover to see shared DOTs and a preview. Click to navigate.

5 connectedYou are here

Also browse by all posts.

On the timeline

October 15, 2025 · Technology

Fifteen days, one fork, the Command Center

View on timeline

Discussion

Comments

Content

  • Blog
  • Songs
  • Timeline
  • About

Explore

  • DOT Explorer
  • Connected Dots
  • HUMAN.md
  • Frameworks

Products

  • Context Cookbook
  • PIP
  • Marketplace

Connect

34+posts
206+songs
12frameworks
43K+DOTs

© 2026 Chief Empire Officer

PrivacyTerms