<!-- 0Gkit docs — Build & publish a kit
     Source: https://docs.0gkit.com/kits/authoring
     LLM-friendly Markdown twin of the page. -->

# 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. **Scaffold** — `0g kits new <name>` generates a valid kit skeleton.
2. **Build** — fill in the portable core and per-base adapters.
3. **Validate** — `pnpm 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:

```bash
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`](https://github.com/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`:

```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:

```bash
# 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`](https://github.com/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:

   ```ts
   { 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](/kits/agent-memory),
[AI Oracle](/kits/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.
