Skip to content

Client

Client

The client is the typed surface every app, automation, and remote uses to read, write, and invoke. It is imported from $bolt/client and generated by bolt sync, so every call is type-checked against your collections.

One client, one surface per concern

The client exposes everything your workspace can do:

SurfaceUse it for
client.dbreads — live findMany/findFirst prefixes and one-shot count/findGrouped/findNearest
client.collectionwrites — the declared create/createMany/update/updateMany/delete/deleteMany, each returning an optimistic row and a settlement handle that reports accepted, rebased, rejected, or quarantined
client.collection_historyhistory — every revision of one record, or the record at a chosen revision, instant, or before an approval request
client.approvalsapproval decisions — process a request (APPROVED, REJECTED, REQUEST_FOR_CHANGE, SUPERSEDED) or withdraw it
client.recordspublic system collections — records.findMany(collectionName, query) for tables outside the typed tenant registry
client.collectionsthe read-only catalog — each collection’s declared fields and relationships, for building generic surfaces
client.invokeremote functions — typed query and command handlers discovered from src/functions/
client.automations— start a declared automation in the background and watch its durable run
client.devicedevice — location, share, copy, haptics, and online state, each answering a value or a typed DeviceRefusal instead of throwing

The client in action

The same client powers every app — reads, writes, and invokes all flow through it:

import { client } from '$bolt/client';
import { Effect } from 'effect';

// Live read — registered with the server; its current answer is held in memory
// and commits that change the answer arrive as SSE apply frames
const sites = client.db.sites.findMany({
  where: { status: { eq: 'active' } },
  orderBy: { name: 'asc' },
  limit: 25
});

// Collection write — queued in this tab's memory and pushed to the authority;
// the server allocates the id
const write = await client.collection.site_visits.create({
  site_id: siteId,
  visited_at: new Date()
});
write.row; // optimistic row projected immediately
await write.settlement.settled; // accepted, rebased, rejected, or quarantined

// History — every revision of one record, one-shot, never live.
// A create's authoritative id arrives with the live read; the optimistic row carries none.
const revisions = await client.collection_history.site_visits.revisions(visitId);

// Remote function — typed query or command handler
const forecast = await client.invoke.holiday_feed({ year: 2026 });

// Device — the platform seam for location, share, copy, and haptics;
// every call answers a value or a typed DeviceRefusal, never throws
const fix = await Effect.runPromise(client.device.location({ highAccuracy: true }));

Live data

Reads are live queries registered and answered by the server; browser writes use each collection’s declared operations under client.collection.<name>, which return an optimistic result with memory durability and a settlement handle. Reads and writes are separate surfaces: client.db never writes.

AI

Model access flows through the ai facility — the host binds the provider, and tenant code never sees credentials.

Boundaries

  • The client never talks to server-side cache APIs.
  • Apps cannot reach private runtime facilities.
  • The generated client is the only sanctioned data path into a workspace.