Publish a plugin

Three commands from scaffolding to published package.

1. Create

Scaffold a new plugin. Pick a sandbox: quickjs for JS, wasm for compiled code, nsjail for system access.

$ bext plugin init my-plugin --sandbox quickjs

2. Test

Run your plugin locally. Hot-reloads on save, shows sandbox logs.

$ bext dev --plugin ./my-plugin

3. Publish

Authenticates via GitHub, runs security scans, and makes the plugin available.

$ bext plugin publish

Manifest

Every plugin needs a bext.plugin.toml at the root.

bext.plugin.toml
[plugin]
name = "bext-plugin-my-plugin"
version = "1.0.0"
description = "What your plugin does"
license = "MIT"
author = "your-github-username"

[plugin.sandbox]
type = "quickjs"       # quickjs | wasm | nsjail
memory_limit = "64mb"
timeout = "5s"

[plugin.hooks]
on_request = "src/on_request.ts"
on_response = "src/on_response.ts"

[plugin.config]
api_key = { type = "string", required = true, env = "MY_PLUGIN_API_KEY" }
max_retries = { type = "integer", default = 3 }

Hooks

Plugins hook into the request lifecycle. Intercept requests, modify responses, or run background work.

src/on_request.ts
import type { BextRequest, BextResponse } from "bext:plugin";

export function onRequest(req: BextRequest): BextRequest | BextResponse {
  const apiKey = req.headers.get("x-api-key");
  if (!apiKey) {
    return new BextResponse("Unauthorized", { status: 401 });
  }
  return req;
}

export function onResponse(req: BextRequest, res: BextResponse): BextResponse {
  res.headers.set("X-Plugin-Version", "1.0.0");
  return res;
}

Guidelines

  • Names must start with bext-plugin-
  • Include a README with usage examples
  • Pin sandbox memory and timeout limits
  • Add at least one integration test
  • Use semver for releases
  • Don't bundle secrets in the package