Catalog Search
Fuzzy-match against a finite, pre-built list of items. Best for app launchers and clipboard history.
This page is a living reference for all available documentation components and styling. It is not part of the public documentation structure.
The following examples are temporary and exist solely to verify styling across all documentation elements.
Configure your activation hotkey in ~/.config/torchsnap/settings.json. The default is Option + Space.
Use the gadget-sdk crate’s prelude module to import all common types: use gadget_sdk::prelude::*;. The SearchResult struct requires a title: String and an action: Action.
Press Cmd + K to open the command palette, Esc to dismiss, or ↵ to execute.
| Permission | Description | Risk Level |
|---|---|---|
clipboard.read |
Read clipboard contents | Low |
clipboard.write |
Write to clipboard | Low |
http.fetch |
Make outbound HTTP requests | Medium |
fs.read |
Read files from specified paths | Medium |
fs.write |
Write files to specified paths | High |
shell.execute |
Run shell commands on the host | Critical |
Torchsnap’s gadget system is designed around the principle of least privilege. Every host capability requires explicit opt-in through the manifest, and users are prompted before granting sensitive permissions.
Unordered:
= for calculator! for bangsOrdered:
cargo init --libgadget-sdk as a dependencyGadget traitgadget.toml manifestwasm32-wasip2torchsnap gadget packInstall the WASM target
rustup target add wasm32-wasip2Create a new gadget project
cargo init --lib my-gadgetcd my-gadgetcargo add gadget-sdkImplement the Gadget trait
use gadget_sdk::prelude::*;
pub struct MyGadget;
impl Gadget for MyGadget { fn search(&self, query: &str) -> Vec<SearchResult> { vec![] }}Build and package
cargo build --target wasm32-wasip2 --releasetorchsnap gadget pack --manifest gadget.tomlbrew install torchsnapgit clone https://github.com/jakobwesthoff/torchsnapcd torchsnapjust build-releaseCatalog Search
Fuzzy-match against a finite, pre-built list of items. Best for app launchers and clipboard history.
Query Search
Every keystroke is forwarded to the gadget’s search function. Best for calculators and web searches.
Prefix Routing
A single character prefix routes input exclusively to one gadget. Best for bangs and quick commands.
Background Tasks
Gadgets can declare cron-scheduled background tasks for periodic data refreshes.
Gadgets can provide custom icons by including them in the .torchsnap archive. Icons are resolved in the following order:
data: URI in the SearchResult.icon fieldThe following examples are temporary and exist solely to verify syntax highlighting across languages.
use gadget_sdk::prelude::*;
#[derive(Debug, Clone)]pub struct Calculator { history: Vec<String>,}
impl Gadget for Calculator { fn search(&self, query: &str) -> Vec<SearchResult> { let result = match evaluate(query) { Ok(value) => value, Err(_) => return vec![], };
vec![SearchResult { title: format!("{result}"), subtitle: Some(format!("{query} = {result}")), icon: Icon::named("calculator"), action: Action::copy(result.to_string()), }] }}
fn evaluate(expr: &str) -> anyhow::Result<f64> { // Recursive descent parser for basic arithmetic let tokens: Vec<char> = expr.chars().filter(|c| !c.is_whitespace()).collect(); let (result, _) = parse_expression(&tokens, 0)?; Ok(result)}interface SearchResult { title: string; subtitle?: string; icon: string; score: number;}
async function queryGadgets( input: string, gadgets: Map<string, GadgetHandle>,): Promise<SearchResult[]> { const results = await Promise.all( [...gadgets.values()].map(async (gadget) => { try { return await gadget.search(input); } catch (err) { console.error(`Gadget ${gadget.id} failed:`, err); return []; } }), );
return results .flat() .sort((a, b) => b.score - a.score) .slice(0, 20);}
export type { SearchResult };[gadget]id = "com.example.calculator"name = "Calculator"version = "0.1.0"description = "Evaluate math expressions inline"
[search]mode = "query"debounce_ms = 50
[permissions]clipboard = "write"# Build the gadget for the WASM targetcargo build --target wasm32-wasip2 --release
# Package into a .torchsnap archivetorchsnap gadget pack \ --manifest gadget.toml \ --wasm target/wasm32-wasip2/release/calculator.wasm \ --output calculator.torchsnap{ "launcher": { "hotkey": "Option+Space", "max_results": 12, "theme": "system" }, "gadgets": { "com.example.calculator": { "enabled": true, "prefix": "=" } }}@theme { --color-accent: var(--color-orange-500); --color-accent-hover: var(--color-orange-600); --color-surface-sidebar: #f8f5ef;}
[data-theme="dark"] { --color-surface: #1c1c1e; --color-surface-sidebar: #222224; --color-border: #3a3a3c;}