← Developer docs

FrontierOS SDK · Browser JavaScript

Build an app. Give it a skill.

The SDK connects a sandboxed browser mini-app to Gotchi Local. Your JavaScript runs in an isolated frame; a permission-checked bridge provides app-owned storage and Watcher display/input. Local keeps its login cookie, device transport and privileged APIs outside that frame.

Run the Tally example

Tally counts completed tasks, saves its count across restarts and registers a callable tally.add skill. Its browser and Watcher buttons use the same handler. You can use it without a device.

Download the SDK and Tally example (.zip)
  1. Use the Gotchi Local source version that includes the Mini apps runtime, and set a password in its web interface.
  2. Extract the ZIP and run python3 install.py from its example-sdk folder. Python 3.10+ bundles the JavaScript and installs it in ~/.gotchi/mini-apps/tally.
  3. Restart Local, reload http://127.0.0.1:8088, sign in and open Mini apps → Tally.
  4. Click Add one, then reopen the app and confirm its count persists. With a linked Watcher, open Tally in its launcher and press or tap its Add one button.

The SDK download does not update an older Local installation or firmware. Use the updated Local source; Watcher rendering needs remote-UI-capable firmware and an active Local connection.

If your Local launcher has no Mini apps entry, that installation does not contain the required runtime. Restarting it or downloading this ZIP will not add the runtime; update Local from the project source first. Publishing these Hub docs also does not update Local’s download or your device.

Change the source

FilePurpose
manifest.jsonIdentity, version, Local target and declared capabilities.
index.htmlBrowser interface and script bundle markers.
app.jsApp logic, skill handler and Watcher scene.
frontier-sdk.jsReusable browser client and scene helpers.
install.pyLocal bundling and installation without dependencies.

Create a callable skill

const sdk = await FrontierOS.connect();

sdk.registerSkill("tally.add", "Add to your tally", async ({ delta = 1 }) => {
  if (!Number.isInteger(delta) || delta < 1 || delta > 100) {
    throw new Error("delta must be an integer from 1 to 100");
  }
  return { count: await sdk.storage.increment("count", delta) };
});

const result = await sdk.invokeSkill("tally.add", { delta: 1 });

Skills are named handlers inside the sandbox. Validate arguments before acting and return a JSON-compatible result. Calls through the SDK run sequentially; atomic storage increments prevent concurrent additions from overwriting each other. The Local host can explicitly invoke registered skills, and your app can call them directly.

Automatic voice-agent tool selection is not integrated. Registering a skill does not change the agent’s tool policy or grant new capabilities.

Make it yours

Change the manifest’s ID and name, the scene’s app ID and the skill namespace. Edit the HTML and JavaScript, then run python3 install.py --replace to replace installed source while retaining its stored data.

Verify your changes

node --test test_sdk.mjs
python3 -m unittest -v test_install.py

These checks cover SDK connection, persistence calls, skills and installer boundaries. Local has separate permission and scene-validation tests. Run your modified app in Local before sharing it; a Hub listing draft does not upload or install your source.