Skip to content

CodeCrew CLI reference

Every gh codecrew verb: what it takes, what it reads, what it writes, what it prints, what it refuses, and what it exits with. The protocol these verbs implement is SPEC.md; the refusal-code catalogue is SPEC §10, which every code below links to.

Every verb is safe to run by any role from any repo in the project: the pointer file resolves the hub.

Invocation

gh codecrew <verb> [<argument>…] [<option>…]

Installed as a gh extension the command is gh codecrew; the binary built from source takes the same arguments without the gh prefix. gh 2.50.0 or later must be on PATH.

--help or -h anywhere in the arguments prints the verb list on stderr and exits 0, before the verb runs. gh codecrew help prints the same list on stdout. --version and -v are version. An unknown verb or subcommand prints the verb list on stderr and exits 1.

An issue reference — the <ref> argument of task start, task finish and checkpoint — is N, #N or owner/repo#N; a bare number resolves against the repository the verb runs in. A milestone number is <n>, and milestone close also accepts M<n>. Where a verb takes options as well as a leading argument, the argument may be given before or after them; roles diff and roles show want the role name first, roles sync takes its role names and --dry-run in any order, and task start and milestone evidence take their argument and nothing else.

Exit status

0 when the verb did what it was asked, 1 on every failure — a refused gate, an unusable flag, an unreachable GitHub, a gh that failed. There is no exit-code taxonomy: 1 says only "this did not happen". --dry-run follows the same rule and exits 1 when it reports a gate that would refuse.

Output channels

stdout carries everything a verb prints as it works: what a caller consumes — a minted token, role <name>'s identity — and the report or receipt, with the note: and warning: lines that qualify it. A note: is advisory and never a failure: it stands beside a verb that goes on to succeed. Each verb's own section says which lines it writes.

stderr carries the rest. The refusal line, once, as the verb exits 1:

codecrew: refused[CODE]: detail

The code is a fixed vocabulary, catalogued in SPEC §10; the detail is prose for a human and may be reworded in any release. A failure that is not a gate — an unknown verb or subcommand, a missing argument, a flag the verb does not define — ends on the same codecrew: prefix with no refused[...], and exits 1 too: after the verb list for a verb or subcommand it does not know, and after the flag set's own diagnostic and usage for most verbs' bad flags (identity webhook prints that diagnostic and usage on stdout; only its last line is on stderr). --help and -h print the verb list on stderr and exit 0. The note: lines raised while the pointer is read — a pointer, or a hub's pointer, carrying no codecrew: version, and a gh whose version could not be read — which precede anything the verb itself prints. And identity token's receipt, with its note that an --installation hint is stale, which are on stderr so that stdout carries the token alone.

Under --dry-run the gate lines and the plan are stdout; a dry run that ends in a refusal prints that one line on stderr like any other.

Common refusals

Every verb that loads and validates the working repo's .codecrew/config.yml can raise these, before its own work begins. The verbs that neither require nor validate a pointer, and so raise none of these, are version, help, init, migrate, identity token and identity webhook; init and migrate raise the layout codes themselves, and identity token reads a pointer only when one is there, to prefer the hub's owner.

Code Condition
LAYOUT_LEGACY The repo is still on the protocol 1.x layout: a root .codecrew.yml, or a root roles/ holding one of the five contracts, with no .codecrew/config.yml. The detail names what was found and gh codecrew migrate.
PROTOCOL_MISMATCH The pointer's protocol major differs from the one this binary implements — the local pointer, or the hub's on a spoke's fetch.
IDENTITY_UNTYPED A routing row's identity carries no type prefix; the detail names the row and the four forms.
SPOKE_ROUTING A spoke's pointer carries a roles: block; the hub carries the one routing table.
HUB_UNREADABLE In a spoke: the hub's pointer could not be fetched or parsed, so no role resolves. Routing fails closed.
GH_TOO_OLD The installed gh is below 2.50.0, checked once, up front.
GH_UNREACHABLE gh never reached GitHub — no route, no DNS, no credentials. Never folded into another condition.

A hub reads its own pointer from disk and resolves roles with no network. version, help, and roles show / roles diff / roles sync in a hub need no network at all.

gh codecrew init

gh codecrew init [--hub owner/repo]

Scaffolds a repository into a CodeCrew project and creates the protocol's labels. Hub mode — the default — writes the pointer with the full ~-routed roles table, a ROADMAP.md seed, the role contracts embedded in the installed release under .codecrew/roles/, and a blank .codecrew/roles/<role>.local.md extension beside each. Spoke mode writes the pointer alone of those. Both modes write the entry point, .codecrew/AGENTS.md, and the two root files that reach it: an AGENTS.md naming the path and importing it, and a CLAUDE.md importing AGENTS.md. Existing files are kept and reported. It then commits exactly the files it wrote and ensures the three cc: labels exist. Rerunning it writes no file it already wrote, commits nothing when it wrote nothing, and creates no label it already created.

Options

Option Argument Default Effect
--hub owner/repo, or self self Spoke mode: the pointer names that hub and nothing else is scaffolded. self is hub mode.

Reads. The working directory, which must be the repository root; the repository's default branch and its pull-request requirement, through gh; the repository's existing labels.

Writes. .codecrew/config.yml, .codecrew/AGENTS.md, AGENTS.md, CLAUDE.md, and in hub mode ROADMAP.md, .codecrew/roles/<role>.md and .codecrew/roles/<role>.local.md — each only when it is absent. One commit of exactly those paths, on the current branch, or on codecrew-bootstrap cut from the default branch when the default branch requires pull requests; it never pushes. The commit is housekeeping, and its body names the tool that defined it, as SPEC §4 requires — the invocation (--hub only in spoke mode), the release gh codecrew version prints (dev on a source build), the protocol the binary implements, each file written, and the trailer. No line passes 100 characters: the tool line wraps at a space, and an owner/repo too long for a line of its own — GitHub allows 140 characters — is split just after the slash, the repository name continuing on the next line:

chore: scaffold codecrew

Scaffolded by gh codecrew init --hub myorg/platform (gh-codecrew v2.1.1, protocol 2.1):
.codecrew/AGENTS.md
.codecrew/config.yml
AGENTS.md
CLAUDE.md
Housekeeping (SPEC §4); no task.

