0Gkitdocs↗ HomePlaygroundGitHub

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:

  1. Scaffold0g kits new <name> generates a valid kit skeleton.
  2. Build — fill in the portable core and per-base adapters.
  3. Validatepnpm kits:check proves the kit applies and type-checks.
  4. 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
FlagDefaultNotes
--titleTitle Case of the nameHuman-readable name shown in 0g kits list.
--domainagent-infraOne of verifiable-ai, agent-infra, markets, assets, defi.
--summarya TODO: placeholderOne-sentence description.
--basesreact-appComma-separated compatible bases.
--dirtemplates/_kits in-repo, otherwise cwdWhere the kit folder is written.
--dry-runoffPrint 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

FieldTypeRequiredDescription
namekebab-case stringYesUnique kit identifier — matches the directory name.
titlestringYesHuman-readable name shown in 0g kits list.
domainenumYesOne of verifiable-ai, agent-infra, markets, assets, defi.
summarystringYesOne-sentence description. Shown in 0g kits info.
compatibleBasesstring[]YesBases this kit supports (e.g. react-app, chat, mcp-agent, storage-app, tee-attested-api).
tiers.libstring[]NoLib-tier file paths (relative to templates/_kits/<kit>/). Always applied.
tiers.adaptersRecord<base, string[]>NoAdapter files per base. Only the matching base's files are applied.
tiers.uistring[]NoUI-tier files. Applied for React-capable bases only.
env{ key, example, note? }[]NoEnv vars added to .env.example. note is shown by 0g kits info.
dependenciesRecord<string, string>NoNPM deps merged into the target project's package.json.
devDependenciesRecord<string, string>NoDev deps merged into the target project's package.json.
requiresstring[]No0gkit package names the target base must already declare (e.g. "0gkit-storage").
composesstring[]NoOther kit names auto-applied before this kit (deps-first, deduped, cycle-safe).
conflictsstring[]NoKit 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:

  1. Validates kit.json against KitManifestSchema.
  2. Confirms every file named in the manifest exists on disk.
  3. Confirms the kit is in the compiled KITS registry.
  4. Runs applyKit() into a temp copy of the base template.
  5. Type-checks the applied overlay against the real @foundryprotocol/0gkit-* types (isolated tsc for Next.js bases; full tsc for the rest).

4. Publish to the catalog

A published kit is available to every 0gkit user. To publish:

  1. Fork / clone rajkaria/0gkit.

  2. Put your kit under templates/_kits/<name>/ (the scaffolder does this for you when run in-repo).

  3. Add a docs page at apps/docs/app/kits/<name>/page.mdx and register it in apps/docs/lib/nav.ts under the "Kits" section:

    { title: "My Feature", href: "/kits/my-feature" },
    
  4. Run pnpm kits:check and pnpm format && pnpm docs:check.

  5. Open a PR. Once it's merged and the packages publish, anyone can run 0g add <name>.

PR checklist

  • kit.json validates against KitManifestSchema (run pnpm kits:check).
  • name matches the directory name exactly (kebab-case).
  • compatibleBases lists only bases that have a matching adapters/<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).
  • env lists every environment variable the kit reads (with example and note).
  • dependencies lists every runtime npm package the kit's files import.
  • composes is set if this kit depends on another kit being applied first.
  • A doc page exists at apps/docs/app/kits/<name>/page.mdx and is registered in apps/docs/lib/nav.ts.
  • pnpm kits:check passes locally.
  • pnpm format && pnpm docs:check passes 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.json env.
  • 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 with recoverSigner. There is no TEE quote verification in the current stack. Badge text must be "✓ signature verified" — never "TEE attested". Do not name signEnvelope or verifyEnvelope — 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.