StreamNook
StreamNook

Plugin Development

Quick Start

From an empty folder to a plugin running inside StreamNook, for both runtime kinds.

This is a start-to-finish walkthrough: from an empty folder to a plugin running inside StreamNook. There are two runtime kinds, and the first decision you make is which one you are building. Pick the path that matches your feature, then follow it top to bottom.

Before you start

You need:

  • A working StreamNook build you can run (the dev build for plugin work). You will register your plugin folder through Settings, Plugins, Develop, which gives you the real install and consent behavior with no packaging.
  • For a process plugin: a toolchain for your language (Node, Rust, Go, Python, anything that does stdio).
  • For a ui plugin: Node and esbuild for bundling.
  • For publishing later: minisign to sign your release. See Publishing.

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. The full field reference is in Manifest.

Info

Not sure which kind to build? Build a process plugin if the feature is something the app does in the background (mining, watching, polling, networking on a timer). Build a ui plugin if the feature is something the user sees and touches (a panel, a button, a window, a command). If it is both, build a hybrid (covered at the end).

Hybrid plugins

A background worker that also wants native controls is a hybrid: a process plugin that adds ui_entry to its runtime block. The executable does the background work, the module contributes the native controls and settings screen. Both halves install, enable, and disable as one plugin. See UI plugins for the full hybrid contract and how the two halves talk through the hook system.

[runtime]
kind      = "process"
entry     = "target/release/worker.exe"   # the sidecar
ui_entry  = "ui/dist/main.js"             # the in-app UI module
transport = "stdio"

Run it, test it, debug it

Dev install

You do not package anything to develop. In StreamNook: Settings, Plugins, Sources, Develop, and register the folder that contains your plugin.toml. The plugin gets the same capability and consent behavior an installed plugin gets. Enable it from the plugins list.

Logs

The host hands your plugin a log_dir in the initialize handshake and captures both your log calls and your stderr into a log file there. On Windows dev builds this is under:

%LOCALAPPDATA%\com.streamnook.dev\plugins\<your-plugin-id>\plugin.log

Reading this file is the fastest way to see what your plugin is actually doing. It is readable even while the plugin runs.

Re-registering after a manifest change

The folder registration reads plugin.toml once. If you change the manifest (new capabilities, new [contributes] entries), disable the plugin, re-register the folder via Develop so the new manifest is picked up, then enable it again.

The rebuild lock (compiled process plugins)

Warning

A running plugin process holds its own executable open. On Windows a fresh cargo build --release (or any rebuild that overwrites the exe) fails with "Access is denied" while the plugin is enabled. The flow is: disable the plugin in Settings (the process exits cleanly), rebuild, then re-enable. A cargo check works while it runs because it writes no exe.

Common pitfalls

  • No response to initialize within 10 seconds kills the plugin. Do not do slow startup work before responding; do it on initialized.
  • Missing ping responses restart you. Make sure your read loop is never blocked.
  • Assuming event replay. After a restart, rebuild state from host methods.
  • Requesting capabilities you do not use. It reads as a red flag in the consent dialog and during index review.
  • ui plugin hooks not working. If React hooks throw, your bundle did not alias react to the host copy. Check the shims.

Next steps