Past 20 files the list is a count. Outside a git repository nothing is committed: init prints the git init, git commit and gh repo create to run, the commit carrying the same body as a second, single-quoted -m; so does every note: that leaves a commit to make by hand. In GitHub: the missing cc:task, cc:milestone and cc:needs-decision labels, with the protocol's colour and description; an existing label is left exactly as it is. Everything it prints as it works is on stdout: a line per file written or kept, the commit, a line per label, each note:, the next: lines, and last an action needed block naming any kept root entry point that does not reach .codecrew/AGENTS.md, with the lines to add to it. It reads no pointer, so no pointer note reaches stderr; a refusal, or a bad flag's diagnostic and usage, does (Output channels).

Before the first task. The next: lines say where the project goes from here — in hub mode, that every seat is routed to the operator and the milestone new to run; in spoke mode, the hub its tasks attach to — and, in both modes, the one requirement nothing init writes can meet: task finish requires at least one check reporting on every pull request and refuses NO_CHECKS without one (SPEC §8: the gate cannot be satisfied by absence), so a repository without a workflow on pull_request adds one before its first task. init writes no workflow and reads none, so the lines are printed whatever the repository holds; task new and task start say it again, as a note:, while the repository still has none.

Refusals. LAYOUT_LEGACY — the repo is on the 1.x layout; gh codecrew migrate moves it. A directory that is not the repository root, and a scaffold that cannot be written, exit 1 without a code. A label step that cannot reach GitHub is a note:, not a refusal, and the scaffold stands; so is a directory that is not yet a git repository, and the labels arrive on the rerun once it is one.

Exit status. 0 when the scaffold is complete, including a rerun that writes nothing; 1 on a refusal or an unusable argument.

gh codecrew init                              # this repo is the hub
gh codecrew init --hub myorg/platform         # a spoke pointing at that hub

gh codecrew migrate

gh codecrew migrate [--dry-run]

Moves a repository from the protocol 1.x layout to 2.0. git mv takes .codecrew.yml to .codecrew/config.yml and, out of a root roles/, the five role contracts and their <role>.local.md extensions into .codecrew/roles/, removing the emptied directory. The pointer is then rewritten in place: codecrew: "2.1", the protocol the binary implements; a coordinator row when the table declares none; and every identity typed by asking GitHub what each bare 1.0 login is. Comments, blank lines and key order are kept. It writes .codecrew/AGENTS.md when the repo has none, and does for the root AGENTS.md and CLAUDE.md what init does. Every refusal is raised before anything is written. A repo already on the 2.0 layout says so, moves nothing and commits nothing — a pointer naming an earlier minor, such as "2.0", is current and left as it is (SPEC §5) — and the label step still runs.

Options

Option Argument Default Effect
--dry-run none off Prints every file step and every label creation and restyle; writes nothing.

Reads. The working directory, which must be the repository root of a git repository; .codecrew.yml; a root roles/, and only when it already holds one of the ten CodeCrew names; GitHub, for the account behind each bare 1.0 identity (users/<login>, then users/<login>[bot]).

Writes. The moved and rewritten files above, in one commit of exactly those paths on the current branch; it never pushes. The commit's subject is chore: migrate codecrew to the 2.0 layout, and its body, in the shape init writes (SPEC §4), names the tool and lists each move and each file written:

Migrated by gh codecrew migrate (gh-codecrew v2.1.1, protocol 2.1):
.codecrew.yml -> .codecrew/config.yml, rewritten
roles/qa.md -> .codecrew/roles/qa.md
.codecrew/AGENTS.md
Housekeeping (SPEC §4); no task.

With a detached HEAD the files move and a note: prints that commit, body included, to make by hand. In GitHub: the missing cc: labels created, and the existing ones restyled to the protocol's colour and description, each reported; every other label untouched. Everything it prints as it works is on stdout: a line per step, each note:, and last an action needed block for a kept root entry point that does not reach the instructions. It reads no pointer, so no pointer note reaches stderr; a refusal, or a bad flag's diagnostic and usage, does (Output channels).

--dry-run. The same steps in the same order, the same refusals, and the same label lines; nothing written.

Refusals. BOTH_LAYOUTS — the 1.x and 2.0 layouts overlap. FOREIGN_ROLES_DIR — a CodeCrew-owned root roles/ holds an entry outside the ten names. MIGRATION_UNSUPPORTED — the pointer's protocol major is not 1. SPOKE_ROUTING — a 1.x spoke's pointer carries a roles: block. IDENTITY_UNRESOLVED — a bare identity answers to nothing, to both a user and an App, or to an organization. GH_UNREACHABLE — the lookup could not reach GitHub at all. A directory that is not a git repository, or not its root, exits 1 without a code. A label step that cannot reach GitHub is a note:; the rerun completes it.

Exit status. 0 when the repo is on the 2.0 layout, including a rerun that moves nothing; 1 on a refusal. --dry-run exits with the first refusal it reports.

gh codecrew migrate --dry-run    # every step, nothing written
gh codecrew migrate              # the move, in one local commit

gh codecrew status

gh codecrew status

Reports where the project is: the open milestones and their tasks, each task's inferred state, and every raised gate — on tasks and on milestone issues alike, the latter marked (milestone). A task in progress or in review names its holder, taken from the login in its latest **Started by** record and falling back to the first assignee only when nothing records a start. It then reports the stale task branches of the repository it runs in — every task/<n>-… branch on the remote whose task issue is closed — with the delete-or-keep verdict the next milestone close would give it. With no open milestone it says so in place of the board and the gates. Last, in a hub, a line for every role contract that is not the embedded one: contract missing: for a contract the release carries and the hub does not, and contract drift: for one that differs — naming roles sync when the local file is absent or an earlier release's text, which that verb writes, and roles diff <role> when it is a fork. A spoke holds no contracts and prints none of these. In hub and spoke alike, one line for .codecrew/AGENTS.md when it is not the embedded scaffold: agents file missing: or agents file drift:, naming roles sync for an absent file or a release's scaffold and roles diff .codecrew/AGENTS.md for the project's own.

Under each milestone it prints struck: <ID> — decision <link> for every requirement struck by a recorded Decision, read and verified exactly as milestone close counts strikes; a note: for a struck or reinstated line whose link does not verify, naming DECISION_UNRECORDED; and a note: for a bold ID struck through in the body with no strike behind it, which is still a requirement.

Options. None.

Reads. The pointer and, from a spoke, the hub's; the hub's open milestones, their sub-issues, labels and comments, and the comments a strike links to; the running repository's remote task/<n>-… branches and one issue per branch; the repository's delete-branch-on-merge setting; in a hub, the local .codecrew/roles/ contracts, for the contract lines.

