A ClickHouse migrations CLI with templated SQL and environment-aware config.
- Templates in migrations — like in Atlas, but free.
- Multi-statement migrations — write real SQL without splitting into tiny files.
- Declarative environments — keep local/staging/prod configs in one place.
npm install -g clismanpm install --save-dev clismanpx clismaCreate clisma.hcl:
env "local" {
url = "http://default:password@localhost:8123/mydb"
migrations {
dir = "migrations"
}
}Run migrations:
clisma run --env local
clisma status --env localenv "name"defines an environment.migrationsholds migration settings.variable "name"defines inputs forvar.*.env("NAME")reads environment variables.
variable "ttl_days" {
type = string
default = "30"
}
env "production" {
url = env("CLICKHOUSE_PROD_URL")
migrations {
dir = "migrations"
table {
name = "schema_migrations"
is_replicated = true
# Optional: force a specific cluster for ON CLUSTER.
cluster_name = "prod-cluster"
# If replication_path is set, is_replicated can be omitted.
replication_path = "/clickhouse/tables/cluster-{cluster}/shard-{shard}/{database}/schema_migrations"
}
vars = {
is_replicated = true
create_table_options = "ON CLUSTER prod-cluster"
ttl_days = var.ttl_days
}
}
}migrations.table controls the tracking table:
namesets a custom table name.is_replicated = trueenables replicated tracking.cluster_nameoptionally selects cluster forON CLUSTER.replication_pathoverrides the default replication path (and also enables replicated mode ifis_replicatedis omitted).
If your ClickHouse endpoint uses a self-signed certificate, add a tls block so clisma can trust your CA.
env "production" {
url = env("CLICKHOUSE_URL") # e.g. https://user:pass@host:8443/db
tls {
ca_file = env("CLICKHOUSE_CA_FILE")
# cert_file = env("CLICKHOUSE_CLIENT_CERT_FILE") # optional, for mTLS
# key_file = env("CLICKHOUSE_CLIENT_KEY_FILE") # optional, for mTLS
}
...
}Notes:
ca_fileis required whentlsis set.cert_fileandkey_filemust be provided together.- Relative paths are resolved from the directory where
clisma.hcllives.
Templates are Handlebars. Variables come from migrations.vars.
CREATE TABLE IF NOT EXISTS events {{create_table_options}} (
id UUID,
created_at DateTime DEFAULT now()
)
{{#if is_replicated}}
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{cluster}/events', '{replica}')
{{else}}
ENGINE = MergeTree()
{{/if}}
ORDER BY id;Multi-statement migrations are supported (split on semicolons outside strings/comments).
Common commands:
clisma run --env local
clisma status --env local
clisma create --name create_events
clisma checksum ./migrations/20240101123045_create_events.sql--config <path>--env <name>--env-file <path>--var <key=value>(repeatable)
The CLI requires a config file. Use --config or place clisma.hcl in the current directory.
Example with variables and env file:
clisma run --env local --var ttl_days=30 --env-file .envThis project borrows ideas from tools we like:
-
Atlas for the idea of templated migrations and config-driven environments.
-
Prisma for the simple, friendly CLI experience.
"clisma" is a mashup of ClickHouse + Prisma. A dumb pun, but it stuck. 👉👈