@openkeyai/tool-manifest
v0.2.1
Published
Schema + AST scanner that enforces the OpenKey AI tool contract.
Readme
@openkeyai/tool-manifest
Schema + AST scanner that defines and enforces the OpenKey AI tool contract. Used by tool CI and the Phase 13 auto-scaffolder.
pnpm add -D @openkeyai/tool-manifestWhat this package gives you
| Export | Purpose |
|---|---|
| ToolManifestSchema (zod) | The FROZEN shape of every tool's tool.json |
| validateManifest(json) | Parse + validate. Returns typed ToolManifest or throws ZodError |
| validateManifestFile(path) | Same, reading from disk |
| scanToolSource({ srcDir, manifestPath? }) | Walks the tool's source tree, returns contract violations |
| okai-scan CLI | Thin wrapper around scanToolSource for npx okai-scan |
tool.json — the manifest
Every tool ships a tool.json at its repo root:
{
"slug": "yt-thumbnails",
"name": "YouTube Thumbnails",
"description": "AI-generated thumbnails for YouTube videos.",
"version": "0.1.0",
"runtime": "edge",
"scopes": ["keys.read"],
"providers": ["openai"],
"homepage": "https://yt-thumbnails.openkeyai.com",
"callback_url": "https://yt-thumbnails.openkeyai.com/start",
"owner": {
"name": "Scott Goodwin",
"email": "[email protected]",
"github": "scottgoodwin"
},
"sdk_version": "^0.1.0"
}| Field | Required | Notes |
|---|---|---|
| slug | ✓ | Lowercase kebab-case, 3–40 chars. Becomes the JWT aud claim. |
| name | ✓ | Display name. |
| description | | One-sentence catalog blurb. |
| version | ✓ | semver (x.y.z). |
| runtime | ✓ | edge (Cloudflare Workers) or container (Fly Machines). |
| scopes | ✓ | Subset of keys.read, user.read, billing.read. Min 1. |
| providers | | Provider slugs the tool may request keys for. |
| callback_url | ✓ | Where the hub sends users after issuing a token. https only. |
| owner | ✓ | At least a name; email + github are nice-to-have for support. |
| sdk_version | ✓ | semver range — the SDK version the tool was built against. |
| category, homepage | | Optional catalog metadata. |
Schema lives in src/schema.ts.
Scanner — what it catches
Run from your tool repo:
npx okai-scanOr programmatically:
import { scanToolSource } from "@openkeyai/tool-manifest";
const { violations, scannedFileCount } = scanToolSource({
srcDir: "src",
manifestPath: "tool.json",
});
if (violations.length > 0) {
process.exit(1);
}| Code | Catches |
|---|---|
| missing-hubheader-import | No layout file imports HubHeader from @openkeyai/ui |
| missing-hubheader-mount | HubHeader imported but <HubHeader /> never appears as JSX |
| banned-internal-import | Any source file imports from @openkeyai/sdk/_internal/* |
| manifest-missing / manifest-invalid | tool.json is unreadable or fails the Zod schema |
| io-error | Source dir is unreachable / unreadable |
The scanner uses regex-based text scanning rather than a full TypeScript AST. That keeps the dep tree small and CI fast. It catches the obvious violations; subtler patterns (like a HubHeader mount inside an unreachable branch) are out of scope for v1. If we ever need stricter checks the function signature stays the same — we'd swap the backend.
Heuristics
- "Layout file" = any source file whose basename matches
layout.{ts,tsx,js,jsx,mjs,cjs}. Covers Next.js App Router (app/layout.tsx) and the variants containers use. node_modules,dist,.next,.open-next,.turbo,build,out,coverage, and dot-directories are skipped during the walk.
CLI
okai-scan [options]
Options:
-s, --src <dir> Source directory (default: src/, then app/, then .)
-m, --manifest <path> Path to tool.json (default: ./tool.json if present)
--no-manifest Skip the manifest check
-h, --help Show this help
Exit codes:
0 no violations
1 one or more violations
2 bad CLI usageWhere this fits
- Tool CI (Phase 11) runs
okai-scanon every PR. Failed scans block merge. - Auto-scaffolder (Phase 13) uses
ToolManifestSchemato generate a startertool.jsonfor newly-voted tools. - Hub tool registry validates incoming manifest data against the same schema before inserting into
public.tools.
Versioning
- Semver. The schema's required-field set is frozen — additions are minor bumps, renames/removals are major (with 60 days notice per hub CLAUDE.md).
- The scanner rule set can grow without breaking consumers (a new rule reports a new code; existing codes don't change).
Development
pnpm install
pnpm typecheck
pnpm test # 17 tests across schema + scanner
pnpm buildLicense
MIT — see LICENSE.
