Skip to content

rh CLI Reference ​

The rh binary is Rhei's command-line interface. It covers one-shot scripting, interactive exploration, and long-running service mode.

Global synopsis ​

sh
rh [SUBCOMMAND] [OPTIONS]

When invoked with no subcommand, rh launches the interactive TUI dashboard (same as rh dashboard).


rh exec ​

Execute SQL on the OLTP layer (reads and writes).

Synopsis ​

sh
rh exec --db <PATH> "<SQL>"

Flags ​

FlagTypeDefaultDescription
--dbpathrhei.dbPath to the SQLite database file

A positional <SQL> argument follows the flags.

What it does ​

  • SELECT, PRAGMA, and EXPLAIN — returns a formatted result table.
  • Everything else (INSERT, UPDATE, DELETE, CREATE, ALTER, DROP) — executes the statement and prints the affected-row count.

Write statements never touch the OLAP mirror directly; they enter the CDC log and are picked up on the next sync cycle.

When to use it ​

Use exec when you need to write data or read from the authoritative OLTP source — for example, inserting seed data, running DDL, or verifying raw row values before a sync.

Example ​

sh
# DDL
rh exec --db mydb.db "CREATE TABLE orders (id INTEGER PRIMARY KEY, amount REAL)"

# Insert
rh exec --db mydb.db "INSERT INTO orders VALUES (1, 99.99)"

# Read back from OLTP
rh exec --db mydb.db "SELECT * FROM orders LIMIT 5"

rh query ​

Execute an analytical SQL query on the OLAP mirror (read-only).

Synopsis ​

sh
rh query --db <PATH> "<SQL>"

Flags ​

FlagTypeDefaultDescription
--dbpathrhei.dbPath to the SQLite database file

A positional <SQL> argument follows the flags.

What it does ​

Routes the query directly to the OLAP backend (DataFusion or DuckDB). Write statements (INSERT, UPDATE, DELETE, CREATE, ALTER, DROP) are rejected with an error — use rh exec for writes.

When to use it ​

Use query for aggregates, JOINs, CTEs, window functions, and any analytical workload that benefits from columnar execution. The OLAP mirror must already be populated (run rh sync first if needed).

Example ​

sh
rh query --db mydb.db "SELECT region, SUM(amount) FROM orders GROUP BY region ORDER BY 2 DESC"

rh query --db mydb.db "
  WITH ranked AS (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY region ORDER BY amount DESC) AS rn
    FROM orders
  )
  SELECT * FROM ranked WHERE rn = 1
"

rh sync ​

Perform a single CDC sync cycle and print the result.

Synopsis ​

sh
rh sync --db <PATH>

Flags ​

FlagTypeDefaultDescription
--dbpathrhei.dbPath to the SQLite database file

What it does ​

Flushes all pending CDC events from _rhei_cdc_log into the OLAP mirror and prints a summary:

text
Sync Result
  Events processed:   42
  Rows inserted:      38
  Rows updated:       3
  Rows deleted:       1
  Last seq:           187
  Pruned:             -

When to use it ​

Use sync in scripts that write via exec then read via query — call it between the two steps to ensure the OLAP mirror is fresh. In production, use rh serve with sync_interval_ms for continuous background sync.

Example ​

sh
rh exec  --db mydb.db "INSERT INTO orders VALUES (2, 49.50)"
rh sync  --db mydb.db
rh query --db mydb.db "SELECT COUNT(*) FROM orders"

rh status ​

Print the current sync status and CDC lag.

Synopsis ​

sh
rh status --db <PATH>

Flags ​

FlagTypeDefaultDescription
--dbpathrhei.dbPath to the SQLite database file

What it does ​

Opens the engine in read mode and prints:

text
Sync Status
  Running:            false
  Last synced seq:    187
  Latest available:   189
  CDC lag:            2
  Registered tables:  1
    - orders

Fields:

  • Running — whether a background sync loop is active.
  • Last synced seq — CDC sequence number of the most recently applied event.
  • Latest available — highest sequence number in _rhei_cdc_log.
  • CDC lag — unsynced event count (latest - last_synced).
  • Registered tables — list of tables known to the schema registry.

When to use it ​

Use status in health checks, CI pipelines, or to diagnose why OLAP results appear stale.


rh repl ​

Interactive REPL with a persistent engine and connection pool.

Synopsis ​

sh
rh repl --db <PATH>

Flags ​

FlagTypeDefaultDescription
--dbpathrhei.dbPath to the SQLite database file

What it does ​

Starts an interactive prompt that keeps the HtapEngine alive across commands — no per-command startup cost. The prompt supports:

CommandDescription
<sql>Execute SQL on OLTP (reads + writes)
.olap <sql>Execute SQL on OLAP (read-only)
.syncTrigger a manual CDC sync cycle
.statusPrint CDC lag and last-synced sequence
.help / .hShow available commands
.quit / .exit / .qExit the REPL

When to use it ​

Use repl for interactive exploration of a database without paying a cold-start overhead on every query. The engine and its connection pool persist for the lifetime of the session.

Example ​

sh
rh repl --db mydb.db
text
Rhei REPL v2.0.0 — type .help for commands, .quit to exit
Database: mydb.db
Engine ready (connection pool active).

rhei> SELECT * FROM orders LIMIT 5
+----+--------+
| id | amount |
+----+--------+
|  1 |  99.99 |
+----+--------+

rhei> INSERT INTO orders VALUES (3, 12.00)
  1 row(s) affected

rhei> .sync
  Synced 1 events (1 ins, 0 upd, 0 del) in 0.8ms

rhei> .olap SELECT COUNT(*), SUM(amount) FROM orders
+----------+------------+
| count(*) | sum(amount)|
+----------+------------+
|        2 |     111.99 |
+----------+------------+

