Skip to content
ChatJS
Esc
navigateopen⌘Jpreview
On this page

Authoring Tools

Author tested source files and publish them as shadcn registry items

Author tools as real TypeScript files that you can import, type-check, and test. In this repository, canonical implementations live in packages/registry/src/tools/<id>/. The app consumes installed copies through normal local imports.

Server and renderer

Use the AI SDK’s tool() helper for the server implementation:

import { tool } from "ai";
import { z } from "zod";

export const wordCount = tool({
  description: "Count words in text",
  inputSchema: z.object({ text: z.string() }),
  execute: ({ text }) => ({
    words: text.trim() ? text.trim().split(/\s+/).length : 0,
  }),
});

The renderer exports a named React component. Use the source tool’s inferred input/output types and the shared ToolPartFromTool helper, keeping runtime imports of server code out of the client bundle. See the existing word-count source for loading, result, and error states.

Item metadata

Declare standard shadcn files and dependencies in packages/registry/registry.ts. ChatJS metadata describes only registration and environment requirements:

{
  "contractVersion": 1,
  "kind": "tool",
  "id": "word-count",
  "toolExport": "wordCount",
  "rendererExport": "WordCountRenderer",
  "envRequirements": []
}

The same metadata is emitted as meta.chatjs in the registry item and as an installed tools/chatjs/word-count/chatjs.json descriptor. Each item targets tool.ts, renderer.tsx, and chatjs.json under ~/tools/chatjs/<id>/. Shared helpers use standard registryDependencies. npm packages use dependencies or devDependencies.

For credentials, declare environment alternatives in the typed item metadata:

const envRequirements = [{ options: [["FIRECRAWL_API_KEY"]] }];

Every outer requirement must be satisfied. Within one requirement, options contains alternatives, and each alternative lists variables needed together. The build serializes this data into the descriptor. The installed app’s check-env command reads it without evaluating remote source. The old toolEnvVars source parser and registry authoring-type npm exports are removed.

Build and verify

bun run --cwd packages/registry test:types
bun run --cwd packages/registry test:unit
bun run --cwd packages/registry build

The small build script emits registry.json, then pinned shadcn@4.21.0 build reads the actual sources and generates dist/r/*.json. Do not hand-maintain JSON source strings. Publish those generated files from your registry endpoint.

Install the built item into an independent ChatJS app and type-check it. Source tests validate execution logic, while installation tests catch missing files, dependencies, incorrect targets, and renderer registration problems.

npx @chat-js/cli@latest add https://example.com/r/word-count.json

Third-party registries use the same standard item format and descriptor contract. There is no runtime plugin loader or general compatibility solver. The installed app’s TypeScript checks validate composition against its actual local contracts.

Last updated on Sep 9, 2026

Was this page helpful?