Host services
Discover the APIs your Host actually provides, with parameter and result examples for everyday tasks.
Verified September 11, 2026
On this page
Discover your Host’s contracts#
Tables list contract parameter schemas. Generated methods without business parameters are called directly, for example host.runtime.getPaths(). Arbitrary JSON results are unknown; validate them against your application’s data shape.
Call host.services to inspect the running Host. Its response gives registered services and their actual parameter/result contracts, including differences between builds.
import { host } from "@trove/plugin-sdk";
await host.ready();
const available = await host.services.list({ prefix: "host." });
const storageContract = await host.services.describe({
service: "host.storage",
});
console.log(available, storageContract);
| Method | Parameters | Result |
|---|---|---|
list | { prefix?: string } | { services: [{ id, version, provider }] } |
describe | { service: string, version?: string } | { descriptor, contract } |
resolve | { service: string, version?: string } | { id, version, provider } |
getStatus | { service: string, version?: string } | { id, version, state } |
A version range mismatch rejects with service.version_mismatch. Status is Declared, Starting, Available, or Unavailable; registration alone does not prove a Backend is running.
Runtime and paths#
| Method | Parameters | Result |
|---|---|---|
echo | Any JSON value | The same JSON value |
getHostInfo | {} | { name, version, platform, arch, protocol } |
getContext | {} | Current Curio identity and mode |
getPaths | {} | { data, cache, temp }, each an absolute path |
openCurio | { id } | { ok: true } |
closeSelf | {} | { ok: true } |
revealPath | { path } | { ok: true } |
openUrl | { url } | { ok: true } |
The final four operations require the desktop Host. Use the returned paths rather than hard-coding a user’s home or application data directory. data is for persistent files, cache for regenerable content, and temp for session work.
Store small JSON values#
host.storage isolates keys by the Host-bound Curio ID. A single serialized value is limited to 1 MiB and the serialized store to 16 MiB. It is JSON storage, not a keychain.
| Method | Parameters | Result |
|---|---|---|
set | { key: string, value: JSON } | { stored: true } |
get | { key: string } | { value: JSON, found: boolean } |
delete | { key: string } | { deleted: boolean } |
list | { prefix?: string } | { keys: string[] } |
clear | {} | { cleared: true } |
import { host } from "@trove/plugin-sdk";
const key = `docs-demo-${crypto.randomUUID()}`;
try {
await host.storage.set({ key, value: { theme: "system" } });
const saved = await host.storage.get({ key });
console.log(saved.found, saved.value);
} finally {
await host.storage.delete({ key });
}
A missing key returns found: false, value: null. A stored JSON null returns found: true, value: null; check found before interpreting the value. Use the data directory for larger files.
Work with files#
host.fs.readText({ path }) returns { content: string }; writeText({ path, content }) returns { written: true }. Paths are filesystem paths, not browser URLs. Current text and binary transfers are limited to 4 MiB per file.
import { host } from "@trove/plugin-sdk";
const { temp } = await host.runtime.getPaths();
const path = `${temp}/docs-${crypto.randomUUID()}.txt`;
try {
await host.fs.writeText({ path, content: "Hello Trove" });
console.log((await host.fs.readText({ path })).content);
} finally {
await host.fs.remove({ path });
}
| Method | Parameters | Result |
|---|---|---|
stat | { path } | { type, size, modifiedUnixMs } |
list | { path } | { entries: [{ name, path, type }] }; up to 20,000 entries |
exists | { path } | { exists: boolean } |
readBinary | { path } | { data: string }, Base64 encoded |
writeBinary | { path, data } | { written: true }; data is Base64 |
createDirectory | { path } | { created: true } |
copy / move | { from, to } | { copied: true } / { moved: true } |
remove | { path, recursive?: boolean } | { removed: true } |
createTempFile | {} | { path: string } |
Ask users to select their files through host.dialog when appropriate. Host filesystem calls do not imply the selected path is a Curio-only sandbox; respect the user’s intended file scope and macOS permissions.
Desktop integrations#
import { host } from "@trove/plugin-sdk";
console.log((await host.clipboard.readText()).text);
await host.notification.show({ title: "Export complete", body: "Your file is ready." });
Clipboard supports readText({}) → { text }, writeText({ text }) → { written: true }, and clear({}) → { cleared: true }. Notification currently supports only show({ title, body }) → { shown: true, curioId }.
Use describe to retrieve the full contract before integrating the following services:
| Service | Registered methods / topics |
|---|---|
host.window | show, hide, close, focus, getBounds, setBounds, center, setTitle, setAlwaysOnTop, setResizable, setDecorations, setShadow, setIgnoreCursorEvents, openChild; activated topic |
host.dialog | openFile, openDirectory, saveFile, message, confirm |
host.application | listInstalled, listRunning, launch, activate, terminate, open, getFrontmost, getIcons |
host.shortcut | register, unregister, listSelf; triggered topic |
System trust and child windows#
Trove owns system trust for accessibility, input monitoring, and screen recording. Curios display capability status and direct users to the Host permissions page when action is needed; the Host handles requests or opens system settings:
import { host } from "@trove/plugin-sdk";
const { permissions } = await host.permission.list();
const accessibility = permissions.find(item => item.id === "accessibility");
if (accessibility?.status !== "allowed") {
await host.permission.openSettings({ id: "accessibility" });
}
openSettings accepts accessibility, input, or screen and opens the Trove permissions page. Curios do not request Host permissions themselves. This is not a Curio access allowlist and does not restrict authors from implementing their own native capabilities.
Clipboard also exposes getChangeCount, readCapture, writeImage, getPastePermission, and paste({ pid }). Automatic paste requires Trove's accessibility authorization. The running Host reports foreground application and permission state; Curios should not guess them.
host.window.openChild opens an independent window belonging to the same Curio. Parameters include id, title, query, width, height, and optional minimum dimensions. Reusing an ID focuses its existing window. Calls to host.window from a child act on that calling window. Hiding the main window and retaining a background process are separate responsibilities.
Implemented and planned capabilities#
| Capability | Current implementation |
|---|---|
| Runtime, discovery, storage, filesystem | Implemented |
| Windows, dialogs, text clipboard, notifications, applications, shortcuts | Implemented in desktop Host; inspect its contract |
| Clipboard capture, image writing, automatic paste, permission status, Host permissions page | Implemented; inspect the current Host contract |
host.clipboard.readFiles/writeFiles | Not registered as separate methods; readCapture can return file information |
host.notification.remove/removeAllForCurio | Draft only |
host.fs.watch | Draft only |
host.process, host.accessibility, host.input, host.screen, host.keychain | Planned; not registered in the current build |
Do not infer method availability from a service name in an architecture draft. Handle service.not_found and service.method_not_found and check the installed Host version before enabling a feature.
Discover Curios by ID#
The Web SDK exposes host.curios.has/status/get/start(id); see the complete semantics. Wire registers service host.curios with methods has, status, describe and start. Each takes { "id": "dev.example.text-tools" }.
Has returns boolean; status/start return CurioStatus; describe returns { id, version, services: ServiceContract[] } containing public contracts only. Get is an SDK convenience that builds a reference using describe; Wire has no get method. Backends can call the same discovery methods over Wire, then request public capabilities by service and method. Requests retain caller identity and version checks.