Volt LogoVolt

API Reference

Complete Volt Plugin API documentation

Plugin API Reference

Complete API documentation for Volt plugins.

VoltAPI - Global API

Essential for Extension Development

The window.VoltAPI object is the primary interface for extensions to interact with Volt. All utilities, types, and communication methods are accessed through this global object.

Extensions access Volt's features through the global window.VoltAPI object:

interface VoltAPI {
  // Plugin types and enums
  types: {
    PluginResultType: typeof PluginResultType;
  };

  // Utility functions
  utils: {
    fuzzyScore(query: string, target: string): number;
    copyToClipboard(text: string): Promise<boolean>;
    openUrl(url: string): Promise<void>;
    formatNumber(num: number): string;
  };

  // Tauri invoke (direct backend access)
  invoke: typeof invoke;

  // Event system
  events: {
    emit(event: string, detail?: unknown): void;
    on(event: string, handler: (detail: unknown) => void): () => void;
  };

  // Notifications
  notify(message: string, type?: "info" | "success" | "error"): void;
}

VoltAPI.types

Access to plugin type definitions:

// Get PluginResultType enum
const { PluginResultType } = window.VoltAPI.types;

// Use in your results
const result: PluginResult = {
  id: "1",
  type: PluginResultType.Info,
  title: "My Result",
  score: 100,
};

VoltAPI.utils

Utility functions available to all extensions:

Prop

Type

Example usage:

async execute(result: PluginResult): Promise<void> {
  const password = result.data?.password as string;

  // Copy to clipboard
  const success = await window.VoltAPI.utils.copyToClipboard(password);

  if (success) {
    window.VoltAPI.notify("Copied to clipboard!", "success");
  } else {
    window.VoltAPI.notify("Failed to copy", "error");
  }
}

VoltAPI.invoke

Direct access to Tauri backend commands:

// Call any Tauri command
const result = await window.VoltAPI.invoke("command_name", { param: "value" });

// Example: Get extension configuration
const config = await window.VoltAPI.invoke("get_plugin_config", {
  pluginId: "my-extension",
});

VoltAPI.events

Event system for communication:

// Emit an event
window.VoltAPI.events.emit("my-custom-event", { data: "value" });

// Subscribe to an event (returns unsubscribe function)
const unsubscribe = window.VoltAPI.events.on("some-event", (detail) => {
  console.log("Event received:", detail);
});

// Later: unsubscribe
unsubscribe();

Available events:

  • plugin-update - Fired when a plugin is updated
  • plugin-enabled - Fired when a plugin is enabled
  • plugin-disabled - Fired when a plugin is disabled
  • plugin-error - Fired when a plugin encounters an error

VoltAPI.notify

Display notifications to the user:

// Info notification (default)
window.VoltAPI.notify("Processing complete");

// Success notification
window.VoltAPI.notify("Password copied!", "success");

// Error notification
window.VoltAPI.notify("Failed to connect", "error");

Plugin Interface

The main interface that all plugins must implement:

interface Plugin {
  id: string;
  name: string;
  description: string;
  enabled: boolean;
  canHandle(context: PluginContext): boolean;
  match(context: PluginContext): Promise<PluginResult[]> | PluginResult[] | null;
  execute(result: PluginResult): Promise<void> | void;
}

Plugin Properties

Prop

Type

Plugin Methods

canHandle(context: PluginContext): boolean

Performance Critical

This method must be fast (target: <1ms). Use simple string checks, not complex parsing.

Determines if this plugin should handle the current query.

canHandle(context: PluginContext): boolean {
  const query = context.query.toLowerCase().trim();
  // Fast prefix check
  return query.startsWith('pass') || query.startsWith('password');
}

match(context: PluginContext): Promise<PluginResult[]> | PluginResult[] | null

Generates results for the query. Can be sync or async.

Timeout

This method has a 500ms timeout. If your plugin takes longer, it will be skipped.

async match(context: PluginContext): Promise<PluginResult[]> {
  const query = context.query.replace('pass ', '');
  const length = parseInt(query) || 16;
  const password = generatePassword(length);

  return [{
    id: 'password-1',
    type: window.VoltAPI.types.PluginResultType.Password,
    title: password,
    subtitle: `${length} characters - Press Enter to copy`,
    icon: '🔐',
    score: 100,
    data: { password }
  }];
}

