Skip to content

Latest commit

 

History

History
803 lines (592 loc) · 27.2 KB

cli.md

File metadata and controls

803 lines (592 loc) · 27.2 KB

Kalam CLI

Interactive terminal client for KalamDB, built on kalam-client.

Binary name: kalam (from the cli crate).

Quickstart (first 5 minutes)

  1. Start the server (default is http://localhost:2900)
cd backend
cargo run
  1. Install the CLI
npm install -g @kalamdb/cli

# or
curl -fsSL https://kalamdb.org/install.sh | sh

kalam --help
  1. Connect and run a query
./target/release/kalam

# inside kalam
\dt
SELECT * FROM information_schema.tables LIMIT 5;
  1. Optional: start a live query
# inside kalam
\subscribe SELECT * FROM app.messages WHERE user_id = 'alice';

Install

npm install -g @kalamdb/cli

# or
curl -fsSL https://kalamdb.org/install.sh | sh

# from source
cd cli && cargo build --release

Tooling Commands

kalam 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

Connect

# 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.

Run SQL

# 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

Watch schema generation

# 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

Important flags

  • --url, -u – server URL
  • --host, -H and --port, -p – alternative to --url
  • --instance – saved server from kalam instances. Inside a project, SQL uses that project unless you pass a name other than the default local
  • --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 – poll information_schema.tables and 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 more namespace.table targets
  • --run – shell command executed after schema changes are detected
  • --run-on-start – execute the watch command once before polling
  • --interval – schema watch poll interval, default 5s

Top-level commands

  • kalam version – print CLI version/build metadata
  • kalam update [--version <version>] [--pre-release | --stable] – replace the current binary with a verified GitHub release artifact. --pre-release installs the newest published rc/beta/alpha and never downgrades. --stable switches 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 reachability
  • kalam login --instance <name> --url <url> – login, save access/refresh tokens, and enter the interactive shell immediately when run from a terminal
  • kalam logout [--all] – remove saved credentials locally and best-effort notify the server
  • kalam whoami – call /v1/api/auth/me with the resolved credentials
  • kalam token create --name <name> – create a service account and print a fresh access/refresh token pair

Interactive \ commands

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 meta-commands

  • \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>

How follower writes are forwarded

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).

  1. The request can hit any node, including a follower for that group.
  2. The SQL layer prepares and classifies the statement once, then derives the target Raft group from the table type and current user_id.
  3. For user and stream tables, KalamDB hashes user_id into one of cluster.user_shards groups.
  4. 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.
  5. The group leader executes the write, appends it to that Raft log, replicates it to followers, commits it, and returns the result.
  6. 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.

Multi-Raft routing today

  • 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.

Output formats

  • table – pretty table with row count and latency
  • json – raw JSON rows
  • csv – header + rows (good for piping)

Live subscriptions

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';"

Multiple Instances

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.

Advanced Queries

# 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.

File uploads in INSERT/UPDATE

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 affected
KalamDB[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.


Smoke Tests

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:

Run options:

  1. Directly with Cargo
cargo test -p kalam-cli smoke -- --test-threads=1 --nocapture

Run 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 -- --nocapture

Notes:


Keyboard Shortcuts

Line Editing

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

History Navigation

Shortcut Action
↑ Previous command
↓ Next command
Ctrl+R Reverse search history
Ctrl+S Forward search history

Completion

Shortcut Action
Tab Autocomplete SQL keywords, tables, columns
Tab Tab Show all completions

Control

Shortcut Action
Ctrl+C Cancel current query/subscription
Ctrl+D Exit CLI (alternative to \quit)
Ctrl+L Clear screen

Tips & Tricks

1. Auto-Completion

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]

2. Loading Indicator

Queries taking longer than 200ms show a loading spinner:

Executing query...

3. Pretty Tables

Tables automatically adjust to terminal width:

  • Columns exceeding 50 characters are truncated with ...
  • Total table width respects terminal size
  • Change format with \format json or \format csv

4. Color Output

Disable colors for piping or logging:

kalam --no-color -c "SELECT * FROM users" > output.txt

5. Timing Information

Execution metadata is displayed for all queries:

(10 rows)

As: root
Took: 245.123 ms

6. Error Messages

Clear, actionable error messages:

ERROR 1001: Table 'users' not found
Details: Available tables: system.tables, system.users, events

7. Batch Operations

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.sql

8. Watch Mode (Real-Time)

Monitor 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 row

9. Quick Health Check

Health check is a CLI meta-command (interactive mode):

kalam

# inside kalam
\health

10. System Introspection

-- 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';

11. Cache Statistics and System Metrics

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> \metrics

Recent 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;

Troubleshooting

Connection Issues

# Use interactive health check
kalam --url http://localhost:2900

# inside kalam
\health

# Verbose mode for debugging
kalam --verbose --url http://localhost:2900

Authentication Failures

# Verify stored credentials
kalam whoami --instance local

# Clear and re-enter credentials
kalam logout --instance local
kalam login --instance local

Performance Issues

# 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

Display Issues

# 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

Related Documentation


Project workflow commands

KalamDB projects use a kalam.toml file at the repository root to configure schema sources, generated language targets, migrations, and local development orchestration.

Initialize a project

kalam init --yes --name my-app --schema-mode sql --languages typescript,dart

This creates:

  • kalam.toml — project configuration (server_version pinned, purpose = "development")
  • schema.sql — file-based schema source (sql mode)
  • kalam/migrations/ — ordered migration history
  • kalam/seed.sql — development fixtures
  • .kalam/ — runtime identity (gitignored)
  • src/generated/kalam.ts and lib/generated/kalam.dart — generated output directories
  • .env.example — environment override template

Schema and migrations (sql mode)

# 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 migrate

Environment 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.

Link environments

kalam link --env prod --url https://db.example.com --namespace app

Stores URL and namespace in kalam.toml only — credentials stay in ~/.kalam/. Does not change project.default_env.

Local development orchestration

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 data

kalam 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.sql for 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

List and select instances

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 analytics

Local 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.

Inspect project state

kalam status
kalam status --env prod

In 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).

Deploy with migration guardrails

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 prod

The 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.

Server functions

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 dev

status 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.


Support

For issues, questions, or contributions:


Version: 0.1.3
Last Updated: October 28, 2025