Connect with the CLI

v3.0.0

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 ...]
OptionMeaning
--hostServer address. Default 127.0.0.1.
--portServer port. Default 15432.
-f, --file PATHRun a .sql file. Repeat it to run several files in order. - reads the script from standard input.
--echoWith -f only: print each statement before its reply.
--textUse the newline debug protocol instead of KWP/1. See Protocol.
commandA 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.
  • exit or quit leaves the prompt. It does not stop the server.
  • help or ? 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:

KeyAction
Up / DownWalk through earlier statements
Ctrl+RSearch history backwards
Ctrl+A / Ctrl+EJump to the start / end of the line
Ctrl+CAbandon the current line; stay in the prompt
Ctrl+DLeave 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

  • SELECT results 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 SHOW and DESCRIBE, print one section per line.
  • Errors start with ERR. A coded error has the form ERR <TOKEN> retryable=<0|1> <message>; retry only when it says retryable=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.

See also