execute(result: PluginResult): Promise<void> | void

Called when the user selects a result (presses Enter).

async execute(result: PluginResult): Promise<void> {
  const password = result.data?.password as string;
  await window.VoltAPI.utils.copyToClipboard(password);
  window.VoltAPI.notify("Password copied!", "success");
}

Types

PluginContext

Context information passed to plugin methods:

interface PluginContext {
  query: string; // User's search query
  settings?: Record<string, unknown>; // Plugin-specific settings
}

PluginResult

Result object returned by plugins:

interface PluginResult {
  id: string; // Unique result ID
  type: PluginResultType; // Result type (affects display)
  title: string; // Main display text
  subtitle?: string; // Secondary text
  icon?: string; // Emoji or icon path
  badge?: string; // Badge text (e.g., "Plugin")
  score: number; // Ranking score (0-100, higher = better)
  data?: Record<string, unknown>; // Custom data for execute()
  pluginId?: string; // Auto-added by registry
}

Scoring Guidelines:

Score RangeUsage
90-100Exact matches
70-89Strong matches (query is substring)
50-69Partial/fuzzy matches
< 50Weak matches

PluginResultType

Types of results plugins can return:

enum PluginResultType {
  Calculator = "calculator",
  WebSearch = "websearch",
  SystemCommand = "systemcommand",
  FileExplorer = "fileexplorer",
  Timer = "timer",
  SystemMonitor = "systemmonitor",
  Steam = "steam",
  Game = "game",
  Clipboard = "clipboard",
  Emoji = "emoji",
  Info = "info",
  Password = "password",
}

Extension Manifest

Every extension must have a manifest.json file at the root:

{
  "id": "password-generator",
  "name": "Password Generator",
  "version": "1.0.4",
  "description": "Generate cryptographically secure passwords",
  "author": {
    "name": "VoltLaunchr Community",
    "github": "VoltLaunchr",
    "email": "contact@volt.dev"
  },
  "main": "index.ts",
  "icon": "assets/icon.png",
  "category": "utilities",
  "keywords": ["password", "security", "generator"],
  "repository": "https://github.com/VoltLaunchr/volt-extensions",
  "license": "MIT",
  "minVoltVersion": "0.4.0",
  "permissions": ["clipboard"]
}

Manifest Fields

Prop

Type


Backend API (Rust)

For advanced system integrations, you can create Rust backend plugins.

Plugin Trait

use async_trait::async_trait;

#[async_trait]
pub trait Plugin: Send + Sync {
    fn id(&self) -> &str;
    fn name(&self) -> &str;
    fn description(&self) -> &str;
    fn is_enabled(&self) -> bool;
    async fn initialize(&mut self) -> Result<(), String>;
    async fn shutdown(&mut self) -> Result<(), String>;
}

VoltPluginAPI (Rust)

The VoltPluginAPI provides filesystem, config, cache, and logging to backend plugins:

// Filesystem — scoped to plugin directories
api.get_plugin_data_dir("my-plugin")?;    // app_data/plugins/my-plugin/
api.get_plugin_cache_dir("my-plugin")?;   // cache/plugins/my-plugin/
api.get_plugin_config_dir("my-plugin")?;  // config/plugins/my-plugin/

// Configuration persistence (JSON)
api.save_config("my-plugin", "settings", &config)?;
api.load_config::<MyConfig>("my-plugin", "settings")?;

// Binary cache
api.write_cache("my-plugin", "data", &bytes)?;
api.read_cache("my-plugin", "data")?;  // -> Vec<u8>
api.clear_cache("my-plugin")?;

// Logging
api.log("my-plugin", LogLevel::Info, "Scanning...");

// App info
api.get_volt_version();  // -> &str

Security: Plugin IDs are validated (max 64 chars, alphanumeric + hyphens/underscores). Cache/config keys are validated to prevent path traversal.

Example Backend Plugin

use async_trait::async_trait;
use crate::core::traits::Plugin;

pub struct SteamPlugin {
    enabled: bool,
}

