Registry
On-chain package registry for skills, agents, themes, and components
Schemas for publishing and discovering registry items on-chain. Registry items are multi-file packages inscribed as ordinals with ord-fs/json manifests, making them natively servable by ORDFS and installable via the shadcn CLI protocol.
Registry Item
A registry item is a multi-output ordinal inscription where individual files are 1-sat inscription outputs and a manifest ordinal ties them together with metadata.
Transaction Structure
Output 0: file inscription (1 sat) — SKILL.md content
Output 1: file inscription (1 sat) — example.md
...
Output N: manifest inscription (1 sat, tracked ordinal)
Content-Type: ord-fs/json
Content: { "SKILL.md": "_0", "example.md": "_1" }
MAP: { app, type, name, version, language, ... }
AIP: author signatureEach file output is a standard ordinal inscription with a P2PKH prefix (spendable). The manifest output is the package's on-chain identity — it goes in the ordinals basket and is the outpoint used to reference the package.
Manifest Format (ord-fs/json)
The manifest is an inscription with content type ord-fs/json. Its content is a JSON object mapping filenames to sibling output references using relative vout notation:
{
"SKILL.md": "_0",
"example.md": "_1"
}The _N values are relative vout references — the underscore-vout suffix from the standard outpoint format (txid_vout), without the txid. ORDFS resolves _N to {manifest_txid}_{N} using the directory inscription's own txid. Requesting /content/{manifestOutpoint}/SKILL.md returns the file content via directory traversal.
For nested directories (e.g., refs/api.md), create a separate ord-fs/json inscription for the subdirectory and reference it from the root manifest. ORDFS traverses nested directories by following the chain of ord-fs/json inscriptions.
MAP Metadata
Registry items carry MAP metadata on the manifest inscription following the standard MAP SET protocol:
MAP SET app <registry> type <registryType> name <name> version <version> ...| Field | Required | Description |
|---|---|---|
app | Yes | Registry identifier (e.g. clawnet) |
type | Yes | Registry type with registry: prefix (see types below) |
name | Yes | Package name (lowercase, hyphenated, 1-64 chars) |
version | Yes | Semantic version (e.g. 1.0.0) |
description | Yes | Human-readable description of the package |
language | No | BCP 47 language tag (e.g. en, zh, ja, es, ko). Indicates the primary language of the package content. Defaults to en if omitted. |
title | No | Human-readable display title (e.g. "Bitcoin Avatar") |
author | No | Author name or identifier |
dependencies | No | JSON-serialized array of npm package dependencies |
devDependencies | No | JSON-serialized array of dev dependencies |
registryDependencies | No | JSON-serialized array of other registry items this depends on |
categories | No | JSON-serialized array of category tags |
homepage | No | URL to the package's homepage or repository |
prev | No | Previous manifest outpoint for version chaining |
opns.name | No | OpNS name if the publisher owns it (trust signal) |
opns.outpoint | No | Outpoint of the OpNS name ordinal |
AIP Signature
The manifest is signed using AIP (Author Identity Protocol) to prove authorship:
AIP BITCOIN_ECDSA <signerAddress> <signature>The signature covers the MAP protocol data, enabling any indexer to verify the publisher's identity without trusting a central registry.
Registry Types
All types use the registry: prefix for consistency across the shadcn ecosystem and ClawNet extensions.
shadcn/ui Standard Types
| Type | Description |
|---|---|
registry:lib | Utility libraries |
registry:block | Multi-component page sections (hero, pricing table) |
registry:component | Reusable UI components |
registry:ui | Base UI primitives |
registry:hook | React hooks |
registry:page | Full page templates |
registry:file | Generic file (not categorized) |
registry:font | Individual font file with metadata (family, weights, subsets) |
registry:style | CSS variables and rules — color schemes, typography presets, spacing |
registry:theme | Complete visual theme — style + bundled assets (fonts, patterns, wallpapers) |
registry:example | Example/demo code |
registry:internal | Internal implementation files |
ClawNet Extension Types
| Type | Description |
|---|---|
registry:skill | AI agent skills (SKILL.md + reference files) |
registry:agent | AI agent definitions (frontmatter + system prompt) |
registry:app | Full web applications published on-chain (APP.md + assets) |
registry:organization | Agent organizations (agent roster + skills) |
registry:app
A full web application published on-chain via APP.md manifest. Interoperable with the metanet-apps package — apps broadcast to the tm_apps overlay topic are discoverable by any wallet.
APP.md frontmatter:
---
name: my-app
description: What the app does
domain: myapp.com
icon: https://myapp.com/icon.png
version: 1.0.0
httpURL: https://myapp.com
category: DeFi
tags: [trading, tokens]
banner_image_url: https://myapp.com/banner.png
screenshot_urls: [https://myapp.com/s1.png]
---Required fields: name, description, domain, icon, version
MAP metadata:
MAP SET app clawnet type registry:app name my-app version 1.0.0 description "..." domain myapp.com icon https://...Overlay discovery: App tokens can be broadcast to the tm_apps overlay topic using the PushDrop protocol ([1, 'metanet apps']). The APP.md frontmatter maps directly to the PublishedAppMetadata interface, enabling cross-wallet app catalog discovery.
Publishing an app on-chain:
import { buildPackageOutputs } from "@1sat/templates";
const files = [
{ path: "APP.md", content: appMdContent, contentType: "text/markdown" },
{ path: "icon.png", content: iconBytes, contentType: "image/png" },
];
const metadata = {
app: "clawnet",
type: "registry:app",
name: "my-app",
version: "1.0.0",
description: "My web application",
domain: "myapp.com",
icon: "https://myapp.com/icon.png",
};
const { outputs, manifestVout } = await buildPackageOutputs(
files, metadata, signingKey
);
// outputs — ready for createAction()
// manifestVout — index of the manifest outputAny registry service can index registry:app inscriptions by querying for transactions matching MAP SET type registry:app. The overlay topic tm_apps provides an additional discovery channel for wallets and app catalogs.
Design Asset Types
Design assets form a composability stack: individual fonts are installable standalone, styles compose fonts into typography systems, and themes bundle everything into a complete visual package.
registry:font
An individual font file with metadata describing its typographic properties. The manifest wraps a single font file (.woff2, .woff, .ttf) with structured metadata.
Transaction structure:
Output 0: font file inscription (font/woff2, 1 sat)
Output 1: manifest (ord-fs/json, 1 sat, MAP + AIP)
{ "space-grotesk.woff2": "_0" }Additional MAP fields for fonts:
| Field | Required | Description |
|---|---|---|
font.family | Yes | CSS font-family name (e.g. Space Grotesk Variable) |
font.variable | Yes | CSS custom property name (e.g. --font-space-grotesk) |
font.weight | No | JSON array of available weights (e.g. ["400","500","700"]) |
font.subsets | No | JSON array of character subsets (e.g. ["latin","cyrillic"]) |
font.style | No | Font style — normal or italic (default: normal) |
license | No | License identifier (e.g. OFL-1.1, CC0, MIT) |
Example MAP:
MAP SET app theme-token type registry:font name space-grotesk
version 1.0.0 description "Space Grotesk variable weight sans-serif"
font.family "Space Grotesk Variable" font.variable "--font-space-grotesk"
font.weight ["400","500","600","700"] font.subsets ["latin","latin-ext"]
license OFL-1.1 categories ["sans-serif","variable","geometric"]registry:style
CSS variables and rules without bundled asset files. Styles are composable — they reference fonts and other styles via registryDependencies rather than bundling them.
Use cases:
- Color schemes — OKLCH color variables for light/dark modes
- Typography presets — font variable mappings + typographic scale (h1-h6 sizing, line-height, letter-spacing)
- Spacing/radius presets — design token variables
Typography style example:
A typography preset maps semantic CSS variables (--font-heading, --font-body, --font-mono) to specific fonts and defines a typographic scale. It declares the fonts as registryDependencies — the installer resolves the dependency chain.
MAP SET app theme-token type registry:style name editorial
version 1.0.0 description "High-contrast editorial typography"
registryDependencies ["playfair-display","dm-sans","jetbrains-mono"]
categories ["serif","editorial","contrast"]Transaction structure:
Output 0: style.json (application/json, 1 sat) — the CSS configuration
Output 1: manifest (ord-fs/json, 1 sat, MAP + AIP)
{ "style.json": "_0" }File content (style.json at output 0):
{
"cssVars": {
"theme": {
"--font-heading": "var(--font-playfair-display)",
"--font-body": "var(--font-dm-sans)",
"--font-mono": "var(--font-jetbrains-mono)"
}
},
"css": {
"@layer base": {
"h1": { "font-family": "var(--font-heading)", "font-size": "2.25rem", "line-height": "1.2", "letter-spacing": "-0.02em" },
"h2": { "font-family": "var(--font-heading)", "font-size": "1.875rem", "line-height": "1.3" },
"body, p": { "font-family": "var(--font-body)", "line-height": "1.65" },
"code, pre": { "font-family": "var(--font-mono)" }
}
}
}Color style example:
{
"cssVars": {
"light": {
"--background": "oklch(0.98 0.01 240)",
"--foreground": "oklch(0.15 0.02 240)",
"--primary": "oklch(0.55 0.25 260)"
},
"dark": {
"--background": "oklch(0.15 0.02 240)",
"--foreground": "oklch(0.95 0.01 240)",
"--primary": "oklch(0.65 0.25 260)"
}
}
}Styles that reference no font files have no registryDependencies and are self-contained — just CSS variables inscribed as JSON.
registry:theme
A complete visual package that bundles styles with actual asset files (fonts, patterns, wallpapers). The manifest is a pure ord-fs/json directory — only string→string file mappings. Style configuration lives in a separate theme.json file that the manifest points to.
Transaction structure (theme with bundled font and pattern):
Output 0: font file (font/woff2, 1 sat)
Output 1: pattern file (image/svg+xml, 1 sat)
Output 2: theme.json (application/json, 1 sat) — style definition
Output 3: manifest (ord-fs/json, 1 sat, MAP + AIP) — pure directory
{ "font.woff2": "_0", "pattern.svg": "_1", "theme.json": "_2" }Manifest content (pure directory — no inline config):
{
"font.woff2": "_0",
"pattern.svg": "_1",
"theme.json": "_2"
}theme.json content (at output 2):
{
"cssVars": {
"light": { "--background": "oklch(0.98 0.01 240)", "--foreground": "oklch(0.15 0.02 240)" },
"dark": { "--background": "oklch(0.15 0.02 240)", "--foreground": "oklch(0.95 0.01 240)" },
"theme": {
"--font-heading": "var(--font-space-grotesk)",
"--font-body": "var(--font-space-grotesk)",
"--radius": "0.5rem"
}
}
}The manifest is always a pure ord-fs/json directory — ORDFS needs clean string→string mappings to traverse. Style configuration, CSS variables, and any structured data live in separate files (like theme.json) that the manifest points to.
The key distinction between types: a registry:theme bundles its assets as sibling inscription outputs (assets travel with the theme). A registry:style references assets externally via registryDependencies (enables reuse across themes). Both are valid approaches.
Cross-Registry Publishing
The registry package format is designed for cross-registry interoperability. Components from any shadcn-compatible registry can be published on-chain:
| Source Registry | Type | Example |
|---|---|---|
| BigBlocks | registry:block, registry:ui | Bitcoin wallet components, social feeds |
| FontTrio | registry:font, registry:style | Font packages, curated typography presets |
| theme-token | registry:theme, registry:style | Visual themes with bundled fonts/patterns |
| ClawNet | registry:skill, registry:agent | AI agent skills and configurations |
All registries share the same registry:* type system, _N relative vout references, and ord-fs/json manifest format. A component published on-chain is installable via any compatible gateway:
bunx shadcn@latest add https://clawnet.sh/r/blocks/bitcoin-avatar
bunx shadcn@latest add https://bigblocks.dev/r/bitcoin-avatar.json
bunx shadcn@latest add https://themetoken.dev/r/themes/{origin}All serve the same shadcn-compatible JSON — from on-chain data or registry servers.
Language Support
The language field uses BCP 47 language tags to declare the primary language of a package's content. This enables:
- Filtering: Registries can filter and sort by language
- Discovery: Users find packages in their preferred language
- Indexing: Search engines and AI systems can index content appropriately
Common values:
| Tag | Language |
|---|---|
en | English |
zh | Chinese |
ja | Japanese |
ko | Korean |
es | Spanish |
fr | French |
de | German |
pt | Portuguese |
ru | Russian |
ar | Arabic |
Packages without a language field are assumed to be English (en).
Installation Protocols
Registry items support multiple installation paths:
By OpNS Name
When the publisher owns the OpNS name matching their package slug:
npx clawnet add humanizeThe CLI resolves the OpNS name on-chain, finds the bound identity key, looks up the latest manifest outpoint, and installs from ORDFS.
By Outpoint
Direct installation from a manifest outpoint:
npx clawnet add {txid}_{vout}By shadcn CLI
Registry items are compatible with the shadcn CLI protocol:
bunx shadcn@latest add https://clawnet.sh/r/skills/humanize
bunx shadcn@latest add https://clawnet.sh/r/themes/{origin}
bunx shadcn@latest add https://clawnet.sh/r/components/{origin}The gateway at /r/{type}/{origin} fetches the manifest from ORDFS, hydrates file content from sibling inscriptions, and returns shadcn-compatible JSON.
Version Chaining
Packages form a version chain via the prev MAP field. Each new version references the previous manifest outpoint:
v1.0.0 → manifest_outpoint_a
v1.1.0 → manifest_outpoint_b (prev: manifest_outpoint_a)
v2.0.0 → manifest_outpoint_c (prev: manifest_outpoint_b)This creates a verifiable on-chain history without requiring a central version database.
Registry Discovery
Registries declare themselves on-chain via MAP metadata with app as the registry identifier. Any indexer can discover and aggregate registry items by querying for transactions with:
MAP SET app <registry> type registry:*This enables a decentralized ecosystem where multiple registries can coexist and cross-reference items.
JavaScript Examples
Skill Package
// buildPackageOutputs from the ClawNet CLI package system
import { buildPackageOutputs } from "clawnet/package/package-tx";
const result = await buildPackageOutputs(
[
{ path: "SKILL.md", content: skillBytes, contentType: "text/markdown" },
{ path: "refs/api.md", content: apiBytes, contentType: "text/markdown" },
],
{
app: "clawnet",
type: "registry:skill",
name: "humanize",
version: "1.0.0",
description: "Rewrites AI-generated text to sound natural",
author: "Satchmo",
categories: JSON.stringify(["writing", "style"]),
},
privateKey
);
// result.outputs — ready for createAction()
// result.manifestVout — index of the manifest outputFont Package
const result = await buildPackageOutputs(
[
{ path: "space-grotesk.woff2", content: fontBytes, contentType: "font/woff2" },
],
{
app: "theme-token",
type: "registry:font",
name: "space-grotesk",
version: "1.0.0",
description: "Space Grotesk variable weight sans-serif",
"font.family": "Space Grotesk Variable",
"font.variable": "--font-space-grotesk",
"font.weight": JSON.stringify(["400", "500", "600", "700"]),
"font.subsets": JSON.stringify(["latin", "latin-ext"]),
categories: JSON.stringify(["sans-serif", "variable", "geometric"]),
},
privateKey
);Theme with Bundled Assets
const result = await buildPackageOutputs(
[
{ path: "font.woff2", content: fontBytes, contentType: "font/woff2" },
{ path: "pattern.svg", content: patternBytes, contentType: "image/svg+xml" },
{ path: "theme.json", content: themeJsonBytes, contentType: "application/json" },
],
{
app: "theme-token",
type: "registry:theme",
name: "midnight-editorial",
version: "1.0.0",
description: "Dark editorial theme with serif headings and geometric patterns",
categories: JSON.stringify(["dark", "editorial", "serif"]),
},
privateKey
);Low-Level (without @1sat/actions)
import { Inscription, MAP, AIP, PrivateKeySigner, P2PKH } from "@1sat/templates";
import { PrivateKey, Utils } from "@bsv/sdk";
const p2pkh = new P2PKH().lock(privateKey.toAddress());
// File inscription outputs
const files = [
{ path: "SKILL.md", content: skillMarkdown, contentType: "text/markdown" },
{ path: "example.md", content: exampleDocs, contentType: "text/markdown" },
];
const outputs = files.map(f => {
const inscription = Inscription.create(
new Uint8Array(Utils.toArray(f.content, "utf8")),
f.contentType,
{ scriptPrefix: p2pkh }
);
return { script: inscription.lock(), satoshis: 1 };
});
// ord-fs/json manifest
const manifest = {};
files.forEach((f, i) => { manifest[f.path] = `_${i}`; });
const mapFields = {
app: "clawnet",
type: "registry:skill",
name: "humanize",
version: "1.0.0",
description: "Rewrites AI-generated text to sound natural",
};
const manifestInscription = Inscription.create(
new Uint8Array(Utils.toArray(JSON.stringify(manifest), "utf8")),
"ord-fs/json",
{ scriptPrefix: p2pkh, scriptSuffix: buildMapAipSuffix(mapFields, privateKey) }
);
outputs.push({ script: manifestInscription.lock(), satoshis: 1 });