Build & publish your own kit
Kits are the shared skills repo for 0G. Anything you build once — an
attested inference flow, a storage-backed cache, an indexer view — can be
packaged as a kit and published to the catalog, where every project on
0gkit can install it with a single 0g add <kit>.
This guide takes you from an empty directory to a merged kit in four steps:
- Scaffold —
0g kits new <name>generates a valid kit skeleton. - Build — fill in the portable core and per-base adapters.
- Validate —
pnpm kits:checkproves the kit applies and type-checks. - Publish — open a PR to the catalog. Once merged it's live for everyone.
1. Scaffold with 0g kits new
The fastest way to start is the scaffolder — it writes a registry-valid
kit.json, a dependency-injected portable core, one adapter per base you name,
and (for React-capable bases) a UI component + hook:
0g kits new my-feature \
--title "My Feature" \
--domain agent-infra \
--summary "Does a useful thing on 0G." \
--bases react-app,mcp-agent
| Flag | Default | Notes |
|---|---|---|
--title | Title Case of the name | Human-readable name shown in 0g kits list. |
--domain | agent-infra | One of verifiable-ai, agent-infra, markets, assets, defi. |
--summary | a TODO: placeholder | One-sentence description. |
--bases | react-app | Comma-separated compatible bases. |
--dir | templates/_kits in-repo, otherwise cwd | Where the kit folder is written. |
--dry-run | off | Print the plan without writing files. |
Run inside a clone of rajkaria/0gkit
and the command writes straight into templates/_kits/<name>/, adds a docs-page
stub under apps/docs/app/kits/<name>/, and prints the exact nav.ts line to
register. Names must be kebab-case, the domain must be one of the canonical
five, and an existing kit is never overwritten.
Prefer to wire it by hand? The scaffolder is optional — the manifest schema and directory layout below are all you need.
2. Build — the 3-tier model
Every kit follows a 3-tier model:
templates/_kits/<kit-name>/
kit.json ← manifest (required)
lib/ ← portable tier (always applied)
my-feature.ts
adapters/
react-app/ ← files applied only when base = react-app
app/api/…
mcp-agent/
src/tools/…
ui/ ← React tier (applied for React-capable bases)
components/
hooks/
lib tier — portable TypeScript. All 0G primitives are injected through a
Deps interface, so the lib compiles and unit-tests with mocks and has zero
hard @foundryprotocol/* imports. Framework-agnostic.
adapters tier — one sub-directory per base. Each adapter wires the real
0gkit packages into the lib's injected-deps interface. Adapters are the only
tier allowed to import @foundryprotocol/0gkit-*. Only the adapter matching the
detected base is written to the project.
ui tier — React components and hooks. Applied only for React-capable bases
(react-app, chat). Must import from lib/hook interfaces only — never from
adapters.
Templates live under templates/_kits/ — they are not listed in
pnpm-workspace.yaml (see D24). The engine fetches them at apply-time via
giget.
kit.json schema
Every field is validated by KitManifestSchema (zod) in
packages/0gkit-kits/src/manifest.ts. A minimal valid kit.json:
{
"name": "my-feature",
"title": "My Feature",
"domain": "agent-infra",
"summary": "One-sentence description of what the kit adds.",
"compatibleBases": ["react-app", "chat"],
"tiers": {
"lib": ["lib/my-feature.ts"],
"adapters": {
"react-app": ["app/api/my-feature/route.ts"]
},
"ui": ["components/MyFeature.tsx"]
},
"env": [
{
"key": "OG_MY_VAR",
"example": "my-value",
"note": "What this env var controls"
}
],
"dependencies": {
"@foundryprotocol/0gkit-storage": "^1.0.0"
},
"devDependencies": {},
"requires": [],
"composes": [],
"conflicts": []
}
Field reference
| Field | Type | Required | Description |
|---|---|---|---|
name | kebab-case string | Yes | Unique kit identifier — matches the directory name. |
title | string | Yes | Human-readable name shown in 0g kits list. |
domain | enum | Yes | One of verifiable-ai, agent-infra, markets, assets, defi. |
summary | string | Yes | One-sentence description. Shown in 0g kits info. |
compatibleBases | string[] | Yes | Bases this kit supports (e.g. react-app, chat, mcp-agent, storage-app, tee-attested-api). |
tiers.lib | string[] | No | Lib-tier file paths (relative to templates/_kits/<kit>/). Always applied. |
tiers.adapters | Record<base, string[]> | No | Adapter files per base. Only the matching base's files are applied. |
tiers.ui | string[] | No | UI-tier files. Applied for React-capable bases only. |
env | { key, example, note? }[] | No | Env vars added to .env.example. note is shown by 0g kits info. |
dependencies | Record<string, string> | No | NPM deps merged into the target project's package.json. |
devDependencies | Record<string, string> | No | Dev deps merged into the target project's package.json. |
requires | string[] | No | 0gkit package names the target base must already declare (e.g. "0gkit-storage"). |
composes | string[] | No | Other kit names auto-applied before this kit (deps-first, deduped, cycle-safe). |
conflicts | string[] | No | Kit names that are illegal to apply together with this kit. |
Neutrality rule (hard invariant)
No file in templates/_kits/<kit>/ may import from @foundryprotocol/* app
packages (anything outside @foundryprotocol/0gkit-*). 0gkit-* packages are
allowed in adapter files — they are injected at apply-time, not at lib level.
This invariant is enforced at CI by pnpm boundary:check. A kit that imports an
app package will fail CI.
3. Validate
Run locally before opening a PR:
# regenerate the compiled registry from templates/_kits/*/kit.json
pnpm --filter @foundryprotocol/0gkit-kits build
# apply the kit to every compatible base and type-check the overlay
pnpm kits:check
pnpm kits:check is the real gate. For every (kit × base) combo it:
- Validates
kit.jsonagainstKitManifestSchema. - Confirms every file named in the manifest exists on disk.
- Confirms the kit is in the compiled
KITSregistry. - Runs
applyKit()into a temp copy of the base template. - Type-checks the applied overlay against the real
@foundryprotocol/0gkit-*types (isolatedtscfor Next.js bases; fulltscfor the rest).
4. Publish to the catalog
A published kit is available to every 0gkit user. To publish:
-
Fork / clone
rajkaria/0gkit. -
Put your kit under
templates/_kits/<name>/(the scaffolder does this for you when run in-repo). -
Add a docs page at
apps/docs/app/kits/<name>/page.mdxand register it inapps/docs/lib/nav.tsunder the"Kits"section:{ title: "My Feature", href: "/kits/my-feature" }, -
Run
pnpm kits:checkandpnpm format && pnpm docs:check. -
Open a PR. Once it's merged and the packages publish, anyone can run
0g add <name>.
PR checklist
-
kit.jsonvalidates againstKitManifestSchema(runpnpm kits:check). -
namematches the directory name exactly (kebab-case). -
compatibleBaseslists only bases that have a matchingadapters/<base>/entry (or lib-only if no adapter needed). - Lib tier has zero hard
@foundryprotocol/*imports — all deps injected by adapters. - No file imports from Foundry app packages (neutrality rule).
-
envlists every environment variable the kit reads (withexampleandnote). -
dependencieslists every runtime npm package the kit's files import. -
composesis set if this kit depends on another kit being applied first. - A doc page exists at
apps/docs/app/kits/<name>/page.mdxand is registered inapps/docs/lib/nav.ts. -
pnpm kits:checkpasses locally. -
pnpm format && pnpm docs:checkpasses locally (new doc pages must be nav-registered and prettier-clean).
Adding a doc page
Every kit must have a doc page at apps/docs/app/kits/<name>/page.mdx and a
nav entry in apps/docs/lib/nav.ts under the "Kits" section. Without both,
pnpm docs:check will fail. The scaffolder writes a starter stub for you.
Follow the shape of existing pages (see Agent Memory, AI Oracle) and include:
- A blockquote summary with the honesty caveat if attestation is involved.
- What it does — step-by-step description of real behavior.
- Compatible bases.
- Apply — both scaffold-time (
npm create 0gkit-app -- --kits <kit>) and post-scaffold (0g add <kit>) commands. - Environment variables — table mirroring
kit.jsonenv. - Tiers — what each tier file contains.
- 0gkit packages used.
- Honesty note — any caveats about attestation, network mode, or execution scope.
Honesty guidelines
- Attestation = a signed receipt. The operator key signs
digestJson(receipt)via EIP-191 personal-sign; the signer is recovered withrecoverSigner. There is no TEE quote verification in the current stack. Badge text must be "✓ signature verified" — never "TEE attested". Do not namesignEnvelopeorverifyEnvelope— those functions do not exist. - Real exports only — name only exports that exist in the package:
JobRunner,jobs.define,MemoryBackend,Storage.upload,Storage.download,Compute.router,createTypedContract,Erc721Abi,INFT_ABI,Indexer,onReorg,digestJson,recoverSigner,fromPrivateKey. If unsure, read the package source before documenting. - Execution scope — if a kit is read-only (e.g.
yield-intel), state that explicitly and include a non-removable disclaimer component.