A LivOS plugin ships routes, widgets, slash commands and MCP servers as a single signed bundle. The runtime mounts plugins at <user>.livinity.io/p/<plugin-id>/ with no server restart on install. Operator-signed for v37; community submissions open in v38.
A plugin is a .livpkg.tgz archive that LivOS extracts into /opt/livos/plugins/<id>/. The runtime reads the manifest, verifies the Ed25519 signature, and mounts whichever of the four hook types the plugin declares.
Mounted under /p/<id>/ on the user's livinityd. Standard Express handlers — request, response, async middleware. Useful for webhook receivers, reverse proxies, and custom APIs that need to live on the user's own domain.
Pre-compiled UMD bundles rendered into mount points across the LivOS shell — dock, settings panel, AI chat, window titlebar. Shadow-DOM by default for CSS isolation.
Plugin-declared /foo commands appear in the user's Liv chat. The runtime routes args + session context to the plugin's handler and injects the response back into the conversation as a tool result.
Register MCP servers (stdio or streamableHttp transport) into the user's mcpConfigManager. Same shape AI Chat uses today — your plugin's tools become available to the local Liv assistant on install.
.livpkg.tgzEverything the runtime needs to mount, sign and load the plugin lives in the archive. No external resources are fetched at install time except the bundle URL itself.
plugin-manifest.jsonOne JSON file declares the plugin's identity, signing tier, every hook it exposes, and every capability it needs. The runtime refuses install if a capability is requested beyond the plugin's signing tier.
backend/index.mjs exportsA single default export — a PluginBackendModule with activate / deactivate lifecycle hooks plus the named handlers referenced from the manifest.
Plugins expose React components via a UMD wrapper. The plugin loader injects each declared widget into its mount point usingReact.createPortal wrapped in a Shadow-DOM root, so plugin CSS never leaks into the LivOS shell and vice versa.
v37 ships operator-signed-only. Community submissions open in v38 via this repo. For now, contact the operator and they'll co-sign and publish under operator-v1.
utopusc/livinity-appsThe plugin repository hosts release artifacts and the public signing-key registry at .signing/pubkeys.json.
.livpkg.tgzPack plugin-manifest.json, backend/,ui/, migrations/ and assets/ into a tarball. Run npm pack after structuring your directory.
Open a pull request adding the bundle hash + manifest toplugins/<your-id>/. Operator reviews, signs plugin-manifest.sig with the operator key, and publishes a release.
The operator adds a row to the Supabase apps table with section='plugin', pointing at the GitHub release URL + bundle SHA-256. Once committed it's live in the /store within seconds.
The minimal plugin that touches every hook type — route + dock widget + slash command + redis capability. Use this as your starting fork.
Claude API at /p/livinity-broker/v1/* via the user's Anthropic subscription. Demonstrates path-mounted routes and a plugin-managed settings widget.
TypeScript types for the manifest schema and the runtime API your backend module receives. Drop into devDependencies to get autocomplete for free.