Writes. Nothing. The report and every note: line it carries — the delete-on-merge setting, the contract lines, a branch listing it could not read or could not finish — go to stdout.

Refusals. The common ones. Nothing in the report refuses: an ID that is not the milestone's own prints as a line and the report carries on, a branch whose task cannot be read is a note: and is left, a listing that held more than one page says it is partial, and a repository that could not be read at all replaces the branch report with a note: — the report's silence means clean and nothing else.

Exit status. 0 when the report printed; 1 on a common refusal.

gh codecrew status

gh codecrew milestone new

gh codecrew milestone new --title T [--goal G]
                          [--requirement R]...
                          [--dry-run]

Creates a milestone tracking issue in the hub from the template, labelled cc:milestone and titled M<n>: <title>. Each --requirement becomes a bold-ID line under ## Requirements, numbered M<n>-R1, R2, … in the order given — the section the close gate reads. The number n is derived twice: before creating, as one past the highest M<k>: title across the hub's label-filtered milestone listing and its newest unfiltered issues; and after creating, when both listings are read again and the number must be the new issue's alone. Another issue already carrying the prefix has the new issue renumbered to the next free number, title and M<n>-R<k> IDs, printed as a renumbered: line.

Options

Option Argument Default Effect
--title text none; required The milestone's title. A title carrying an M<k> prefix that disagrees with the derived number is refused; one that agrees is stripped.
--goal text _To be written._ The ## Goal paragraph.
--requirement text none One requirement, repeatable. The CLI numbers them; text that brings its own ID is refused.
--dry-run none off Prints the number, title and requirement IDs the milestone would get; creates nothing.

Reads. The pointer and, from a spoke, the hub's; the hub's milestone listing and its newest issues.

Writes. One issue in the hub, labelled cc:milestone. No file: the milestone's ROADMAP.md row is added, Done, by its document PR. On stdout: the issue reference, the title, the requirement IDs counted, any renumbered: line, and a note: when the requirements section it wrote yields no bold ID.

--dry-run. The number, title and requirement IDs; no issue.

Refusals. MILESTONE_NUMBER_TAKEN — the issue was created and another milestone holds its M<n>: prefix, and the renumbering did not settle it; the detail names both issues and the hand fix. A missing --title, a title whose own M<k> prefix disagrees, and a --requirement carrying an ID exit 1 without a code. Plus the common refusals.

Exit status. 0 when the issue exists as described; 1 otherwise.

gh codecrew milestone new --title "Greeting service" --dry-run
gh codecrew milestone new --title "Greeting service" --goal "…" \
  --requirement "visiting the app's URL returns a greeting" \
  --requirement "the greeting is configurable"

gh codecrew milestone close

gh codecrew milestone close <milestone number>
                            [--dry-run]

Closes a milestone once every gate passes, then sweeps the task branches it leaves behind. The gates, in order: the milestone issue carries no cc:needs-decision; every task under it is closed; its ## Requirements section declares at least one bold requirement ID; every ID it declares is the milestone's own; every requirement's latest QA verdict is satisfied — only verdicts from the qa role's holder count, and the latest comment carrying a verdict for an ID wins — unless the requirement is struck; and the milestone document is on the default branch. A requirement struck by a recorded Decision (milestone strike) is terminal and wants no verdict: only the coordinator seat's holder's struck and reinstated lines count, the latest per ID winning, and each one's decision link is verified again, so a line posted by hand is held to the verb's own check. The closing comment names the struck IDs. It then deletes each task branch whose PR merged and which still sits at the merged commit, or which has no open PR and carries nothing beyond the default branch, reporting every branch it keeps and why. A second pass reaches the branches earlier closes left behind, across the hub and every repo the milestone's tasks name, and names them in the closing comment under Swept from earlier closes:. It gathers the milestone's Decision and Deviation comments — the milestone issue's own, its tasks' and their PRs' — as raw material for the doc-synthesizer.

Options

Option Argument Default Effect
--dry-run none off Prints every gate in order with its outcome, then every branch either sweep would delete or keep and why, then the closing comment; writes nothing; exits with the first refusal's code.

Reads. The pointer and, from a spoke, the hub's; the milestone issue, its sub-issues, their labels and comments; docs/milestones/<n>-*.md on the hub's default branch; the task/<n>-… branches of the hub and of every repo the tasks name, and the pull requests whose head each candidate branch is.

Writes. In GitHub: the closing comment on the milestone issue, the issue closed, and the branches the two sweeps delete. Nothing on disk. The report, the gate lines and the sweep's note: lines all go to stdout.

--dry-run. The same gates in the same order, the same sweep verdicts and the same closing comment; nothing written.

Refusals. NOT_FOUND — no open milestone with that number. MILESTONE_GATED — the milestone issue carries cc:needs-decision. OPEN_TASKS — tasks under it are still open. NO_REQUIREMENTS — the ## Requirements section declares no bold ID. REQUIREMENT_ID_MISMATCH — an ID declared there is not the milestone's own; the grammar is M<milestone>-R<k>. DECISION_UNRECORDED — a counted struck or reinstated line's link does not verify; checked before the verdicts. VERDICT_MISSING — a requirement that is not struck has no QA verdict from the qa seat's holder. VERDICT_UNSATISFIED — the latest verdict on a requirement is not satisfied. DOC_MISSING — no docs/milestones/<n>-*.md on the default branch; the doc-synthesizer delivers it as a housekeeping PR with no task (SPEC §4), and the gate checks that it is there, not how it arrived. Plus the common refusals. Nothing in the sweep refuses: a branch the verb could not read is a note: and is left standing, and a repo carrying more task branches than one listing holds is swept in part and says so.

Exit status. 0 when the milestone is closed; 1 on the first refusal, whose code it exits with under --dry-run too.

gh codecrew milestone close 4 --dry-run
gh codecrew milestone close 4

gh codecrew milestone strike

gh codecrew milestone strike <milestone number> <ID>
                             --decision <comment URL>
                             [--reinstate]
                             [--dry-run]

Strikes a requirement from the milestone's scope by a recorded Decision (SPEC §4): posts **<ID> — struck.** <comment URL> as a comment on the milestone issue. It never edits the body. Striking is the coordination layer's scope change, not QA's. The gates, in order: the milestone is open; the ID, written in full (M4-R2), is declared under its ## Requirements; and the decision link is an issue-comment URL on the milestone issue or one of its tasks whose comment carries a **Decision:** or **Gate resolved:** record naming the ID. The verb checks the record, not the actor, but milestone close counts only the coordinator seat's holder's lines, so a caller who does not hold that seat gets a note: saying so, and the line is posted anyway. An ID already struck posts nothing and says so, so a repeated run is a no-op.