rhei> .quit
Goodbye.

rh dashboard ​

Interactive TUI dashboard with a built-in demo workload.

Synopsis ​

sh
rh dashboard

No flags. This is also the default command when rh is invoked without a subcommand.

What it does ​

Creates an in-memory HTAP engine, registers a users table, and runs a continuous INSERT / UPDATE / DELETE workload while syncing CDC events to the OLAP mirror. Four panels display live metrics:

  • OLTP — database path, write connection state, read pool size, total writes.
  • OLAP — backend name, storage mode, registered table count.
  • CDC Sync — lag, last sequence, event totals (insert/update/delete/pruned), throughput, cycle duration.
  • Activity Log — scrollable real-time log of every batch operation and sync cycle.

Controls ​

KeyAction
q / EscQuit
Up / DownScroll the activity log

rh info ​

Print build information and enabled feature flags.

Synopsis ​

sh
rh info

No flags.

What it does ​

text
Rhei HTAP Engine
  Version:        2.0.0
  Rust version:   unknown
  Target:         x86_64
  Features:       duckdb-backend, sidecar

The Features line lists non-default Cargo features compiled into the binary. A binary built with only the defaults shows (default).


rh serve ​

Run Rhei as a long-lived HTAP service.

Synopsis ​

sh
rh serve --config <PATH> [--headless]

Flags ​

FlagTypeDefaultDescription
--configpath(required)Path to the TOML config file
--headlessbool flagautoForce headless mode (log to stdout, no TUI). Auto-detected when stdout is not a TTY

What it does ​

  1. Loads and validates the TOML config.
  2. Initialises the tracing subscriber — tracing_subscriber fmt (text or JSON) in headless mode, or a TUI ring-buffer layer in dashboard mode.
  3. Optionally starts the Prometheus metrics exporter on metrics_port (requires metrics-exporter feature).
  4. Creates HtapEngine, executes any [[tables]] DDL, and registers schemas.
  5. Starts the background CDC sync loop at sync_interval_ms.
  6. Optionally starts the Arrow Flight SQL gRPC server on flight_port (requires flight-sql feature).
  7. Renders a live TUI dashboard when stdout is a TTY (same layout as rh dashboard), or logs a 10-second heartbeat in headless mode.
  8. On SIGINT (Ctrl-C) or SIGTERM, drains in-flight work and shuts down cleanly.

Headless vs TUI mode ​

ConditionMode
stdout is a TTY and --headless not setTUI dashboard
stdout is not a TTY (Docker, redirected)Headless (structured logs)
--headless flag presentHeadless (structured logs)

Set log_format = "json" in [engine] for structured JSON logs compatible with Loki, Datadog, or the ELK stack.

Typical TOML layout ​

A minimal config has an [engine] section, an optional [engine.datafusion_storage] for persisted DataFusion, and one or more [[tables]] arrays:

toml
[engine]
oltp_path        = "/var/lib/rhei/htap.db"
olap_backend     = "datafusion"
sync_interval_ms = 250
sync_mode        = "destructive"

[engine.datafusion_storage]
mode = "vortex"
path = "/var/lib/rhei/data"

[[tables]]
name = "orders"
# ... columns

For the full schema (every key, every default, and complete worked examples for HTAP, sidecar, FlightSQL, temporal, and Prometheus configurations), see TOML Config Reference.

Example ​

sh
# Run with live TUI (stdout is a TTY)
rh serve --config config/htap.toml

# Run headless inside Docker / systemd
rh serve --config /etc/rhei/htap.toml --headless

Signal handling

rh serve handles both SIGINT (Ctrl-C) and SIGTERM, so it integrates cleanly with container orchestrators and systemd service units.

Flight SQL auth token

The flight_auth_token TOML key takes precedence over the RHEI_FLIGHT_AUTH_TOKEN environment variable. Use the environment variable to avoid storing tokens on disk.


Common workflows ​

(a) One-shot scripting with exec + query ​

Ideal for CI pipelines, data-loading scripts, and ad-hoc queries where you want a quick write-sync-read cycle from the shell:

sh
#!/usr/bin/env bash
set -euo pipefail

DB=mydb.db

# Seed data
rh exec  --db "$DB" "INSERT INTO events VALUES (1, 'login', '2024-01-15')"
rh exec  --db "$DB" "INSERT INTO events VALUES (2, 'purchase', '2024-01-15')"

# Flush CDC to OLAP
rh sync  --db "$DB"

# Analytical query
rh query --db "$DB" "SELECT type, COUNT(*) FROM events GROUP BY type"

Each invocation pays a fresh engine startup cost (~5–50 ms depending on database size). For many sequential queries, prefer repl instead.

(b) Interactive exploration via repl ​

Use repl when you are iterating on a query or exploring an unfamiliar database. The engine and connection pool stay warm for the entire session:

sh
rh repl --db analytics.db

Inside the REPL you can mix OLTP writes, OLAP reads, and manual sync calls without any per-command overhead. The REPL is the fastest tool for development and debugging.

(c) Running as a service via serve ​

rh serve is the production deployment path. The engine is created once and kept alive indefinitely. The background sync loop runs automatically at sync_interval_ms:

sh
rh serve --config /etc/rhei/htap.toml --headless

serve and repl both hold the engine open across queries, eliminating per-call cold starts. In serve mode the background sync loop also removes the need to manually call sync_now.

One-shot commands create a fresh engine

rh exec, rh query, rh sync, and rh status each create a new HtapEngine instance on start and destroy it on exit. For frequent calls in a tight loop, this overhead accumulates. Use repl or serve instead.

Released under the Apache-2.0 License.