How to Develop and Install Plugins Using the Paperclip Local Plugin Runtime
The Paperclip local plugin runtime enables developers to author, install, and execute plugins locally using the @paperclipai/plugin-sdk package and CLI commands without requiring cloud marketplace deployment.
The paperclipai/paperclip repository ships an early local plugin runtime that transforms how developers extend Paperclip functionality. This runtime allows you to develop plugins using a dedicated SDK, install them directly from local paths or npm, and manage their lifecycle through a comprehensive CLI—all while maintaining complete isolation via worker processes.
Understanding the Local Plugin Runtime Architecture
The Paperclip plugin runtime consists of several coordinated components that manage plugin discovery, validation, and execution.
Core SDK Components
The @paperclipai/plugin-sdk provides the foundational APIs for plugin development. The definePlugin() function, implemented in packages/plugins/sdk/src/define-plugin.ts at line 520, serves as the single entry point for declaring a plugin's capabilities, UI components, and actions. The runWorker() function, defined in packages/plugins/sdk/src/worker-rpc-host.ts at line 273, launches the plugin in its own process and establishes RPC communication with the host.
Manifest Configuration
Every plugin requires a manifest.ts file that declares the plugin's metadata, including its unique ID, version, SDK compatibility range (sdkVersion), UI slots, capabilities, and required secrets. The host validates this manifest during installation to ensure version compatibility (e.g., ">=1.4.0 <2.0.0").
CLI Installation Commands
The paperclipai CLI provides essential plugin management commands:
plugin init– Scaffolds a new plugin skeletonplugin install <path|npm>– Installs a plugin from a local directory or npm packageplugin list– Displays installed plugins and their statusplugin uninstall– Removes a plugin with a 30-day grace period
According to the plugin specification at doc/plugins/PLUGIN_SPEC.md (lines 248-251), the install command writes a record to the Postgres plugins table and copies the package into the host's plugin directory.
Host Process and Hot-Reloading
On startup, the host process reads persisted installation records from the plugins table, loads each package, and launches dedicated workers via runWorker(). The runtime supports hot-install, hot-uninstall, and hot-upgrade capabilities without requiring a server restart, enabling rapid development cycles. Plugin code resides in a writable plugins/ directory, making the runtime global to the Paperclip instance.
Creating Your First Plugin
Developing a plugin requires scaffolding the project structure and implementing the core plugin definition.
Scaffolding a New Plugin
Initialize a new plugin using the CLI:
npx paperclipai plugin init my-plugin
This command generates a skeleton structure including manifest.ts, worker.ts, and package.json with the SDK pre-configured.
Minimal Plugin Implementation
Create a functional plugin by exporting a sealed plugin object via definePlugin():
// src/worker.ts
import { definePlugin, runWorker } from "@paperclipai/plugin-sdk";
import { z } from "@paperclipai/plugin-sdk";
const plugin = definePlugin({
id: "hello-world",
version: "0.1.0",
sdkVersion: ">=1.4.0 <2.0.0",
ui: {
slots: [{
id: "plugin-hello",
title: "Hello",
component: "./ui/hello.tsx"
}],
},
actions: {
greet: {
description: "Return a greeting string",
input: z.object({ name: z.string() }),
output: z.string(),
async run({ input }) {
return `Hello, ${input.name}!`;
},
},
},
async setup() {
console.log("Hello-World plugin started");
},
});
runWorker(plugin, import.meta.url);
The definePlugin() function validates the definition and seals the plugin object, while runWorker() initiates the child process and establishes the RPC channel with the host. The SDK exports z for schema validation to ensure type-safe action inputs and outputs.
Installing Plugins into the Local Runtime
Once developed, plugins must be installed into the running Paperclip instance to become available to agents and the UI.
Local Installation Workflow
Install your plugin from a local directory during development:
# Install the local plugin
npx paperclipai plugin install ./my-plugin
# Verify installation status
npx paperclipai plugin list
For production distribution, install directly from npm:
npx paperclipai plugin install package-name@version
During installation, the CLI runs npm install in the host's plugin directory (as implemented in packages/plugins/create-paperclip-plugin/src/index.ts at line 350), ensuring all dependencies resolve correctly.
Installation Mechanics and Validation
The installation process performs several critical validation steps:
- Manifest validation – Verifies that the plugin's
sdkVersionrange satisfies the host's installed SDK version - Persistence – Records the installation in the Postgres
pluginstable with fields forplugin_id,installed_at,status, andinstall_order - Worker initialization – Immediately starts a dedicated worker process via
runWorker()
The host serves UI bundles from the endpoint /_plugins/:id/ui/:version/, making components available to the frontend instantly after installation.
Calling Plugin Actions from Agents
Once installed, agents can invoke plugin actions through the API:
const result = await agentApi.runAction({
pluginId: "hello-world",
action: "greet",
input: { name: "Alice" },
});
// Returns: "Hello, Alice!"
The runtime routes these calls through the worker RPC host to the appropriate plugin process, maintaining isolation while enabling seamless integration with agent workflows.
Summary
- The Paperclip local plugin runtime uses
@paperclipai/plugin-sdkwithdefinePlugin()andrunWorker()as core APIs for plugin development. - Plugins are installed globally via the
paperclipaiCLI usingplugin install <path|npm>, which validates manifests and persists records to Postgres. - The architecture supports hot-installation and hot-upgrades without server restarts, enabling rapid development workflows.
- Workers run in isolated processes communicating via RPC, with UI bundles served dynamically from
/_plugins/:id/ui/:version/. - The
pluginstable tracks installation state, while theplugin_stateandplugin_entitiestables store runtime data subject to 30-day grace periods upon uninstallation.
Frequently Asked Questions
How does the Paperclip local plugin runtime handle plugin updates?
The runtime supports hot-upgrades by detecting file changes during development and automatically stopping old workers before spawning updated ones. For production updates, running npx paperclipai plugin install with a new version updates the package in the host directory and restarts the worker process without requiring a full server restart.
What SDK version constraints are required for local plugins?
Plugins must specify an sdkVersion range in their manifest (e.g., ">=1.4.0 <2.0.0") that satisfies the host's installed SDK version. The host validates this compatibility at installation time, refusing to load plugins with incompatible SDK requirements to ensure API contract adherence.
Can I distribute Paperclip plugins via npm?
Yes, plugins are distributed as standard npm packages. The plugin install command accepts either a local filesystem path or an npm package specifier (including version tags), and the host runs npm install in the plugin directory to resolve dependencies, supporting complex dependency graphs and semantic versioning.
How does plugin isolation work in the local runtime?
Each plugin runs in its own child process launched by runWorker() from packages/plugins/sdk/src/worker-rpc-host.ts. The Worker RPC Host manages communication between the main Paperclip process and plugin workers via RPC channels, ensuring that plugin crashes or resource consumption do not affect the host system or other plugins.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →