CLI Reference

August 6, 2026 ยท View on GitHub

Install the command:

nimble install koutendb
kouten --help

When working from a source checkout, install the local package onto your PATH:

nimble install -y
kouten --help

Nimble installs binaries into ~/.nimble/bin by default. If kouten is not found, add it to your shell PATH:

export PATH="$HOME/.nimble/bin:$PATH"

For persistent shell setup:

printf '\nexport PATH="$HOME/.nimble/bin:$PATH"\n' >> ~/.profile

For server-style installs, use /usr/local/bin:

nim c -d:release --nimcache:/tmp/nimcache_kouten -o:bin/kouten src/koutencli.nim
nim c -d:release --nimcache:/tmp/nimcache_koutend -o:bin/koutend src/koutend.nim
sudo install -m 0755 bin/kouten /usr/local/bin/kouten
sudo install -m 0755 bin/koutend /usr/local/bin/koutend

For repo-local development without installing, you can also build and run a local binary:

nim c -d:release --nimcache:/tmp/nimcache_kouten -o:bin/kouten src/koutencli.nim
bin/kouten --help

Common Cluster Flags

FlagMeaning
--config=FILELoad cluster connection defaults from JSON. CLI flags override the file. KOUTEN_CONFIG can point to the same file.
--peers=host:port,...Target cluster.
--user=NAME / --password=TEXTUsername/password auth. Prefer --password-file or KOUTEN_PASSWORD outside local smoke tests.
--password-file=FILERead password from a file. Trailing whitespace is stripped.
--auth-token=TEXTToken-style auth. Prefer --auth-token-file or KOUTEN_AUTH_TOKEN outside local smoke tests.
--auth-token-file=FILERead token-style auth value from a file.
--secret-key=TEXTSecret-key gate. Prefer --secret-key-file or KOUTEN_SECRET_KEY outside local smoke tests.
--secret-key-file=FILERead the secret-key gate value from a file.
--galaxy=NAMEExpected remote galaxy.
--tlsUse standard TLS for the TCP transport. Requires TLS-enabled binaries built with -d:ssl.
--tls-ca=FILECA/self-signed PEM file for server certificate verification.
--tls-server-name=NAMEOptional hostname override for TLS verification and SNI.
--tls-insecure-skip-verifySkip certificate verification for local smoke tests only.
--metricsEmit key/value metrics where supported.
--jsonEmit JSON where supported.

Example:

{
  "peers": ["127.0.0.1:7301"],
  "user": "alice",
  "passwordFile": "/run/secrets/kouten_password",
  "secretKeyFile": "/run/secrets/kouten_secret_key",
  "tls": true,
  "tlsCaFile": "/etc/koutendb/ca.crt"
}
kouten health --config=/etc/koutendb/client.json
kouten get --config=/etc/koutendb/client.json --ring=docs/japan

Cluster Commands

