Fundamentals

The Manifest

Complete field-by-field reference for oxp.json — the heart of every OXP extension.

Every OXP extension is defined by a single oxp.json file at its root. This manifest declares identity, permissions, entry points, compatibility, and more. It conforms to the JSON Schema at spec/v1/manifest.schema.json.

Minimal Example

json
{
  "specVersion": "1",
  "id": "@acme/hello",
  "publisher": "acme",
  "version": "1.0.0",
  "displayName": "Hello Extension",
  "license": "MIT",
  "engines": { "oxp": "^1.0.0" },
  "main": { "ui": "ui/index.html" },
  "permissions": []
}

Field Reference

Identity Fields

FieldTypeRequiredDescription
specVersion"1"Always "1" for v1 extensions
idstringUnique ID in @publisher/slug format
publisherstringLowercase kebab-case handle, must match the id
versionstringStrict semver 2.0.0 (e.g. "1.2.3")
displayNamestringHuman-readable name shown in UIs
descriptionstringShort description for search and browse
licensestringSPDX identifier or "UNLICENSED"

Entry Points

The main object tells the host how to load your extension:

json
{ "main": { "ui": "ui/index.html" } }
{ "main": { "wasm": "wasm/core.wasm" } }
{ "main": { "ui": "ui/index.html", "wasm": "wasm/core.wasm" } }

At least one of ui or wasm is required. Setting both creates a hybrid-v1 bundle.

Bundle Kind

json
{ "kind": "ui-v1" }

Explicit classification. When omitted, derived from main:

  • main.ui only → ui-v1 (declarative, no code)
  • main.wasm only → component-v1 (WASI component)
  • Both → hybrid-v1

Permissions

json
{
  "permissions": [
    { "id": "fs.read", "scope": ["/workspace/**"], "rationale": "Read project files" },
    { "id": "net.fetch", "scope": ["https://api.example.com/*"], "rationale": "Fetch data" }
  ]
}

Each permission has an id from the capability catalog, optional scope globs, and a rationale shown to users at install. See Permissions for the full catalog.

UI Hints

json
{
  "ui": {
    "components": "oxp-ui-v1",
    "preferredSurface": "panel",
    "themeable": true
  }
}
ValueMeaning
oxp-ui-onlyDeclarative tree only, no code execution path
oxp-ui-v1Standard V1 component vocabulary
escape-hatchFull HTML/JS (deprecated — closed by WASM pivot)

preferredSurface can be "sidebar", "panel", "editor", "modal", or "statusbar".

Host Compatibility

json
{
  "hosts": {
    "vscode": { "compatible": true, "minVersion": "1.95.0" },
    "cursor": { "compatible": true },
    "jetbrains": { "compatible": false, "reason": "L2 adapter pending" }
  }
}

Contributions

The contributes object declares UI surfaces and behaviors your extension registers with the host. Each contribution is declarative — the host parses it at install time and wires up the chrome (commands, view containers, menus) without running any of your code. This is what lets a single bundle paint native UI in VS Code, Cursor, Windsurf, VSCodium, and JetBrains.

json
{
  "contributes": {
    "commands": [ ... ],
    "viewsContainers": { ... },
    "views": { ... },
    "keybindings": [ ... ],
    "mcpServers": [ ... ]
  }
}

Contributions may be inlined as shown, or pulled from sibling files for tidiness:

json
{
  "contributes": {
    "commands": "contributions/commands.json",
    "viewsContainers": "contributions/viewsContainers.json"
  }
}

contributes.commands

Each command registers a callable handler that shows up in the IDE's command palette and can be bound to keybindings, menus, or invoked programmatically by your extension.

json
{
  "contributes": {
    "commands": [
      {
        "id": "hello.greet",
        "title": "Hello: Greet the World",
        "category": "Hello",
        "icon": "$(megaphone)",
        "when": "workspaceFolderCount > 0"
      },
      {
        "id": "hello.refresh",
        "title": "Hello: Refresh View",
        "category": "Hello",
        "icon": "$(refresh)"
      }
    ]
  }
}
FieldTypeRequiredDescription
idstringyesUnique within the extension. Convention: <prefix>.<verb> (e.g. hello.greet)
titlestringyesShown in the command palette and menus
categorystringnoGroups commands in the palette (e.g. "Hello"Hello: Greet the World)
iconstringnoCodicon ($(name)) on VS Code family; mapped to the closest IntelliJ icon on JetBrains
whenstringnoBoolean expression evaluated against host context keys; command is hidden when false

Commands are dispatched to your extension over the commands/execute RPC. Register the handler in your extension code:

ts
import { commands } from "@oxprotocol/sdk";

commands.register("hello.greet", async () => {
  // your handler
});

contributes.viewsContainers

A view container is a top-level UI slot in the IDE chrome — the activity-bar icon (VS Code family) or tool-window stripe button (JetBrains) that owns your extension's sidebar.

json
{
  "contributes": {
    "viewsContainers": {
      "activitybar": [
        {
          "id": "hello-sidebar",
          "title": "Hello",
          "icon": "media/hello.svg"
        }
      ],
      "panel": [
        {
          "id": "hello-panel",
          "title": "Hello Logs",
          "icon": "$(output)"
        }
      ]
    }
  }
}
FieldTypeRequiredDescription
idstringyesReferenced by contributes.views to mount views inside this container
titlestringyesTooltip text and accessible label
iconstring \$(codicon)yesPath to an SVG (16×16, monochrome) or a codicon reference

Two locations are supported in v0.1:

  • activitybar — the vertical icon strip on the left in VS Code family, the right tool-window stripe in JetBrains.
  • panel — the horizontal bottom panel in VS Code family, the bottom tool-window strip in JetBrains.

Views inside a container are declared with contributes.views (keyed by container id) — covered separately in UI Components.

contributes.keybindings

json
{
  "contributes": {
    "keybindings": [
      { "command": "hello.greet", "key": "ctrl+alt+h", "mac": "cmd+alt+h" }
    ]
  }
}

contributes.mcpServers

Auto-registers Model Context Protocol servers with the IDE's MCP client. See the MCP Integration guide for the full schema.

Categories

Valid categories: ai, database, data-tools, debuggers, devops, editor, education, formatters, language-support, linters, notebooks, other, productivity, scm, snippets, testing, themes, visualization.

WIT Pin (Component Extensions)

Required for component-v1 and hybrid-v1 bundles:

json
{
  "wit": {
    "package": "oxp:extension",
    "version": "0.1.0",
    "sha256": "a1b2c3..."
  }
}

The SHA-256 is computed over the canonical form of the WIT world. The registry rejects mismatches on publish; the host refuses to instantiate mismatched components on install.

Resource Limits

json
{
  "limits": {
    "timeMsPerCall": 100,
    "maxMemoryMb": 64
  }
}
LimitDefaultMaximum
timeMsPerCall100 ms5,000 ms
maxMemoryMb64 MiB256 MiB

Auto-Generated Fields

These are set by oxp publish — do not write them by hand:

  • **integrity.bundleSha256** — SHA-256 of the uncompressed tar stream
  • **integrity.signedBy** — publisher key ID
  • **integrity.signatureAlgo** — "ed25519" or "sigstore"