Skip to content

Gadget SDK

Torchsnap is extensible through gadgets: sandboxed WebAssembly components that plug into the launcher’s search pipeline. A gadget can provide search results, render custom UI inside the launcher, store data in a local SQLite database, make HTTP requests, and run system commands. All of this runs within a permission sandbox controlled by the gadget’s manifest.

Gadgets compile to the wasm32-wasip2 target using the WebAssembly Component Model. The host loads them at runtime via wasmtime and mediates every capability they access.

The boundary between host and gadget is defined by a WIT (WebAssembly Interface Types) contract. WIT is a typed interface definition language that specifies exactly what the gadget implements and what the host provides. The full contract lives in a single file (gadgets/gadget-sdk/wit/torchsnap-gadget.wit) and is reproduced in the Interfaces section for reference.

The contract is organized into two sides.

Exports are interfaces the gadget implements and the host calls into:

Interface Purpose
lifecycle Activation, deactivation, and settings change notifications.
search Catalog entries, query-driven search, and result execution.
messaging Custom RPC between the gadget’s frontend view and its backend.
tasks Cron-scheduled background work.

Imports are capabilities the host provides to the gadget:

Interface Purpose
logging Structured log output with timing spans.
settings Read settings scoped to the gadget’s namespace.
assets Read files bundled inside the gadget archive.
platform Detect the host OS and CPU architecture.
path-resolver Resolve substitution variables to host paths.
clipboard Write text to the system clipboard.
frecency Query the gadget’s own frecency ranking data.
sql-storage Per-gadget SQLite database with managed migrations.
http Synchronous HTTP requests.
filesystem Read host files.
opener Open URLs and file paths via OS default handlers.
command Run system processes.
website-metadata Look up cached website titles and favicons.

Every import except logging, assets, and platform requires an explicit permission grant in the gadget’s manifest. Capabilities not declared are unreachable at runtime. The host returns a permission error if the gadget tries to call them. Permissions that go beyond a simple boolean toggle are scoped further: HTTP requests are restricted to declared origins, filesystem reads to declared glob patterns, and command execution to per-binary argv-shape rules. See the Permissions section in the manifest reference for the full model.

The Rust SDK covers the gadget’s core logic: search, execution, lifecycle, and communication with host capabilities.

Any language that can compile to wasm32-wasip2 and produce a valid component can be used to write gadgets. The WIT contract is language-agnostic, and the host does not care what language produced the WASM binary.

For Rust, the torchsnap-gadget-sdk crate provides a convenience layer: it handles WIT binding generation and adds ergonomic helpers on top of the raw interfaces. Its prelude brings the four guest traits (LifecycleGuest, SearchGuest, MessagingGuest, TasksGuest), all search-related types, host import functions, and registration macros into scope. All bundled gadgets are built with it. The Getting Started tutorial walks through building a gadget with the SDK step by step.

The React SDK covers the gadget’s UI: custom views rendered inside the launcher and settings panels for configuration.

Gadgets that only provide search results through the catalog or query interface do not need a frontend at all. A frontend is only required for gadgets that render custom views in the launcher (like the Calculator’s history view or the Emoji Picker’s grid) or provide their own settings panel. Both use the same React-based frontend SDK.

The @torchsnap/gadget-sdk TypeScript package provides types, hooks, and shared components for building these views. The host owns the React instance. Gadget frontends import React and all SDK hooks through the SDK’s shims, which resolve to the host’s implementations at runtime. This keeps gadget bundles small and guarantees a single React context across host and gadgets.

Frontend development is covered in the Frontend section.

The gadgets/template/ directory in the Torchsnap repository is a complete starting point for new gadgets. It demonstrates catalog entries, prefix-routed custom UI, settings, SQLite storage, messaging RPC, and scheduled tasks. Copy it, rename the gadget ID, and start from there.