Connect with the CLI
Use tools/ckdbs_cli.py to run statements interactively, one at a time from the shell, or from .sql script files.
In this article
tools/ckdbs_cli.py is the reference client that ships with the engine. It has three modes: an interactive prompt, a one-shot mode that runs one statement from the shell, and a script mode that runs .sql files. It sends what you type as it is, prints the server’s reply, and formats SELECT results as a table. It needs only Python 3 and the kwp.py module next to it in tools/.
Options
ckdbs_cli.py [--host HOST] [--port PORT] [-f PATH [-f PATH ...]] [--echo] [--text] [command ...]
| Option | Meaning |
|---|---|
--host | Server address. Default 127.0.0.1. |
--port | Server port. Default 15432. |
-f, --file PATH | Run a .sql file. Repeat it to run several files in order. - reads the script from standard input. |
--echo | With -f only: print each statement before its reply. |
--text | Use the newline debug protocol instead of KWP/1. See Protocol. |
command | A statement to run once. Leave it out for the interactive prompt. |
-f and a command cannot be combined.
Interactive prompt
Run the CLI with no command:
$ python3 tools/ckdbs_cli.py
ckdbs interactive CLI. Type 'help' for known commands, 'exit' to quit.
ckdbs> SELECT * FROM passengers WHERE id = 3
id name member joined_on
-- --------- ------ ----------
3 Park Jiho 0 2024-01-20
ckdbs> exit
- Each line you enter is one statement. A trailing
;is not needed. exitorquitleaves the prompt. It does not stop the server.helpor?prints a short list of commands. The list is a hint kept in the client and can be out of date; the server decides what it accepts.
The prompt uses Python’s readline module for line editing:
| Key | Action |
|---|---|
| Up / Down | Walk through earlier statements |
| Ctrl+R | Search history backwards |
| Ctrl+A / Ctrl+E | Jump to the start / end of the line |
| Ctrl+C | Abandon the current line; stay in the prompt |
| Ctrl+D | Leave the prompt (on an empty line) |
History is saved in ~/.ckdbs_history, up to 1,000 entries, shared across sessions. A statement repeated twice in a row is stored once. Without readline the prompt still works, without line editing.
One statement from the shell
Give the statement as arguments. Quote SQL as one shell argument so the shell does not split or expand it.
python3 tools/ckdbs_cli.py PING
python3 tools/ckdbs_cli.py SHOW TABLES
python3 tools/ckdbs_cli.py "DESCRIBE airlines"
python3 tools/ckdbs_cli.py --port 15432 "SELECT * FROM flights WHERE id = 1"
Words are joined with single spaces and sent as one statement. For example, DESCRIBE airlines on the table from Quickstart: Run a server after two rows were inserted prints:
oid=4000 root_page_id=129 clustered_type=BTREE next_id=3 columns=4 ids_issued=2 ids_remaining=281474976710653 budget_used=0.000% height=1 leaves=1
pos=0 name=id type=int64 notnull=yes pk=yes autoincrement=if-omitted
pos=1 name=code type=char(2) notnull=yes pk=no autoincrement=no cabin=auto
pos=2 name=name type=varchar notnull=yes pk=no autoincrement=no cabin=auto
pos=3 name=country type=varchar notnull=yes pk=no autoincrement=no cabin=auto
Run a script
python3 tools/ckdbs_cli.py -f schema.sql -f load.sql > out.txt
cat report.sql | python3 tools/ckdbs_cli.py -f -
How a script file is read:
- Statements are separated by
;. A statement may span several lines; it is joined into one line before it is sent. - A file with no
;at all is read as one statement per line. --starts a comment that runs to the end of the line, except inside a quoted string.- A failed statement does not stop the script. The remaining statements still run.
Only replies go to standard output, so the output can be redirected and compared. If any statement replied ERR, the CLI prints <n> statement(s) replied ERR to standard error and exits with status 1.
With --echo, each statement is printed as a -- comment before its reply. For this file:
-- demo script
INSERT INTO passengers VALUES ('Oh Jisoo', 0, '2026-10-13');
SELECT * FROM flights
WHERE base_fare >= 200;
UPDATE flights SET id = 9 WHERE id = 1;
python3 tools/ckdbs_cli.py -f demo.sql --echo
-- INSERT INTO passengers VALUES ('Oh Jisoo', 0, '2026-10-13')
INSERTED oid=4005 id=9 page=133 slot=8
-- SELECT * FROM flights WHERE base_fare >= 200
id airline_id code origin dest departs aircraft base_fare
-- ---------- ------ ------ ---- ------------------- -------- ---------
1 1 KE0101 ICN NRT 2026-11-02 08:30:00 A321 212.50
3 1 KE0303 ICN SFO 2026-11-03 19:40:00 B777 1180.00
-- UPDATE flights SET id = 9 WHERE id = 1
ERR primary-key column 'id' cannot be updated at byte 19; it is the tuple's identity, not a field of it
Standard error then carries 1 statement(s) replied ERR, and the exit status is 1.
For scripts that check their own results (-- expect:, -- error:, -- rows:), use tools/run_sql.py instead.
How replies are shown
SELECTresults are shown as a table. With pandas installed, the CLI prints a pandas DataFrame without its index; otherwise it prints the column-aligned text table shown above. The CLI splits each row on commas, so a text value that contains a comma breaks into extra cells; such a reply is always shown as the text table, under an unnamed extra column.- Every other reply is printed as the server sent it. Replies with several sections, such as
SHOWandDESCRIBE, print one section per line. - Errors start with
ERR. A coded error has the formERR <TOKEN> retryable=<0|1> <message>; retry only when it saysretryable=1. See Errors and refusals.
Stop the server
STOP shuts down the whole server, not only your connection:
python3 tools/ckdbs_cli.py STOP
The server closes the connection without a reply. In the interactive prompt the CLI prints connection lost: server closed the connection and exits; in one-shot mode it prints a Python ConnectionError traceback. Both are expected.
Protocol
The server’s port speaks KWP/1, a binary protocol of length-prefixed frames, and the CLI uses it by default. The CLI turns each reply back into the same text lines shown on this page.
The older newline protocol (one statement per line in, one reply line out) is kept only as a debug surface on debug_text_port. That port is 0 by default, which opens no socket. To use it, set debug_text_port in the server’s configuration and pass --text together with --port <debug_text_port>.
The server listens on 127.0.0.1 only, so the CLI must run on the same host.