package.json should point runtime loading at built
JavaScript when available:
extensions and setupEntry remain valid source entries for workspace and git
checkout development. runtimeExtensions and runtimeSetupEntry are preferred
when FluffBuzz loads an installed package and let npm packages avoid runtime
TypeScript compilation. If an installed package only declares a TypeScript
source entry, FluffBuzz will use a matching built dist/*.js peer when one
exists, then fall back to the TypeScript source.
All entry paths must stay inside the plugin package directory. Runtime entries
and inferred built JavaScript peers do not make an escaping extensions or
setupEntry source path valid.
definePluginEntry
Import: fluffbuzz/plugin-sdk/plugin-entry
For provider plugins, tool plugins, hook plugins, and anything that is not
a messaging channel.
| Field | Type | Required | Default |
|---|---|---|---|
id | string | Yes | — |
name | string | Yes | — |
description | string | Yes | — |
kind | string | No | — |
configSchema | FluffBuzzPluginConfigSchema | () => FluffBuzzPluginConfigSchema | No | Empty object schema |
register | (api: FluffBuzzPluginApi) => void | Yes | — |
idmust match yourfluffbuzz.plugin.jsonmanifest.kindis for exclusive slots:"memory"or"context-engine".configSchemacan be a function for lazy evaluation.- FluffBuzz resolves and memoizes that schema on first access, so expensive schema builders only run once.
defineChannelPluginEntry
Import: fluffbuzz/plugin-sdk/channel-core
Wraps definePluginEntry with channel-specific wiring. Automatically calls
api.registerChannel({ plugin }), exposes an optional root-help CLI metadata
seam, and gates registerFull on registration mode.
| Field | Type | Required | Default |
|---|---|---|---|
id | string | Yes | — |
name | string | Yes | — |
description | string | Yes | — |
plugin | ChannelPlugin | Yes | — |
configSchema | FluffBuzzPluginConfigSchema | () => FluffBuzzPluginConfigSchema | No | Empty object schema |
setRuntime | (runtime: PluginRuntime) => void | No | — |
registerCliMetadata | (api: FluffBuzzPluginApi) => void | No | — |
registerFull | (api: FluffBuzzPluginApi) => void | No | — |
setRuntimeis called during registration so you can store the runtime reference (typically viacreatePluginRuntimeStore). It is skipped during CLI metadata capture.registerCliMetadataruns during bothapi.registrationMode === "cli-metadata"andapi.registrationMode === "full". Use it as the canonical place for channel-owned CLI descriptors so root help stays non-activating while normal CLI command registration remains compatible with full plugin loads.registerFullonly runs whenapi.registrationMode === "full". It is skipped during setup-only loading.- Like
definePluginEntry,configSchemacan be a lazy factory and FluffBuzz memoizes the resolved schema on first access. - For plugin-owned root CLI commands, prefer
api.registerCli(..., { descriptors: [...] })when you want the command to stay lazy-loaded without disappearing from the root CLI parse tree. For channel plugins, prefer registering those descriptors fromregisterCliMetadata(...)and keepregisterFull(...)focused on runtime-only work. - If
registerFull(...)also registers gateway RPC methods, keep them on a plugin-specific prefix. Reserved core admin namespaces (config.*,exec.approvals.*,wizard.*,update.*) are always coerced tooperator.admin.
defineSetupPluginEntry
Import: fluffbuzz/plugin-sdk/channel-core
For the lightweight setup-entry.ts file. Returns just { plugin } with no
runtime or CLI wiring.
defineSetupPluginEntry(...) with the narrow setup helper
families:
fluffbuzz/plugin-sdk/setup-runtimefor runtime-safe setup helpers such as import-safe setup patch adapters, lookup-note output,promptResolvedAllowFrom,splitSetupEntries, and delegated setup proxiesfluffbuzz/plugin-sdk/channel-setupfor optional-install setup surfacesfluffbuzz/plugin-sdk/setup-toolsfor setup/install CLI/archive/docs helpers
defineBundledChannelSetupEntry(...) from
fluffbuzz/plugin-sdk/channel-entry-contract instead. That contract lets the
setup entry keep setup-safe plugin/secrets exports while still exposing a
runtime setter:
Registration mode
api.registrationMode tells your plugin how it was loaded:
| Mode | When | What to register |
|---|---|---|
"full" | Normal gateway startup | Everything |
"setup-only" | Disabled/unconfigured channel | Channel registration only |
"setup-runtime" | Setup flow with runtime available | Channel registration plus only the lightweight runtime needed before the full entry loads |
"cli-metadata" | Root help / CLI metadata capture | CLI descriptors only |
defineChannelPluginEntry handles this split automatically. If you use
definePluginEntry directly for a channel, check mode yourself:
"setup-runtime" as the window where setup-only startup surfaces must
exist without re-entering the full bundled channel runtime. Good fits are
channel registration, setup-safe HTTP routes, setup-safe gateway methods, and
delegated setup helpers. Heavy background services, CLI registrars, and
provider/client SDK bootstraps still belong in "full".
For CLI registrars specifically:
- use
descriptorswhen the registrar owns one or more root commands and you want FluffBuzz to lazy-load the real CLI module on first invocation - make sure those descriptors cover every top-level command root exposed by the registrar
- use
commandsalone only for eager compatibility paths
Plugin shapes
FluffBuzz classifies loaded plugins by their registration behavior:| Shape | Description |
|---|---|
| plain-capability | One capability type (e.g. provider-only) |
| hybrid-capability | Multiple capability types (e.g. provider + speech) |
| hook-only | Only hooks, no capabilities |
| non-capability | Tools/commands/services but no capabilities |
fluffbuzz plugins inspect <id> to see a plugin’s shape.
Related
- SDK Overview — registration API and subpath reference
- Runtime Helpers —
api.runtimeandcreatePluginRuntimeStore - Setup and Config — manifest, setup entry, deferred loading
- Channel Plugins — building the
ChannelPluginobject - Provider Plugins — provider registration and hooks