Developer docs/Reference

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#

Call host.services to inspect the running Host. Its response gives registered services and their actual parameter/result contracts, including differences between builds.

ts
import { trove } from "@trove/plugin-sdk";

await trove.ready();
const available = await trove.call("host.services", "list", { prefix: "host." });
const storageContract = await trove.call("host.services", "describe", {
  service: "host.storage",
});
console.log(available, storageContract);
MethodParametersResult
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#

MethodParametersResult
echoAny JSON valueThe same JSON value
getHostInfo{}{ name, version, platform, arch, protocol }
getContext{}Current Curio identity and mode
getPaths{}{ data, cache, logs, 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.

MethodParametersResult
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 }
ts
const storage = trove.service("host.storage");
const key = `docs-demo-${crypto.randomUUID()}`;
try {
  await storage.call("set", { key, value: { theme: "system" } });
  const saved = await storage.call<{
    found: boolean;
    value: { theme: string } | null;
  }>("get", { key });
  console.log(saved.found, saved.value);
} finally {
  await storage.call("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.

ts
const { temp } = await trove.call<{ temp: string }>("host.runtime", "getPaths", {});
const path = `${temp}/docs-${crypto.randomUUID()}.txt`;
try {
  await trove.call("host.fs", "writeText", { path, content: "Hello Trove" });
  const file = await trove.call<{ content: string }>("host.fs", "readText", { path });
  console.log(file.content);
} finally {
  await trove.call("host.fs", "remove", { path });
}
MethodParametersResult
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#

ts
const clipboard = await trove.call<{ text: string }>("host.clipboard", "readText", {});
console.log(clipboard.text);
await trove.call("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:

ServiceRegistered methods / topics
host.windowshow, hide, close, focus, getBounds, setBounds, center, setTitle, setAlwaysOnTop, setResizable, setDecorations, setIgnoreCursorEvents
host.dialogopenFile, openDirectory, saveFile, message, confirm
host.applicationlistInstalled, listRunning, launch, activate, terminate, open, getFrontmost
host.shortcutregister, unregister, listSelf; triggered topic

Implemented and planned capabilities#

CapabilityCurrent implementation
Runtime, discovery, storage, filesystemImplemented
Windows, dialogs, text clipboard, notifications, applications, shortcutsImplemented in desktop Host; inspect its contract
host.clipboard.readFiles/writeFiles/getChangeCountDraft only
host.notification.remove/removeAllForCurioDraft only
host.fs.watchDraft only
host.process, host.accessibility, host.input, host.screen, host.keychainPlanned; 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.