CommandPurpose
healthCheck cluster health.
metricsEmit server metrics. `--format=key-value
ringsShow ring summaries.
atlasEmit the galaxy/ring map. Works with --data or --peers.
drainPut cluster nodes into read-only maintenance mode. Requires admin auth.
snapshotFlush cluster nodes and report a snapshot barrier. Requires admin auth.
resumeLeave drain mode only after every peer has the same topology and zero migration backlog. Requires admin auth.
shutdownStop a server.
demoRun a small cluster demo.

For maintenance or backup windows, use drain, then snapshot, then run the backup or replacement operation, and finally resume:

kouten drain --peers=127.0.0.1:7301,127.0.0.1:7302 --user=admin --password-file=/run/secrets/kouten_admin
kouten snapshot --peers=127.0.0.1:7301,127.0.0.1:7302 --user=admin --password-file=/run/secrets/kouten_admin
kouten resume --peers=127.0.0.1:7301,127.0.0.1:7302 --user=admin --password-file=/run/secrets/kouten_admin

Drain mode rejects new write commands, including body-carrying frames, after consuming their remaining payload bytes. That keeps the TCP protocol boundary intact so the same connection can continue to serve reads and admin commands. snapshot is a flush/report barrier; use it after drain when a quiet point is required. resume first checks every configured peer. Unreachable peers, mixed placement epochs, and pending migration all fail closed without clearing the local drain marker.

Scale-In Commands

Scale-in copies persistently drained old node directories into a fresh smaller cluster with a higher placement epoch. Run each source directory separately and keep the target outside application routing until all sources verify.

CommandPurpose
scale-in-planValidate the source/target boundary and report record, tombstone, metadata, and per-target counts without writing.
scale-in-migrateTransfer versioned records, tombstones, and database metadata with a durable resumable checkpoint.
scale-in-verifyIndependently compare target mutation state and metadata before activation.
scale-in-statusRead a checkpoint without connecting to either cluster.
kouten scale-in-plan --data=/var/lib/koutendb/old/node0 \
  --peers=127.0.0.1:7401,127.0.0.1:7402 --json
kouten scale-in-migrate --data=/var/lib/koutendb/old/node0 \
  --peers=127.0.0.1:7401,127.0.0.1:7402 \
  --checkpoint-every=1000
kouten scale-in-verify --data=/var/lib/koutendb/old/node0 \
  --peers=127.0.0.1:7401,127.0.0.1:7402 --json
kouten scale-in-status \
  --checkpoint=/var/lib/koutendb/old/node0/kouten.scale-in.2.json

Authentication and TLS flags are the same as other cluster commands. See Physical Placement and Topology Remapping for the complete maintenance order, safety boundaries, and recovery behavior.

Driver Commands

KoutenDB keeps language drivers small and publishable as language-native packages. External drivers can live outside the core repository while the kouten CLI keeps the discovery path consistent.

kouten driver list
kouten driver info rust
kouten driver install rust
kouten driver install rust --manifest-path=/path/to/Cargo.toml

driver install currently prints the official repository/package path and package-manager command. It does not execute remote scripts or download code. For Rust it resolves the target Cargo.toml in this order:

  1. --manifest-path=FILE
  2. KOUTEN_DRIVER_MANIFEST
  3. --project-dir=DIR
  4. KOUTEN_DRIVER_PROJECT
  5. Cargo.toml in the current directory

Pass --execute to run the package-manager command when the selected driver is published and the target project can be resolved. KoutenDB refuses to execute package-manager commands for unpublished drivers and prints the command instead.

CommandPurpose
driver listShow known official driver targets and their publication status.
driver info LANGShow repository, package name, mode, and notes for one driver.
driver install LANGPrint the recommended setup command and target project path.

Document Commands

These commands work with --data=DIR for embedded mode and --peers=... for a running cluster. When --data=DIR is omitted, embedded commands use KOUTEN_DATA if set, otherwise ./data.

kouten put --ring=docs/japan --payload='{"title":"Hello"}' --codec=json
kouten get --ring=docs/japan
kouten put --ring=orders --near=users/123 --payload='{"orderNo":"A-001"}' --codec=json
kouten get --ring=users/123 --subring=orders
kouten get --stellar=users/123 --filter='{"kind":"order"}' --subring=orders
kouten get --ring=users/123 --subring=profile,orders,billing --subring-limit=orders:10,billing:1 --subring-rsort=orders:time
kouten stellar attach --stellar=commerce/order/A-001 --ring=users/123
kouten stellar detach --stellar=commerce/order/A-001 --ring=users/123
kouten get --ring=docs/japan --limit=1 --rsort=time
kouten get --ring=docs/japan --pagination=on --page=2 --pagelimit=20 --sort=id
kouten get --ring=docs/japan --filter='{"id":"RAW_ID"}' --selection='{ title }'
kouten get --ring=docs/japan --filter='{"status":"draft"}' --selection='{ title }'
kouten count-ring --ring=docs/japan

Codec is explicit at write time. If you do not pass a codec, KoutenDB stores the payload as raw bytes unless --codec=auto resolves to a ring profile.

# JSON document: projection and JSON filters can be used later.
kouten put --ring=docs/japan --payload='{"title":"Hello","status":"draft"}' --codec=json
kouten get --ring=docs/japan --filter='{"status":"draft"}' --selection='{ title }'

# NIF text: stored as NIF-tagged bytes. KoutenDB does not parse it as JSON.
kouten put --ring=docs/nif --in=sample.nif --codec=nif
kouten get --ring=docs/nif --limit=1

# BIF binary: stored as BIF-tagged bytes. `auto` view decodes through an
# optional adapter when available; otherwise it returns base64.
kouten put --ring=docs/bif --in=sample.bif --codec=bif
kouten get --ring=docs/bif --limit=1
kouten get --ring=docs/bif --limit=1 --view=base64
kouten get --ring=docs/bif --limit=1 --view=hex

# Plain raw bytes or text.
kouten put --ring=logs/raw --payload='plain text payload' --codec=raw
kouten get --ring=logs/raw --limit=1
CommandRequired flagsPurpose
put--ring=RING plus --payload=TEXT or --in=FILE; optional --near=BASE_RING, `--codec=autoraw
get--ring=RING or --stellar=RING; optional --subring=a,b, --subring-limit=a:10,b:1, --subring-sort=a:id, --subring-rsort=b:time, --filter=JSON, --selection=SEL, --limit=N, --cursor=CURSOR, `--sort=idtime, --rsort=id
stellar attach--stellar=RING --ring=RINGAdd an existing ring coordinate to a stellar coordinate's visible lens. Payloads are not copied.
stellar detach--stellar=RING --ring=RINGRemove a ring coordinate from a stellar coordinate's visible lens. Payloads are not deleted.
stellar list--stellar=RINGList rings attached to a stellar coordinate.
time-orbit--data=DIR --ring=RING; optional --bucket-ms=N, --bits=N, --phase=N, --salt=TEXTRead or update the embedded ring-local time-orbit profile used by time-put and time-get. Remote profile administration is not available yet.
time-put--data=DIR --ring=RING --time-ms=N plus --payload=TEXT or --in=FILEStore a log/event payload into the ring's calculated time bucket. JSON object payloads receive eventTimeMs and ingestTimeMs metadata when missing.
time-get--data=DIR --ring=RING --from-ms=N --to-ms=N; optional --filter=JSON, --selection=SEL, --limit=N, `--sort=idtime, --rsort=id
query--ring=RING --filter='{"id":"ID"}' --selection=SEL; optional --id=IDCompatibility command for JSON projection by ID. Prefer get --selection=... for new CLI use.
list-ring--ring=RINGCompatibility command for listing records in one ring. Prefer get --ring=... for new CLI use.
count-ring--ring=RINGCount records in one ring.
ring-profile--ring=RINGRead or update the persisted defaultCodec, charset, and formatVersion declaration.

