Guide

Tauri Desktop

The station-tauri package lets you run Station as a Tauri v2 desktop app sidecar. Your Tauri app spawns Station as a background process, communicates over localhost HTTP, and shuts it down when the window closes. No server deployment needed — everything runs on the user’s machine.


Install

npm install station-tauri

Programmatic API

Use createTauriStation to start Station from Node.js code (e.g. an Electron main process, a test harness, or a custom launcher).

import { createTauriStation } from "station-tauri"; const station = await createTauriStation({  dataDir: "/path/to/app/data",  // absolute path — Tauri app data directory  port: 4400,                     // optional, default 4400  signalsDir: "./signals",        // path to signal definitions  broadcastsDir: "./broadcasts",  // optional  station: { /* overrides */ },   // optional partial StationUserConfig}); await station.start(); console.log(station.port);    // 4400console.log(station.apiKey);  // "sk_live_..." await station.stop();

Options

OptionTypeDefaultDescription
dataDirstringAbsolute path to the application data directory. The SQLite database and API key file are stored here. In Tauri, use the appDataDir resolver.
portnumber4400Port for the Station API server. Binds to 127.0.0.1 only.
signalsDirstringPath to signal definition files.
broadcastsDirstringPath to broadcast definition files.
stationPartial<StationUserConfig>Optional overrides for the underlying Station configuration (adapters, auth, runner options, etc.).

Return value

createTauriStation returns a station handle with these properties and methods:

Property / MethodTypeDescription
portnumberThe port Station is listening on.
apiKeystringAuto-provisioned API key (sk_live_...) with all scopes.
start()Promise<void>Start the Station server and runners.
stop()Promise<void>Gracefully shut down the server and runners.

Sidecar binary

The package ships a station-sidecar binary designed for use as a Tauri v2 sidecar. Register it in tauri.conf.json and spawn it on app start. The binary communicates readiness and errors via structured JSON on stdout.

Environment variables

VariableRequiredDefaultDescription
STATION_DATA_DIRYesAbsolute path to the data directory.
STATION_PORTNo4400API server port.
STATION_SIGNALS_DIRNo./signalsPath to signal definitions.
STATION_BROADCASTS_DIRNoPath to broadcast definitions.

Stdout protocol

On successful startup, the binary writes a single JSON line to stdout:

{"event":"ready","port":4400,"apiKey":"sk_live_..."}

On failure:

{"event":"error","message":"STATION_DATA_DIR is required"}

The binary handles SIGTERM and SIGINT for graceful shutdown — runners and adapters are stopped cleanly before the process exits.


Authentication

The desktop integration auto-provisions a single API key with all scopes (trigger, read, cancel, admin) on first launch. The key is persisted to {dataDir}/.station-key and reused on subsequent launches.

No login UI is needed. The Tauri frontend uses the API key directly in HTTP headers:

fetch("http://127.0.0.1:4400/api/v1/signals", {  headers: {    Authorization: "Bearer sk_live_...",  },});

The server binds to 127.0.0.1 only — it is not accessible from other machines on the network.


Tauri v2 integration

The typical integration pattern involves three pieces: registering the sidecar in Tauri config, spawning it from Rust on app start, and calling the API from the frontend.

1. Register the sidecar

Add the station-sidecar binary to your tauri.conf.json external binaries list. Tauri resolves sidecar paths relative to your app bundle.

2. Spawn on app start

In your Rust setup, spawn the sidecar process, set the required environment variables, and read stdout for the ready event:

// Pseudocode — Rust side// 1. Spawn the station-sidecar with STATION_DATA_DIR set to appDataDir// 2. Read stdout line-by-line until {"event":"ready",...}// 3. Extract port and apiKey from the JSON// 4. Pass port + apiKey to the frontend via Tauri state or IPC

3. Call the API from the frontend

The Tauri frontend talks to Station over localhost using the port and API key extracted from the ready event:

// Frontend (TypeScript)const response = await fetch(`http://127.0.0.1:${port}/api/v1/signals`, {  headers: { Authorization: `Bearer ${apiKey}` },});const signals = await response.json();

4. Shut down on app close

When the Tauri window closes, kill the sidecar process. The binary intercepts SIGTERM and shuts down gracefully — flushing the database WAL, stopping runners, and closing adapter connections before exiting.