Interactive terminal client for KalamDB, built on kalam-client.
Binary name: kalam (from the cli crate).
- Start the server (default is
http://localhost:2900)
cd backend
cargo run- Install the CLI
npm install -g @kalamdb/cli
# or
curl -fsSL https://kalamdb.org/install.sh | sh
kalam --help- Connect and run a query
./target/release/kalam
# inside kalam
\dt
SELECT * FROM information_schema.tables LIMIT 5;- Optional: start a live query
# inside kalam
\subscribe SELECT * FROM app.messages WHERE user_id = 'alice';npm install -g @kalamdb/cli
# or
curl -fsSL https://kalamdb.org/install.sh | sh
# from source
cd cli && cargo build --releasekalam version
kalam doctor
kalam update
kalam login --instance prod --url https://db.example.com --user root --password
kalam whoami --instance prod
kalam logout --instance prod
kalam token create --name ci-prod# Default – uses stored credentials/config, otherwise http://localhost:2900
kalam
# Explicit URL
kalam --url http://localhost:2900
# Host/port alternative (note: if you use --host without --port, the default port is 3000)
kalam --host localhost --port 2900
# User/password login
kalam login --instance dev --user alice --password Secret123!
# JWT
kalam --token "<JWT_TOKEN>"
# Save credentials and drop into the shell immediately when run from a terminal
kalam login --instance dev --user alice --password Secret123!When kalam login runs in an interactive terminal, it enters the normal SQL shell immediately after a successful local or OIDC login. Non-interactive invocations still save credentials and exit so shell scripts can keep treating login as a one-shot command.
# One command and exit
kalam -c "SELECT * FROM information_schema.tables LIMIT 5;"
# Inside a project, unqualified names use that project's namespace.
# A local server signs in with the password in kalam/server/server.toml
# when saved credentials are missing or expired.
# File and exit
kalam -f setup.sql# Run your schema generator once, then rerun it whenever app namespace metadata changes
kalam --watch-schema --namespace app --run "npm run schema:gen" --run-on-start
# Watch one specific table with a tighter poll interval
kalam --watch-schema --table app.messages --run "npm run schema:gen" --interval 2s--url,-u– server URL--host,-Hand--port,-p– alternative to--url--instance– saved server fromkalam instances. Inside a project, SQL uses that project unless you pass a name other than the defaultlocal--token– JWT bearer token--user/--password– user/password login--save-credentials– save JWT token after login--list-instances– list stored credential instances--format–table(default) |json|csv--json/--csv– shorthand for--format--no-color– disable colored output--no-spinner– disable spinners/animations--loading-threshold-ms– loading indicator threshold--file,-f– execute SQL file--command,-c– execute a single SQL statement--config– config path (default~/.kalam/config.toml)--verbose,-v– verbose logging--timeout– HTTP timeout in seconds--connection-timeout– connection timeout in seconds--receive-timeout– receive timeout in seconds--auth-timeout– WebSocket auth timeout in seconds--fast-timeouts/--relaxed-timeouts– timeout presets--subscribe <SQL>– subscribe (non-interactive) to a live query--subscription-timeout– subscription idle timeout in seconds (0 = no timeout)--initial-data-timeout– max seconds to wait for initial data batch--list-subscriptions– list active subscriptions--watch-schema– pollinformation_schema.tablesand run a local command on schema changes--namespace– repeat to scope schema watch to one or more namespaces--table– repeat to scope schema watch to one or morenamespace.tabletargets--run– shell command executed after schema changes are detected--run-on-start– execute the watch command once before polling--interval– schema watch poll interval, default5s
kalam version– print CLI version/build metadatakalam update [--version <version>] [--pre-release | --stable]– replace the current binary with a verified GitHub release artifact.--pre-releaseinstalls the newest published rc/beta/alpha and never downgrades.--stableswitches to GitHub's latest non-draft release and is the only implicit path that may leave a newer installed pre-release.kalam doctor [--strict]– inspect binary path, config, credentials, healthcheck, and auth reachabilitykalam login --instance <name> --url <url>– login, save access/refresh tokens, and enter the interactive shell immediately when run from a terminalkalam logout [--all]– remove saved credentials locally and best-effort notify the serverkalam whoami– call/v1/api/auth/mewith the resolved credentialskalam token create --name <name>– create a service account and print a fresh access/refresh token pair
In interactive mode, meta-commands start with \:
| Command | Description |
|---|---|
\help, \? |
Show help |
\quit, \q |
Exit |
\info, \session |
Show session info |
\history, \h |
Open command history |
\dt, \tables |
List tables (information_schema.tables) |
\d <table>, \describe <table> |
Describe table |
\as <user_id> <SQL> |
Wrap one statement as EXECUTE AS '<user_id>' |
\stats, \metrics |
Show system.stats |
\health |
Server healthcheck |
\flush |
Run STORAGE FLUSH ALL |
| `\format table | json |
\live <SQL>, \subscribe <SQL> |
Start live subscription (\subscribe is an alias) |
\cluster ... |
Cluster commands (see below) |
\refresh-tables, \refresh |
Refresh autocomplete metadata |
\sessions |
Show active sessions |
\consume <topic> ... |
Consume topic messages |
\show-credentials, \credentials |
Show stored credentials |
\update-credentials <u> <p> |
Update stored credentials |
\delete-credentials |
Delete stored credentials |
Backup/export SQL examples you can run directly from the CLI:
BACKUP DATABASE TO '/tmp/kalamdb-backup.tar.gz';
EXPORT USER DATA;
SHOW EXPORT;\cluster snapshot\cluster purge --upto <index>(or\cluster purge <index>)\cluster trigger-election\cluster transfer-leader <node_id>\cluster rebalance\cluster stepdown\cluster clear\cluster list(alias:\cluster ls)\cluster list groups\cluster join <node_id> <rpc_addr> <api_addr>
KalamDB uses Multi-Raft groups. A request does not have to land on the leader node first.
Example:
kalam --url http://node-2:2900 --command "INSERT INTO app.messages (id, body) VALUES (101, 'hello')"Assume the authenticated or effective user for that request is user-42, and user-42 hashes to user data group DataUserShard(7).
- The request can hit any node, including a follower for that group.
- The SQL layer prepares and classifies the statement once, then derives the target Raft group from the table type and current
user_id. - For user and stream tables, KalamDB hashes
user_idinto one ofcluster.user_shardsgroups. - If the receiving node is not the leader for that target group, it forwards the original SQL, params, auth header, and request id over gRPC to the current leader for that group.
- The group leader executes the write, appends it to that Raft log, replicates it to followers, commits it, and returns the result.
- The follower relays that leader-built response back to the client.
This keeps writes local to the correct group leader even when clients connect to follower nodes.
- KalamDB runs one metadata Raft group plus multiple user data groups.
- User and stream data are routed by
user_id, so all rows for the same user go through the same user-data Raft group leader at a given time instead of scattering one user's working set across many leaders. - That locality reduces cross-group coordination and improves cache and write-path behavior.
- Shared tables are different today: they currently route to a single shared group.
- Shared-table sharding is still a work in progress. The planned direction is partition-by-key so each shared table can define how a row is partitioned and where it should be placed.
table– pretty table with row count and latencyjson– raw JSON rowscsv– header + rows (good for piping)
Start a live query from interactive mode:
kalam> \subscribe SELECT * FROM app.messages WHERE user_id = 'alice';Or start one from a non-interactive invocation:
kalam --subscribe "SELECT * FROM app.messages WHERE user_id = 'alice';"Each saved name is one server. kalam dev in a project directory keeps using that project's database. --instance <name> selects a different server from any directory, including SQL.
# Local project database
kalam dev
# Cloud server that signs users in with OIDC
kalam login --oidc --instance prod --url https://db.example.com
# SQL against that cloud server, even from inside the local project
kalam --instance prod -c "SELECT current_user"
# Another local project, using the name from `kalam instances`
kalam status --instance analytics
kalam --instance analytics -c "SELECT 1"A remote login needs its own name. Signing in to a cloud URL without --instance <name> is refused, so it cannot overwrite the default local profile or get sent to the project database by mistake. If the cloud server disables password login, kalam login and non-interactive kalam -c say to add --oidc and print the server they reached, instead of trying the project password. A saved token for that same server still works. --url and --host override --instance, and the CLI says which server the command is using. kalam db, kalam deploy, kalam link, and kalam functions stay on the project: passing --instance for a different server is an error instead of changing the local database. kalam dev prints the same distinction and keeps the project database. A stopped local server keeps the port it last used. If another server is running there, kalam instances says so, and SQL against the stopped name is refused instead of landing on the running database. SQL from a project whose configured URL belongs to a different running server is refused the same way. kalam up --instance <name> moves that server to a free port.
# Complex aggregation with output formatting
kalam --instance prod \
--command "SELECT country, COUNT(*) as users FROM users GROUP BY country" \
--format json \
--no-color > stats.json
# Any SQL supported by the server works here.You can upload files directly from the CLI using the file() helper in INSERT or UPDATE statements.
KalamDB[cluster] root@0.0.0.0:2900 ❯ INSERT INTO chat.uploads (id, name, attachment)
VALUES ('doc2', 'CLI Doc', file('/Users/user/document1.pdf', 'text/plain'));
Inserted 1 row(s)
Query OK, 1 rows affectedKalamDB[cluster] root@0.0.0.0:2900 ❯ UPDATE chat.uploads
SET attachment = file('/Users/user/document1.pdf', 'text/plain')
WHERE id = 'doc2';Selecting the row returns file metadata in the column value.
Fast end-to-end checks that your server and CLI are wired correctly. The suite covers:
- User table subscription lifecycle
- Shared table CRUD
- System tables and user lifecycle
- Stream table subscription
- User table row-level security (per-user isolation)
Requirements:
- Server running at http://localhost:2900
Run options:
- Directly with Cargo
cargo test -p kalam-cli smoke -- --test-threads=1 --nocaptureRun individual tests (examples):
# User table subscription lifecycle
cargo test -p kalam-cli smoke_user_table_subscription_lifecycle -- --nocapture
# Shared table CRUD
cargo test -p kalam-cli smoke_shared_table_crud -- --nocapture
# System tables + user lifecycle
cargo test -p kalam-cli smoke_system_tables_and_user_lifecycle -- --nocapture
# Stream table subscription
cargo test -p kalam-cli smoke_stream_table_subscription -- --nocapture
# User table RLS (per-user isolation)
cargo test -p kalam-cli smoke_user_table_rls_isolation -- --nocaptureNotes:
- Default server URL for tests is http://localhost:2900.
| Shortcut | Action |
|---|---|
Ctrl+A |
Move to beginning of line |
Ctrl+E |
Move to end of line |
Ctrl+K |
Delete from cursor to end of line |
Ctrl+U |
Delete from cursor to beginning of line |
Ctrl+W |
Delete word before cursor |
Alt+D |
Delete word after cursor |
| Shortcut | Action |
|---|---|
↑ |
Previous command |
↓ |
Next command |
Ctrl+R |
Reverse search history |
Ctrl+S |
Forward search history |
| Shortcut | Action |
|---|---|
Tab |
Autocomplete SQL keywords, tables, columns |
Tab Tab |
Show all completions |
| Shortcut | Action |
|---|---|
Ctrl+C |
Cancel current query/subscription |
Ctrl+D |
Exit CLI (alternative to \quit) |
Ctrl+L |
Clear screen |
The CLI provides intelligent auto-completion:
- SQL Keywords:
SEL+ Tab →SELECT - Table Names:
FROM us+ Tab →FROM users - Column Names: Context-aware completion in SELECT/WHERE clauses
kalam> SELECT na[Tab]
kalam> SELECT name FROM us[Tab]
kalam> SELECT name FROM users WHERE a[Tab]Queries taking longer than 200ms show a loading spinner:
Executing query...
Tables automatically adjust to terminal width:
- Columns exceeding 50 characters are truncated with
... - Total table width respects terminal size
- Change format with
\format jsonor\format csv
Disable colors for piping or logging:
kalam --no-color -c "SELECT * FROM users" > output.txtExecution metadata is displayed for all queries:
(10 rows)
As: root
Took: 245.123 ms
Clear, actionable error messages:
ERROR 1001: Table 'users' not found
Details: Available tables: system.tables, system.users, events
Execute multiple statements from a file:
-- migration.sql
CREATE TABLE products (id INT, name VARCHAR(100));
INSERT INTO products VALUES (1, 'Laptop'), (2, 'Phone');
SELECT * FROM products;kalam -f migration.sqlMonitor live data changes:
-- Terminal 1: Start watching
kalam> \subscribe SELECT * FROM orders WHERE status = 'pending'
-- Terminal 2: Insert data
kalam> INSERT INTO orders (id, status) VALUES (1, 'pending');
-- Terminal 1 automatically shows the new rowHealth check is a CLI meta-command (interactive mode):
kalam
# inside kalam
\health-- Find large tables
SELECT table_name, row_count
FROM system.tables
ORDER BY row_count DESC;
-- Monitor active connections
SELECT * FROM system.users WHERE last_seen > NOW() - INTERVAL 5 MINUTES;
-- Check running jobs
SELECT * FROM system.jobs WHERE status = 'running';View server metrics using the \stats command (alias: \metrics). This runs:
SELECT metric_name, metric_value FROM system.stats ORDER BY metric_name;# Show all cache statistics
kalam> \stats
# Or use the alias
kalam> \metricsRecent slow queries are available as a system view:
SELECT timestamp, duration_ms, user_id, table_name, query
FROM system.slow_queries
ORDER BY timestamp_ms DESC
LIMIT 20;# Use interactive health check
kalam --url http://localhost:2900
# inside kalam
\health
# Verbose mode for debugging
kalam --verbose --url http://localhost:2900# Verify stored credentials
kalam whoami --instance local
# Clear and re-enter credentials
kalam logout --instance local
kalam login --instance local# Reduce timeout for faster failures (CLI flag)
kalam --timeout 10
# Check query execution time
kalam> SELECT * FROM large_table LIMIT 1;
# Took: 1234.567 ms# Disable colors if rendering incorrectly
kalam --no-color
# Switch to JSON for machine-readable output
kalam --format json
# Adjust terminal width or use CSV
kalam --csv- API Examples (Bruno collection) - REST API request examples
- SQL Syntax - Complete SQL syntax guide
- WebSocket Protocol - Real-time subscription details
- Development Setup - Build and development guide
KalamDB projects use a kalam.toml file at the repository root to configure schema sources, generated language targets, migrations, and local development orchestration.
kalam init --yes --name my-app --schema-mode sql --languages typescript,dartThis creates:
kalam.toml— project configuration (server_versionpinned,purpose = "development")schema.sql— file-based schema source (sql mode)kalam/migrations/— ordered migration historykalam/seed.sql— development fixtures.kalam/— runtime identity (gitignored)src/generated/kalam.tsandlib/generated/kalam.dart— generated output directories.env.example— environment override template
# Regenerate workflow artifacts
# TypeScript uses @kalamdb/orm against the resolved server/namespace.
# Dart reads schema.sql and writes KalamTableSpec codecs plus typed KalamFunctions to lib/generated/kalam.dart.
kalam schema gen
kalam schema gen --languages dart
# Create a migration from the current schema
kalam db migration create add_profile
# Inspect local migration state
kalam db migration status
# Apply pending migrations (local state tracking in v1)
kalam db migrateEnvironment resolution order: CLI flag → environment variable (KALAM_ENV, KALAM_URL, KALAM_NAMESPACE) → kalam.toml. --global / -g selects the shared local database. schema.mode = "remote" is rejected.
kalam link --env prod --url https://db.example.com --namespace appStores URL and namespace in kalam.toml only — credentials stay in ~/.kalam/. Does not change project.default_env.
kalam up # database only, background
kalam status
kalam servers # list tracked local and global servers
kalam logs --follow # --tail is an alias
kalam dev # full loop; reuses `up` and leaves it running
kalam dev --force # retry a paused schema pipeline
kalam dev --exec "npm test"
kalam down # stop the database; keep datakalam up prints the server URL, the kalamdb-server binary and version it
started, the server.toml path, data folder, log file, and initial root login
credentials. Existing databases retain their current password.
Passwords are omitted from JSON/agent output and saved workflow logs.
kalam logs prints the selected log file before reading it; --follow and
--tail follow new lines until Ctrl+C. Managed console output is captured in
console.log, separately from the server's structured server.log.
kalam down distinguishes a stopped server from one that was already stopped
and preserves its data. Add -g to these commands for the shared server.
kalam dev:
- applies pending migrations and regenerates enabled language targets when configured
- watches
schema.sqlfor changes (2s poll) and re-runs the schema pipeline - supervises
[dev.processes]child commands with prefixed, color-coded stderr logs - pauses only the schema pipeline on migration/apply failure while keeping processes running
kalam instances, kalam servers, and kalam list show the same inventory:
managed local servers and saved cloud connections. The legacy --list-instances
flag uses this view too. Rows show name, local/cloud type, status, and URL.
Indented local details show the folder and global scope; cloud details show
the saved user and authentication expiry, never tokens.
Use --local or --cloud to filter, --check to probe cloud reachability,
and --json for an instances array. Cloud endpoints are not contacted
unless requested; saved authentication and reachability are separate.
Names shown in the list select that server from any folder. kalam --instance <name> runs SQL there and does not reuse the current project's namespace or root password. kalam dev is unchanged: it follows the project you are in. Lifecycle commands use the same name:
kalam status --instance analytics
kalam logs --instance analytics --follow
kalam down --instance analytics
kalam up --instance analyticsLocal names normally use their folder basename; the shared server uses global.
Conflicting names receive a suffix. Ambiguous short names fail with suggested
unique names. Named selection cannot be combined with --global, --env,
--url, --host, or --project-dir. Cloud names support authenticated status and logs; up and down
manage local processes only.
status queries system.cluster with saved authentication. logs queries
system.server_logs, including --follow / --tail and -n. Running local
instances use the same SQL diagnostics when matching credentials are saved;
otherwise local process status and capture files remain available.
Use kalam logs --instance analytics --local-file to explicitly inspect the
local capture file, including startup failures.
SQL diagnostics retain the server's system-table authorization requirements.
SQL log entries require [logging] format = "json" on the server. Following
polls once per second and reads the logs of the node answering the query, not a
durable cluster-wide stream. Expired credentials use the existing refresh flow
when a refresh token is available; otherwise login is required.
Starts through up and dev register under ~/.kalam/server-registry/.
Older instances are discovered by status in their folder or listing from
that folder; the default global instance is discovered automatically.
Missing/unreadable records appear unavailable. Manually launched processes
are not scanned. Saved credentials matching one local URL merge into that row.
kalam status
kalam status --env prodIn a folder with no managed instance or server configuration, status says
"No local server is configured in this folder" and suggests kalam up,
kalam status -g, or kalam servers. It does not probe the default port and
report an unrelated server as belonging to that folder.
For a server started with kalam up, reports server state, URL, server.toml,
data folder, and log file. Development sessions retain project, environment,
namespace migration details alongside the server paths. The human label is
namespace migrations; schema is retained only as a legacy JSON field. A
reachable server without a matching local process record is labeled
running (not managed from this folder).
kalam deploy generates schema artifacts, builds the project's server functions,
applies migrations, activates the function module, runs configured rollout steps,
and checks the target's health. Use a CLI and server build with functions support
and configure the target environment and DBA or System credentials first.
kalam dev also builds and activates on startup and when functions/src changes;
build or activation failures are printed as errors (CALL stays procedure not implemented until the next successful activate).
kalam deploy --env dev --dry-run # validate locally without activating
kalam deploy --env dev
kalam deploy --env prodThe dry run generates schema artifacts and builds functions when
functions/package.json is present. It does not apply migrations, upload functions,
or activate a revision. To build functions independently, use kalam functions build.
Production-like environments enforce migration history when automatic migrations
are enabled: schema changes must be covered by a migration before deployment.
Declare a bodyless CREATE PROCEDURE in your schema and run kalam schema gen.
TypeScript generation writes procedure.<schema>.<method> builders and a one-time
named-export scaffold at functions/src/<namespace>/<procedure>.ts for each
unbound procedure. Existing implementations are preserved. Edit the implementation, then use kalam deploy
to build and activate the project module. See the
README example
and SQL procedure reference.
kalam functions build
kalam functions status --env dev
kalam functions revisions --env dev
kalam functions runtime --env dev
kalam functions logs --env dev
kalam functions logs api.health --env dev
kalam functions override api.health
kalam functions rollback backend:<artifact> --env devstatus prints the current module, every procedure (implementation and
signature), and function memory/isolate stats. revisions lists module
history with is_current. runtime lists resident V8 isolates and
in-flight root calls. logs prints recent invocation, V8 console/ctx.log, and error records from
system.procedure_logs. On disk those files are
{data_path}/functions/runtime/<procedure_id>/logs/procedures.jsonl
(default ./data/functions/runtime/...).
To restore a previously activated revision, use
kalam functions rollback <revision> --env dev with an identifier from
kalam functions revisions. This changes the active revision without rebuilding.
For issues, questions, or contributions:
- GitHub: github.com/kalamdb/KalamDB
- Documentation: docs/README.md
Version: 0.1.3
Last Updated: October 28, 2025