#[async_trait]
impl Plugin for SteamPlugin {
    fn id(&self) -> &str { "steam" }
    fn name(&self) -> &str { "Steam Games" }
    fn description(&self) -> &str { "Scan and launch Steam games" }
    fn is_enabled(&self) -> bool { self.enabled }

    async fn initialize(&mut self) -> Result<(), String> {
        // Scan Steam library on startup
        Ok(())
    }

    async fn shutdown(&mut self) -> Result<(), String> {
        Ok(())
    }
}

Tauri Commands

Available Tauri commands for extension management:

get_plugin_config(pluginId: string)

Get configuration for a specific plugin.

const config = await window.VoltAPI.invoke('get_plugin_config', {
  pluginId: 'my-plugin'
});

set_plugin_config(pluginId: string, config: any)

Save plugin configuration.

await window.VoltAPI.invoke('set_plugin_config', {
  pluginId: 'my-plugin',
  config: { enabled: true, apiKey: 'xxx' }
});

install_extension(extensionId: string, downloadUrl: string)

Install an extension from a URL.

uninstall_extension(extensionId: string)

Uninstall an extension.

toggle_extension(extensionId: string, enabled: boolean)

Enable or disable an extension.

get_installed_extensions()

Get list of all installed extensions.

get_extension_details(extensionId: string)

Get detailed information about an extension.

fetch_extension_registry(url: string)

Fetch the extension registry from a URL.

check_extension_updates()

Check for available updates for installed extensions.

update_extension(extensionId: string, downloadUrl: string)

Update an extension to a new version.


Complete Extension Example

Here's a complete, production-ready extension:

index.ts
// Password Generator Extension
// manifest.json: { "id": "password-generator", "main": "index.ts", ... }

interface Plugin {
  id: string;
  name: string;
  description: string;
  enabled: boolean;
  canHandle(context: PluginContext): boolean;
  match(context: PluginContext): Promise<PluginResult[]> | PluginResult[];
  execute(result: PluginResult): Promise<void>;
}

interface PluginContext {
  query: string;
  settings?: Record<string, unknown>;
}

interface PluginResult {
  id: string;
  type: any;
  title: string;
  subtitle?: string;
  icon?: string;
  score: number;
  data?: Record<string, unknown>;
}

const TRIGGERS = ["pass", "password", "pwd"];

function generatePassword(length: number): string {
  const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*";
  const array = new Uint32Array(length);
  crypto.getRandomValues(array);
  return Array.from(array, (num) => charset[num % charset.length]).join("");
}

class PasswordGeneratorPlugin implements Plugin {
  id = "password-generator";
  name = "Password Generator";
  description = "Generate cryptographically secure passwords";
  enabled = true;

  canHandle(context: PluginContext): boolean {
    const query = context.query.toLowerCase().trim();
    return TRIGGERS.some((trigger) => query.startsWith(trigger));
  }

  match(context: PluginContext): PluginResult[] {
    const query = context.query.toLowerCase().trim();

    // Parse length from query (e.g., "pass 20" → 20)
    const parts = query.split(/\s+/);
    const lengthArg = parts.find((p) => /^\d+$/.test(p));
    const length = lengthArg ? parseInt(lengthArg, 10) : 16;

    // Clamp length to reasonable bounds
    const finalLength = Math.max(8, Math.min(128, length));
    const password = generatePassword(finalLength);

    const { PluginResultType } = window.VoltAPI.types;

    return [
      {
        id: "generated-password",
        type: PluginResultType.Password,
        title: password,
        subtitle: `${finalLength} characters - Press Enter to copy`,
        icon: "🔐",
        score: 100,
        data: { password },
      },
    ];
  }

  async execute(result: PluginResult): Promise<void> {
    const password = result.data?.password as string;

    if (password) {
      const success = await window.VoltAPI.utils.copyToClipboard(password);

      if (success) {
        window.VoltAPI.notify("Password copied to clipboard!", "success");
      } else {
        window.VoltAPI.notify("Failed to copy password", "error");
      }
    }
  }
}

export default PasswordGeneratorPlugin;

For more examples, check out the Plugin Examples section. For publishing your extension, see the Publishing Guide.

On this page