Options

Option Argument Default Effect
--decision URL none; required The Decision comment: https://github.com/<owner>/<repo>/issues/<n>#issuecomment-<id>, on the milestone issue or one of its tasks, naming the ID.
--reinstate none off Posts **<ID> — reinstated.** <comment URL> instead, under the same checks: the requirement is back in scope and QA verdicts count again. Posts nothing when the ID is not struck.
--dry-run none off Prints every gate and the line it would post; writes nothing; exits with the first refusal's code.

Reads. The pointer and, from a spoke, the hub's; the hub's open milestones and their sub-issues; the milestone issue's body and comments; the comments of the issue the decision link names; the caller's login.

Writes. One comment on the milestone issue, unless the ID is already in the state asked for. Nothing on disk. On stdout: the line and the issue it was posted on, or why nothing was posted, and the note: for a caller who does not hold the coordinator seat.

--dry-run. The same gates in the same order and the line; nothing written.

Refusals. NOT_FOUND — no open milestone with that number. REQUIREMENT_UNDECLARED — the ID is not declared under that milestone's ## Requirements. DECISION_UNRECORDED — the link is not an issue-comment URL, names an issue that is neither the milestone nor one of its tasks, names no comment there, or names a comment with no Decision naming the ID. A missing --decision, an ID not written in full, or a missing argument exits 1 without a code. Plus the common refusals.

Exit status. 0 when the line is posted or there was nothing to post; 1 otherwise, and on the first refusal under --dry-run too.

gh codecrew milestone strike 4 M4-R2 --decision https://github.com/acme/hub/issues/40#issuecomment-123 --dry-run
gh codecrew milestone strike 4 M4-R2 --decision https://github.com/acme/hub/issues/40#issuecomment-123

gh codecrew milestone evidence

gh codecrew milestone evidence <milestone number>

Walks the milestone's record — the tracking issue and every sub-issue, bodies and comments — and verifies that every citation resolves. A citation is a URL in prose or in a Markdown link outside code; a URL inside an inline code span, a fenced block, or a block indented four columns where it does not continue a paragraph is content and is not checked. It checks the milestone's own requirement-ID grammar before the walk. The milestone resolves whatever its state: a closed one resolves too and is reported as closed before the citation report.

A github.com citation resolves through the REST API under the caller's auth, private repositories included, when its shape is one of these (a query such as ?pr=12 is ignored, and so is a fragment the list does not name):

Cited page Resolved as
{o}/{r} — the repository repos/{o}/{r}
issues/{n}, pull/{n} and its tabs repos/{o}/{r}/issues/{n}
…#issuecomment-{id} on an issue or a pull request repos/{o}/{r}/issues/comments/{id}
pull/{n}#pullrequestreview-{id} repos/{o}/{r}/pulls/{n}/reviews/{id}
pull/{n}#discussion_r{id}, pull/{n}/files#r{id} repos/{o}/{r}/pulls/comments/{id}
commit/{sha}, pull/{n}/commits/{sha}, commits/{ref}, tree/{ref} repos/{o}/{r}/commits/{sha or ref}
blob/{ref}/{path}, tree/{ref}/{path} repos/{o}/{r}/contents/{path}?ref={ref}
compare/{base}...{head} repos/{o}/{r}/compare/{base}...{head}
releases, releases/latest, releases/tag/{tag} repos/{o}/{r}/releases, …/latest, …/tags/{tag}
actions/runs/{run}, …/attempts/{n} repos/{o}/{r}/actions/runs/{run}, …/attempts/{n}
actions/runs/{run}/job/{job} repos/{o}/{r}/actions/jobs/{job}
actions/workflows/{file} repos/{o}/{r}/actions/workflows/{file}
milestone/{n} repos/{o}/{r}/milestones/{n}

Any other github.com citation under a repository the API reads is fetched by HTTP when the repository is public. When it is private, an anonymous fetch answers 404 whatever the page holds, so the verb cannot check it: it prints a warning: naming the path shape (/wiki, say) and does not refuse. A github.com page under no repository the API reads — an App, a user — and every other host are fetched by HTTP.

Options. None.

Reads. The pointer and, from a spoke, the hub's; the hub's milestone listing in every state; the milestone issue and its sub-issues, bodies and comments; each cited URL.

Writes. Nothing. The report goes to stdout, including the note: that says the milestone is closed, a warning: line per unresolved external citation, and a warning: line per github.com citation in a private repository whose shape the API cannot resolve.

Refusals. NOT_FOUND — no milestone carries that number, open or closed. REQUIREMENT_ID_MISMATCH — an ID under ## Requirements is not the milestone's own, checked before the walk. EVIDENCE_UNREACHABLE — a github.com citation does not resolve: the API cannot find what a mapped shape names, or a public repository's page answers an error. An external citation that does not resolve, and a private one the verb cannot verify, print a warning: and do not block. Plus the common refusals.

Exit status. 0 when no github.com citation failed to resolve — every one resolved, or warned as unverifiable; 1 when one did not, or on any other refusal.

gh codecrew milestone evidence 4

gh codecrew task new

gh codecrew task new --milestone N --title T
                     [--repo owner/repo] [--goal G] [--requirements IDs]
                     [--adopts <ref>[,<ref>]]

Creates a task issue from the template, labelled cc:task, in the spoke named by --repo or in the current repository, and attaches it to the milestone as a sub-issue. --adopts names the backlog captures the task takes up: they are written under an ## Adopts section of the body, each capture is commented on to say this task carries it, and task finish closes them after the merge. Every adopted ref must be an open issue and is checked before anything is created, so a refusal leaves no half-adopted task; duplicates collapse. The milestone resolves by number from the hub's open-milestone listing, then from the hub's newest issues regardless of label, then again after a short wait — three reads in all, and a milestone found by either fallback is named in the output.

Options

Option Argument Default Effect
--milestone number none; required The milestone the task links into.
--title text none; required The task's title.
--repo owner/repo the current repository The spoke the task issue is created in.
--goal text _To be written._ The ## Goal paragraph.
--requirements comma-separated IDs None directly. The ## Requirements line: the milestone requirement IDs this task serves.
--adopts <ref>[,<ref>] none A backlog issue this task adopts and task finish closes; repeatable, and each value may be a comma-separated list. A bare number resolves against the task's own repo.

