Interactive command-line client for KalamDB - a real-time database with WebSocket subscriptions.
- 🎯 Interactive SQL Execution - Execute queries with instant results
- 📊 Multiple Output Formats - Table, JSON, and CSV output modes
- 🔄 Live Query Subscriptions - Real-time data updates via WebSocket
- 🎨 Syntax Highlighting - Beautiful colored SQL syntax
- 📝 Command History - Persistent history with arrow key navigation and interactive menu
- ⚡ Auto-completion - TAB completion for SQL keywords, tables, and columns
- 🔐 Authentication - JWT tokens, user/password login, and stored credentials
- 📁 Batch Execution - Run SQL scripts from files
- 🎭 Progress Indicators - Visual feedback for long-running queries
npm install -g @kalamdb/clicurl -fsSL https://kalamdb.org/install.sh | shcd cli
cargo build --releaseThe binary will be available at target/release/kalam.
# Set custom server URL and root password
export KALAMDB_SERVER_URL="http://127.0.0.1:3000"
export KALAMDB_ROOT_PASSWORD="your-password"
# Run all tests
cd cli
cargo test
# Run smoke tests
cargo test --test smoke -- --nocapture
# Or inline for a single run
KALAMDB_SERVER_URL="http://localhost:3000" \
KALAMDB_ROOT_PASSWORD="kalamdb123" \
cargo test --test smoke -- --nocaptureEnvironment Variables:
KALAMDB_SERVER_URL- Server URL (default:http://127.0.0.1:2900)KALAMDB_ROOT_PASSWORD- Root password (default:kalamdb123for local dev servers)
# Run only the dedicated cluster integration target
cd cli
./run-cluster-tests.sh
# Run the follower/replication-focused cluster bundle
./run-cluster-tests.sh --followers --nocapture
# Run a single cluster test function
./run-cluster-tests.sh --test cluster_test_ws_follower_receives_leader_changes --nocapturerun-cluster-tests.sh delegates to run-tests.sh, pins the test target to cluster,
and keeps the same environment loading and cluster autodetection behavior.
# Connect to default localhost:3000
kalam
# Connect to specific host
kalam --host myserver.com
# Connect with authentication
kalam --token YOUR_JWT_TOKEN-- Create namespace
CREATE NAMESPACE app;
-- Create table
CREATE TABLE app.users (
id BIGINT PRIMARY KEY DEFAULT SNOWFLAKE_ID(),
username TEXT NOT NULL,
email TEXT,
created_at TIMESTAMP DEFAULT NOW()
) WITH (TYPE = 'USER');
-- Insert data
INSERT INTO app.users (username, email)
VALUES ('alice', 'alice@example.com');
-- Query data
SELECT * FROM app.users;-- Subscribe to changes
SUBSCRIBE TO app.messages WHERE user_id = 'user123';
-- Or use the interactive CLI aliases
\subscribe SELECT * FROM app.messages WHERE user_id = 'user123';
\live SELECT * FROM app.messages WHERE user_id = 'user123';
-- Stop subscription (Ctrl+C)kalam [OPTIONS] [COMMAND]
COMMANDS:
update Update this kalam binary from release assets
version Print version information
doctor Run local, server, and authentication diagnostics
login Login and save credentials for an instance
logout Delete saved credentials for an instance
whoami Show the authenticated user
token create --name <NAME> Create a service account and print tokens
CONNECTION:
-u, --url <URL> Server URL (e.g., http://localhost:3000)
-H, --host <HOST> Host address (alternative to URL)
-p, --port <PORT> Port number (default: 3000)
AUTHENTICATION:
--token <TOKEN> JWT authentication token
--user <USER> User/password login identifier
--password [PASSWORD] User/password login secret (prompts if flag is present without value)
--instance <INSTANCE> Credential instance name (default: local)
--save-credentials Save credentials after successful login
EXECUTION:
-f, --file <FILE> Execute SQL from file and exit
-c, --command <SQL> Execute SQL command and exit
--subscribe <SQL> Subscribe to a table or live query
--list-subscriptions List active subscriptions (non-interactive)
OUTPUT:
--format <FORMAT> Output format: table|json|csv (default: table)
--json Shorthand for --format=json
--csv Shorthand for --format=csv
--no-color Disable colored output
--no-spinner Disable spinners/animations
--loading-threshold-ms <MS> Loading indicator threshold (0 to always show)
TIMEOUTS:
--timeout <SECONDS> HTTP request timeout (default: 30)
--connection-timeout <SECONDS> Connection timeout (default: 10)
--receive-timeout <SECONDS> Receive timeout (default: 30)
--auth-timeout <SECONDS> WebSocket auth timeout (default: 5)
--subscription-timeout <SECONDS>Subscription timeout (0 = no timeout, default: 0)
--initial-data-timeout <SECONDS>Initial data timeout (default: 30)
--fast-timeouts Fast timeout preset (local dev)
--relaxed-timeouts Relaxed timeout preset (high latency)
CONFIG:
--config <PATH> Configuration file path (default: ~/.kalam/config.toml)
-v, --verbose Enable verbose logging
CREDENTIALS:
--show-credentials Show stored credentials for instance
--update-credentials Login and update stored credentials
--delete-credentials Delete stored credentials
--list-instances List all stored credential instances
INFO:
--help Print help information
--version Print version information
# Run a single SQL command and exit
kalam --command "SELECT * FROM system.tables LIMIT 5"
# Run SQL from a file and exit
kalam --file setup.sql
# Subscribe to a live query (non-interactive)
kalam --subscribe "SUBSCRIBE TO app.messages WHERE user_id = 'alice'"
# Manage stored credentials
kalam login --instance local --user root --password ""
kalam whoami --instance local
kalam logout --instance local
kalam --show-credentials --instance local
kalam --list-instances
# Create a CI service token
kalam token create --name ci-prod
# Check the local install and configured server
kalam doctor
# Update the installed binary
kalam updateWhen kalam login is run from an interactive terminal, a successful local or OIDC login now drops straight into the normal SQL shell. Piped or otherwise non-interactive invocations keep the one-shot behavior and exit after saving credentials so automation does not hang.
Special commands starting with backslash (\):
| Command | Description |
|---|---|
\help / \? |
Show available commands |
\quit / \q |
Exit the CLI |
\info / \session |
Show session info |
\sessions |
Show active pg-extension gRPC sessions |
\format <table|json|csv> |
Set output format |
\dt / \tables |
List tables |
\d <table> / \describe <table> |
Describe a table (<table> or <namespace.table>) |
\as <user_id> <SQL> |
Wrap one statement as EXECUTE AS '<user_id>' |
\stats / \metrics |
Show system stats |
\health |
Check server health |
\flush |
Execute STORAGE FLUSH ALL |
\refresh-tables / \refresh |
Refresh autocomplete cache |
\live <SQL> / \subscribe <SQL> |
Start live query (\subscribe is an alias) |
\show-credentials / \credentials |
Show stored credentials |
\update-credentials <u> <p> |
Update stored credentials |
\delete-credentials |
Delete stored credentials |
\cluster ... |
Cluster inspection and admin commands. See docs/getting-started/cli.md. |
Once the CLI starts, type SQL directly and press Enter (or end with ;) to run it. Use backslash commands (like \help) for CLI-specific actions.
Tips:
- Use Tab for auto-completion of SQL keywords, namespaces, tables, and columns.
- Use ↑/↓ to navigate command history.
- Use
\format jsonor\format csvto switch output formats. - Use
\live <SQL>for live updates. - Run
BACKUP DATABASE TO '/tmp/kalamdb-backup.tar.gz';as SQL for server-side backups. - Run
EXPORT USER DATA;followed bySHOW EXPORT;to fetch your export download URL.
┌─────────┬──────────┬─────────────────────┬────────────────────────┐
│ id │ username │ email │ created_at │
├─────────┼──────────┼─────────────────────┼────────────────────────┤
│ 1234567 │ alice │ alice@example.com │ 2025-10-24 10:30:00 │
│ 1234568 │ bob │ bob@example.com │ 2025-10-24 10:31:00 │
└─────────┴──────────┴─────────────────────┴────────────────────────┘
(2 rows)
Took: 5.234 ms
kalam --json{
"status": "success",
"results": [
{
"id": 1234567,
"username": "alice",
"email": "alice@example.com",
"created_at": "2025-10-24T10:30:00Z"
}
],
"took_ms": 5.234
}kalam --csvid,username,email,created_at
1234567,alice,alice@example.com,2025-10-24T10:30:00Z
1234568,bob,bob@example.com,2025-10-24T10:31:00ZExecute SQL from a file:
kalam --file setup.sqlExample setup.sql:
CREATE NAMESPACE prod;
CREATE TABLE prod.events (
id BIGINT PRIMARY KEY DEFAULT SNOWFLAKE_ID(),
event_type TEXT NOT NULL,
data TEXT,
created_at TIMESTAMP DEFAULT NOW()
) WITH (TYPE = 'USER');
INSERT INTO prod.events (event_type, data) VALUES ('login', '{"user":"alice"}');The CLI automatically creates and reads configuration from ~/.kalam/config.toml on first run:
[server]
timeout = 30
max_retries = 0
http_version = "http2" # http1, http2, auto
[connection]
auto_reconnect = true
reconnect_delay_ms = 100
max_reconnect_delay_ms = 30000
max_reconnect_attempts = 10
[ui]
format = "table" # table, json, csv
color = true
history_size = 1000
timestamp_format = "iso8601" # iso8601, iso8601-date, iso8601-datetime, unix-ms, unix-sec, relative, rfc2822, rfc3339The configuration file is created with default values when you first run the CLI. You can edit it to customize the behavior or override settings with command-line flags.
When connecting from localhost without credentials, the CLI automatically uses a default user:
kalam # Uses default user on localhostkalam --token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...# Login and store credentials
kalam login --instance local --user root --password ""
# Login to a named production instance
kalam login --instance prod --url https://db.example.com --user root --password
# Show current identity
kalam whoami --instance prod
# Remove saved credentials
kalam logout --instance prod
# Legacy credential flags still work for scripts that already use them
kalam --update-credentials --instance local --user root --password ""kalam token create --name ci-prod creates a service account with a generated password, logs in once, and prints an access/refresh token pair. The generated password is not stored or shown. Use --json for automation and --save if you also want the token stored locally as a credential instance named after the token.
The CLI provides beautiful SQL syntax highlighting with:
- Blue bold keywords (SELECT, INSERT, CREATE, etc.)
- Magenta data types (INT, TEXT, TIMESTAMP, etc.)
- Green string literals
- Yellow numeric literals
Press TAB to auto-complete:
- SQL keywords (SELECT, INSERT, UPDATE, etc.)
- Table names (loaded from
system.tables) - Column names (context-aware after table name)
- SQL types (INT, TEXT, TIMESTAMP, etc.)
- CLI commands (\help, \quit, etc.)
Refresh table/column cache:
\refresh-tables- ↑ arrow (on empty line): Opens interactive history dropdown menu
- Oldest commands at top, newest at bottom
- Selection starts at bottom (newest command)
- ↑ to navigate to older commands (up), ↓ to newer commands (down)
- Enter to select, Esc to cancel
- Type to filter history entries in real-time
- Selected command appears in your prompt ready to edit
- Multi-line commands show first 2 lines for easy identification
\historyor\h: Alternative way to open the history menu- History stored in
~/.kalam/history - Persistent across sessions
\history,\h,\quit, and\qcommands are not saved to history
For queries taking longer than 200ms, the CLI shows a spinner with elapsed time:
⠋ Executing query... 1.2s
When subscribed, the CLI displays real-time notifications:
[2025-10-24 10:30:15] INSERT: {"id": 1234567, "content": "New message"}
[2025-10-24 10:30:20] UPDATE: {"id": 1234567, "content": "Updated message"}
[2025-10-24 10:30:25] DELETE: {"id": 1234567}
Error: Failed to connect to localhost:3000
Solution: Ensure the KalamDB server is running:
cd backend
cargo run --bin kalamdb-serverError: Authentication failed (401 Unauthorized)
Solution: Provide valid credentials:
kalam --token YOUR_JWT_TOKENError: table 'app.users' not found
Solution: Create the namespace and table first:
CREATE NAMESPACE app;
CREATE TABLE app.users (...) WITH (TYPE = 'USER');-- Create namespace
CREATE NAMESPACE myapp;
-- Create table with auto-incrementing ID
CREATE TABLE myapp.users (
id BIGINT PRIMARY KEY DEFAULT SNOWFLAKE_ID(),
username TEXT NOT NULL,
email TEXT,
created_at TIMESTAMP DEFAULT NOW()
) WITH (TYPE = 'USER');
-- Insert data
INSERT INTO myapp.users (username, email) VALUES
('alice', 'alice@example.com'),
('bob', 'bob@example.com');
-- Query all users
SELECT * FROM myapp.users;
-- Query with filter
SELECT username, email FROM myapp.users WHERE username = 'alice';-- Create messages table
CREATE TABLE chat.messages (
id BIGINT PRIMARY KEY DEFAULT SNOWFLAKE_ID(),
user_id TEXT NOT NULL,
content TEXT NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
) WITH (TYPE = 'USER');
-- Subscribe to new messages
SUBSCRIBE TO chat.messages WHERE user_id = 'alice';
-- In another terminal, insert messages:
-- INSERT INTO chat.messages (user_id, content) VALUES ('alice', 'Hello!');
-- The first terminal will show real-time notificationsCreate import.sql:
CREATE NAMESPACE analytics;
CREATE TABLE analytics.events (
id BIGINT PRIMARY KEY DEFAULT SNOWFLAKE_ID(),
event_type TEXT NOT NULL,
user_id TEXT,
data TEXT,
created_at TIMESTAMP DEFAULT NOW()
) WITH (TYPE = 'USER');
INSERT INTO analytics.events (event_type, user_id, data) VALUES
('page_view', 'user1', '{"page":"/home"}'),
('click', 'user1', '{"button":"signup"}'),
('conversion', 'user1', '{"amount":99.99}');Execute:
kalam --file import.sqlcd cli
cargo testcd cli
cargo build --releaseProject-oriented workflow commands such as kalam init, kalam dev, kalam link,
kalam schema gen, kalam migration create, kalam status, and kalam deploy are
documented in DEV.md.
When kalam dev starts a local server, the generated kalam/server/server.toml uses
root / kalamdb123 by default. Scaffolded .env files include the same password for
local development.
Access the running server at http://localhost:2900 (UI at http://localhost:2900/ui)
with root / kalamdb123, or run
kalam --url http://127.0.0.1:2900 --user root --password kalamdb123 in another terminal.
Use kalam db reset to clear local project state (kalam/server/, schema baseline) and drop the linked namespace when appropriate. Use --yes when reusing a non-project server or in non-interactive shells. Run kalam dev afterward for a fresh database.
Use that guide for:
- interactive and non-interactive project initialization
- local vs remote server mode
kalam.tomlstructure and environment resolution- the day-to-day development loop
- production-like environment linking and deploy guardrails
Licensed under the Apache License, Version 2.0 (Apache-2.0). See ../LICENSE.txt and ../NOTICE.
Contributions welcome! Please see the main KalamDB repository for contribution guidelines.