StreamNook
StreamNook

Plugin Development

Building Plugins

What StreamNook plugins are, the two runtime kinds, and how the whole system fits together.

What a plugin is

A plugin is an opt-in add-on you build and a user installs. The user grants it permissions, and they can disable or remove it at any time. The StreamNook core binary ships with zero plugins. It contains none of their behavior and gives them nothing beyond the narrow surfaces documented here.

Note

Plugins are entirely opt-in. The core does nothing a plugin does until a user installs that plugin and grants it the permissions it asks for. Everything not granted is denied by default.

This page is the starting point for building one. If you only want to install and manage plugins as a user, see the Plugins page instead.

The two runtime kinds

The first decision you make is which runtime kind you are building. There are two, plus a combined shape.

KindWhat it isBest forLanguage
processA separate executable that runs beside the app and talks JSON-RPC over stdioBackground behavior: long-running loops, its own networking, work that should keep going whether or not any window is openAny language that can read stdin and write stdout
uiA JavaScript module the app loads into its own interfaceInterface features the user sees and operates: panels, title-bar buttons, popout windows, palette commands, hotkeysTypeScript or JavaScript, bundled to one ES module

A third shape, hybrid, is a process plugin that also ships a ui module. The executable does the background work, and the module contributes the native controls and settings screen. Both halves install, enable, and disable as one plugin.

Choosing a kind

Does it run in the background?

If the feature is something the app does in the background (mining, watching, polling, networking on a timer), build a process plugin.

Does the user see and touch it?

If the feature is something the user sees and operates (a panel, a button, a window, a command), build a ui plugin. See UI plugins.

Is it both?

A background worker with its own native controls and settings is a hybrid: a process plugin that also ships a ui module.

Why behavior plugins run out-of-process

A process plugin is a separate program, not a library loaded into the app. That is deliberate, for three concrete reasons.

Isolation

The OS process boundary is the strongest practical isolation. A crashing or misbehaving plugin cannot corrupt the app.

Own network stack

The plugin's network traffic originates from the plugin's own process. The core contains none of the endpoints, queries, or loops a plugin uses.

Any language

A plugin can be written in any language that can read stdin and write stdout.

The deliberate omission that makes this work: the host exposes no generic HTTP method. A plugin that needs the network brings its own network stack. The host hands a plugin only events, a handful of read and display methods, and (with explicit per-use consent) a credential.

Info

That credential handoff is the single sensitive boundary crossing in the whole system. It is gated, logged, and revocable.

How the pieces fit

Every plugin, regardless of kind, ships a plugin.toml manifest at the root of its folder. That file is the complete machine-readable statement of what the plugin is and what it may ask for. Anything not declared there is denied at runtime. Both kinds share the manifest, the marketplace, the signing chain, and the install and consent flow.

A few terms recur throughout the rest of the docs.

TermWhat it means
HostThe StreamNook app, which spawns and supervises plugins.
PluginA separate executable (or a ui module) described by a manifest.
CapabilityA named permission a plugin declares in its manifest and a user grants at install. Anything not granted is denied by default.
Credential brokerThe host component that hands credentials to plugins, with first-use consent and an audit log.
IndexA signed JSON document listing installable plugins. The official index lists a curated set. Heavier or specialized add-ons reach users through community indexes the user adds explicitly.

Tip

Request only the capabilities you use. Every capability shows up in the consent dialog, and a plugin asking for more than it plausibly needs reads exactly that way to the user. See Capabilities for the full vocabulary and the exact consent language.

The wire protocol is at version 1 and the surface is frozen. Breaking changes require a protocol version bump. Additive changes (new events, new optional fields, new capability strings) do not, and both sides ignore unknown fields. See the protocol reference for the wire format, lifecycle, full event and host-method list, and error codes. Signing, the index format, and key rotation are covered in signing.

Next steps