Reads. The pointer and, from a spoke, the hub's; the hub's milestone listing and newest issues; each adopted issue's state; and, once the task exists, the target repository's Actions workflows (GET /repos/{owner}/{repo}/actions/workflows) and the file of each active one under .github/workflows/, from the default branch.

Writes. In GitHub: one issue in the target repo labelled cc:task, linked to the milestone as a sub-issue, and one comment on each adopted capture. Nothing on disk. On stdout: the issue reference, the adoptions recorded, a note: for a comment that could not be posted or a milestone found by one of the fallback reads, and the workflow note below.

The workflow note. When the target repository — --repo, or the current one — has no workflow triggered on pull_request, one note: says that task finish will refuse NO_CHECKS until a check reports on the task's pull request, and to add a workflow that runs on pull_request, on the task's branch or before it, and let it report. No workflow at all counts, and so does a set of workflows none of which names pull_request in its on: — as one event, in a list, or as a key of the map; pull_request_target is a different event and does not count, nor does a disabled workflow, nor a GitHub-managed one with no file in the repository. The note is advisory: no refusal, no change to the exit status. Where the listing cannot be read (403, 404) or a workflow file cannot be read or parsed, it says nothing.

Refusals. NOT_FOUND — no open milestone with that number, after all three reads. ADOPT_NOT_OPEN — an adopted ref could not be read, or is already closed; checked before the task is created. GH_UNREACHABLE — GitHub could not be reached. Plus the common refusals. A comment on a capture that fails once the task exists is a note:; the body carries the link either way.

Exit status. 0 when the task issue exists and is linked; 1 otherwise.

gh codecrew task new --milestone 4 --title "Serve the greeting" \
  --requirements M4-R1 --adopts 31

gh codecrew task start

gh codecrew task start <ref>

Starts a task: it verifies that the issue is an open cc:task whose ## Plan section is not empty, posts the **Started by** @<login>. record that makes the caller the task's owner — the record task finish holds to — assigns the caller when the routing table types them as a human, and creates the linked development branch task/<n>-<slug>. An app:-typed caller, and any login carrying the [bot] suffix, is not assigned: GitHub does not accept a GitHub App as an issue assignee, and the record is the fact. A caller whose role routing resolves to a contract that forbids commits — qa, reviewer — gets no branch. Where it creates the branch, it also reads the branch policy the task's pull request will meet: each status check a ruleset in force on the default branch requires, and that no check run or commit status has reported on the newest pull requests into that branch, is named in a note: saying no workflow in the repository reports it, so the merge will block or rely on a bypass until one does. The note is advisory and changes nothing; where the rules cannot be read — a plan without rulesets answers 404 or 403 — or there is no pull request yet to compare with, it says nothing. Beside it, the same workflow note as task new: when the task's repository has no workflow triggered on pull_request, one note: that task finish will refuse NO_CHECKS until a check reports on the task's pull request, and to add a workflow that runs on pull_request and let it report — silent when any read fails, and no refusal either way.

Options. None.

Reads. The pointer and, from a spoke, the hub's routing table; the task issue, its labels, its body's ## Plan section; the caller's login; and, where it creates the branch, the repository's default branch, the rules in force on it (GET /repos/{owner}/{repo}/rules/branches/{branch}) and, when they require status checks, the check runs and commit statuses on the heads of the three newest pull requests into it; and the repository's Actions workflows (GET /repos/{owner}/{repo}/actions/workflows) with the file of each active one under .github/workflows/, from the default branch.

Writes. In GitHub: the **Started by** comment on the task issue, the assignment where the caller is human, and the linked branch. Nothing on disk — the branch is created on the remote, and the printed line names the git fetch && git switch that brings it local. On stdout: the branch created, the local command, the start record, a note: for an assignment or a branch creation that failed, a note: for each required status check nothing has reported, and the workflow note.

Refusals. CLOSED — the task issue is already closed. NOT_A_TASK — the issue is not labelled cc:task. NO_PLAN — the task's Plan section is empty. Plus the common refusals. A failed assignment is a note:.

Exit status. 0 when the record is posted; 1 on a refusal.

gh codecrew task start 12
gh codecrew task start myorg/service#12

gh codecrew task finish

gh codecrew task finish <ref> [--operator-confirm]
                        [--bypass]
                        [--dry-run]

The gatekeeper: it checks every gate, merges the closing pull request by rebase, reads the task back to see that GitHub closed it, closes the captures the task adopted, deletes the head branch and tidies the clone it runs in. The gates, in order: the task is open; it carries no cc:needs-decision; every gate raised on it has a **Gate resolved:** answer; the caller is the seat that started it — the login in the latest **Started by** record, the same login with the [bot] suffix ignored, or the same routed seat, a team-held role being any member; a pull request closes the task; its CI checks exist and are green; the reviewer role's holder has approved when that role routes to a distinct principal, and otherwise any non-doer has; and GitHub's own required-review rule counts the approval. The merge is a request GitHub decides: the verb asks GitHub's merge endpoint (PUT /repos/{owner}/{repo}/pulls/{n}/merge, rebase, pinned to the head commit the gates read), so a ruleset bypass the caller holds is honoured, and anything GitHub refuses — a rule the caller cannot bypass, a head that moved after the gates read it — is reported in GitHub's own words and the verb exits 1 with nothing after the merge done. Before the merge it prints a note: naming every issue the pull request's closing references would close besides the task itself; a note: for each status check a ruleset on the base branch requires that nothing has reported on the pull request's head, saying no workflow in the repository reports it, so the merge will block or rely on a bypass until one does; and, when GitHub reports the pull request BLOCKED while every gate passed, a note: that the merge is asked of GitHub as the caller, who GitHub lets through on a ruleset bypass they hold and refuses otherwise, naming the rule types in force when they can be read. Whether the caller holds a bypass is not read — only an administrator can — so the note reports the record rather than predicting the outcome. Where the rules cannot be read — 404 on a plan without rulesets, 403 — or the head's checks cannot, these notes say nothing; none of them is a gate. After the merge it reads the task back rather than assuming its closing keyword closed it: GitHub closes on the keyword asynchronously, and has been seen not to act on one present at merge time (#386). It reads up to four times, two seconds apart — about six seconds of waiting at most — and prints <task> closed as soon as a read finds it closed, or, after the last, note: <task> is still open after the merge: GitHub did not act on the closing reference; close it by hand with a comment naming PR #<n> and <merge sha>. The verb does not close the task itself. It then closes each adopted capture with a comment naming the task, the pull request and the merge commit, and reads each back the same way: closed <capture> (adopted by <task>) once it reads closed, or note: <capture> is still open after the close (adopted by <task>): GitHub did not act on it; close it by hand with a comment naming PR #<n> and <merge sha>. A read that fails every time is a note: saying the issue could not be read back. Then it deletes the head branch, and — in a clone of the task's own repo that holds the merged branch — fetches with prune, switches to the default branch if that branch is checked out, fast-forwards it, and deletes the local task branch. Nothing after the merge refuses.

