The ClickHouse CLI for data engineers — query, profile, debug, migrate.
Project description
ClickHawk
中文版文档: README_CN.md
The command-line Swiss Army knife for ClickHouse data engineers — query, diagnose, monitor, and explore, all in one command.
Documentation
| Document | Description |
|---|---|
| TUTORIAL.md | Local ClickHouse setup guide for macOS / Linux / Windows, including full config and troubleshooting |
| CHANGELOG.md | Version history and release notes |
| LESSONS_LEARNED.md | Pitfalls encountered during development — useful for contributors |
| STRUCTURE.md | Project layout and module responsibilities |
| examples/BASIC_QUERY.md | ch query usage examples |
| examples/PROFILING.md | ch profile — how to read metrics and diagnose slow queries |
| examples/MONITORING.md | ch monitor + ch slowlog — production incident workflow |
| examples/SCHEMA_EXPLORATION.md | ch schema — table inspection and schema workflows |
All documents are available in English and Chinese (append
_CNto the filename for the Chinese version, e.g.TUTORIAL_CN.md).
Why ClickHawk?
The ClickHouse ecosystem has many tools, but none of them address the real pain points data engineers face in daily work:
- Debugging slow queries? You have to hand-write
SELECT * FROM system.query_log WHERE ...and wade through raw text output. - Checking currently running queries? You have to log into
clickhouse-clientand runSELECT * FROM system.processes. - Analyzing EXPLAIN output? It's plain-text tree output with no colors or hierarchy — nearly unreadable.
- Inspecting table schemas? You switch to DBeaver/DataGrip, which is slow and heavyweight.
- Comparing schemas across environments? No tool exists; you do it manually.
ClickHawk unifies these high-frequency operations into a single ch command — one line in the terminal, ready for scripting and pipeline integration.
Comparison with Existing Tools
| Tool | Type | Formatted Output | Performance Analysis | Slow Queries | Live Monitoring | Schema Exploration | Script-Friendly |
|---|---|---|---|---|---|---|---|
| ClickHawk | CLI Tool | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
clickhouse-client |
Official CLI | ❌ | ❌ | ❌ | ❌ | Limited | ✅ |
clickhouse-connect |
Python SDK | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
| DBeaver / DataGrip | GUI | ✅ | Limited | ❌ | ❌ | ✅ | ❌ |
infi.clickhouse_orm |
ORM Library | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
Core advantages:
- One command, complete workflow — from query execution to performance debugging to schema management, with no tool switching required.
- Native terminal experience — Rich-powered colored tables and live refresh, a significant step up from the raw text output of
clickhouse-client. - Zero-configuration startup — a single
.envfile, or set environment variables directly; ready to use afterpip install. - Script-friendly — supports
--format json/csvoutput that can be piped directly. - Cross-platform — pure Python implementation; runs on macOS, Linux, and Windows with no system-level dependencies.
- Lightweight — no Java, Electron, or any system dependencies required; just
pip install. - Open source and extensible — MIT license; contributions of new commands are welcome.
Installation
pip install clickhawk
Or install from source (development mode):
git clone https://github.com/handsomevictor/clickhawk.git
cd clickhawk
pip install -e ".[dev]"
Requirements: Python 3.13+
No ClickHouse? See the local installation tutorial for complete setup steps on macOS, Linux, and Windows, including solutions to common issues.
Quick Start
Step 1: Configure the connection
cp .env.example .env
# Edit .env and fill in your ClickHouse connection details
Or set environment variables directly:
export CH_HOST=your-clickhouse-host
export CH_USER=default
export CH_PASSWORD=your-password
export CH_DATABASE=default
Step 2: Verify the connection
ch health
✓ ClickHouse 24.3.1.1
Uptime : 7 days, 3 hours
Databases: 5
Tables : 42
Step 3: Start using
ch query "SELECT version()"
ch profile "SELECT uniq(user_id) FROM events WHERE date >= today() - 7"
ch slowlog --top 20
ch monitor
Command Reference
ch health — Cluster Health Check
ch health
✓ ClickHouse 24.3.1.1
Uptime : 7 days, 3 hours
Databases: 5
Tables : 42
ch query — Execute SQL Queries
ch query "SELECT database, count() FROM system.tables GROUP BY database"
┌──────────────────┬──────────┐
│ database │ count() │
├──────────────────┼──────────┤
│ default │ 12 │
│ system │ 73 │
│ demo │ 5 │
└──────────────────┴──────────┘
3 rows (0.021s)
# JSON / CSV output for scripting
ch query "SELECT database, count() FROM system.tables GROUP BY database" --format json
# Limit rows
ch query "SELECT * FROM events" --limit 5
| Option | Short | Default | Description |
|---|---|---|---|
--format |
-f |
table |
Output format: table / json / csv |
--limit |
-l |
none | Limit the number of rows returned |
ch profile — Query Performance Analysis
ch profile "SELECT uniq(user_id) FROM events"
╔══════════════════════╦══════════════╗
║ Metric ║ Value ║
╠══════════════════════╬══════════════╣
║ Wall time ║ 0.342s ║
║ DB duration ║ 298 ms ║
║ Rows read ║ 12,847,291 ║
║ Bytes read ║ 412.30 MB ║
║ Memory used ║ 87.50 MB ║
║ Parts selected ║ 24 ║
║ Ranges selected ║ 156 ║
╚══════════════════════╩══════════════╝
Extracts real execution statistics from system.query_log, including rows read, bytes read, memory usage, and parts/ranges selected — the core metrics for optimizing ClickHouse queries.
ch slowlog — Slow Query History
ch slowlog
ch slowlog --top 50 --threshold 500 --hours 48
┌──────────────────────┬────────────┬───────────┬──────────────────────────────────────┐
│ started │ duration │ user │ query │
├──────────────────────┼────────────┼───────────┼──────────────────────────────────────┤
│ 2026-03-17 09:12:44 │ 4,821 ms │ analyst │ SELECT uniq(session_id) FROM events… │
│ 2026-03-17 08:55:01 │ 3,102 ms │ default │ SELECT * FROM orders WHERE date >=… │
└──────────────────────┴────────────┴───────────┴──────────────────────────────────────┘
| Option | Short | Default | Description |
|---|---|---|---|
--top |
-n |
20 |
Number of results to display |
--threshold |
-t |
1000 |
Minimum duration in milliseconds |
--hours |
24 |
Look-back window in hours |
ch schema show — Inspect Table Structure
ch schema show events
ch schema show events --database analytics
┌─────────────┬─────────────────────────┬─────────┬─────────┐
│ Column │ Type │ Default │ Comment │
├─────────────┼─────────────────────────┼─────────┼─────────┤
│ event_id │ UUID │ │ │
│ user_id │ UInt64 │ │ │
│ event_type │ LowCardinality(String) │ │ │
│ date │ Date │ │ │
│ created_at │ DateTime │ now() │ │
└─────────────┴─────────────────────────┴─────────┴─────────┘
ch schema tables — List All Tables
ch schema tables
ch schema tables --database analytics
┌──────────────┬──────────────┬──────────────────┬──────────┬────────────┐
│ database │ table │ engine │ size │ rows │
├──────────────┼──────────────┼──────────────────┼──────────┼────────────┤
│ demo │ events │ MergeTree │ 412.3 MB │ 12,847,291 │
│ demo │ orders │ MergeTree │ 87.1 MB │ 1,203,445 │
│ demo │ users │ ReplacingMergeT… │ 2.1 MB │ 45,231 │
└──────────────┴──────────────┴──────────────────┴──────────┴────────────┘
ch monitor — Live Query Monitoring
ch monitor # default 2s refresh
ch monitor --interval 5
Running queries (2026-03-17 09:15:30)
┌──────────────────┬──────────┬───────────┬──────────────────────────────────────┐
│ query_id │ elapsed │ user │ query │
├──────────────────┼──────────┼───────────┼──────────────────────────────────────┤
│ 3a7f1c2b… │ 38.2 s │ analyst │ SELECT uniq(session_id) FROM events… │ ← red
│ d91e4f07… │ 6.7 s │ default │ SELECT count() FROM orders WHERE … │ ← yellow
└──────────────────┴──────────┴───────────┴──────────────────────────────────────┘
Queries running longer than 5 seconds are highlighted in yellow; those running longer than 30 seconds are shown in red. Press Ctrl+C to exit.
ch explain — Colorized EXPLAIN Tree
ch explain "SELECT uniq(user_id) FROM events WHERE date >= today() - 7"
ch explain "SELECT count() FROM events" --kind pipeline
ch explain "select count() from events" --kind syntax
Expression
└── Aggregating
└── Filter
└── ReadFromMergeTree (demo.events)
Indexes:
PrimaryKey
Condition: true
Parts: 24/24
Granules: 3721/3721
Renders the EXPLAIN output as a color-coded tree — ReadFromMergeTree in cyan, Filter in yellow, Aggregating in magenta — making query plans readable at a glance.
ch schema diff — Compare Schemas Across Environments
ch schema diff events --host2 staging.internal --database analytics
Schema diff: demo.events (prod vs staging)
┌─────────────┬──────────────────────────┬──────────────────────────┐
│ Column │ prod │ staging │
├─────────────┼──────────────────────────┼──────────────────────────┤
│ session_id │ String │ — (removed) │ ← red
│ v2_flag │ — (missing) │ UInt8 │ ← green
│ event_type │ String │ LowCardinality(String) │ ← yellow
└─────────────┴──────────────────────────┴──────────────────────────┘
ch migrate — Schema Migration Management
ch migrate status --dir migrations/
ch migrate run --dir migrations/ --dry-run
ch migrate run --dir migrations/
Migration status (dir: migrations/)
┌───────────────────────────────┬──────────┬──────────────────────┐
│ File │ Status │ Applied at │
├───────────────────────────────┼──────────┼──────────────────────┤
│ 001_create_events.sql │ applied │ 2026-03-15 10:22:01 │
│ 002_add_session_id.sql │ applied │ 2026-03-16 08:45:33 │
│ 003_add_v2_flag.sql │ pending │ — │
└───────────────────────────────┴──────────┴──────────────────────┘
✓ Applied 003_add_v2_flag.sql
1 migration applied.
Applies .sql files from a directory in alphabetical order. Tracks applied migrations in a _clickhawk_migrations table so runs are idempotent.
ch check nulls — Null Percentage per Column
ch check nulls events --database analytics
ch check nulls large_table --sample 500000
Null analysis: demo.events (sample: 1,000,000 rows)
┌─────────────┬────────────┬──────────┐
│ Column │ Null count │ Null % │
├─────────────┼────────────┼──────────┤
│ event_id │ 0 │ 0.00 % │
│ user_id │ 0 │ 0.00 % │
│ session_id │ 142,301 │ 14.23 % │ ← yellow
│ referrer │ 603,812 │ 60.38 % │ ← red
└─────────────┴────────────┴──────────┘
ch check cardinality — Unique Value Count per Column
ch check cardinality events --database analytics
Cardinality: demo.events (sample: 1,000,000 rows)
┌─────────────┬─────────────┬───────────┬──────────────────────────────┐
│ Column │ Cardinality │ Ratio % │ Verdict │
├─────────────┼─────────────┼───────────┼──────────────────────────────┤
│ user_id │ 891,204 │ 89.12 % │ high — consider skip index │
│ session_id │ 712,448 │ 71.24 % │ high │
│ event_type │ 12 │ 0.00 % │ low — consider LowCardinality│
│ date │ 365 │ 0.04 % │ low — consider LowCardinality│
└─────────────┴─────────────┴───────────┴──────────────────────────────┘
ch export — Export to CSV / JSON / Parquet / S3
ch export "SELECT * FROM events WHERE date = today()" --output today.csv
ch export "SELECT * FROM events" --output snapshot.parquet # requires: pip install pyarrow
ch export events --output events.json --limit 10000
# Upload directly to S3 (requires: pip install boto3)
ch export "SELECT * FROM events" --s3 s3://my-bucket/exports/events.csv
✓ 12,847,291 rows → today.csv
✓ 12,847,291 rows → s3://my-bucket/exports/events.csv
| Option | Short | Default | Description |
|---|---|---|---|
--output |
-o |
— | Local output file |
--s3 |
— | S3 destination URI (s3://bucket/key) |
|
--format |
-f |
auto | Format: csv / json / parquet |
--limit |
-l |
none | Max rows to export |
S3 credentials are read from environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) or ~/.aws/credentials via boto3.
ch kill — Kill Running Queries
ch kill 3a7f1c2b
ch kill --user analyst
ch kill --user etl_user --yes
Queries to kill:
┌──────────────────┬──────────┬───────────┬──────────────────────────────────────┐
│ query_id │ elapsed │ user │ query │
├──────────────────┼──────────┼───────────┼──────────────────────────────────────┤
│ 3a7f1c2b… │ 38.2 s │ analyst │ SELECT uniq(session_id) FROM events… │
└──────────────────┴──────────┴───────────┴──────────────────────────────────────┘
Kill 1 query? [y/N]: y
✓ Killed 3a7f1c2b…
ch top — Top Queries by Resource Usage
ch top
ch top --sort memory
ch top --sort rows --top 10 --interval 5
Running: 3 Memory: 234.5 MB Rows read: 28,103,445
┌──────────────────┬──────────┬───────────┬───────────────┬──────────────────────────────────────┐
│ query_id │ Elapsed │ user │ Memory │ query │
├──────────────────┼──────────┼───────────┼───────────────┼──────────────────────────────────────┤
│ 3a7f1c2b… │ 38.2 s │ analyst │ 87.5 MB │ SELECT uniq(session_id) FROM events… │
│ d91e4f07… │ 6.7 s │ default │ 45.0 MB │ SELECT count() FROM orders WHERE … │
└──────────────────┴──────────┴───────────┴───────────────┴──────────────────────────────────────┘
--sort value |
Description |
|---|---|
elapsed |
Time since query started (default) |
memory |
Current memory usage |
rows |
Rows read so far |
cpu |
CPU time (microseconds) |
Press Ctrl+C to exit.
Configuration
ClickHawk is configured via environment variables or a .env file (backed by Pydantic Settings, with priority-based override support):
| Variable | Default | Description |
|---|---|---|
CH_HOST |
localhost |
ClickHouse host address |
CH_PORT |
8123 |
HTTP port |
CH_USER |
default |
Username |
CH_PASSWORD |
"" |
Password |
CH_DATABASE |
default |
Default database |
CH_SECURE |
false |
Enable HTTPS/TLS |
Example .env file:
CH_HOST=clickhouse.prod.internal
CH_PORT=8123
CH_USER=analyst
CH_PASSWORD=secret
CH_DATABASE=analytics
CH_SECURE=true
Testing
Run unit tests:
pytest tests/unit/
Run integration tests (requires a running ClickHouse instance):
pytest tests/integration/ -m integration
Run all tests:
pytest
Integration tests automatically skip if ClickHouse is not available, so the full test suite can always be run safely in any environment.
Roadmap
| Version | Feature | Status |
|---|---|---|
| v0.1 | query / profile / slowlog / schema / monitor / health |
✅ Released |
| v0.2 | ch explain — colorized tree-style EXPLAIN output |
✅ Released |
| v0.2 | ch schema diff — schema comparison across environments |
✅ Released |
| v0.2 | ch migrate run/status — file-based schema migration management |
✅ Released |
| v0.2 | ch check nulls/cardinality — data quality scanning |
✅ Released |
| v0.2 | ch export — export to CSV / JSON / Parquet |
✅ Released |
| v0.3 | ch kill <query_id> — terminate a running query from the terminal |
✅ Released |
| v0.3 | ch export --s3 — upload results directly to S3 |
✅ Released |
| v0.3 | ch top — top queries by CPU / memory / rows / elapsed (live dashboard) |
✅ Released |
| v0.4 | ch top --filter <user> — narrow live view to a specific user |
Planned |
| v0.4 | ch export --s3 chunked multipart upload for very large result sets |
Planned |
| v0.4 | ch profile --compare — diff two query profiles side by side |
Planned |
Contributing
PRs and issues are welcome!
# Clone the repository
git clone https://github.com/your-username/clickhawk.git
cd clickhawk
# Install development dependencies
pip install -e ".[dev]"
# Run the linter
ruff check .
# Run type checks
mypy clickhawk/
# Run tests
pytest
License
MIT © Victor Li
If ClickHawk has saved you time, please give it a Star — it means a lot to the project.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file clickhawk-0.3.0.tar.gz.
File metadata
- Download URL: clickhawk-0.3.0.tar.gz
- Upload date:
- Size: 73.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.9 {"installer":{"name":"uv","version":"0.9.9"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ca8667c2aeb73bc1f9935fe32deeee1520c7f6a065110c070f8f89379e3d8f5f
|
|
| MD5 |
5feeb62ead854cae014c568eaf3fd9c0
|
|
| BLAKE2b-256 |
029ef79ac3c4426cd53851a652257304058c699d65e27d1aa2aaea6730f585a2
|
File details
Details for the file clickhawk-0.3.0-py3-none-any.whl.
File metadata
- Download URL: clickhawk-0.3.0-py3-none-any.whl
- Upload date:
- Size: 26.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.9 {"installer":{"name":"uv","version":"0.9.9"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2e8a04293bd9996f09e2b827eed173f5f22f5ddfc9090553e62599a51743d12e
|
|
| MD5 |
cb316183c3618d70844be1f49b358c8b
|
|
| BLAKE2b-256 |
711dbb593008250c2a49e04bf169b806678a23e023d560f93daf6ae628c12111
|