Skip to content

Plugin Manifest

Suggest Edits

Every plugin starts with bakin-plugin.json. Bakin reads this file before loading plugin code, so keep it explicit and stable. The manifest is not just package metadata. It is the review surface for installers, permissions, public contributions, docs generation, and lifecycle decisions.

The tested manifest fixture for these docs lives at docs/snippets/plugin-basic/bakin-plugin.json.

Source: docs/snippets/plugin-basic/bakin-plugin.json

{
"id": "docs-basic",
"name": "Docs Basic",
"version": "0.1.0",
"bakin": ">=0.1.0",
"description": "Minimal plugin used by the public Bakin docs.",
"entry": {
"server": "index.ts",
"client": "client.tsx"
},
"contributes": {
"apiRoutes": [
{
"method": "GET",
"path": "/hello",
"summary": "Say hello",
"description": "Returns a small JSON payload from the docs example plugin.",
"visibility": "public",
"stability": "stable",
"responses": {
"200": {
"description": "Greeting payload"
}
}
}
],
"clientRoutes": [
{
"path": "/docs-basic",
"summary": "Minimal docs plugin page"
}
]
},
"permissions": [
"storage.read"
]
}
FieldMeaning
idStable machine ID. Must match ^[a-z][a-z0-9-]{0,39}$.
nameHuman-readable plugin name.
versionPlugin version. Use SemVer.
bakinCompatible Bakin version range.
descriptionShort public summary.
entry.serverServer entry loaded by the plugin runtime.
FieldMeaning
entry.clientBrowser entry loaded into the Bakin shell.
contentFilesFiles the plugin contributes under Bakin content.
secretsSecret names the plugin expects.
testsPlugin-local test command.
dependenciesOther Bakin plugin IDs that must be available before this plugin loads.
permissionsCapability labels used for install consent and runtime permission checks.
runtimeCapabilitiesRuntime adapter capabilities the plugin needs, such as tasks, search, models, or channels.message.
contributesPublic API, UI, CLI, settings, exec tool, and docs metadata.
devWatchExtra plugin-local paths to watch during development.
signatureOptional Ed25519 manifest signature. Enforced only when settings.plugins.requireSignatures is true.

By default, plugin installs use trust-on-first-use: unsigned manifests are accepted, then Bakin records the installed source and manifest hash in the plugin lockfile.

Set settings.plugins.requireSignatures to true to fail closed for unsigned, untrusted, or tampered manifests during install, dev-link, and upgrade. Trusted roots live in settings.plugins.trustedSigners and may be a sha256:<hex> public-key fingerprint, a raw base64 Ed25519 SPKI public key, or ed25519:<base64-public-key>.

When present, signature has this shape:

{
"signature": {
"algorithm": "ed25519",
"signer": "markhayden",
"publicKey": "base64-spki-public-key",
"signature": "base64-signature"
}
}

The signature covers canonical JSON for bakin-plugin.json with the top-level signature block omitted. signer is display metadata; trust is bound to the public key or fingerprint.

contributes tells Bakin what the plugin exposes before code runs.

ContributionRequired core fields
apiRoutes[]method, plugin-relative path, summary
clientRoutes[]app path, summary
execTools[]name, summary
cliCommands[]name, usage, summary, dispatch
settings[]key, summary
docsslug

API route paths are plugin-relative. A route declared as /hello is exposed under /api/plugins/{pluginId}/hello. Do not declare /api/... paths in a plugin manifest.

Exec tool names must use the plugin-owned MCP namespace: bakin_exec_{pluginId}_{action}. The manifest declaration and runtime ctx.registerExecTool() call must agree. Bakin rejects undeclared tools, duplicate tool names, and user plugin tools that register outside their own plugin prefix.

Declare permissions before calling the corresponding APIs.

PermissionTypical use
events.emitBroadcast Server-Sent Events to connected browsers
assets.readRead asset metadata and runtime-deliverable asset references
runtime.readRead general runtime adapter state
runtime.agentsRead runtime agent identity and status
runtime.messagingSend messages through the runtime adapter
runtime.channelsSend messages or content to configured runtime channels
runtime.cronCreate and manage runtime cron jobs
runtime.skillsRead runtime skills
runtime.modelsRead runtime model metadata
search.readQuery Bakin search indexes
search.writeRegister or mutate plugin-owned search indexes
storage.readRead files in ~/.bakin/
storage.writeWrite files in ~/.bakin/
tasks.readRead tasks through the public task service
tasks.writeCreate and mutate tasks through the public task service

Runtime permission mode may warn or enforce depending on configuration. Missing declarations are still bugs: they show up in audit trails and can become hard failures.

  • Treat id as permanent once users install the plugin.
  • Keep entry paths relative to the plugin root.
  • Declare plugin dependencies by plugin ID. bakin plugins install refuses a plugin when a dependency is neither core nor already installed.
  • Keep contributes in sync with registered routes, tools, settings, and docs.
  • Use runtimeCapabilities for adapter-level needs and permissions for plugin capability consent.
  • Import supported APIs from @makinbakin/sdk and @makinbakin/sdk/*.

Docs examples that show real files should be backed by snippet fixtures. bun run docs:check validates bakin shell commands, source-backed snippets, generated docs blocks, route metadata, JSON fences, and the docs site build.