Options

Option Argument Default Effect
--operator-confirm none off Solo tier: records an explicit operator confirmation on the pull request in place of a non-doer approval. A crew identity is refused.
--bypass none off Merges with the ruleset's administrator bypass when GitHub does not count the recorded approval, recorded as a comment on the pull request. For a human operator the ruleset lists as a bypass actor; a crew identity is refused. The merge is the same request to GitHub's merge endpoint, and GitHub decides eligibility.
--dry-run none off Prints every gate in order — ok, refused with its code, not reached, not applicable — then the comments, merge, adopted captures, head deletion and local cleanup it would perform; writes nothing, the clone included; exits with the first refusal's code.

Reads. The pointer and, from a spoke, the hub's routing table; the task issue, its labels and comments; the pull requests that close it, their checks, reviews, review decision, base branch and merge state; the closing references GitHub parsed from the pull request body; the rules in force on the base branch (GET /repos/{owner}/{repo}/rules/branches/{branch}) and the check runs and commit statuses on the pull request's head; after the merge, the merge commit, and the task and each capture it closed, read back up to four times two seconds apart; the local clone's branches and remotes.

Writes. In GitHub: the operator-confirmation or bypass comment where one applies, the rebase merge through GitHub's merge endpoint — GitHub closes the task on the pull request's closing keyword; the verb writes no close on it — a comment on each adopted capture and that capture closed, and the head branch deleted. On disk, and only in a clone of the task's own repo: a fetch with prune, a switch to the default branch, a fast-forward of it, and the deletion of the local task branch — forced, and allowed only when the branch sits at the merge commit or is contained in the fetched default branch. A branch carrying anything else is named and kept. Run anywhere else, the local half does nothing and prints nothing. Everything it prints as it works is on stdout: the gate lines, the merge, the note: lines before it — the BLOCKED merge, the pull request's other closing references, a required check nothing has reported — the read-back's <task> closed or its still-open note:, and every note: after it.

--dry-run. Every gate and every write above, printed and not performed — the merge as would merge PR #<n> (rebase); <task> closes via its closing keyword, since a dry run cannot observe the close and reads nothing back; the BLOCKED note indented under the bypass actor gate; the same note: lines about the pull request's other closing references and about a required check nothing has reported; the same exit code as the real run's first refusal.

Refusals. CLOSED — the task issue is already closed. GATED — the task carries cc:needs-decision. GATE_UNRECORDED — a gate was raised and the label removed with no **Gate resolved:** comment answering it. NOT_OWNER — the caller is not the seat that started the task, or nothing records a start. NO_PR — no open pull request closes the task. NO_CHECKS_PERMISSION — the caller's installation token cannot read the pull request's checks at all. NO_CHECKS — the pull request reports no checks; a check reporting skipping is a reported check and satisfies the gate, a [skip ci] commit produces none at all, and there is no override. A repository needs a workflow on pull_request before its first task: init says so in its next: lines, and task new and task start in a note: while the repository has none. CHECKS_PENDING — its checks are still running. CHECKS_FAILING — a check failed. NO_HOLDER_REVIEW — the reviewer seat's holder has not approved. NO_NONDOER_APPROVAL — the reviewer seat is operator-held and no non-author has approved. REVIEW_NOT_COUNTED — the protocol's review gate passed and GitHub's own required-review rule has not; the detail names the supported paths. SELF_CONFIRM — --operator-confirm was given by a crew identity. CREW_BYPASS — --bypass was given by a crew identity. Plus the common refusals. A merge GitHub refuses is not a refusal code: the verb prints GitHub's message and exits 1. After the merge nothing refuses: a capture already closed is reported, one that cannot be closed is a note:, and so are a task or capture still open after the read-back and a failed deletion.

Exit status. 0 when the merge happened — a task still open after the read-back is a note:, not a failure, because the merge is done and the output must say so; 1 on the first refusal, whose code --dry-run exits with too, or when GitHub refuses the merge.

gh codecrew task finish 12 --dry-run
gh codecrew task finish 12
gh codecrew task finish 12 --operator-confirm   # solo tier, human operator

gh codecrew checkpoint

gh codecrew checkpoint <ref> --question "..."

Raises a human gate: it posts the question as a comment and applies cc:needs-decision, creating the label with the protocol's colour and description if the repository does not define it yet. The ref is a task, or the milestone issue when the question is about a requirement and no task carries it; the comment and the receipt say which. The gate blocks task finish until a human removes the label and a **Gate resolved:** comment records the answer.

Options

Option Argument Default Effect
--question text none; required The judgment call a human must make. Posted verbatim as the comment.

Reads. The pointer and, from a spoke, the hub's; the referenced issue and the repository's labels.

Writes. In GitHub: the question as a comment on the referenced issue, the cc:needs-decision label created if absent, and the label applied. Nothing on disk. On stdout: the receipt naming the issue and that the gate is raised, and a note: for a label creation that failed.

Refusals. The common ones. A missing --question or <ref> exits 1 without a code. A label creation that fails is a note: and the gate is still raised: applying an unknown label creates it implicitly, and only the colour is lost.

Exit status. 0 when the gate is raised; 1 otherwise.

gh codecrew checkpoint 12 --question "which of the two schemas do we keep?"

gh codecrew role

gh codecrew role <name> [--login]

Prints the typed identity holding a role — app:<slug>, user:<login>, team:<org>/<slug>, or ~ for the operator — on one line. Script-consumable, and correct from a pointer-only spoke, where the hub's routing table is fetched at load. With --login it prints instead the handle GitHub will accept a review request for, and nothing at all for an app: or ~ seat, neither of which can be requested: the emptiness is the caller's whole decision.

Options

Option Argument Default Effect
--login none off Prints the review-requestable handle: the login of a user: seat, <org>/<slug> for a team: seat, and nothing for an app: or ~ seat.

Reads. The pointer and, from a spoke, the hub's routing table.