For example:

kouten ring-profile --ring=docs/nif --codec=nif --charset=UTF-8 --format-version=1
kouten put --ring=docs/nif --payload='(example)' # codec=nif via the profile

The profile is advisory. Every record keeps its explicit codec, so a later profile change does not reinterpret existing bytes. Remote profile administration is not available in this release.

Time orbit is an embedded PoC for log/event/time-series placement:

kouten time-orbit --ring=logs/api --bucket-ms=1000 --bits=60 --phase=100 --salt=api
kouten time-put --ring=logs/api --time-ms=1784376000000 \
  --payload='{"level":"error","message":"timeout"}'
kouten time-get --ring=logs/api --from-ms=1784376000000 --to-ms=1784376300000 \
  --filter='{"level":"error"}' --selection='{ level message eventTimeMs }'

--filter is a JSON object. {"id":"RAW_ID"} performs an exact read, while other top-level fields filter JSON records in the selected ring. --where is accepted as a compatibility alias for --filter.

--near is a write-time placement hint, not a persistent relationship field. For example, kouten put --near=users/123 --ring=orders ... writes the record to users/123/orders. Later reads use the coordinate itself:

kouten get --ring=users/123
kouten get --stellar=users/123 --filter='{"kind":"order"}' --subring=orders
kouten get --ring=users/123/orders
kouten get --ring=users/123 --subring=orders

This is similar to pointing a telescope at a ring. Nearby satellites are in the same field of view; distant rings are not pulled in just to emulate a global join.

stellar attach and stellar detach adjust a stellar coordinate's lens after data already exists:

kouten put --ring=users/123 --payload='{"kind":"user"}' --codec=json
kouten put --ring=shops/1123 --payload='{"kind":"shop"}' --codec=json
kouten put --ring=orders/A-001 --payload='{"kind":"order"}' --codec=json

kouten stellar attach --stellar=commerce/order/A-001 --ring=users/123
kouten stellar attach --stellar=commerce/order/A-001 --ring=shops/1123
kouten stellar attach --stellar=commerce/order/A-001 --ring=orders/A-001

