Fundamentals
Extension SDK
Use @oxprotocol/sdk to define extensions with typed APIs for host interaction.
@oxprotocol/sdk is the author-facing SDK for OXP extensions. It provides defineExtension(), the HostApi interface, and typed wrappers around host capabilities. It works across VS Code webviews, Piye Workers, and oxp dev.
defineExtension
Every extension's entry module exports a definition:
import { defineExtension } from "@oxprotocol/sdk";
export default defineExtension({
async activate(host) {
host.log("info", "Extension activated!");
host.renderHtml("<h1>Hello, OXP!</h1>");
},
deactivate(host) {
host.log("info", "Extension deactivated.");
},
});defineExtension() is an identity helper — it provides full IntelliSense without any runtime overhead.
The HostApi
The host object injected into activate() provides the runtime API:
| Method | Description |
|---|---|
host.manifest | The parsed oxp.json manifest |
host.files | Bundled files as a ReadonlyMap<string, Uint8Array> |
host.renderHtml(html) | Render raw HTML in the extension panel |
host.renderTree(tree) | Render an @oxprotocol/ui component tree |
host.capability(name, args) | Call a host capability by name |
host.log(level, message, data) | Log to the host output channel |
Capability Helpers
Instead of stringly-typed host.capability() calls, use the typed helpers:
Clipboard
import { clipboard } from "@oxprotocol/sdk";
const cb = clipboard(host);
const text = await cb.read();
await cb.write("copied!");Storage
import { storage } from "@oxprotocol/sdk";
const store = storage(host);
await store.set("count", 42);
const val = await store.get("count");
await store.delete("count");Network
import { net } from "@oxprotocol/sdk";
const api = net(host);
const response = await api.fetch("https://api.example.com/data");
const data = await response.json();Network calls are routed through the capability broker. The user must grant net.fetch permission, and the URL must match the scope declared in your manifest.Typed Manifests
Use OxpManifest for type-safe manifest access:
import type { OxpManifest } from "@oxprotocol/sdk";
const manifest: OxpManifest = host.manifest;
console.log(manifest.version);Lifecycle
Extensions follow a simple lifecycle:
- Activate — called once when the extension loads. Set up your UI, register commands, connect to services.
- Deactivate — called on uninstall, host shutdown, or eviction. Clean up resources. Best-effort — the host may kill the instance if this exceeds its time budget.
Both are optional, but at least activate should be provided to do anything useful.