CodeCrew, precisely¶
codecrew.works is the introduction site; the repository's README is the technical entry point, with the install line and the routing-table example. This page says what CodeCrew is, what exists today, and where everything else lives — it is the map.
Read in this order¶
Two things first, because the pages below can give the wrong impression.
The verbs are documented so they can be run by hand; in practice the coding
agent runs them and a human answers the gates. And onboarding is the three
commands under Start now — install the extension,
cd into the repo, gh codecrew init — after which an agent dispatched into
the repo reads .codecrew/AGENTS.md (the root
AGENTS.md points at it) and its role contract and does the
rest; the quickstart is the long form of what happens next, not a
prerequisite.
- codecrew.works — the introduction site: what the problem is, how the protocol works, and what it has delivered.
- This page — the three parts, what is shipped, the refusal codes.
- Your first milestone — the quickstart: one human, one agent, a milestone from opening to audited close.
- Identities — running solo, staffing seats with humans, teams and App identities, dispatching a role session.
- Platform interop — the ladder's last rung: how an orchestration platform hosts the whole crew, written from four cycles of doing it.
- CLI.md — the CLI reference: every verb's synopsis, options, what it reads and writes, refusal codes and exit status. Read it before the SPEC if you are running the verbs.
- Working offline — which verbs run with no network, how the rest refuse, and the recipe for work begun offline.
- SPEC.md — the protocol itself: topology, state model, configuration, verbs, roles, gates.
- Founding decisions and the per-milestone records in milestones/ — the "why", as it was recorded.
- GSD vs. "just let the model orchestrate" — the essay that started the project: one person's experience with GSD across several projects, kept as the motivation, not a verdict on GSD.
Three parts¶
CodeCrew is a lightweight framework for agent-driven software delivery: the auditability and reproducible discipline of heavyweight frameworks, without the ceremony. Project state lives in the tools teams already use — GitHub issues, PRs, and CI — and the only documents the framework produces are per-milestone records of the decisions that shaped the system and why.
- A protocol (SPEC.md) — conventions for representing milestones, tasks, plans, decisions, deviations, and gates in GitHub, and how agents and humans transact over them.
- Role contracts (.codecrew/roles/) —
harness-neutral prompt files for the implementer, reviewer, qa, and
doc-synthesizer roles, and for the coordinator that dispatches them,
loadable by any agent (Claude Code, Codex, Gemini CLI, or an
orchestrator's company).
A project extends a contract without forking it in
.codecrew/roles/<role>.local.md(SPEC §7). - A CLI —
codecrew, a single static Go binary wrappinggh, providing the workflow verbs with gates enforced as code.
What exists¶
Shipped: v2.1.1 of the gh extension, implementing protocol 2.1
(version prints both: v2.1.1 (protocol 2.1); the pointer's protocol
major is checked, another major refuses, and a pointer naming an earlier
minor such as "2.0" is current; gh itself must be 2.50.0 or later, or
the CLI refuses GH_TOO_OLD before any verb runs). Verbs:
init, migrate, status, milestone new/evidence/close/strike,
task new/start/finish, checkpoint,
role, roles diff/show/sync, identity new/token/webhook, and version — all implemented,
with machine-readable refusals (refused[CODE]: detail, catalogued below)
when a gate blocks. What each verb takes, what it reads and writes, which
codes it can refuse with and what --dry-run does where it has one is
CLI.md, a section per verb. milestone new, task finish,
milestone close, milestone strike, migrate and roles sync take
--dry-run, which shows what the verb would do and writes nothing.
Protocol 2.1 adds three things to the 2.0 lifecycle. A requirement can be
struck by a recorded decision of the coordination layer
(milestone strike), and milestone close counts a struck requirement as
terminal, as it does a QA satisfied. A change with no decision in it — a
tool's output, such as a contract sync or a dependency bump — is
housekeeping and takes a light path: a reviewed chore: pull request
with no task, milestone or verdict; the milestone record takes the same
path. And roles sync brings a hub's contracts, and any repo's
.codecrew/AGENTS.md, up to the release's text where they are absent or an
earlier release's, refusing a fork rather than overwriting it. What changed
and when:
CHANGELOG.md. Not yet here: any backend other than GitHub,
and GitHub Enterprise Server — github.com only.
Who holds a seat. Every role is always staffed, by exactly one of four
kinds of principal, named by the routing table's type prefix: the operator
themselves (identity: ~), a named human (user:<login>), a GitHub team
(team:<org>/<slug> — any member holds the role), or a GitHub App identity
(app:<slug>). Solo is a routing
configuration, not a degraded tier: the qa holder's verdicts are the ones
that count at close, and the reviewer holder's approving review is the one
task finish requires. A solo operator therefore needs nothing but gh auth
login; gh codecrew init scaffolds a project with every role routed to ~.
When a project outgrows solo, identity new <role> mints a dedicated App
identity through the manifest flow and routes it for you — minted with
--with-approval-permission, a reviewer App's approvals count toward
GitHub's own required-review rules, which makes fully agent-gated merges
possible (identities.md).
The routing table. Who holds which seat is one roles: table in the hub's
.codecrew/config.yml: a row per seat, naming the typed identity that holds
it and the harness and model it is dispatched under, with ~ where the
operator holds it. Two
worked examples are one click away — this repository's own table, as it stands
today, in the README, and an annotated
generic one on the home page. SPEC §5 is
the field-by-field reference.
How a repo joins. Every repo in a CodeCrew project carries a
.codecrew/config.yml pointing at the hub — a spoke's is a two-line pointer
(init --hub owner/repo); this repo is its own hub (hub: self; SPEC §3
on choosing yours). The hub's config also routes the five roles — the four
crew seats and the coordinator, which unrouted is you — and init writes
that table for you. Every repo also carries the entry point — the
instructions in .codecrew/AGENTS.md, a root
AGENTS.md pointing at them and a CLAUDE.md importing that
— so an agent dispatched into a spoke lands the same way it does in the hub. Agent identities are GitHub Apps; a seat's
first act is export GH_TOKEN=$(gh codecrew identity token <slug>), which
mints a short-lived installation token from the platform's env bindings
or the local key and stub and discovers the installation from the App
itself — see identities.md (SPEC §5 for the tiers).
What it has done — the receipts are on the home page; the per-milestone records are in milestones/. The largest environment it has run in — an orchestration platform dispatching all five seats — has its own page: Platform interop.
Install and use¶
gh extension install radiusred/gh-codecrew # precompiled, all platforms
gh codecrew version # confirm what you installed (gh never auto-updates extensions)
gh codecrew init # scaffold a new project (see first-milestone.md)
gh codecrew migrate # a repo still on the 1.x layout: move it to 2.0 (--dry-run first)
gh codecrew status # open milestones, inferred task states, raised gates, notes
gh codecrew role reviewer # who holds a role: app:<slug>, user:<login>, team:<org>/<slug>, or ~ (you)
gh codecrew help # the full verb list
# or build from source (single static binary; requires gh on PATH):
go build -o gh-codecrew ./cmd/codecrew
Projects with external contributors¶
A project that takes issues from outside the crew accumulates community
reports alongside protocol traffic, in one issue list. That is safe by
construction, because the framework reads labels and an unlabelled issue is
invisible to every verb: status lists the hub's cc:milestone issues and
walks their sub-issues, milestone close counts the same set, task start
refuses NOT_A_TASK on an issue that is not labelled cc:task, and
task finish then refuses NOT_OWNER, because nothing recorded a start on
it. A report nobody labelled is a report, however many of them arrive. Three
conventions keep it that way.
No issue template may auto-apply a cc: label. GitHub restricts
labelling to triage permission and above, so a first-time reporter cannot
apply one by hand — but a template's labels: front matter, and an issue
form's labels: key, label the issue on the reporter's behalf whatever
their permission. That is the one path by which a read-only user's issue
arrives already wearing a protocol label, and a template naming cc:task
would hand the verbs an issue with no plan, no requirement IDs and no
milestone above it. So: no template under .github/ISSUE_TEMPLATE/ names a
cc: label, in front matter or in a form key. It is a convention a
project's template review holds to and not a gate — the CLI never reads
.github/ISSUE_TEMPLATE/, and nothing refuses over one.
A community report is adopted, never converted. When the project takes
one up, it becomes work the way any backlog capture does: a task, opened
with gh codecrew task new --milestone <n> --adopts <ref>, which lists the
report under the task's ## Adopts section and comments on the report
naming the task. The report itself is left exactly as filed — not relabelled
cc:task, not rewritten into the task template, not edited to carry a plan.
task finish closes it after the merge with a comment naming the task, the
pull request and the commit the merge left, so no pull request body has to
remember a closing keyword for it
(#193). Converting in
place loses on both counts: the report is the reporter's account of a
problem, and the trail is worth more showing what was asked for and what was
built as two linked objects than as one issue the maintainer overwrote — and
a report relabelled cc:task is an issue the verbs will now pick up, where
the good case is task start refusing it for having no plan and the bad one
is a plan pasted over the reporter's words.
SPEC §4 has the adoption grammar, and
the coordinator contract the rule as a
coordinator meets it.
Reverting a cc: label applied below maintain is deferred. A project
that grew enough triage-level helpers to worry about the protocol labels
being misapplied could add a workflow on the labeled event that reads the
actor's permission, removes any cc: label applied by an actor below
maintain who is not one of the routing table's role Apps, and comments to
say why. Nothing here ships it: no protocol behaviour depends on it,
GitHub's triage floor already keeps reporters out, and it would cost a
workflow run on every label event in the repository — build it when a
project has the helpers that make the misuse real, not before.
Refusal codes¶
A blocked gate exits 1 — every failure does, and there is no exit-code taxonomy — with one line on stderr:
The code is for the agent: a fixed vocabulary whose meanings are stable
within a protocol major, so an orchestrator branches on it. The detail
is for the human, and is free to be reworded in any release; nothing should
parse it. A note: line is advisory and not a failure, and most are not on
that stream: they go to stdout beside the report they qualify, and
CLI.md's Output channels names the few on
stderr.
The catalogue is SPEC §10 — every code, the
verbs that raise it and what it means, in one table. It is the single list:
this page carried a second one until protocol 2.0, and keeping two in step
across a milestone's worth of new codes proved to be exactly the drift the
table exists to prevent. The source of record behind both is refuse("CODE"
in internal/cli/, and a test fails the build when the table and the source
disagree. The other direction — which codes a given verb can exit with — is
that verb's section in CLI.md, and a test fails the build when
those two disagree too.
The fix for a refusal is in the detail line the CLI prints, which names the
condition met and the way out — read it before reaching for a code table.
Your first milestone walks through the ones a new
project meets first: NO_PLAN, NO_CHECKS, VERDICT_MISSING,
DOC_MISSING.
NO_CHECKS is about facts, not effort: a check that reports skipping
satisfies the gate, so a docs-only pull request can be cheap — see the
self-gating workflow.
[skip ci] produces no check at all, and absence is refused.
Licensed under Apache 2.0.