Writes. Nothing. One line on stdout, or no line at all under --login for an unrequestable seat.

Refusals. The common ones — a hub that cannot be read refuses rather than answering ~. A missing or unknown role name exits 1 without a code.

Exit status. 0 when the role resolved, including the empty --login output; 1 otherwise.

gh codecrew role reviewer            # app:myorg-checker
reviewer=$(gh codecrew role reviewer --login)
[ -n "$reviewer" ] && gh pr create --reviewer "$reviewer"

gh codecrew roles diff

gh codecrew roles diff <role>|.codecrew/AGENTS.md

Shows how the project's .codecrew/roles/<role>.md differs from the contract embedded in the installed CLI — or, given the path .codecrew/AGENTS.md, how that file differs from the scaffold the CLI writes, in a hub or a spoke; its last line says whether it is a release's scaffold, which roles sync rewrites, or the project's own, which it never does. A .codecrew/roles/<role>.local.md extension is never drift. A contract that is still an earlier release's text, unedited, is brought up to date by roles sync; one that differs from every release's text is the project's own fork, and reconciling it is a judgment routed through a task and a pull request, never an overwrite. The diff's last line says which of the two it is.

Options. None.

Reads. The pointer; the local .codecrew/roles/<role>.md (or .codecrew/AGENTS.md); the contract (or scaffold) embedded in the binary, and the table of every release's text it carries.

Writes. Nothing. The diff goes to stdout.

Refusals. The common ones. A role name the CLI does not embed exits 1 without a code.

Exit status. 0 whether or not the contracts differ; 1 on a refusal.

gh codecrew roles diff implementer

gh codecrew roles show

gh codecrew roles show <role> [--latest]

Prints the contract a dispatched session loads: the hub's .codecrew/roles/<role>.md with its local extensions appended in order — the hub's, then the spoke's. With --latest it prints the contract embedded in the installed binary, whole and without extensions.

Options

Option Argument Default Effect
--latest none off Prints the contract embedded in the installed binary instead of the composed one.

Reads. The pointer; in a hub, .codecrew/roles/<role>.md and .codecrew/roles/<role>.local.md from disk; from a spoke, the hub's contract and extension from its default branch through GitHub, and the spoke's own extension from disk.

Writes. Nothing. The contract goes to stdout.

Refusals. GH_UNREACHABLE — from a spoke, the hub's contract could not be fetched. Plus the common refusals. In a hub the verb reads only local files and needs no network.

Exit status. 0 when the contract printed; 1 on a refusal.

gh codecrew roles show implementer
gh codecrew roles show implementer --latest

gh codecrew roles sync

gh codecrew roles sync [<role>...] [--dry-run]
                       [.codecrew/AGENTS.md]

Brings the hub's role contracts, and .codecrew/AGENTS.md in a hub or a spoke, to the ones embedded in the installed CLI, where that needs no judgment. With no arguments it takes everything the repository holds: in a hub every embedded contract and the agents file, in a spoke the agents file alone. A role list selects those contracts and leaves the agents file alone; its path, .codecrew/AGENTS.md, selects it. The agents file is measured against the scaffold init writes and every earlier release's, exactly as a contract is, and is never stamped. Each contract — every embedded role, or the roles named — is read stamp-stripped, with line endings ignored, and is one of four things: the embedded text, kept; absent, written; an earlier release's text, unedited, written; or anything else, a fork, which refuses the whole run before anything is written. A .codecrew/roles/<role>.local.md extension is never read, written or committed. The result is one local commit, never pushed, for a pull request on the housekeeping path (SPEC §4): the tool defined the target, and the commit says so.

A written file keeps its form: one that carried init's provenance stamp, or was absent, is written stamped as init writes it; one kept unstamped, as a hub's own contracts are, stays unstamped.

Options

Option Argument Default Effect
<role> a role name, repeatable every embedded role, and the agents file Limits the run to the roles named, so the others can be synced past a fork; the agents file is not among them. In a spoke there are no roles to name.
.codecrew/AGENTS.md none included when no target is named Adds the agents file to a run that names roles, or is the whole run when named alone.
--dry-run none off Prints every line the run would print, the commit and the branch it would go on; writes nothing.

Reads. The pointer; the hub's .codecrew/roles/<role>.md files and .codecrew/AGENTS.md; the contracts and the scaffold embedded in the binary, and the table of every release's text it carries; the local git repository — its current branch and the default branch as the clone records it (origin/HEAD). No network.

Writes. The files to write, then one commit of exactly those paths with the subject chore: sync codecrew role contracts to <version> — chore: sync the codecrew agents file to <version> when the agents file is all it writes, chore: sync codecrew role contracts and agents file to <version> when it writes both — and a body, in the shape init writes (SPEC §4), naming the run with the targets it was given, the release, the protocol, and each file with what it was:

Written by gh codecrew roles sync qa (gh-codecrew v2.1.1, protocol 2.1):
.codecrew/roles/qa.md: written (was the v2.0.0 text)
Housekeeping (SPEC §4); no task.

Every other staged and unstaged change is left as it was. On the default branch the commit goes on a new codecrew-roles-sync branch cut from it, since the housekeeping path is always a pull request; on any other branch it goes where it is; with a detached HEAD the files are written and a note: prints the commit to make by hand, body included. It never pushes. Everything it prints is on stdout.

--dry-run. The same lines with would write and would keep, the commit and the branch it would go on, and the same refusal; nothing written.

Refusals. CONTRACT_FORKED — a contract among those named is a fork: the detail names each one with its roles diff, and the .local.md mechanism for the project's additions, and a forked agents file beside it. AGENTS_FORKED — no contract is forked but .codecrew/AGENTS.md is the project's own: the detail names its roles diff and, in a hub, how to sync the contracts alone. Plus the common refusals. A role named in a spoke, which holds no contracts, exits 1 without a code; so does a role name the CLI does not embed, a hub outside a git repository, and a codecrew-roles-sync branch left over from an earlier run when it is run on the default branch.

Exit status. 0 when the files were written and committed, or were already current; 1 on a refusal. --dry-run exits 1 when it reports the refusal.

gh codecrew roles sync --dry-run          # what would be written, and where
gh codecrew roles sync                    # hub: the contracts and .codecrew/AGENTS.md;
                                          # spoke: the agents file alone; one local commit
gh codecrew roles sync coordinator qa     # only these, past a fork elsewhere

gh codecrew identity new

