ClickHouse
Generic ClickHouse JSON CLI. Read commands use readonly=1; exec runs one statement allowed by the configured ClickHouse user.
Local .env
The CLI automatically looks for a private .env beside this SKILL.md. Copy .env.example to .env; never commit the real file.
CLICKHOUSE_HOST=clickhouse.example.net
CLICKHOUSE_PORT=443
CLICKHOUSE_SECURE=true
CLICKHOUSE_VERIFY=true
CLICKHOUSE_USER=pass://<vault>/<item>/<field>
CLICKHOUSE_PASSWORD=pass://<vault>/<item>/<field>
When the file exists, the CLI re-runs itself once through:
pass-cli run --env-file .env -- <skill-command>
The .env may contain ordinary non-secret connection settings and Proton Pass references. It is private, ignored by Git, and must never contain resolved secrets in a repository. The CLI does not print or copy its values.
Without a local .env, use these environment variables or non-secret flags:
| Variable | Flag | Default |
|---|---|---|
CLICKHOUSE_HOST |
--host |
none |
CLICKHOUSE_PORT |
--port |
client default |
CLICKHOUSE_USER |
--user |
default |
CLICKHOUSE_PASSWORD |
none | empty |
CLICKHOUSE_DATABASE |
--database |
server default |
CLICKHOUSE_SECURE |
--secure / --no-secure |
true |
CLICKHOUSE_VERIFY |
--verify / --no-verify |
true |
Never pass a password as a CLI argument.
Read
uv run --python 3.13 --with clickhouse-connect python scripts/ch.py query --sql "SELECT count() AS n FROM analytics.events"
uv run --python 3.13 --with clickhouse-connect python scripts/ch.py query --sql @query.sql --params '{"day":"2026-01-01"}'
uv run --python 3.13 --with clickhouse-connect python scripts/ch.py list-databases
uv run --python 3.13 --with clickhouse-connect python scripts/ch.py list-tables --database analytics
uv run --python 3.13 --with clickhouse-connect python scripts/ch.py describe-table --database analytics --table events
Read commands allow only obvious read-only SQL and send ClickHouse readonly=1, timeout, and result-row limits.
Execute
Use exec after the user approves the exact operation and target:
uv run --python 3.13 --with clickhouse-connect python scripts/ch.py \
exec --sql "CREATE TABLE analytics.example (id UInt64) ENGINE=MergeTree ORDER BY id"
exec accepts one DDL, DML, or administrative statement. It rejects empty and multi-statement input. There is no local write authorization gate: ClickHouse user grants are the only authorization boundary.
--sql accepts literal SQL, @file.sql, or - for stdin. Named ClickHouse parameters use {name:Type} with a JSON object from --params.
Safety contract
- Obtain fresh user approval before each mutation scope. CREATE, backfill, swap, and DROP are separate operations.
- Read commands keep local SQL guards and server
readonly=1. execdoes not addreadonly=1; the configured ClickHouse user decides what is allowed.execrejects empty and multi-statement SQL.- Do not print secrets, connection strings,
.envcontents, or environment variables. - Ask before touching sensitive data, even in read mode.
Output
Read success:
{
"rows": [{"n": 42}],
"row_count": 1
}
Execution success:
{
"ok": true
}
Tests
uv run --python 3.13 --with clickhouse-connect python tests/test_ch.py