Skip to main content

clawdesk-plugin

Plugin system supporting hot-reloadable, sandboxed plugins. Provides plugin hosting, resolution, sandboxing, and registry infrastructure for extending ClawDesk at runtime.

Dependencies

Internal: clawdesk-types

External: tokio, async-trait, serde, tracing, thiserror

Modules

ModuleDescription
hostPlugin host — manages plugin lifecycle (load, start, stop, reload)
resolverResolves plugin locations from filesystem or registry
sandboxSandboxed execution environment (WASM or process isolation)
registryPluginRegistry — tracks loaded plugins and their state

Key Types

/// Plugin manifest describing a plugin's metadata and capabilities
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PluginManifest {
pub name: String,
pub version: String,
pub description: String,
pub author: String,
pub capabilities: Vec<PluginCapability>,
pub sandbox: SandboxType,
pub entry_point: String,
}

/// What a plugin can do
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PluginCapability {
ToolCall, // Provide tools to the agent
MessageTransform, // Transform messages pre/post processing
ChannelAdapter, // Add a new channel
EventListener, // Listen to system events
}

/// Sandbox isolation level
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SandboxType {
Wasm, // WebAssembly sandbox (most isolated)
Process, // Separate process with IPC
Native, // In-process (least isolated, fastest)
}

/// Plugin host managing plugin lifecycle
pub struct PluginHost {
registry: Arc<PluginRegistry>,
resolver: PluginResolver,
}

impl PluginHost {
pub async fn load(&self, manifest: &PluginManifest) -> Result<(), PluginError> { /* ... */ }
pub async fn reload(&self, name: &str) -> Result<(), PluginError> { /* ... */ }
pub async fn unload(&self, name: &str) -> Result<(), PluginError> { /* ... */ }
}

/// Plugin registry
pub struct PluginRegistry {
plugins: RwLock<HashMap<String, LoadedPlugin>>,
}

Plugin Lifecycle

  ┌──────────┐     ┌────────┐     ┌─────────┐     ┌──────────┐
│ Resolved │────▶│ Loaded │────▶│ Active │────▶│ Stopped │
└──────────┘ └────────┘ └─────────┘ └──────────┘
│ │
└──── Reload ─────┘

Example Usage

use clawdesk_plugin::{PluginHost, PluginManifest, PluginRegistry};

let registry = Arc::new(PluginRegistry::new());
let host = PluginHost::new(registry.clone());

// Load a plugin from manifest
let manifest = PluginManifest {
name: "weather-tool".into(),
version: "1.0.0".into(),
capabilities: vec![PluginCapability::ToolCall],
sandbox: SandboxType::Wasm,
entry_point: "./plugins/weather.wasm".into(),
..Default::default()
};

host.load(&manifest).await?;

// Hot-reload
host.reload("weather-tool").await?;

// List loaded plugins
let plugins = registry.list().await;
warning

Native sandbox mode runs plugins in-process without isolation. Use WASM or Process sandbox for untrusted plugins.