kouten get --stellar=commerce/order/A-001 --filter='{"kind":"shop"}'
kouten stellar detach --stellar=commerce/order/A-001 --ring=shops/1123

This is a lens relationship, not a copy operation. Compaction can later use the same metadata to place related coordinates more favorably on disk.

--sort=FIELD sorts ascending and --rsort=FIELD sorts descending. Supported fields are id and time (write is accepted as a compatibility alias for time). The default is --rsort=time. --pagination=on --page=N --pagelimit=N is a human-friendly page interface. For high-volume scans, prefer cursor-based reads with --cursor because deep pages must skip earlier filtered matches.

For BIF payloads, the default auto view looks for an optional adapter in this order: KOUTENDB_NIF_TOOL, koutendb-nif, then nif_file_tool. The adapter command must support:

ADAPTER decode --in=input.bif --out=output.nif

ID formats accepted by get and query:

  • parent:seq
  • parent:epoch:seq:tWrite

Use the rawId printed by put for scripts and reproducible examples.

Interactive Shell

kouten shell provides a small MySQL-like interactive command surface for manual exploration:

kouten shell

Minimal shell commands:

put RING PAYLOAD
get ID [RING]
query ID SELECTION
query ID RING SELECTION  # cluster mode
list RING [LIMIT]
count RING
atlas
help
exit

The shell intentionally uses KoutenDB terms directly. It is not an SQL parser. For scripts and reproducible examples, prefer the single-shot commands above.

Local Data Commands