gh codecrew identity new <role> --name N
                         [--owner O] [--with-webhook --webhook-url U]
                         [--no-route]
                         [--with-approval-permission]
                         [--events E,E] [--webhook-secret S]

Mints the role's App identity through the GitHub App manifest flow: it builds a manifest carrying the role's minimal permission set, serves a one-click loopback URL for the operator to open, stores the private key GitHub returns, writes the role's routing into the hub's .codecrew/config.yml in typed form (identity: app:<slug>), and prints the steps that remain — installing the App, which is per account, and the optional display polish. Webhooks are off by default.

Options

Option Argument Default Effect
--name App name none; required The App's name — a crew member (myorg-coder), not a role.
--owner account the hub's owner The account that owns the App.
--no-route none off Prints the routing step instead of writing it into the hub's pointer.
--with-webhook none off Subscribes the App to protocol traffic; requires --webhook-url.
--webhook-url URL none The receiver for --with-webhook deliveries.
--with-approval-permission none off Reviewer only: grants contents: write, so the App's approvals satisfy GitHub's required-review rules.
--events comma-separated events pull_request,pull_request_review With --with-webhook: the events to subscribe, validated against the role's permissions.
--webhook-secret secret none With --with-webhook: sets the hook secret to the receiver's as soon as the App exists.

Reads. The pointer and the hub it names; the owner account's type, through GitHub; the manifest conversion GitHub returns at the end of the browser flow.

Writes. On disk: ~/.config/codecrew/<slug>.<date>.private-key.pem and the credential stub ~/.config/codecrew/<slug>.json; the hub's .codecrew/config.yml routing row, uncommitted, unless --no-route. In GitHub: the App itself, and its hook secret when --webhook-secret is given. On stdout: the loopback URL to open, the stored paths, and the numbered steps that remain.

Refusals. The common ones. A missing <role> or --name, a manifest the flags do not make valid, --webhook-secret without --with-webhook, and a browser flow that does not complete within the hour exit 1 without a code.

Exit status. 0 when the App exists and its key is stored; 1 otherwise.

gh codecrew identity new implementer --name myorg-coder
gh codecrew identity new reviewer --name myorg-checker --with-approval-permission

gh codecrew identity webhook

gh codecrew identity webhook <slug> [--show]
                             [--url U] [--secret S|--rotate-secret]

Reads and sets an existing App's own hook, under the App's own key: --show prints the URL, the content type, whether a secret is set and the App's subscribed events; --url and --secret set them; --rotate-secret mints a new secret, sets it and prints it once. An App hook covers every repository its installation sees. Event subscriptions cannot be set after creation — GitHub offers no endpoint — and the verb prints the settings page where they are ticked.

Options

Option Argument Default Effect
--show none off Prints the hook's URL, content type, whether a secret is set, and the subscribed events.
--url URL none Sets the receiver URL.
--secret secret none Sets the hook secret to the receiver's. Never stored, never printed. Exclusive with --rotate-secret.
--rotate-secret none off Generates a new secret, sets it, and prints it once.
--events comma-separated events none Not settable after creation: the verb prints where they change, and what is subscribed now.

Reads. The App's private key and credential stub — the environment bindings first (GITHUB_APP_ID or GITHUB_CLIENT_ID, and GITHUB_PRIVATE_KEY or GITHUB_PEM as PEM text or a path), else ~/.config/codecrew/<slug>; the App's own record and hook configuration from GitHub. It reads no pointer and runs from anywhere.

Writes. In GitHub: the App's hook URL and secret, where those flags are given. Nothing on disk. On stdout: the hook's configuration, and a rotated secret once.

Refusals. NO_CREDENTIALS — nothing to sign with: no App id and key in the environment, and no key and stub under ~/.config/codecrew/. BAD_CREDENTIALS — GitHub rejected the App JWT, or knows no App by the id it was signed as. NO_WEBHOOK — the App was minted without a webhook and GitHub's API cannot create one; the detail names the settings page. --secret with --rotate-secret, and --events, exit 1 without a code.

Exit status. 0 when the hook was printed or set; 1 otherwise.

gh codecrew identity webhook myorg-coder --show
gh codecrew identity webhook myorg-coder --url https://example.test/hook --rotate-secret

gh codecrew identity token

gh codecrew identity token [<slug>]
                           [--installation ID]

Mints a short-lived installation token as the App and prints it alone on stdout, with a receipt on stderr naming the slug, App id, installation and account it minted for. Credentials come from the environment first, under the names platforms bind, and otherwise from the key and stub under ~/.config/codecrew/ for the slug. It signs the App JWT, discovers the installation from the App itself — one installation is taken, several narrow to the hub's owner — and never writes gh's config. The <slug> argument selects the key and stub under ~/.config/codecrew/ and is optional when the environment binds an App id and key. It requires no pointer and runs from anywhere: a pointer in the directory it runs in is read only to prefer the hub's owner, and a missing or broken one is no refusal.

Options

Option Argument Default Effect
--installation id GITHUB_INSTALLATION_ID, else none A hint, used only when the App can see that installation.

Reads. GITHUB_APP_ID or GITHUB_CLIENT_ID, and GITHUB_PRIVATE_KEY or GITHUB_PEM (PEM text or a path), then GITHUB_INSTALLATION_ID; failing those, ~/.config/codecrew/<slug>.json and its private key. GitHub, for the App's installations and the token. The pointer, only to learn the hub's owner for narrowing, and never as a requirement.

Writes. Nothing on disk, and nothing in GitHub beyond the token GitHub mints. The token alone on stdout; the receipt on stderr.

Refusals. NO_CREDENTIALS — no App id and key in the environment, and no key and stub under ~/.config/codecrew/. BAD_CREDENTIALS — GitHub rejected the App JWT, or knows no App by the id it was signed as. NO_INSTALLATION — the App is installed on no account its key can see. INSTALLATION_AMBIGUOUS — the App is installed on several accounts and nothing selects one.

Exit status. 0 when a token was printed; 1 otherwise.

export GH_TOKEN=$(gh codecrew identity token myorg-coder)
gh codecrew identity token myorg-coder --installation 12345678

gh codecrew version

gh codecrew version

Prints the installed release tag and the protocol version it implements, as <tag> (protocol <major.minor>). A build from source reports dev. The shape is stable within a major.

Options. None. --version and -v are the same verb.

Reads. Nothing: no pointer, no network, no files.

Writes. Nothing. One line on stdout.

Refusals. None.

Exit status. 0.

gh codecrew version     # v2.1.0 (protocol 2.1)

Licensed under Apache 2.0.