Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ chkit is an open-source CLI for ClickHouse. Review migration SQL before applying

[Get started](https://chkit.obsessiondb.com/getting-started/) · [Build a data source](https://chkit.obsessiondb.com/api-sync/quickstart/) · [Documentation](https://chkit.obsessiondb.com)

New to chkit? Scaffold the small [hello example](examples/hello) with `bun create chkit@latest my-app --example hello`, or clone that folder and follow its README. The heavier ClickBench load stays at [`examples/clickbench`](examples/clickbench).

> **Beta:** the public API is still evolving. Keep the CLI, core, and plugins on matching versions.

## Why chkit
Expand Down
4 changes: 3 additions & 1 deletion apps/docs/src/content/docs/ai-agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,11 @@ It guides decisions about raw versus shaped data, transformations, pagination, i
`create-chkit` downloads a curated example and wires it to the user's package manager. Pass a target directory and an example to skip the prompts:

```sh
bun create chkit@latest my-chkit-app --example clickbench
bun create chkit@latest my-chkit-app --example hello
```

`hello` is the small default schema (two tables, one migration). Pass `--example clickbench` for the full ClickBench dataset load.

It then runs the same connect flow as `chkit init` (Step 4). Drive it non-interactively with `--connect <choice>` (and `--email` for the claim path), or `--skip-onboarding` to scaffold only.

### 3b. Existing project: `chkit init`
Expand Down
4 changes: 2 additions & 2 deletions apps/docs/src/content/docs/getting-started/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ For manual setup, start with an example or add chkit to an existing project.
<LinkCard
title="Start with an example"
href="/getting-started/with-an-example/"
description="Use create-chkit to scaffold a project with example schema and configuration files."
description="Scaffold the hello example with create-chkit: two tables and one migration. ClickBench stays available for a full dataset load."
/>
<LinkCard
title="Add to an existing project"
Expand All @@ -43,7 +43,7 @@ For manual setup, start with an example or add chkit to an existing project.
Both paths need the same baseline:

- Node.js 20+ or Bun 1.3.5+
- A ClickHouse endpoint (`CLICKHOUSE_URL`, optionally `CLICKHOUSE_USER`, `CLICKHOUSE_PASSWORD`): ClickHouse 24.x or newer (see [compatibility](/guides/clickhouse-compatibility/))
- A ClickHouse endpoint (`CLICKHOUSE_URL`, optionally `CLICKHOUSE_USER`, `CLICKHOUSE_PASSWORD`): ClickHouse 24.x or newer (see [compatibility](/guides/clickhouse-compatibility/)). The [example path](/getting-started/with-an-example/) can claim a free ObsessionDB dev instance from the scaffold prompt instead.

## Where to next

Expand Down
42 changes: 35 additions & 7 deletions apps/docs/src/content/docs/getting-started/with-an-example.mdx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
title: Start with an example
description: Scaffold a working chkit project from a curated example with create-chkit.
description: Scaffold the hello example with create-chkit and apply its first migration.
sidebar:
order: 1
---

import PackagedCommand from '../../../components/PackagedCommand.astro';
import Command from '../../../components/Command.astro';

`create-chkit` scaffolds a working chkit project by downloading a curated example from the chkit repository and wiring it up against your chosen package manager. Use this path when you want a known-good project as a starting point.
`create-chkit` scaffolds a working chkit project by downloading a curated example from the chkit repository and wiring it up against your chosen package manager. The default example is [`hello`](https://github.com/obsessiondb/chkit/tree/main/examples/hello): two small tables and one migration.

:::note[Working in Python?]
The `create-chkit` examples are TypeScript projects. For Python, start with `pip install chkit-py` and run `chkit init` in your project instead — see the [Python overview](/python/overview/).
Expand All @@ -17,15 +17,30 @@ The `create-chkit` examples are TypeScript projects. For Python, start with `pip
## Prerequisites

- Node.js 20+ or Bun 1.3.5+
- A ClickHouse endpoint (`CLICKHOUSE_URL`, optionally `CLICKHOUSE_USER`, `CLICKHOUSE_PASSWORD`)
- A database. The scaffold prompt claims a free ObsessionDB dev instance, or set `CLICKHOUSE_URL` (and optionally `CLICKHOUSE_USER` / `CLICKHOUSE_PASSWORD`) for an existing ClickHouse.

## Scaffold a project

Run the package without arguments to be prompted for a project name and to pick from the list of bundled examples.
Run the package without arguments to be prompted for a project name and to pick from the bundled examples. `hello` is the default in the repository manifest; pass `--example hello` to select it directly.

<PackagedCommand create="chkit@latest" />

Pass a project directory and pick an example explicitly:
Pass a project directory and select `hello` explicitly:

<PackagedCommand create="chkit@latest" args="my-chkit-app --example hello" />

The scaffold then asks how to connect:

```
Claim a free ObsessionDB dev instance email code, ready in seconds
I already have an ObsessionDB account log in and pick a service
I already have a ClickHouse instance connect with env vars
Configure later
```

Choose **Claim a free ObsessionDB dev instance** and enter the emailed code. chkit creates a personal organization, provisions a free instance, and selects it. See [Getting Started with ObsessionDB](/obsessiondb/getting-started/) for the other paths, including the non-interactive signup commands.

For the full ClickBench schema and public dataset load, pass `--example clickbench` instead:

<PackagedCommand create="chkit@latest" args="my-chkit-app --example clickbench" />

Expand All @@ -42,23 +57,36 @@ Pass a project directory and pick an example explicitly:

| Name | Description |
| --- | --- |
| `hello` | Two small tables and one migration. Default. Claim a free ObsessionDB instance or use local ClickHouse. |
| `clickbench` | Full ClickBench schema and dataset load against ObsessionDB or ClickHouse. |

More examples will land in the [`examples/` directory](https://github.com/obsessiondb/chkit/tree/main/examples) over time.
The list and default live in [`examples/manifest.json`](https://github.com/obsessiondb/chkit/blob/main/examples/manifest.json). The same `hello` project can be cloned from [`examples/hello`](https://github.com/obsessiondb/chkit/tree/main/examples/hello) without the scaffolder.

## Run your first migration

Once the scaffold completes:
Once the scaffold completes and a database is connected:

```sh
cd my-chkit-app
bun run migrate
bunx chkit query "SELECT name FROM system.tables WHERE database = 'default' AND name IN ('users', 'events') ORDER BY name"
```

Both tables come back, `events` then `users`. They are empty.

For a local ClickHouse instead of the claimed instance, set the endpoint before migrating:

```sh
cd my-chkit-app
export CLICKHOUSE_URL=http://localhost:8123
# export CLICKHOUSE_PASSWORD=...
bun run migrate
bunx chkit query "SELECT name FROM system.tables WHERE database = 'default' AND name IN ('users', 'events') ORDER BY name"
```

## Where to next

- [Tutorial: your first schema](/tutorials/first-schema/) — the same loop from `chkit init`, including an insert and a schema change
- [CLI reference](/cli/overview/) — every command and flag
- [Configuration](/configuration/overview/) — wire up `clickhouse.config.ts`
- [Add chkit to an existing project](/getting-started/add-to-existing-project/) — the other path
73 changes: 73 additions & 0 deletions examples/hello/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Hello chkit example

Two MergeTree tables, `users` and `events`, and one migration that creates them. No dataset load.

## Scaffold

```bash
bun create chkit@latest my-chkit-app --example hello
cd my-chkit-app
```

The scaffolder asks how to connect. Choose **Claim a free ObsessionDB dev instance** and enter the emailed code. That creates a personal organization, provisions a free instance, and selects it.

To use an existing ClickHouse instead, choose **I already have a ClickHouse instance** and set `CLICKHOUSE_URL`.

`clickbench` stays available for the full public dataset:

```bash
bun create chkit@latest my-chkit-app --example clickbench
```

## Or clone this folder

```bash
cd examples/hello
bun install
```

Claim a free ObsessionDB dev instance:

```bash
bunx chkit obsessiondb signup
bunx chkit obsessiondb service claim
```

Or point at a local ClickHouse:

```bash
export CLICKHOUSE_URL=http://localhost:8123
# export CLICKHOUSE_USER=default
# export CLICKHOUSE_PASSWORD=...
```

## Migrate

```bash
bun run migrate
```

## Confirm

```bash
bunx chkit query "SELECT name FROM system.tables WHERE database = 'default' AND name IN ('users', 'events') ORDER BY name"
```

Both tables come back:

```
name
────
events
users
```

Stop there. The tables are empty.

## Schema

`src/db/schema/hello.ts` defines both tables. `chkit/migrations/20260928082853_create_hello_schema.sql` creates them.

## Dependency security

This example pins published chkit packages. Those releases still depend on vulnerable `@orpc/client` and `@orpc/contract` versions. The `overrides` in `package.json` replace them with `1.15.4`, including when this folder is copied out of the monorepo.
64 changes: 64 additions & 0 deletions examples/hello/chkit/meta/snapshot.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
"version": 1,
"generatedAt": "2026-09-28T08:28:53.623Z",
"definitions": [
{
"database": "default",
"name": "events",
"engine": "MergeTree()",
"columns": [
{
"name": "id",
"type": "UInt64"
},
{
"name": "user_id",
"type": "UInt64"
},
{
"name": "name",
"type": "String"
},
{
"name": "created_at",
"type": "DateTime64(3)",
"default": "fn:now64(3)"
}
],
"primaryKey": [
"id"
],
"orderBy": [
"id"
],
"kind": "table"
},
{
"database": "default",
"name": "users",
"engine": "MergeTree()",
"columns": [
{
"name": "id",
"type": "UInt64"
},
{
"name": "email",
"type": "String"
},
{
"name": "created_at",
"type": "DateTime64(3)",
"default": "fn:now64(3)"
}
],
"primaryKey": [
"id"
],
"orderBy": [
"id"
],
"kind": "table"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
-- chkit-migration-format: v1
-- generated-at: 2026-09-28T08:28:53.406Z
-- cli-version: 0.1.2-beta.7
-- definition-count: 2
-- operation-count: 3
-- rename-suggestion-count: 0
-- risk-summary: safe=3, caution=0, danger=0

-- operation: create_database key=database:default risk=safe
CREATE DATABASE IF NOT EXISTS default;

-- operation: create_table key=table:default.events risk=safe
CREATE TABLE IF NOT EXISTS default.events
(
`id` UInt64,
`user_id` UInt64,
`name` String,
`created_at` DateTime64(3) DEFAULT now64(3)
) ENGINE = MergeTree()
PRIMARY KEY (`id`)
ORDER BY (`id`);

-- operation: create_table key=table:default.users risk=safe
CREATE TABLE IF NOT EXISTS default.users
(
`id` UInt64,
`email` String,
`created_at` DateTime64(3) DEFAULT now64(3)
) ENGINE = MergeTree()
PRIMARY KEY (`id`)
ORDER BY (`id`);
16 changes: 16 additions & 0 deletions examples/hello/clickhouse.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { defineConfig } from '@chkit/core'
import { obsessiondb } from '@chkit/plugin-obsessiondb'

export default defineConfig({
schema: './src/db/schema/**/*.ts',
outDir: './chkit',
migrationsDir: './chkit/migrations',
metaDir: './chkit/meta',
plugins: [obsessiondb()],
clickhouse: {
url: process.env.CLICKHOUSE_URL ?? 'http://localhost:8123',
username: process.env.CLICKHOUSE_USER ?? 'default',
password: process.env.CLICKHOUSE_PASSWORD ?? '',
database: 'default',
},
})
20 changes: 20 additions & 0 deletions examples/hello/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "chkit-example-hello",
"private": true,
"type": "module",
"packageManager": "bun@1.3.13",
"scripts": {
"migrate": "chkit migrate --apply",
"status": "chkit status",
"check": "chkit check"
},
"devDependencies": {
"@chkit/core": "0.1.2-beta.7",
"@chkit/plugin-obsessiondb": "0.1.2-beta.7",
"chkit": "0.1.2-beta.7"
},
"overrides": {
"@orpc/client": "1.15.4",
"@orpc/contract": "1.15.4"
}
}
30 changes: 30 additions & 0 deletions examples/hello/src/db/schema/hello.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { schema, table } from '@chkit/core'

const users = table({
database: 'default',
name: 'users',
engine: 'MergeTree',
columns: [
{ name: 'id', type: 'UInt64' },
{ name: 'email', type: 'String' },
{ name: 'created_at', type: 'DateTime64(3)', default: 'fn:now64(3)' },
],
primaryKey: ['id'],
orderBy: ['id'],
})

const events = table({
database: 'default',
name: 'events',
engine: 'MergeTree',
columns: [
{ name: 'id', type: 'UInt64' },
{ name: 'user_id', type: 'UInt64' },
{ name: 'name', type: 'String' },
{ name: 'created_at', type: 'DateTime64(3)', default: 'fn:now64(3)' },
],
primaryKey: ['id'],
orderBy: ['id'],
})

export default schema(users, events)
6 changes: 5 additions & 1 deletion examples/manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
{
"default": "clickbench",
"default": "hello",
"examples": [
{
"name": "hello",
"description": "Two small tables and one migration. Claim a free ObsessionDB instance or use local ClickHouse."
},
{
"name": "clickbench",
"description": "Full ClickBench schema and dataset load against ObsessionDB or ClickHouse."
Expand Down
Loading