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:

typescript
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:

MethodDescription
host.manifestThe parsed oxp.json manifest
host.filesBundled 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

typescript
import { clipboard } from "@oxprotocol/sdk";

const cb = clipboard(host);
const text = await cb.read();
await cb.write("copied!");

Storage

typescript
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

typescript
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:

typescript
import type { OxpManifest } from "@oxprotocol/sdk";

const manifest: OxpManifest = host.manifest;
console.log(manifest.version);

Lifecycle

Extensions follow a simple lifecycle:

  1. Activate — called once when the extension loads. Set up your UI, register commands, connect to services.
  2. 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.