← Back

Step Zero / Install

Nothing else in this team runs until the foundation is confirmed.

A stranger just cloned the repo and has never run any of these agents before. /install is the one command that has to work before anything else can: it detects the repo, gets git/gh/sqlite3 in place, builds the docs/ skeleton, and confirms a GitHub Project board — asking a human for anything it can't safely decide on its own, and re-verifying live state on every re-run rather than trusting what it found last time.

01 / The checklist

Nine steps, walked in order, each verified live.

The installer agent thinks of itself as a building inspector working a new construction site before anyone moves in: check each item with a real test, in order, and don't let the next step start on a foundation that isn't actually confirmed. Most of the checking is a script call; a few steps are a plain question to the human running it.

Step 0

Confirm the directory

Ask plainly which directory to set up in — never assume the working directory is right just because it's where the conversation happens to be running.

Step 1

Install git

Every stage this team runs depends on git — worktrees, branches, per-stage commits — more than it depends on anything else.

Step 2

Install & authenticate gh

gh auth login is a human's browser or device-code flow. The script opens the terminal; it never completes the login itself.

Step 3

Install sqlite3

bin/agent-log shells out to this binary directly for every read and write — without it, no agent in the team can log anything.

Step 4

Repo, labels, database, docs/

Detects the git remote, writes team.yml, creates the feature/bug/tech-debt labels, migrates db/agent_log.sqlite3, builds the docs/ skeleton.

Step 5

Confirm or create the board

Asks first. A GitHub Project (v2) board is owner-scoped, not repo-scoped — confirming or creating one still leaves it unlinked from the repo's own Projects tab until gh project link runs too.

Step 5b

Guarantee the Status option

Makes sure team.yml's default_status actually exists as an option on the board's Status field — the centerpiece story below.

Step 6

Confirm Issues are reachable

The repo's own Issues feature, not the Project board — a simpler, separate thing to verify.

Step 7–8

Record & report

Fills in github.project.owner/number in team.yml, then reports one line per item: present, created, or failed.

02 / Automated vs. permanently manual

Some of this is safe to automate forever. Some never will be.

This split isn't a backlog of things still to build — it's drawn from what a human's own hands are for: a sudo password, a browser login, a yes before something appears on their GitHub account.

Automated

Safe without asking, every time

  • Installing git/gh/sqlite3 via Homebrew on macOS, or any user-owned prefix
  • Writing team.yml — a comment-preserving targeted edit, never a full rewrite
  • Creating the feature/bug/tech-debt repo labels
  • Migrating db/agent_log.sqlite3 and building the docs/ skeleton
  • Linking a confirmed or newly created board to the repo — a no-op, safe to re-run
  • Adding a missing Status field option, via GraphQL

Permanently manual

A human's hands, by design — not a gap

  • gh auth login — unavoidably a human's browser or device-code flow
  • Any install that needs sudo, or macOS's Xcode Command Line Tools GUI installer
  • Creating a GitHub Project, or a repo label, without an explicit yes first
  • Enabling Issues in repo settings, if they're disabled — a settings toggle, not an API call
  • ruby being on PATH — never auto-installed by anything here
A different kind of gap

One thing genuinely isn't built yet, and the source calls it out by that name: copying bin/agent-log itself into a target repo that doesn't already have it. That's a future "not yet built," distinct from the permanently-manual list above — those stay manual no matter how much tooling gets added later.

03 / The centerpiece

There's no gh command for this. So the script talks to the API directly.

Code owns the mechanics here because nothing else can reach them — the judgment (which option, which board, never delete a card's existing status) stays exactly where it was.

What's missing

No CLI command for this

$ gh project field-create
  → makes a brand-new field

$ gh project field-list
  → id, name only —
    no color, no description

The CLI can create a whole new field. Nothing in it edits one option onto a Status field that already exists.

What the script does instead

Calls GraphQL directly

updateProjectV2Field(
  fieldId: $id,
  singleSelectField: {
    options: $fullList  # every existing
                         # option, plus the
                         # one being added
  }
)

The mutation demands the entire option list on every call. Drop one, and it's deleted — with any card already set to it.

Why a GraphQL mutation, verbatim from the docs

Adding a new option to a GitHub Project board's existing Status field (e.g. "Ready" on a board that only ships with Todo/In Progress/Done) has no dedicated gh command — gh project field-create can make a brand-new field, but nothing edits an option onto one that already exists. bin/team-setup-project-status does it through the underlying GraphQL API instead: updateProjectV2Field requires resending the field's entire option list on every call, so the script always reads every existing option's id, name, color, and description first (gh project field-list doesn't expose color/description, so this is a separate query), then resends that full list plus the one new option. Leaving any existing option out of that list would silently delete it — and any card already set to it — so the script never constructs the list from anything but a fresh read. This was verified against a real, item-free project board before being trusted in the installer.

bin/team-setup-project-status

Kind label

    04 / Idempotent, and what it never does alone

    A second run re-checks everything. It never re-asks what it already knows.

    Idempotency, verbatim from the docs

    A second run isn't a no-op — it re-verifies everything live (GitHub state can drift even when team.yml hasn't) and reports it all as already present rather than re-asking the same questions. This is why the scripts print structured status instead of just doing work silently: "already correct" and "just fixed" both look like status: "ok" to the agent, but the detail string says which.

    What it does

    Prepares the substrate

    • Detects the repo, writes team.yml
    • Creates labels, migrates the log database, builds docs/
    • Confirms the board exists and Issues are reachable

    What it cannot do

    Never without a human

    • Modify application code, tests, migrations, or configuration
    • Run gh auth login, or a system package install, on the user's behalf
    • Create a GitHub Project on the user's behalf without an explicit yes
    • Continue past a failed, unresolved step
    Read the source documentation