CommandRequired flagsPurpose
compact--data=DIRCompact WAL.
pack-ring--data=DIR --ring=RINGMerge one disk-backed ring into a new local segment generation.
segment-status--data=DIR; optional --stale-ratio=F, --min-stale-records=N, --metrics, --jsonInspect ring-local generations, stale ratios, bytes, and pack recommendations without rewriting data.
pack-recommended--data=DIR; optional --stale-ratio=F, --min-stale-records=N, --max-rings=NExplicitly pack only rings selected by the current diagnostic.
maintenance-plan--data=DIR; bounded maintenance thresholds and budgets; optional --jsonDry-run the exact count/byte selection used by maintenance execution.
maintenance-runSame as maintenance-planExecute one bounded maintenance pass and durably record its outcome.
maintenance-status--data=DIR; optional --jsonRead the last durable maintenance result and recover a stale running marker as interrupted.
checkpoint-create--data=DIR; optional --checkpoint-root=DIR, --checkpoint-id=ID, --durability=buffered|strong, --jsonCreate, seal, publish, and verify one immutable WAL plus ring-segment generation.
checkpoint-status--checkpoint=DIR; optional --jsonInspect one checkpoint without raising for integrity failure.
checkpoint-verify--checkpoint=DIR; optional --jsonStrictly verify one checkpoint and exit non-zero on failure.
checkpoint-list--checkpoint-root=DIR; optional --jsonList verified and invalid generations, newest first.
checkpoint-clean--checkpoint-root=DIR; optional --keep=N, --jsonRetain the newest verified generations and preserve invalid ones for diagnosis. N must be at least one.
checkpoint-metrics--checkpoint-root=DIR; optional `--format=key-valueprometheus
checkpoint-restore--checkpoint=DIR --data=DIR; optional --overwrite, --jsonVerify and stage a complete generation, then atomically publish the target data directory.
locality--data=DIR; optional --metricsInspect physical WAL locality by ring.
backup--data=DIR --backup=DIRCreate backup.
restore--backup=DIR --data=DIRRestore backup.
backup-encrypted--data=DIR --backup=DIR --passphrase=TEXTCreate encrypted backup.
restore-encrypted--backup=DIR --data=DIR --passphrase=TEXTRestore encrypted backup.
verify--data=DIR or --backup=DIR; optional --segments, --max-wal-bytes=N, --max-segment-bytes=N, --max-dead-records=N, --max-dead-ratio=F, --max-segment-generation=N, --max-segment-files=N, --max-items=N, --max-rings=N, --metrics, --jsonOpen and inspect a persistent data directory or backup. Data-dir verification checks WAL replay, lock, metadata, locality, capacity thresholds, and rebuildable segment layout. Backup verification checks restore readability without writing into the live data directory.
dump--data=DIRExport JSONL.
import-jsonl--data=DIR --in=FILE; optional --batch-size=NImport JSONL with chunked commits.
describe-galaxy--data=DIR --description=TEXTSet galaxy map description.
describe-ring--data=DIR --ring=RING --description=TEXTSet ring map description.

dump / import-jsonl are the portable migration boundary while KoutenDB's pre-v1.0 internal WAL format can still evolve. import-jsonl recognizes koutendb.dump.v1 files produced by dump, and can also route external JSONL exports through --ring-field, --payload-field, and --vec-field. --batch-size=N controls how many successfully parsed records are committed per WAL transaction during bulk load. See Data Migration.

When --checkpoint-root is omitted from checkpoint-create, KoutenDB uses the data-directory sibling DATA_DIR.checkpoints. The root must not overlap the source data directory. See Generation Checkpoints.

Recovery Commands

CommandPurpose
recovery-backupWrite recovery archives from a data directory.
recovery-verifyVerify one recovery archive.
recovery-statusCheck archive health against requiredHealthy.
recovery-restoreRestore from the best healthy archive.

Recovery commands accept --mirror, --universe-config, --universe, --galaxy, --location, --failure-domain, --priority, --snapshot-seq, --auth-ref, --readonly, and --passphrase where applicable.

Universe Sync Commands

CommandPurpose
universe-export --data=DIR [--out=FILE]Export source outbox events.
universe-apply --data=DIR --in=FILEApply exported events to a local data directory.
universe-sync --data=SOURCE --target-data=TARGETOne-shot local sync.
universe-sync --data=SOURCE --peers=host:port,...Deliver source outbox events to a running cluster.
universe-status --data=DIRInspect source outbox status.
universe-status --peers=host:port,... --metricsInspect remote apply counters.

Benchmark / Demo Commands

CommandPurpose
benchBasic cluster operation benchmark.
retrieve-benchRetrieval benchmark.
redis-benchRedis comparison smoke.
rag-benchSynthetic RAG-style working-set/token benchmark.
working-set-benchWorking-set reduction benchmark.
memory-pressure-benchCandidate memory pressure benchmark.
doctorWithout --data / --backup / --server-config, report the dependency-free embedded setup. With --data=DIR, --backup=DIR, or --server-config=FILE, run operational verification.

Operational Verification

CommandPurpose
verify --data=DIR [--segments] [--max-wal-bytes=N] [--max-segment-files=N] [--max-items=N] [--max-rings=N]Open/replay a persistent data directory and check WAL, metadata, locality, optional capacity thresholds, and optional segment rebuild health.
`pack-ring --data=DIR --ring=RING [--durability=bufferedstrong]`
`segment-status --data=DIR [--metrics--json]`
pack-recommended --data=DIR [--max-rings=N]Apply the same recommendation thresholds explicitly.
maintenance-plan --data=DIR [--max-rings=1] [--max-bytes=67108864] [--max-elapsed-ms=1000] [--json]Explain which rings one bounded run would select or skip.
maintenance-run --data=DIR [--max-rings=1] [--max-bytes=67108864] [--max-elapsed-ms=1000] [--json]Execute the bounded plan. A limit interruption leaves the previous segment generation active.
maintenance-status --data=DIR [--json]Show the durable result, including stable per-ring reason codes.
checkpoint-create --data=DIR [--checkpoint-root=DIR] [--checkpoint-id=ID] [--json]Publish and verify a self-contained generation.
checkpoint-verify --checkpoint=DIR [--json]Reject missing, incomplete, corrupt, symlinked, or logically inconsistent generations.
checkpoint-clean --checkpoint-root=DIR [--keep=N] [--json]Apply fail-safe retention without deleting invalid evidence or the final verified generation.
checkpoint-restore --checkpoint=DIR --data=DIR [--overwrite] [--json]Restore through a verified staging directory and atomic directory replacement.
verify --backup=DIRVerify backup readability before restore.
verify --server-config=FILEValidate a koutend server JSON config before startup.
doctor --server-config=FILE --jsonEmit the same server config checks as JSON.

Server config verification checks id / peers, persistence, auth combinations, secret file readability, role entries, ring-prefix authorization shape, TLS cert/key pairing, TLS file existence, and whether certificate verification has been explicitly disabled.