clickhousectl
Beta:
clickhousectlis currently in beta. Features and behavior may change.
clickhousectl is the CLI for ClickHouse: local and cloud.
With clickhousectl you can:
- Install and manage local ClickHouse versions
- Launch and manage local ClickHouse servers
- Execute queries against ClickHouse servers
- Setup ClickHouse Cloud and create cloud-managed ClickHouse clusters
- Manage ClickHouse Cloud resources
- Create and manage ClickPipes for data ingestion (S3, Kafka, Kinesis, Postgres, MySQL, MongoDB, BigQuery)
- Install the official ClickHouse agent skills into supported coding agents
- Push your local ClickHouse development to cloud
clickhousectl helps humans and AI-agents to develop with ClickHouse.
Installation
Quick install
|
The install script will download the correct version for your OS and install to ~/.local/bin/clickhousectl. A chctl alias is also created automatically for convenience.
cargo binstall
If you already have cargo-binstall, this pulls the prebuilt binary from builds.clickhouse.com:
npm
This installs an npm wrapper package that downloads the matching prebuilt binary from builds.clickhouse.com at install time. Both clickhousectl and chctl are exposed as commands. If you use npm install --ignore-scripts, the download is skipped — fall back to one of the other install paths.
pip
# or
# or
This installs a prebuilt wheel containing the matching clickhousectl binary. Linux (glibc and musl, x86_64 and aarch64) and macOS (Intel and Apple Silicon) wheels are published to PyPI.
From crates.io
Builds from source:
From this repo
Direct download
Prebuilt archives for each release are hosted at https://builds.clickhouse.com/clickhousectl/. Archives are named clickhousectl-{target}-v{version}.tar.gz and contain a single directory of the same name with the clickhousectl binary inside. Supported targets: x86_64-unknown-linux-musl, aarch64-unknown-linux-musl, x86_64-apple-darwin, aarch64-apple-darwin. Example: https://builds.clickhouse.com/clickhousectl/clickhousectl-aarch64-apple-darwin-v0.3.0.tar.gz.
Local
Installing and managing ClickHouse versions
clickhousectl downloads ClickHouse binaries from builds.clickhouse.com, falling back to packages.clickhouse.com (Linux) or GitHub releases (macOS) when a build isn't available there.
# Install a version
# List versions
# Manage default version
# Remove a version
local use also creates a symlink at ~/.local/bin/clickhouse pointing to the selected version's binary, so the plain clickhouse command (e.g. clickhouse local, clickhouse client) is on PATH. Pass --no-global to skip. If a regular file already exists at that path it is left alone with a warning. local remove of the active default version also clears the symlink.
ClickHouse binary storage
ClickHouse binaries are stored in a global repository, so they can be used by multiple projects without duplicating storage. Binaries are stored in ~/.clickhouse/:
~/.clickhouse/
├── versions/
│ └── 25.12.5.44/
│ └── clickhouse
└── default # tracks the active version
Initializing a project
init bootstraps your current working directory with a standard folder structure for your ClickHouse project files. It is optional; you are welcome to use your own folder structure if preferred.
It creates the following structure:
clickhouse/
├── tables/ # Table definitions (CREATE TABLE ...)
├── materialized_views/ # Materialized view definitions
├── queries/ # Saved queries
└── seed/ # Seed data / INSERT statements
postgres/
├── tables/ # Table definitions (CREATE TABLE ...)
├── views/ # View definitions (CREATE VIEW ...)
├── functions/ # Function / procedure definitions (CREATE FUNCTION ...)
├── queries/ # Saved queries
└── seed/ # Seed data / INSERT statements
Running queries
# Connect to a running server with clickhouse-client
Creating and managing ClickHouse servers
Start and manage ClickHouse server instances. Each server gets its own isolated data directory at .clickhouse/servers/<name>/data/.
# Start a server (runs in background by default)
# List custom config files available to --config-file
# List all servers (running and stopped)
# Stop servers
# Remove a stopped server and its data
# Write connection env vars to .env file
Server naming: Without --name, the first server is called "default". If "default" is already running, a random name is generated (e.g. "bold-crane"). Use --name for stable identities you can start/stop repeatedly.
Ports: Defaults are HTTP 8123 and TCP 9000. If these are already in use, free ports are automatically assigned and shown in the output. Use --http-port and --tcp-port to set explicit ports.
Orphaned server recovery: If server metadata files are lost while the ClickHouse process is still running, the CLI automatically recovers them via process discovery. Running server list, server start, or any server command will detect orphaned processes belonging to the current project and bring them back under management.
Global server management: Use --global with list, stop, and stop-all to operate across all projects system-wide. server list --global shows all running ClickHouse servers with a Project column indicating which directory each belongs to.
Custom config files
Drop ClickHouse config files into ~/.clickhouse/configs/ and apply one by name when starting a server:
The named file is overlaid on top of ClickHouse's built-in defaults (it is staged into the server's config.d/ directory), so it only needs to contain the settings you want to change — you don't have to reproduce a full config. Files may be .xml, .yaml, or .yml; reference them by name with or without the extension (e.g. --config-file analytics or --config-file analytics.xml). --config-file takes a name within ~/.clickhouse/configs/ not a path.
The managed data directory (.clickhouse/servers/<name>/data/) and the HTTP/TCP ports are always forced as command-line overrides, which take precedence over the config file. This means a custom config can never break the managed server lifecycle (list, stop, remove, dotenv) regardless of its contents. Starting a server again without --config-file reverts it to plain defaults.
Local Postgres (Docker-backed)
When you also need a local Postgres alongside ClickHouse — e.g. for testing CDC pipelines or ingesting from Postgres — use local postgres. Each instance is keyed on (name, major version) so the same name can host multiple Postgres majors with isolated data: data lives at .clickhouse/servers/<name>-pg<major>/data/, metadata at .clickhouse/servers/<name>-pg<major>.json, and the container is clickhousectl-pg-<name>-<major>. ClickHouse paths (<name>/data/, <name>.json) stay separate, so a name can be used by both engines. Requires Docker to be installed and running.
# Pre-pull a Postgres image (optional; start will pull on demand). Supported: 17, 18 (and any sub-tag like 17-alpine, 17.0, 18-bookworm).
# Start a Postgres instance (defaults: postgres:18, port 5432, user "postgres", db "postgres")
# List everything (ClickHouse + Postgres are merged in `server list`)
# Connect with psql (uses host psql if installed; otherwise falls back to docker exec)
# Write POSTGRES_HOST/PORT/USER/PASSWORD/DATABASE into .env
# Stop / remove. Pass --version when more than one major shares a name.
local postgres start --name dev (no --version) resumes the existing instance when there's exactly one for that name; if multiple majors share the name, you'll be asked to pick. Stop preserves the container and metadata so the next start resumes it; only remove tears down the container and deletes the data directory.
Containers are tagged with clickhousectl.engine=postgres, clickhousectl.name=<name>, clickhousectl.major=<major>, clickhousectl.project=<cwd>, and created_by=clickhousectl_<version> labels. server list recovers orphaned containers belonging to the current project via these labels, so deleting .clickhouse/servers/<name>-pg<major>.json is non-destructive — the next list/start rediscovers it.
Project-local data directory
All server data lives inside .clickhouse/ in your project directory:
.clickhouse/
├── .gitignore # auto-created, ignores everything
├── credentials.json # cloud API credentials (if configured)
└── servers/
├── default/
│ └── data/ # ClickHouse data files for "default" server
└── dev/
└── data/ # ClickHouse data files for "dev" server
Each named server has its own data directory, so servers are fully isolated from each other. Data persists between restarts — stop and start a server by name to pick up where you left off. Use clickhousectl local server remove <name> to permanently delete a server's data.
Authentication
Authenticate to ClickHouse Cloud using OAuth (browser-based) or API keys. OAuth provides read-only access; API keys provide full read/write access.
If you don't have a ClickHouse Cloud account yet, clickhousectl cloud auth signup opens the sign-up page in your browser.
OAuth login (read-only)
This opens your browser for authentication via the OAuth device flow. Tokens are saved to .clickhouse/tokens.json (project-local).
Note: OAuth tokens provide read-only access. You can list and inspect resources (organizations, services, backups, etc.) but cannot create, modify, or delete them. For write operations, use API key authentication.
cloud service queryworks under OAuth too, running SQL as your own identity with your console role's permissions — see Query API auth modes.
API key/secret (required for write operations)
# Non-interactive (CI-friendly)
# Interactive prompt
Credentials are saved to .clickhouse/credentials.json (project-local).
You can also use environment variables, either exported in your session:
Or place them in a .env file (only read from your current working directory):
CLICKHOUSE_CLOUD_API_KEY=your-key
CLICKHOUSE_CLOUD_API_SECRET=your-secret
Or pass credentials directly via flags on any command:
Learn how to create API keys.
Auth status and logout
Credential resolution order:
- CLI flags
.clickhouse/credentials.json- Environment variables exported in your session
- Environment variables from
.env - OAuth tokens.
Debugging which credential source was used
Pass --debug to any cloud command to print the resolved credential source (and the API URL) to stderr before the command runs. This works with and without --json.
# [debug] auth source: credentials file (.clickhouse/credentials.json)
# [debug] api url: https://api.clickhouse.cloud/v1
# ... normal output ...
Cloud
Manage ClickHouse Cloud services via the API.
Organizations
Services
# List services
# Get service details
# Create a service (minimal)
# Create with scaling options
# Create with specific IP allowlist
# Create from backup
# Create with release channel
# Create with GA request-only extras
# Start/stop a service
# Run SQL over HTTP via the Query API (no local clickhouse binary needed)
|
# Update service metadata and patches
# Update replica scaling
# Reset password with generated credentials
# Reset password with precomputed hashes
# Query endpoint management (manual — for custom roles or sharing keys with other tools)
# Private endpoint management
# Backup configuration
# Service Prometheus configuration
# Delete a service (must be stopped first)
# Force delete: stops a running service then deletes
Service Create Options:
| Option | Description |
|---|---|
--name |
Service name (required) |
--provider |
Cloud provider: aws, gcp, azure (default: aws) |
--region |
Region (default: us-east-1) |
--min-replica-memory-gb |
Min memory per replica in GB (8-356, multiple of 4) |
--max-replica-memory-gb |
Max memory per replica in GB (8-356, multiple of 4) |
--num-replicas |
Number of replicas (1-20) |
--idle-scaling |
Allow scale to zero (default: true) |
--idle-timeout-minutes |
Min idle timeout in minutes (>= 5) |
--ip-allow |
IP CIDR to allow (repeatable, default: 0.0.0.0/0) |
--backup-id |
Backup ID to restore from |
--release-channel |
Release channel: slow, default, fast |
--data-warehouse-id |
Data warehouse ID (for read replicas) |
--readonly |
Make service read-only |
--encryption-key |
Customer disk encryption key |
--encryption-role |
Role ARN for disk encryption |
--enable-tde |
Enable Transparent Data Encryption |
--compliance-type |
Compliance: hipaa, pci |
--profile |
Instance profile (enterprise) |
--tag |
Attach a GA service tag (key or key=value) |
--enable-endpoint / --disable-endpoint |
Toggle GA service endpoints (currently mysql) |
--private-preview-terms-checked |
Accept private preview terms when required |
--enable-core-dumps |
Enable or disable service core dump collection |
Query API auth modes
cloud service query is the canonical way to run SQL against a cloud service — over HTTP, with no clickhouse binary and no service password required. It works with both credential modes:
- API key auth (read + write SQL): the first time
cloud service queryruns against a service without a stored key, it provisions a Query API endpoint for that service and creates a dedicated API key bound to it. The key (keyId,keySecret, andendpointId) is stored in.clickhouse/credentials.jsonunderservice_query_keys.<service-id>, alongside any user-level API key. Subsequent queries use that key. It is scoped to a single service, so it can read and write (SELECT, INSERT, DDL) against that service but cannot reach any other service in the org. Pass--no-auto-enableto fail instead of provisioning. - OAuth (
cloud auth login): the query runs as your own identity, SQL-console style — the CLI sends your bearer token straight to the Query API, and your SQL permissions follow your ClickHouse Cloud console role. No Query API key is provisioned or stored, and no query endpoint needs to be configured on the service.--no-auto-enablehas no effect in this mode.
Provisioning happens lazily (rather than at service create time) because the endpoint can only be bound once the service has finished provisioning, which can take several minutes — service create returns immediately instead of blocking on it.
Per-service scoping is enforced at the query endpoint binding, which is created with role sql_console_admin (read + write inside the bound service only). The API key itself has no org-level roles, so the binding is the only thing that grants it any access. cloud service delete removes the stored key from credentials.json.
Querying an idled service wakes it automatically in both auth modes — under OAuth the Query API first asks for a wake confirmation, which the CLI sends after printing a notice to stderr (the first query may take a minute while the service wakes). A stopped service is never woken: the query fails with a hint to run cloud service start.
The Query API host is derived from the API base URL per environment (api.[control-plane.]<domain> → queries.<domain>, e.g. https://queries.clickhouse.cloud for production). Set CLICKHOUSE_CLOUD_QUERY_HOST to override it.
Postgres (beta)
Manage ClickHouse Cloud managed Postgres services. All write commands require API key auth.
# List / get
# Create
# Create with HA + tags + advanced config
# Update metadata (all flags optional)
# Delete
# CA certificates
# Runtime configuration
# Password
# Read replica and PITR restore
# Lifecycle
Postgres Create Options:
| Option | Description |
|---|---|
--name |
Service name (required) |
--region |
Cloud region, e.g. us-east-1 (required) |
--size |
Instance size, e.g. m7i.2xlarge (required; server-validated) |
--provider |
Cloud provider (default: aws) |
--pg-version |
Postgres major version: 18, 17 |
--ha-type |
High-availability: none, async, sync |
--tag |
Resource tag key or key=value (repeatable) |
--pg-config-file |
Path to JSON file with a PgConfig object |
--pg-bouncer-config-file |
Path to JSON file with a PgBouncerConfig object |
Backups
ClickPipes
Manage ClickPipes for ingesting data into ClickHouse Cloud from external sources.
# List ClickPipes for a service
# Get ClickPipe details
# Start/stop/resync a ClickPipe
# Delete a ClickPipe
# Update scaling
# Get/update settings
Creating ClickPipes
Each source type has its own subcommand under clickpipe create:
# From S3 / object storage
# From Google Cloud Storage (object storage)
# From Kafka / Redpanda / Confluent / MSK
# From Amazon Kinesis
# From PostgreSQL (CDC)
# From MySQL (CDC)
# From MongoDB (CDC)
# From BigQuery (snapshot)
Use clickhousectl cloud clickpipe create <source> --help for the full list of options per source type.
Members
Invitations
Keys
Activity
JSON output
Use the --json flag to print JSON-formatted responses.
clickhousectl auto-detects coding-agent contexts (Claude Code, Cursor, Codex, Gemini CLI, Goose, Devin, and any tool that sets the standard AGENT env var) and emits JSON to stdout automatically without setting --json.
Exit codes
Follow gh conventions:
| Code | Meaning |
|---|---|
0 |
Success |
1 |
Error (anything not classified below) |
2 |
Cancelled (user aborted) |
4 |
Auth required (no credentials, 401/403, OAuth-only writes) |
Skills
Install the official ClickHouse Agent Skills from ClickHouse/agent-skills.
# Default: interactive mode for humans, choose scope, then choose agents
# Non-interactive: install into every supported project-local agent folder
# Non-interactive: install only into detected agents
# Non-interactive: install into every supported global agent folder
# Non-interactive: install only into detected global agents
# Non-interactive: install into specific project-local agents
# Non-interactive: install into specific global agents
Supported Skills paths
The common path .agents/skills/ is always included regardless of agent selection.
The following agents can be selected, and Skills are installed in the corresponding paths:
claude->.claude/skills/codex->.codex/skills/cursor->.cursor/skills/opencode->.opencode/skills/agent->.agent/skills/roo->.roo/skills/trae->.trae/skills/windsurf->.windsurf/skills/zencoder->.zencoder/skills/neovate->.neovate/skills/pochi->.pochi/skills/adal->.adal/skills/openclaw->.openclaw/skills/cline->.cline/skills/command-code->.command-code/skills/kiro-cli->.kiro/skills/
Supports global or project scope installation. Project scope installs Skills into the current working directory. Global scope installs Skills into the current user's home directory.
Non-interactive flags:
--agentname a specific agent to install Skills for, can be repeated--globaluse global scope; if omitted, project scope is used--allinstall Skills for all supported agents--detected-onlyinstall Skills for supported agents that were detected on the system
Self-update
clickhousectl can update itself to the latest release:
# Update to the latest version
# Check for updates without installing
The CLI also checks for updates in the background (at most once per 24 hours) and displays a notice when a newer version is available.
Cloud integration testing
Cloud API integration is tested against a real ClickHouse Cloud workspace via the library crate. All changes to cloud commands must pass CI testing before merge. Tests live in three binaries, each a single #[tokio::test] lifecycle:
tests/integration_test.rs— ClickHouse service CRUD + service-scoped endpointstests/integration_postgres_test.rs— Postgres service CRUDtests/integration_org_test.rs— org-scoped endpoints (members, invitations, roles, activity, prometheus, private endpoint config)
Required environment variables:
# Required for the org integration suite (members + invitations need a
# second user in the test org); optional otherwise.
Run a suite:
By default, any failed check fails the run. To keep going after non-blocking capability failures and collect them in a summary at the end, set:
Requirements
- macOS (aarch64, x86_64) or Linux (aarch64, x86_64)
- Cloud commands require a ClickHouse Cloud API key