CLI and TUI
celeriant_cli is the command-line client: one-shot commands for scripts and operations, and an interactive TUI when you run it with no command. It is a separate binary from the celeriant server, and it is not in the server's container image. Build it from the source tree:
cargo build --release -p celeriant_cli
./target/release/celeriant_cli --help
Connecting
Connection flags go before the subcommand. Each has an environment variable.
celeriant_cli \
--server 10.0.0.1:10000 \
--tls --ca-cert ca.crt --client-cert client.crt --client-key client.key \
--api-key "$CELERIANT_API_KEY" \
read --org 1 --type 1 --id 1
| Flag | Env | Notes |
|---|---|---|
-s, --server | CELERIANT_SERVER | Default 127.0.0.1:10000. |
--tls | CELERIANT_TLS | Requires --ca-cert. Cert flags without --tls are an error. |
--ca-cert | CELERIANT_CA_CERT | PEM CA to verify the server. |
--client-cert, --client-key | CELERIANT_CLIENT_CERT, CELERIANT_CLIENT_KEY | PEM pair for mTLS; give both or neither. |
--server-name | CELERIANT_SERVER_NAME | TLS SNI. Defaults to the host part of --server. |
--api-key | CELERIANT_API_KEY | Base64 API key. |
--public-key, --private-key | CELERIANT_PUBLIC_KEY, CELERIANT_PRIVATE_KEY | Files holding base64 DER RSA keys, for keypair identity. Give both. |
One-shot commands open a single connection to --server. There is no pool and no leader redirect: point write, trim, delete and register-schema at the leader, or they fail with a not-leader error.
Commands
IDs (--org, --type, --id, --client-id, --user-id, --correlation-id) accept a UUID, a number, or base64. Every command that talks to the server takes --correlation-id.
# inspect
celeriant_cli aggregate-details --org 1 --type 1 --id 1
# read: one page, from version 1 by default
celeriant_cli read --org 1 --type 1 --id 1 [--from 1] [--to 100] \
[--event-types 1,2] [--format json|table|compact]
# append one event
celeriant_cli write --org 1 --type 1 --id 1 --event-type 1 \
(--data '{"sku":"A-1"}' | --file payload.json) \
[--allow-create] [--expected-version 4] [--enforce-idempotency] \
[--client-id <id>] [--user-id <id>]
# retention
celeriant_cli trim --org 1 --type 1 --id 1 --keep-from 100 [--client-id <id>]
celeriant_cli delete --org 1 --type 1 --id 1 [--allow-recreate] \
[--allow-sequence-continuation] [--expected-version 4] [--client-id <id>]
# discovery, across every shard
celeriant_cli list-orgs [--shard 0] [--format table|json]
celeriant_cli list-types [--org 1]
celeriant_cli list-aggregates [--org 1 [--type 1]] [--include-deleted]
# schema
celeriant_cli register-schema --org 1 --type 1 --major 1 [--minor 0] \
--schema-type json|avro --file order.schema.json # or --schema '<inline>'
celeriant_cli register-schema --org 1 --type 1 --major 1 \
--schema-type protobuf --proto-descriptor order.pb --message-name shop.OrderPlaced
read also filters on client, user, server timestamp, event timestamp, event seq and client seq: --include-client, --exclude-client, --include-user, --exclude-user, --min-timestamp, --max-timestamp, --min-event-timestamp, --max-event-timestamp, --min-event-seq, --max-event-seq, --min-client-seq, --max-client-seq. Timestamps are unix milliseconds. read returns one page; it prints the next version when there is more.
--format exists on read and the three list commands. read defaults to json, the lists to table. compact currently prints the same as table.
write, trim, delete and register-schema need a client id. With --public-key/--private-key the server-verified id is used; pass --client-id too and it must match. Without a key pair, --client-id is required.
--expected-version is the optimistic concurrency guard. --enforce-idempotency is weaker than it looks: the CLI writes every event with client_seq 0 and has no flag to set it, so it cannot express a retry sequence. Do idempotent writes from a client library.
The TUI
Run celeriant_cli with no command. It starts disconnected; connect from the home screen. From there you can enter an aggregate by ID or pick one from a list of orgs, types or aggregates, then read, write, trim, delete and register schemas against it.
Watch is TUI-only. There is a per-aggregate watch and an organisation watch, scoped by org with optional aggregate types, operation types (0-5) and a requested latency. The one-shot CLI does not subscribe.
Unlike the one-shot commands, the TUI connects through the Rust client's pool, so it follows leader redirects and can take seed addresses and route reads to followers. Its settings screen covers server and seeds, TLS, API key, identity, pool size and timeouts, and routing; settings persist to ~/.celeriant/settings.toml. Command-line flags override the file.
Identity mode defaults to auto: the TUI generates an RSA key pair in your OS data directory on first run and identifies with it, so its client id is stable across sessions. custom uses the key files you name; none sends no key pair.
Server-side tools
Certificates and API keys come from the server binary, not this one: celeriant cert ... and celeriant keys .... See TLS and mTLS.
The CLI declares a dict train subcommand for building a zstd dictionary from a JSONL corpus, but it is not wired up in this build: it connects to --server, then panics. Do not script against it.