Kitbash
Most of what someone is about to build already exists. This skill breaks an idea into
components, gives each one a verdict — BORROW, KITBASH, or WRITE — and checks
every repository it names against the live GitHub API, so the invented ones are gone
before the user sees the answer.
When to Use This Skill
Use this skill when the user:
- Describes an app, tool, CLI, or feature they want to build
- Asks "is there a library for this" or "should I use a package or write it myself"
- Is about to hand-roll something in a domain where correctness was hard-won (PDF parsing, timezone math, OAuth, codecs, Unicode, crypto)
- Wants a build plan that names real, maintained dependencies instead of plausible-sounding ones
- Asks which parts of a project are worth writing themselves
The Three Verdicts
| Verdict |
Meaning |
| BORROW |
A maintained library exists and the correctness was hard-won. Rewriting it is the mistake — take the dependency. |
| KITBASH |
A good reference exists but is not a clean fit. Read it, adapt the approach, leave the dependency. |
| WRITE |
Generic enough that you should just write it. No repository needed. |
How It Works
- Decompose the idea into 3-6 functionally distinct components.
- Give every component exactly one verdict, and recall 1-3 candidate repositories for the BORROW and KITBASH ones.
- Verify the whole slate — every repository is resolved against the GitHub API, and the ones that do not exist are dropped and counted.
- Present the verified report, and only that.
If the kitbash and kitbash_verify MCP tools are connected, call kitbash instead:
same flow, with verification as a tool call rather than a shell command.
The Rubric
Follow it exactly, then run the verification step below.
KITBASH — COMPONENT SLATE
You are deciding, component by component, what this product should borrow, what it
should adapt, and what it should just write.
IDEA
<the user's idea, in their own words>
CONSTRAINTS
- TARGET STACK: <the stack the user named — drop this constraint if they did not name one>
Candidates must be usable from this stack. A brilliant Rust crate is not a
BORROW for a TypeScript project unless it ships real bindings — say so if it does,
and downgrade to KITBASH (read the algorithm, port it) if it does not.
- TARGET LICENSE: <the SPDX id they ship under — drop this constraint if unstated>
Prefer candidates compatible with this. Do not adjudicate compatibility in prose —
just prefer permissive licenses for BORROW, and note in the rationale when the only
good fit is copyleft. A copyleft repo is often still a fine KITBASH reference.
The claim is not "ship faster." It is "ship less." Four components not built beats
four components built quickly. Everything below serves that.
================================================================================
1. DECOMPOSE
================================================================================
Break the idea into 3-6 discrete functional components. Each gets a stable slug id
(kebab-case), a short name, and a one-sentence role describing its job IN THIS
PRODUCT — not in general.
Components must be FUNCTIONALLY DISTINCT. The failure mode is over-decomposition:
splitting one library's job into three components so the slate looks thorough.
The canonical mistake: "video transcoder" decomposed into transcode +
compress + format-convert. Those are not three components. They are three
flags on ffmpeg. A domain-aware reader spots this instantly and stops
trusting everything else on the page.
Test each boundary: would a working implementation plausibly use a DIFFERENT
library here than the component next to it? If no, it is one component. Merge it.
Under-decomposing is the cheaper error. Prefer 4 real components to 6 padded ones.
================================================================================
2. VERDICT — the heart of this
================================================================================
Every component gets exactly one:
BORROW A real, maintained dependency exists AND the problem has hard-won
correctness. Rewriting it is the mistake. Take the dependency.
KITBASH A good reference exists but is not a clean fit — wrong runtime, too
heavy, half the surface you need, abandoned but instructive. Read it,
adapt the approach into your own code, do NOT take the dependency.
WRITE Generic enough that the agent should just write it. No repo needed.
BORROW requires BOTH halves. A maintained library for something trivial is not a
BORROW — that is a dependency you are taking to save twenty lines. Hard-won
correctness with no maintained library is a KITBASH, not a BORROW.
================================================================================
3. HARD-WON-CORRECTNESS HAZARD LIST
================================================================================
These are domains where correctness was earned over years of edge cases that
appear in NO SPEC. An LLM rewrite of any of them looks correct, passes the tests
you thought to write, and is subtly wrong in production:
- PDF parsing and generation (malformed xref tables, encodings, embedded fonts)
- Video/audio container muxing and demuxing; codec handling
- Timezone and calendar math (DST transitions, leap seconds, historical offsets)
- Character encoding, Unicode normalization, grapheme segmentation, collation
- OAuth / OIDC / SAML flows and token lifecycle
- Cryptography of any kind, and TLS
- Rate limiting under contention; distributed locks
- Retry and backoff semantics (jitter, budget, idempotency)
- Money as floating point — decimal arithmetic and rounding rules
- Natural-language date parsing
- Image format decoding (chunk-level malformed input, EXIF orientation)
- Compression codecs
- Network protocol implementations (HTTP/2, WebSocket framing, DNS, SMTP)
- Text search relevance scoring and tokenization
- Charset/CSV/Excel dialect sniffing
If a component touches this list, that is a STRONG BORROW signal, and the
rationale should name the specific edge case a rewrite would miss. Not "PDFs are
hard" — "PDFs in the wild have broken xref tables and this recovers from them."
================================================================================
4. YOU ARE REQUIRED TO SAY WRITE
================================================================================
This is a requirement, not a suggestion.
In a typical decomposition AT LEAST ONE component must be WRITE. A tool that
recommends a repo for everything is a tool nobody believes, and the reader will
correctly conclude the verdicts are decoration.
Default to WRITE for:
- glue and orchestration between the other components — the queue, the pipeline,
the retry-this-one-file loop
- config loading and validation
- file watching, polling, directory walking (fs.watch + debounce + a seen-set)
- CRUD and straightforward persistence
- HTTP handlers, routing, request validation
- CLI argument parsing and output formatting
- anything whose whole implementation is under ~100 obvious lines
The tell: if you can describe the implementation in one sentence and a number ("an
array with concurrency 2 and a retry counter, about thirty lines"), it is WRITE. If
you cannot, ask what edge case you are afraid of — and if you cannot name one, it is
still WRITE.
For WRITE, the rationale must say plainly why writing it is CORRECT — the shape is
"this is N lines of obvious code and a dependency here costs more than it saves."
WRITE is a positive result. Do not phrase it as a search failure or an apology.
If your slate has zero WRITE components, you have over-borrowed. Go back and find
the glue.
================================================================================
5. RECALL — the reason this tool exists
================================================================================
For BORROW and KITBASH, propose 1-3 ranked candidate repos from your own knowledge.
DO NOT propose the repo GitHub search would return first. GitHub ranks by
popularity, which buries the correct answer under bigger, more general,
wrong-shaped projects. Correcting that ranking is the entire product.
Prefer the under-starred EXACT fit over the popular general-purpose one.
Aim for the repo the developer would never find on their own: the 400-star library
that does precisely this one thing, the maintained fork that fixed the thing the
original never merged, the tool from an adjacent ecosystem that happens to solve
this exactly. Rank it FIRST when it genuinely fits better. Put the obvious popular
option second as the safe alternate if it is legitimately viable.
Every rationale must give a fit reason SPECIFIC TO THIS COMPONENT. It must be a
sentence you could not have written from the README alone.
Bad: "A fast, modern, well-maintained library for working with PDFs."
Good: "Keeps byte offsets for every extracted span, so highlight positions
survive back to the original page — the search index needs that and
most extractors throw it away."
Use "owner/name" exactly as you believe it is spelled. Do not invent a plausible
owner for a package name you half-remember; a wrong guess is caught and dropped,
but you lose the slot. If you are unsure, propose fewer candidates.
================================================================================
6. OUTPUT CONTRACT
================================================================================
Produce ComponentCandidate[] — a JSON array, this exact shape:
{
"id": string, // stable kebab-case slug, e.g. "pdf-text-extraction"
"name": string, // short human name
"role": string, // one sentence: its job IN THIS product
"verdict": "BORROW" | "KITBASH" | "WRITE",
"rationale": string, // why THIS verdict, specific. Not a README summary.
"candidates": [ // [] for WRITE. 1-3 ranked for BORROW/KITBASH.
{ "owner": string, "name": string }
]
}
Worked example (idea: "watch a folder, OCR new PDFs, make them searchable"):
[
{
"id": "inbox-watcher",
"name": "Inbox watcher",
"role": "Notices new PDFs landing in the watched directory and enqueues them.",
"verdict": "WRITE",
"rationale": "fs.watch plus a 200ms debounce and a seen-set is about forty lines. The only real edge case is a file still being written, solved by waiting for size to stabilize. A watcher dependency here buys nothing and adds a native build step.",
"candidates": []
},
{
"id": "pdf-text-extraction",
"name": "PDF text extraction",
"role": "Pulls the existing text layer out of a PDF before falling back to OCR.",
"verdict": "BORROW",
"rationale": "Real-world PDFs carry broken xref tables, mixed encodings and CID fonts with no ToUnicode map. This recovers text from documents that strictly fail the spec, which is precisely the correctness no rewrite will reproduce. It also preserves per-span byte offsets, so the search index can highlight back into the original page.",
"candidates": [
{ "owner": "pdfminer", "name": "pdfminer.six" },
{ "owner": "jsvine", "name": "pdfplumber" }
]
},
{
"id": "ocr-engine",
"name": "OCR engine",
"role": "Reads text off scanned pages that carry no text layer.",
"verdict": "BORROW",
"rationale": "Decades of trained language data and page-segmentation heuristics. Nothing about this is reimplementable, and the failure mode of a weak OCR pass is silently wrong text that still indexes cleanly.",
"candidates": [
{ "owner": "tesseract-ocr", "name": "tesseract" }
]
},
{
"id": "search-index",
"name": "Search index",
"role": "Makes extracted page text queryable with ranked results.",
"verdict": "KITBASH",
"rationale": "A full search server is the wrong shape for a single-user self-hosted tool — it doubles the deployment surface. SQLite FTS5 gets you tokenization and BM25 in-process; take the schema and ranking approach from a small embedded-search project and drop the server.",
"candidates": [
{ "owner": "nalgeon", "name": "sqlean" }
]
}
]
Note the ordering in pdf-text-extraction: pdfminer.six is the lower-level, tighter
fit and has FEWER stars than pdfplumber, the more popular library built on top of it.
The tighter fit still goes first. That is the required shape, not a stylistic
preference — if your first-ranked candidate is always the most popular one, you are
doing GitHub search's job instead of this one.
Note also that both are permissively licensed. When two candidates fit comparably,
prefer the permissive one for a BORROW — you are recommending a dependency, and a
copyleft obligation is a real cost you are asking the developer to take on.
Return the array and nothing else — no prose wrapper, no markdown fence commentary.
Verify Before You Answer
The slate is unverified recall, and some of the repositories in it do not exist. Verification
is what makes the answer trustworthy, so it runs before the user sees anything.
Pipe the whole slate, WRITE components included, into the verifier in one call (needs Node 18+):
npx -y github:Open-Dev-Society/kitbash#ffa0f30d66823a0689fcfd9b90176f9cb7de4abd verify <<'EOF'
{
"idea": "<the idea, verbatim>",
"stack": "<omit if unstated>",
"target_license": "<omit if unstated>",
"components": [ <the full ComponentCandidate[] array> ]
}
EOF
What that command runs
- Kitbash's own verifier, from
github.com/Open-Dev-Society/kitbash, pinned to commit
ffa0f30 — the code is fixed at a revision you can read, not whatever is on
main today.
- Its only network requests are read-only
GET /repos/{owner}/{name} calls to
api.github.com. It writes nothing outside its own package directory.
- A GitHub token is optional. If
GITHUB_TOKEN, GH_TOKEN, or gh auth token is
present it is sent as an Authorization header to api.github.com and to nothing else,
needs no scopes, and is never logged or written to disk. Without one GitHub allows 60
checks an hour, which covers a normal slate.
- If you would rather execute nothing, check each candidate yourself with
curl -s -o /dev/null -w '%{http_code}' https://api.github.com/repos/OWNER/NAME and treat
404 as "does not exist". You lose ranking, health flags and the rendered report, but the
anti-hallucination check still holds.
It resolves every repository against the GitHub API, drops the ones that do not exist, flags
archived, unlicensed and abandoned ones, ranks the survivors, and prints a markdown report
followed by a <kitbash_result_json> block. Read next_action in that JSON:
DONE: show the user the markdown report as-is. Do not add repositories to it, re-rank
it, or restate it from memory — every fact in it was checked and yours were not.
RECALL_REPLACEMENTS: every candidate died for one or more components. Propose new
repositories for exactly those components and run the verifier again with the full slate.
If the verifier cannot run (no Node, no network), say so plainly and present the slate as
unverified recall. Repositories that were never checked are the one failure this skill
exists to prevent.
1---2name: kitbash3description: Decide what to borrow, adapt, or write before building something. Use when the user describes an app, tool, CLI, or feature they want to build and needs to know which parts already exist as open-source GitHub repos (BORROW), which are worth reading and adapting (KITBASH), and which to just write (WRITE). Every repository named is checked against the live GitHub API, so invented ones never reach the user.4---56<!-- Generated by `npm run skill` from src/rubric.ts. Edit the rubric, not this file. -->78# Kitbash910Most of what someone is about to build already exists. This skill breaks an idea into11components, gives each one a verdict — **BORROW**, **KITBASH**, or **WRITE** — and checks12every repository it names against the live GitHub API, so the invented ones are gone13before the user sees the answer.1415## When to Use This Skill1617Use this skill when the user:1819- Describes an app, tool, CLI, or feature they want to build20- Asks "is there a library for this" or "should I use a package or write it myself"21- Is about to hand-roll something in a domain where correctness was hard-won (PDF parsing, timezone math, OAuth, codecs, Unicode, crypto)22- Wants a build plan that names real, maintained dependencies instead of plausible-sounding ones23- Asks which parts of a project are worth writing themselves2425## The Three Verdicts2627| Verdict | Meaning |28| --- | --- |29| **BORROW** | A maintained library exists and the correctness was hard-won. Rewriting it is the mistake — take the dependency. |30| **KITBASH** | A good reference exists but is not a clean fit. Read it, adapt the approach, leave the dependency. |31| **WRITE** | Generic enough that you should just write it. No repository needed. |3233## How It Works34351. Decompose the idea into 3-6 functionally distinct components.362. Give every component exactly one verdict, and recall 1-3 candidate repositories for the BORROW and KITBASH ones.373. Verify the whole slate — every repository is resolved against the GitHub API, and the ones that do not exist are dropped and counted.384. Present the verified report, and only that.3940If the `kitbash` and `kitbash_verify` MCP tools are connected, call `kitbash` instead:41same flow, with verification as a tool call rather than a shell command.4243## The Rubric4445Follow it exactly, then run the verification step below.4647```text48KITBASH — COMPONENT SLATE4950You are deciding, component by component, what this product should borrow, what it51should adapt, and what it should just write.5253IDEA54 <the user's idea, in their own words>5556CONSTRAINTS57- TARGET STACK: <the stack the user named — drop this constraint if they did not name one>58 Candidates must be usable from this stack. A brilliant Rust crate is not a59 BORROW for a TypeScript project unless it ships real bindings — say so if it does,60 and downgrade to KITBASH (read the algorithm, port it) if it does not.6162- TARGET LICENSE: <the SPDX id they ship under — drop this constraint if unstated>63 Prefer candidates compatible with this. Do not adjudicate compatibility in prose —64 just prefer permissive licenses for BORROW, and note in the rationale when the only65 good fit is copyleft. A copyleft repo is often still a fine KITBASH reference.6667The claim is not "ship faster." It is "ship less." Four components not built beats68four components built quickly. Everything below serves that.697071================================================================================721. DECOMPOSE73================================================================================7475Break the idea into 3-6 discrete functional components. Each gets a stable slug id76(kebab-case), a short name, and a one-sentence role describing its job IN THIS77PRODUCT — not in general.7879Components must be FUNCTIONALLY DISTINCT. The failure mode is over-decomposition:80splitting one library's job into three components so the slate looks thorough.8182 The canonical mistake: "video transcoder" decomposed into transcode +83 compress + format-convert. Those are not three components. They are three84 flags on ffmpeg. A domain-aware reader spots this instantly and stops85 trusting everything else on the page.8687Test each boundary: would a working implementation plausibly use a DIFFERENT88library here than the component next to it? If no, it is one component. Merge it.8990Under-decomposing is the cheaper error. Prefer 4 real components to 6 padded ones.919293================================================================================942. VERDICT — the heart of this95================================================================================9697Every component gets exactly one:9899 BORROW A real, maintained dependency exists AND the problem has hard-won100 correctness. Rewriting it is the mistake. Take the dependency.101102 KITBASH A good reference exists but is not a clean fit — wrong runtime, too103 heavy, half the surface you need, abandoned but instructive. Read it,104 adapt the approach into your own code, do NOT take the dependency.105106 WRITE Generic enough that the agent should just write it. No repo needed.107108BORROW requires BOTH halves. A maintained library for something trivial is not a109BORROW — that is a dependency you are taking to save twenty lines. Hard-won110correctness with no maintained library is a KITBASH, not a BORROW.111112113================================================================================1143. HARD-WON-CORRECTNESS HAZARD LIST115================================================================================116117These are domains where correctness was earned over years of edge cases that118appear in NO SPEC. An LLM rewrite of any of them looks correct, passes the tests119you thought to write, and is subtly wrong in production:120121 - PDF parsing and generation (malformed xref tables, encodings, embedded fonts)122 - Video/audio container muxing and demuxing; codec handling123 - Timezone and calendar math (DST transitions, leap seconds, historical offsets)124 - Character encoding, Unicode normalization, grapheme segmentation, collation125 - OAuth / OIDC / SAML flows and token lifecycle126 - Cryptography of any kind, and TLS127 - Rate limiting under contention; distributed locks128 - Retry and backoff semantics (jitter, budget, idempotency)129 - Money as floating point — decimal arithmetic and rounding rules130 - Natural-language date parsing131 - Image format decoding (chunk-level malformed input, EXIF orientation)132 - Compression codecs133 - Network protocol implementations (HTTP/2, WebSocket framing, DNS, SMTP)134 - Text search relevance scoring and tokenization135 - Charset/CSV/Excel dialect sniffing136137If a component touches this list, that is a STRONG BORROW signal, and the138rationale should name the specific edge case a rewrite would miss. Not "PDFs are139hard" — "PDFs in the wild have broken xref tables and this recovers from them."140141142================================================================================1434. YOU ARE REQUIRED TO SAY WRITE144================================================================================145146This is a requirement, not a suggestion.147148In a typical decomposition AT LEAST ONE component must be WRITE. A tool that149recommends a repo for everything is a tool nobody believes, and the reader will150correctly conclude the verdicts are decoration.151152Default to WRITE for:153 - glue and orchestration between the other components — the queue, the pipeline,154 the retry-this-one-file loop155 - config loading and validation156 - file watching, polling, directory walking (fs.watch + debounce + a seen-set)157 - CRUD and straightforward persistence158 - HTTP handlers, routing, request validation159 - CLI argument parsing and output formatting160 - anything whose whole implementation is under ~100 obvious lines161162The tell: if you can describe the implementation in one sentence and a number ("an163array with concurrency 2 and a retry counter, about thirty lines"), it is WRITE. If164you cannot, ask what edge case you are afraid of — and if you cannot name one, it is165still WRITE.166167For WRITE, the rationale must say plainly why writing it is CORRECT — the shape is168"this is N lines of obvious code and a dependency here costs more than it saves."169WRITE is a positive result. Do not phrase it as a search failure or an apology.170171If your slate has zero WRITE components, you have over-borrowed. Go back and find172the glue.173174175================================================================================1765. RECALL — the reason this tool exists177================================================================================178179For BORROW and KITBASH, propose 1-3 ranked candidate repos from your own knowledge.180181DO NOT propose the repo GitHub search would return first. GitHub ranks by182popularity, which buries the correct answer under bigger, more general,183wrong-shaped projects. Correcting that ranking is the entire product.184185 Prefer the under-starred EXACT fit over the popular general-purpose one.186187Aim for the repo the developer would never find on their own: the 400-star library188that does precisely this one thing, the maintained fork that fixed the thing the189original never merged, the tool from an adjacent ecosystem that happens to solve190this exactly. Rank it FIRST when it genuinely fits better. Put the obvious popular191option second as the safe alternate if it is legitimately viable.192193Every rationale must give a fit reason SPECIFIC TO THIS COMPONENT. It must be a194sentence you could not have written from the README alone.195196 Bad: "A fast, modern, well-maintained library for working with PDFs."197 Good: "Keeps byte offsets for every extracted span, so highlight positions198 survive back to the original page — the search index needs that and199 most extractors throw it away."200201Use "owner/name" exactly as you believe it is spelled. Do not invent a plausible202owner for a package name you half-remember; a wrong guess is caught and dropped,203but you lose the slot. If you are unsure, propose fewer candidates.204205206================================================================================2076. OUTPUT CONTRACT208================================================================================209210Produce ComponentCandidate[] — a JSON array, this exact shape:211212 {213 "id": string, // stable kebab-case slug, e.g. "pdf-text-extraction"214 "name": string, // short human name215 "role": string, // one sentence: its job IN THIS product216 "verdict": "BORROW" | "KITBASH" | "WRITE",217 "rationale": string, // why THIS verdict, specific. Not a README summary.218 "candidates": [ // [] for WRITE. 1-3 ranked for BORROW/KITBASH.219 { "owner": string, "name": string }220 ]221 }222223Worked example (idea: "watch a folder, OCR new PDFs, make them searchable"):224225[226 {227 "id": "inbox-watcher",228 "name": "Inbox watcher",229 "role": "Notices new PDFs landing in the watched directory and enqueues them.",230 "verdict": "WRITE",231 "rationale": "fs.watch plus a 200ms debounce and a seen-set is about forty lines. The only real edge case is a file still being written, solved by waiting for size to stabilize. A watcher dependency here buys nothing and adds a native build step.",232 "candidates": []233 },234 {235 "id": "pdf-text-extraction",236 "name": "PDF text extraction",237 "role": "Pulls the existing text layer out of a PDF before falling back to OCR.",238 "verdict": "BORROW",239 "rationale": "Real-world PDFs carry broken xref tables, mixed encodings and CID fonts with no ToUnicode map. This recovers text from documents that strictly fail the spec, which is precisely the correctness no rewrite will reproduce. It also preserves per-span byte offsets, so the search index can highlight back into the original page.",240 "candidates": [241 { "owner": "pdfminer", "name": "pdfminer.six" },242 { "owner": "jsvine", "name": "pdfplumber" }243 ]244 },245 {246 "id": "ocr-engine",247 "name": "OCR engine",248 "role": "Reads text off scanned pages that carry no text layer.",249 "verdict": "BORROW",250 "rationale": "Decades of trained language data and page-segmentation heuristics. Nothing about this is reimplementable, and the failure mode of a weak OCR pass is silently wrong text that still indexes cleanly.",251 "candidates": [252 { "owner": "tesseract-ocr", "name": "tesseract" }253 ]254 },255 {256 "id": "search-index",257 "name": "Search index",258 "role": "Makes extracted page text queryable with ranked results.",259 "verdict": "KITBASH",260 "rationale": "A full search server is the wrong shape for a single-user self-hosted tool — it doubles the deployment surface. SQLite FTS5 gets you tokenization and BM25 in-process; take the schema and ranking approach from a small embedded-search project and drop the server.",261 "candidates": [262 { "owner": "nalgeon", "name": "sqlean" }263 ]264 }265]266267Note the ordering in pdf-text-extraction: pdfminer.six is the lower-level, tighter268fit and has FEWER stars than pdfplumber, the more popular library built on top of it.269The tighter fit still goes first. That is the required shape, not a stylistic270preference — if your first-ranked candidate is always the most popular one, you are271doing GitHub search's job instead of this one.272273Note also that both are permissively licensed. When two candidates fit comparably,274prefer the permissive one for a BORROW — you are recommending a dependency, and a275copyleft obligation is a real cost you are asking the developer to take on.276277Return the array and nothing else — no prose wrapper, no markdown fence commentary.278```279280## Verify Before You Answer281282The slate is unverified recall, and some of the repositories in it do not exist. Verification283is what makes the answer trustworthy, so it runs before the user sees anything.284285Pipe the whole slate, WRITE components included, into the verifier in one call (needs Node 18+):286287```bash288npx -y github:Open-Dev-Society/kitbash#ffa0f30d66823a0689fcfd9b90176f9cb7de4abd verify <<'EOF'289{290 "idea": "<the idea, verbatim>",291 "stack": "<omit if unstated>",292 "target_license": "<omit if unstated>",293 "components": [ <the full ComponentCandidate[] array> ]294}295EOF296```297298### What that command runs299300- Kitbash's own verifier, from `github.com/Open-Dev-Society/kitbash`, **pinned to commit301 `ffa0f30`** — the code is fixed at a revision you can read, not whatever is on302 main today.303- Its only network requests are read-only `GET /repos/{owner}/{name}` calls to304 `api.github.com`. It writes nothing outside its own package directory.305- **A GitHub token is optional.** If `GITHUB_TOKEN`, `GH_TOKEN`, or `gh auth token` is306 present it is sent as an `Authorization` header to `api.github.com` and to nothing else,307 needs no scopes, and is never logged or written to disk. Without one GitHub allows 60308 checks an hour, which covers a normal slate.309- If you would rather execute nothing, check each candidate yourself with310 `curl -s -o /dev/null -w '%{http_code}' https://api.github.com/repos/OWNER/NAME` and treat311 404 as "does not exist". You lose ranking, health flags and the rendered report, but the312 anti-hallucination check still holds.313314It resolves every repository against the GitHub API, drops the ones that do not exist, flags315archived, unlicensed and abandoned ones, ranks the survivors, and prints a markdown report316followed by a `<kitbash_result_json>` block. Read `next_action` in that JSON:317318- `DONE`: show the user the markdown report as-is. Do not add repositories to it, re-rank319 it, or restate it from memory — every fact in it was checked and yours were not.320- `RECALL_REPLACEMENTS`: every candidate died for one or more components. Propose new321 repositories for exactly those components and run the verifier again with the full slate.322323If the verifier cannot run (no Node, no network), say so plainly and present the slate as324unverified recall. Repositories that were never checked are the one failure this skill325exists to prevent.