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
cd 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="mypass" \
cargo test --test smoke -- --nocaptureEnvironment Variables:
KALAMDB_SERVER_URL- Server URL (default:http://127.0.0.1:8080)KALAMDB_ROOT_PASSWORD- Root password (default:"")
# 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]
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
--unsubscribe <ID> Unsubscribe from a subscription (non-interactive)
--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 --update-credentials --instance local --user root --password ""
kalam --show-credentials --instance local
kalam --list-instancesSpecial 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> <SQL> |
Wrap one statement as EXECUTE AS USER |
\stats / \metrics |
Show system stats |
\health |
Check server health |
\flush |
Execute STORAGE FLUSH ALL |
\refresh-tables / \refresh |
Refresh autocomplete cache |
\subscribe <SQL> / \watch <SQL> / \live <SQL> |
Start live query |
\unsubscribe / \unwatch |
Cancel live query |
\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
\subscribe <SQL>for live updates.
┌─────────┬──────────┬─────────────────────┬────────────────────────┐
│ 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 --user root --password "" --save-credentials
# Update stored credentials explicitly
kalam --update-credentials --instance local --user root --password ""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 --releaseSame license as KalamDB main project.
Contributions welcome! Please see the main KalamDB repository for contribution guidelines.