Development Workflow
Set up your local development environment for Volt extensions
Development Workflow
Learn how to set up your local environment for developing and testing Volt extensions.
Project Setup
Create Extension Directory
Use the CLI tool to scaffold a new extension:
# Install the CLI if you haven't already
npm install -g @voltlaunchrr/plugin-cli
# Scaffold a new extension with interactive prompts
volt-plugin init my-extension
cd my-extensionThe CLI prompts for: extension ID, display name, description, author, category, permissions (checkbox), trigger prefix, and keywords.
It generates manifest.json, src/index.ts, package.json, and tsconfig.json, then auto-installs dependencies using your detected package manager (bun > pnpm > npm).
mkdir my-extension
cd my-extensionInitialize Project Structure
Create the essential files:
{
"id": "my-extension",
"name": "My Extension",
"version": "1.0.0",
"description": "My awesome extension",
"author": { "name": "Your Name" },
"main": "index.ts",
"category": "utilities",
"minVoltVersion": "0.4.0",
"permissions": []
}Install the SDK (for types and IDE support)
Install the official SDK to get full type definitions and autocomplete:
npm install @voltlaunchrr/plugin-apibun add @voltlaunchrr/plugin-apipnpm add @voltlaunchrr/plugin-apiThis provides all Plugin, PluginContext, PluginResult, and PluginResultType types automatically.
Type Definitions
The SDK (@voltlaunchrr/plugin-api) exports all the types you need:
import {
Plugin,
PluginContext,
PluginResult,
PluginResultType,
} from '@voltlaunchrr/plugin-api';If you prefer not to install the SDK, you can also define the types locally. See the API Reference for the full interface definitions.
Local Testing
Method 1: Dev Mode (Recommended)
Like Raycast!
Link your extension folder directly to Volt for instant testing with hot reload. No packaging required!
Open Volt Settings
- Press
Ctrl+Spaceto open Volt - Type
settingsand press Enter - Go to Extensions tab
Link Your Extension
- Click "Link Dev Extension"
- Select your extension folder (e.g.,
D:\dev\my-extension) - Your extension is instantly loaded with a DEV badge!
Test and Iterate
- Type your trigger keyword to test
- Edit your code and save
- Press
Ctrl+Rto refresh Volt - Changes are immediately visible!
Dev Mode Commands:
| Command | Description |
|---|---|
| Link Dev Extension | Link a local folder |
| Unlink Dev Extension | Remove a dev extension |
| Refresh Dev Extension | Reload from disk |
Hot Reload
Dev extensions automatically re-read manifest.json on each query, so metadata changes are
instant. For code changes, use Refresh or Ctrl+R.
Method 2: Install from ZIP
For testing the final packaged version:
Package Your Extension
Create a ZIP file with your extension files:
Compress-Archive -Path .\* -DestinationPath ..\my-extension-v1.0.0.zipzip -r ../my-extension-v1.0.0.zip .Install in Volt
- Open Volt
- Go to Settings → Extensions
- Click Install from file
- Select your ZIP file
Test Your Extension
Type your trigger keyword in Volt to test the extension.
Method 3: Direct Folder Installation
For manual installation (advanced):
Find Extension Directory
Volt stores extensions in the app data directory:
%APPDATA%\volt\extensions\~/Library/Application Support/volt/extensions/~/.config/volt/extensions/Copy Your Extension
Copy your extension folder directly:
# Example for Windows
cp -r ./my-extension "$env:APPDATA/volt/extensions/"Update installed.json
Add your extension to installed.json in the extensions directory:
{
"extensions": [
{
"id": "my-extension",
"name": "My Extension",
"version": "1.0.0",
"enabled": true,
"installedAt": "2024-01-01T00:00:00Z"
}
]
}Reload Volt
Restart Volt or use the reload command to load your extension.
Debugging
Browser DevTools
Volt runs in a Tauri webview, which supports Chrome DevTools:
Enable DevTools
In development builds, press F12 or Ctrl+Shift+I to open DevTools.
View Console Output
Your console.log() statements will appear in the Console tab.
canHandle(context: PluginContext): boolean {
console.log('Query received:', context.query);
return context.query.startsWith('my ');
}Debug Errors
Check the Console for any errors in your extension code.
Common Debugging Techniques
class MyPlugin implements Plugin {
// ...
canHandle(context: PluginContext): boolean {
// Debug: Log every query
console.log("[MyPlugin] canHandle called with:", context.query);
const result = context.query.startsWith("my ");
console.log("[MyPlugin] canHandle result:", result);
return result;
}
match(context: PluginContext): PluginResult[] {
console.log("[MyPlugin] match called");
try {
// Your matching logic
const results = this.generateResults(context);
console.log("[MyPlugin] Generated results:", results);
return results;
} catch (error) {
console.error("[MyPlugin] Error in match:", error);
return [];
}
}
async execute(result: PluginResult): Promise<void> {
console.log("[MyPlugin] execute called with:", result);
try {
// Your execution logic
await this.performAction(result);
console.log("[MyPlugin] Action completed successfully");
} catch (error) {
console.error("[MyPlugin] Error in execute:", error);
window.VoltAPI.notify("An error occurred", "error");
}
}
}Extension Loading Process
Understanding how Volt loads extensions helps with debugging:
1. Volt starts
↓
2. Backend reads installed.json
↓
3. For each enabled extension:
a. Read all source files (.ts, .js, .json)
b. Bundle files into single JavaScript
c. Transform TypeScript → JavaScript (via Sucrase)
d. Transform imports/exports to module system
e. Execute the bundle
f. Get default export (your Plugin class)
g. Instantiate and register with Plugin Registry
↓
4. Extension ready to handle queriesKey Points
TypeScript Transformation
Your TypeScript is automatically compiled to JavaScript. You don't need a build step. However, only TypeScript syntax is supported—not Node.js APIs.
- Entry point: The file specified in
manifest.main - Default export: Must be a class implementing
Plugin - No Node.js: Browser APIs only (no
fs,path, etc.) - Web Crypto: Use
crypto.getRandomValues()instead of Node'scrypto
Troubleshooting
Development Tips
1. Start Simple
Begin with a minimal extension and add features incrementally:
class MinimalPlugin implements Plugin {
id = "minimal";
name = "Minimal";
description = "A minimal extension";
enabled = true;
canHandle(context: PluginContext): boolean {
return context.query === "test";
}
match(context: PluginContext): PluginResult[] {
return [
{
id: "1",
type: window.VoltAPI.types.PluginResultType.Info,
title: "It works!",
score: 100,
},
];
}
execute(): void {
window.VoltAPI.notify("Executed!", "success");
}
}
export default MinimalPlugin;2. Use Descriptive Logging
const LOG_PREFIX = "[MyExtension]";
console.log(`${LOG_PREFIX} Initializing...`);
console.log(`${LOG_PREFIX} Query: "${context.query}"`);
console.error(`${LOG_PREFIX} Error:`, error);3. Handle Errors Gracefully
match(context: PluginContext): PluginResult[] {
try {
return this.generateResults(context);
} catch (error) {
console.error('Error generating results:', error);
return [{
id: 'error',
type: window.VoltAPI.types.PluginResultType.Info,
title: 'An error occurred',
subtitle: 'Check console for details',
icon: '⚠️',
score: 0
}];
}
}4. Test Edge Cases
- Empty query
- Very long queries
- Special characters
- Unicode input
- Rapid typing (debouncing)
Using the Extension Templates
Clone the official templates for a quick start:
# Clone the volt-extensions repository
git clone https://github.com/VoltLaunchr/volt-extensions.git
# Copy a template
cp -r volt-extensions/templates/typescript-plugin ./my-extension
# Start developing
cd my-extensionThe templates include:
- TypeScript template — Pre-configured
manifest.json,package.json,tsconfig.json,src/index.ts - Rust template — Minimal Rust backend plugin skeleton for system-level operations
The repository also contains production-ready examples:
- Calculator — Complex multi-handler plugin with parsers, converters, and React UI
- Password Generator — Crypto-secure generation with EFF Diceware wordlist
- Web Search — Simple single-file multi-engine search
CLI Command Reference
| Command | Description |
|---|---|
volt-plugin init | Scaffold a new extension with interactive prompts |
volt-plugin test | Validate manifest, plugin interface, and TypeScript types |
volt-plugin publish | Package as ZIP and output registry entry JSON |
volt-plugin test checks:
manifest.jsonvalidity (required fields, kebab-case ID, semver version)- Plugin interface (canHandle, match, execute methods exist)
- TypeScript compilation (
tsc --noEmit)
Exits with code 1 on any failure.
volt-plugin publish output:
- Validates the manifest
- Creates
{id}-v{version}.zip - Prints a JSON registry entry for
registry.json - Displays submission instructions