@rindle/cli is the JS/TS developer toolchain for Rindle. It installs the
rindle CLI and the matching rindled daemon binary as prebuilt, per-platform
npm artifacts - no Rust toolchain required for app development.
Use it for four jobs:
- scaffold a local topology with
rindle init; - render it and supervise the local write-master + follower pair with
rindle up; - launch app processes with stable bindings derived from the topology using
rindle exec; - apply SQL migrations with
rindle migrate; - generate
@rindle/clientTypeScript schema withrindle schema gen.
Install
pnpm add -D @rindle/cli
# or npm i -D @rindle/cli
Run it through the package manager’s bin resolution:
npx rindle --help
pnpm exec rindle status
The package installs exactly the platform binary it needs through optional
dependencies. The rindle CLI and rindled daemon binary are versioned together
so rindle up can always find and supervise the daemon it was released with.
Supported platforms
Prebuilt binaries ship for macOS (Apple Silicon + Intel) and Linux (x86_64 + arm64, glibc + musl).
Windows: use WSL2. There is no native Windows build — Rindle’s storage engine is
Linux-only — and installing on Windows fails fast with a message pointing here rather
than silently half-working. WSL2 runs a real Linux kernel, so the normal Linux binaries
and the whole rindle up loop work unmodified inside your distro. Your app and browser
stay on Windows: WSL2 forwards localhost, so a dev server started in the distro is
reachable from a Windows browser, and the browser tier is wasm and doesn’t care what OS
it runs on.
One rule that matters:
Keep the database on the WSL filesystem (
~/), never under/mnt/c. Windows drives are exposed to WSL through a translation layer that can’t reliably back a memory-mapped database — the same reason SQLite shouldn’t live on a network share. Your source tree can sit wherever you like; the data directory can’t. It’ll also be dramatically faster on the Linux side.
WSL1 is not supported: it emulates the memory-mapping and file-locking calls the engine depends on, rather than implementing them.
Local dev loop
Most apps use one long-running command for the data-tier side of development:
npx rindle init
npx rindle up --migrate --gen shared/schema.gen.ts --watch
npx rindle exec -- vite dev
rindle up renders your rindle.ncl, starts the write-master + follower + local fleet edge,
waits for it to be ready, applies pending migrations/*.sql to the master, generates
shared/schema.gen.ts from the follower’s live schema, and repeats apply/generate
whenever the migrations directory changes.
Keep your app server and frontend dev server in a separate process. rindle up owns the local
fleet, migrations, and schema generation; rindle exec -- <command> evaluates the same topology
and injects its stable read/write/ws bindings into your web framework process.
Migrations and schema generation
Under rindle up, migrations apply to the write-master and the schema regenerates from
a follower automatically. To run the steps directly, point migrate at the write-master
(:7611 locally) and schema gen at a follower (:7600):
npx rindle migrate create init
npx rindle migrate apply --url http://127.0.0.1:7611 # the write-master
npx rindle migrate status --url http://127.0.0.1:7611
npx rindle schema gen --url http://127.0.0.1:7600 --out shared/schema.gen.ts # a follower
Or point them at a remote deployment — migrations at the write-master, schema at a follower’s control plane:
npx rindle migrate apply --url https://YOUR-WRITE-MASTER --token "$RINDLE_DAEMON_TOKEN"
npx rindle schema gen \
--url https://YOUR-APP:8443 \
--token "$RINDLE_DAEMON_TOKEN" \
--out shared/schema.gen.ts
The daemon token is server/operator-only. It should never be shipped to the browser; browser clients subscribe through the public WebSocket using leases minted by your API server.
rindle up vs. rindled
rindled is the read-follower daemon; the rindle-replicator write-master feeds it.
rindle up is the local-development supervisor that renders your rindle.ncl, starts
the pair, watches it, applies migrations to the master, and generates schema from the
follower.
For application development, prefer rindle up. For production, run the pair under your
real process supervisor or use Rindle Cloud:
- local dev:
npx rindle up --migrate --gen shared/schema.gen.ts --watch; - self-hosted production: run the write-master + follower from release artifacts,
container images, or your own supervisor, then use
rindle migrate apply --url <write-master> --token ...; - managed production: provision Rindle Cloud and run the same
migrate/schema gencommands against its endpoints.
Command reference
Every command talks to a daemon’s control plane at --url (except init, up,
and the local migrate list/create). Aliases in parentheses.
| Command | What it does |
|---|---|
status · stats |
up/down + commit + boot id + the live counters; repaint with --watch |
version |
liveness + deployed commit (no token needed) |
health / ready |
liveness (+ auth) probe with a meaningful exit code — for scripts and orchestrators |
schema [show] |
the deployed base-table shape |
schema gen (generate) |
emit the @rindle/client schema TS — --out <file> (default stdout), --import-from <module>, --schema-const <name> |
migrate apply (up) |
apply pending *.sql from the migrations directory |
migrate list (ls) |
list local migrations |
migrate create <name> (new) |
scaffold a new migration file |
migrate status |
diff local migrations vs. the daemon’s applied journal |
init |
scaffold rindle.ncl (the colocated pair) + migrations/ (--dir .) |
up |
render rindle.ncl + supervise the local write-master + follower(s) + fleet edge — --migrate (to the master), --gen <out> (from a follower), --watch |
exec -- <command> |
launch an app command with RINDLE_DAEMON_URL, RINDLE_REPLICATOR_URL, and the public fleet ws derived from rindle.ncl; inherited secrets are untouched |
ps · stop (kill) |
list / stop running rindle processes (stop --all, or by pid) |
restart |
bounce a supervised daemon and wait for it back (--no-wait to skip the wait) |
login · logout · whoami |
Rindle Cloud auth (browser device flow; $RINDLE_CLOUD_TOKEN overrides for CI) |
rindle --help prints the full list, including the fleet/topology and recovery
commands (render, dematerialize, re-bootstrap).
Flags & environment
Precedence is always flag → environment variable → default.
| Flag | Env var | Default | Meaning |
|---|---|---|---|
--url <url> |
RINDLE_DAEMON_URL (RINDLE_REPLICATOR_URL is preferred by migrate) |
http://127.0.0.1:7600 |
the control plane commands talk to; rindle exec derives both local roles |
--token <bearer> |
RINDLE_DAEMON_TOKEN |
(none) | bearer token for the control plane |
--dir <path> |
RINDLE_MIGRATIONS_DIR |
migrations |
the migrations directory (migrate *) |
--out <file> |
— | stdout | where schema gen writes |
--gen <out> |
— | — | (up) regenerate the schema TS to <out> after --migrate — always takes the path |
--json |
— | off | machine-readable output |
--watch, -w |
— | off | repaint on an interval (status/stats); under up, re-apply/regen on migrations/ change |
--interval <s> |
— | 2 |
the --watch repaint interval |
--timeout <s> |
— | 5 |
per-request timeout |
--daemon-bin <p> |
RINDLE_DAEMON_BIN |
sibling of rindle, then $PATH |
(up) explicit path to the rindled binary |
| — | RINDLE_REPLICATOR_BIN |
sibling of rindle, then $PATH |
(up) explicit path to the write-master binary |
| — | RINDLE_DEV_EDGE_BIN |
sibling of rindle, then $PATH |
(up) explicit path to the native local fleet-edge binary |
| — | RINDLE_BIN_DIR |
the platform npm package | (npm wrapper) a directory of locally built binaries to use instead of the prebuilt ones |
Supervise from Node
If you need to supervise the npm-installed daemon from Node, import the package helpers:
import { rindledBinaryPath, spawnRindled } from "@rindle/cli";
const child = spawnRindled(["--config", "./follower.json"]);
console.log(rindledBinaryPath());
Package scripts
If you want a package script, make it forward to the CLI:
{
"scripts": {
"rindle": "rindle",
"dev:daemon": "rindle up --migrate --gen shared/schema.gen.ts --watch",
"dev:web": "rindle exec -- vite dev"
}
}
Then run:
npm run dev:daemon
# or
npm run rindle -- status
Next steps
- Scaffold with create-rindle - a TanStack Start app that uses this toolchain for its dev loop.
- Schema & migrations - the SQL-first migration and schema-gen workflow.
- Run the daemon - the daemon’s config, two network planes, and restart behavior.
- Synced-app quickstart - the manual app setup
that uses
@rindle/clidirectly.