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.
How gadgets work
Section titled “How gadgets work”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
Section titled “Exports”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
Section titled “Imports”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.
Rust SDK
Section titled “Rust SDK”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.
React SDK
Section titled “React SDK”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 template gadget
Section titled “The template gadget”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.