Overview
OCX registries are collections of components (agents, skills, plugins, commands) distributed as JSON packuments. This guide covers how to build and distribute your own registry.
For the HTTP API specification that registries must implement, see the Registry Protocol.
Quick Start (Cloudflare Workers)
The fastest path is to scaffold a registry project and deploy to Cloudflare Workers:
# Scaffold the registry
ocx init --registry ./my-registry --namespace my-org --author "My Name"
# Build the registry (generates dist/)
cd my-registry && bun run build
# Deploy to Cloudflare Workers
bun run deploy
The build step runs ocx build . --out dist which:
- Validates
registry.jsonc against the schema
- Generates
index.json and component packuments
- Copies component files to
dist/components/
- Generates
.well-known/ocx.json (optional discovery metadata)
ocx init --namespace is a scaffolding input (naming/template convenience). Runtime component refs still use the registry alias chosen by the user via ocx registry add --name <alias>.
Registry Philosophy
OCX follows the Cargo + ShadCN model:
- Registry Name as Identity: Users configure registry names with
ocx registry add --name <name> and reference components as name/component (e.g., kdco/researcher).
- Clean Component Names: Components within a registry use clean names (
researcher, not kdco-researcher). The registry name provides provenance.
- Explicit Trust: Cross-registry dependencies require the user to have that registry configured. No auto-fetching from unknown sources.
- Own Your Code: Components are copied into your project with clean filenames. The receipt file tracks provenance.
Directory Structure
A registry source directory should look like this:
my-registry/
├── registry.jsonc # Registry manifest
└── files/ # Component source files
├── agents/
├── plugins/
├── skills/
└── commands/
Registry Manifest (registry.jsonc)
OCX uses Cargo-style union types for a clean developer experience: use strings for simple cases, objects when you need more control.
{
"$schema": "https://ocx.kdco.dev/schemas/v2/registry.json",
"name": "My Extensions",
"version": "1.0.0",
"author": "Your Name",
"components": [
{
"name": "cool-plugin",
"type": "plugin",
"description": "Does something cool",
"files": ["plugins/my-cool-plugin.ts"],
"dependencies": []
}
]
}
Key fields:
$schema: Required for OCX v2 manifests. Use https://ocx.kdco.dev/schemas/v2/registry.json.
name: Registry display name (human-readable metadata for the registry itself).
- Registry alias: Component resolution uses the alias configured by the user at install time (
ocx registry add <url> --name <alias>). Do not add a top-level namespace field in v2 manifests.
dependencies: Use bare names for same-registry deps (["utils"]), qualified names for cross-registry (["other/utils"]).
Component Types
| Type | Target Directory | Description |
|---|
agent | agents/ | Markdown files defining specialized agents |
skill | skills/ | Instruction sets (must follow skills/<name>/SKILL.md) |
plugin | plugins/ | TypeScript/JavaScript extensions for tools and hooks |
command | commands/ | Markdown templates for TUI commands |
tool | tools/ | Custom tool implementations |
bundle | N/A | Virtual components that install multiple other components |
profile | N/A | Shareable profile configuration |
Cargo-Style Patterns
File References
Use string shorthand when the target can be auto-inferred:
// String shorthand (recommended)
"files": ["plugins/my-plugin.ts"]
// Expands to: { "path": "plugins/my-plugin.ts", "target": "plugins/my-plugin.ts" }
// Full object (when you need a custom target)
"files": [
{
"path": "skills/my-skill/SKILL.md",
"target": "skills/my-skill/SKILL.md"
}
]
MCP Server Shorthand
MCP servers use URL shorthand for remote servers:
"opencode": {
"mcp": {
"context7": "https://mcp.context7.com/mcp"
}
}
// Expands to: { "type": "remote", "url": "https://...", "enabled": true }
OpenCode Config Block
Components can specify settings to merge into the user’s opencode.jsonc:
{
"name": "my-agent",
"type": "agent",
"files": ["agents/my-agent.md"],
"opencode": {
"plugin": ["@some-org/opencode-plugin"],
"tools": { "webfetch": false },
"agent": {
"my-agent": { "temperature": 0.7 }
}
}
}
| Field | Description |
|---|
opencode.mcp | MCP servers (URL shorthand or full config) |
opencode.plugin | npm packages added to opencode.jsonc plugin array |
opencode.tools | Global tool enable/disable settings |
opencode.agent | Per-agent configuration (tools, temperature, permission, prompt) |
opencode.permission | Permission settings for bash/edit/mcp |
opencode.instructions | Global instructions appended to config |
Plugin Discovery vs Registration
OpenCode handles plugins in two ways:
File-Based Plugins (Auto-Discovered)
Registry components with type: "plugin" install files to the plugins/ directory. OpenCode automatically discovers them — no configuration needed.
ocx add kdco/workspace-plugin
# Installs to: plugins/workspace-plugin.ts
# OpenCode auto-discovers it
npm Plugins (Explicitly Registered)
npm plugins installed via ocx add npm:package-name require registration in opencode.jsonc:
ocx add npm:@franlol/opencode-md-table-formatter
# Adds to opencode.jsonc: {"plugin": ["@franlol/opencode-md-table-formatter"]}
Instruction Files for Components
Config-Based Instructions (Recommended)
Use custom paths with the instructions config field:
{
"name": "my-component",
"type": "bundle",
"files": ["instructions/my-guidelines.md"],
"opencode": {
"instructions": ["instructions/my-guidelines.md"]
}
}
Path Resolution for Registry Components:
- Paths are install-root-relative (not cwd-relative)
- OCX resolves them to absolute paths at runtime
- Absolute paths are NOT allowed
When installed, instructions/style-guide.md resolves to:
- Project:
.opencode/instructions/style-guide.md
- Profile:
~/.config/opencode/profiles/myprofile/instructions/style-guide.md
- Global:
~/.config/opencode/instructions/style-guide.md
Do not install instruction files to AGENTS.md, CLAUDE.md, or CONTEXT.md in standard locations. These are reserved for user project-specific instructions and can cause conflicts.
Dependencies
Same-Registry Dependencies
Use bare component names:
{
"name": "researcher",
"dependencies": ["background-agents", "utils"]
}
Cross-Registry Dependencies
Use qualified names:
{
"name": "researcher",
"dependencies": ["background-agents", "acme/shared-utils"]
}
The user must have the acme registry configured in their ocx.jsonc for cross-registry deps to resolve.
Building
Use the OCX CLI to validate and build your registry:
ocx build ./my-registry --out dist
This validates your registry.jsonc, verifies dependencies, and generates index.json plus individual packument files.
Distribution
OCX registries are static JSON files that can be hosted anywhere:
Cloudflare Workers (Recommended)
// wrangler.jsonc
{
"name": "my-registry",
"assets": { "directory": "./dist" }
}
Deploy with wrangler deploy after building.
Other Hosting Options
- GitHub Pages, Vercel, Netlify — Pre-build with
ocx build
- Any HTTP server — Serve the
dist/ directory as static files
Registry Discovery (Optional)
Add a /.well-known/ocx.json endpoint to enable automatic discovery:
{
"registry": "/index.json"
}
OCX currently validates registries by requesting <url>/index.json directly during ocx registry add; it does not resolve /.well-known/ocx.json automatically in that path.
Use a URL whose /index.json is directly available:
ocx registry add https://example.com --name my
Adding and Using Registries
# Add the registry
ocx registry add https://example.com/registry --name my
# Install components
ocx add my/cool-plugin
Conflict Handling
If installing a component would overwrite an existing file from a different component:
$ ocx add acme/researcher
Error: File conflict detected
agents/researcher.md already exists (installed from kdco/researcher)
To resolve:
1. Remove existing file and update receipt
2. Or rename existing file manually
3. Then retry: ocx add acme/researcher
See Also
- Registry Protocol — HTTP API specification for OCX registries.
- ocx build — CLI command reference for building registries.
- ocx init — Scaffold a new registry project with
--registry.