Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ yarn-error.log*
.claude
.superpowers
docs/superpowers
.qoder

# Editors and OS files
.idea/
Expand All @@ -69,4 +70,4 @@ docs/superpowers
*.swo
*~
.vercel
.devtools
.devtools
26 changes: 22 additions & 4 deletions docs-site/content/docs/cli-reference/ktx-setup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,26 @@ prompts.

| Flag | Description |
|------|-------------|
| `--llm-backend <backend>` | LLM backend: `anthropic`, `vertex`, `claude-code`, or `codex` |
| `--llm-backend <backend>` | LLM backend: `anthropic`, `vertex`, `gateway`, `openai-compatible`, `claude-code`, or `codex` |
| `--llm-backend claude-code` | Use the local Claude Code session for **ktx** LLM calls |
| `--llm-backend codex` | Use local Codex authentication for **ktx** LLM calls |
| `--anthropic-api-key-env <name>` | Environment variable containing the Anthropic API key |
| `--anthropic-api-key-file <path>` | File containing the Anthropic API key |
| `--vertex-project <project>` | Vertex AI project ID, `env:NAME`, or `file:/path` reference |
| `--vertex-location <location>` | Vertex AI location, `env:NAME`, or `file:/path` reference |
| `--llm-base-url <url>` | OpenAI-compatible base URL, `env:NAME`, or `file:/path` reference |
| `--llm-model <model>` | OpenAI-compatible model id applied to every ktx role |
| `--llm-api-key-env <name>` | Environment variable containing the OpenAI-compatible API key |
| `--llm-api-key-file <path>` | File containing the OpenAI-compatible API key |
| `--skip-llm` | Leave LLM setup incomplete |

Choose only one Anthropic credential source. Anthropic credential flags are only
valid with the Anthropic backend; Vertex flags are only valid with the Vertex
backend. The `claude-code` and `codex` backends use local authentication instead
backend; the `--llm-base-url`, `--llm-model`, and `--llm-api-key-*` flags are only
valid with `--llm-backend openai-compatible` (and `--llm-api-key-*` are mutually
exclusive). The `openai-compatible` backend needs `--llm-base-url` and
`--llm-model`; the API key flags are optional for keyless endpoints. The
`claude-code` and `codex` backends use local authentication instead
of Anthropic API key or Vertex flags. After you choose a backend, `ktx setup`
writes that backend's per-role model preset to `ktx.yaml`. To change a model,
edit the matching `llm.models.<role>` value in `ktx.yaml`.
Expand All @@ -90,10 +98,20 @@ calls.
| `--embedding-backend <backend>` | Embedding backend: `openai` or `sentence-transformers` |
| `--embedding-api-key-env <name>` | Environment variable containing the embedding provider API key |
| `--embedding-api-key-file <path>` | File containing the embedding provider API key |
| `--embedding-base-url <url>` | OpenAI-compatible embeddings base URL, `env:NAME`, or `file:/path` reference |
| `--embedding-model <model>` | Embedding model id (default `text-embedding-3-small`) |
| `--embedding-dimensions <n>` | Embedding vector dimensionality (default `1536`) |
| `--embedding-batch-size <n>` | Max texts per embedding request; set this when the endpoint caps batch size |
| `--skip-embeddings` | Leave embedding setup incomplete |

`sentence-transformers` uses the **ktx**-managed Python runtime. Choose only one
embedding credential source.
embedding credential source. The `openai` backend can target any
OpenAI-compatible embeddings endpoint: set `--embedding-base-url` and pick the
`--embedding-model` and `--embedding-dimensions` your endpoint expects (for
example `text-embedding-v4` at `1024` dimensions on Alibaba Bailian/DashScope).
Some endpoints reject large embedding batches (DashScope `text-embedding-v4`
caps a request at 10 inputs); set `--embedding-batch-size 10` so schema-scan and
ingest embedding requests stay within the limit.

### Runtime

Expand Down Expand Up @@ -314,7 +332,7 @@ Use `ktx status` for repeatable readiness checks after setup exits.
|-------|-------|----------|
| Setup resumes an unexpected project | `KTX_PROJECT_DIR` or nearest `ktx.yaml` points to another directory | Pass `--project-dir <path>` explicitly |
| Setup cannot run in CI | Required values are missing and `--no-input` disables prompts | Provide the relevant automation flags or create a fixture `ktx.yaml` |
| `Missing LLM backend: pass --llm-backend …` | `--no-input` setup ran without an LLM backend; `--target` does not select one | Pass `--llm-backend claude-code`, `codex`, `anthropic`, or `vertex` (with that backend's credential flags) |
| `Missing LLM backend: pass --llm-backend …` | `--no-input` setup ran without an LLM backend; `--target` does not select one | Pass `--llm-backend claude-code`, `codex`, `anthropic`, `vertex`, or `openai-compatible` (with that backend's credential flags; `openai-compatible` also needs `--llm-base-url` and `--llm-model`) |
| Provider health check fails | Provider key, model id, Vertex project, or Vertex location is invalid | Fix the `env:` or `file:` reference and rerun setup |
| Python runtime is missing | The selected setup needs runtime-backed agent, query-history, Looker, or local embedding features | Accept the interactive prompt, rerun with `--yes`, or run the suggested `ktx admin runtime install` command |
| `--enable-query-history` is rejected | The selected database driver does not support query history | Use Postgres, BigQuery, or Snowflake, or rerun without query-history flags |
Expand Down
4 changes: 3 additions & 1 deletion docs-site/content/docs/configuration/ktx-yaml.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -473,10 +473,12 @@ llm:

| Field | Type | Default | Purpose |
|-------|------|---------|---------|
| `provider.backend` | `none` \| `anthropic` \| `vertex` \| `gateway` \| `claude-code` \| `codex` | `none` | Selected backend. `none` disables LLM features. `claude-code` uses the local Claude Code session and needs no API key. `codex` uses local Codex authentication and needs no API key. |
| `provider.backend` | `none` \| `anthropic` \| `vertex` \| `gateway` \| `openai-compatible` \| `claude-code` \| `codex` | `none` | Selected backend. `none` disables LLM features. `claude-code` uses the local Claude Code session and needs no API key. `codex` uses local Codex authentication and needs no API key. |
| `provider.anthropic.api_key` | `string` | - | Anthropic API key. Required when `backend: anthropic`. Accepts `env:` or `file:` references. |
| `provider.anthropic.base_url` | `string` | - | Override the Anthropic API base URL (proxy, self-hosted gateway). |
| `provider.gateway.api_key` / `base_url` | `string` | - | Credentials for an AI Gateway provider. Required when `backend: gateway`. |
| `provider.openaiCompatible.base_url` | `string` | - | Base URL of an OpenAI-compatible chat completions endpoint. Required when `backend: openai-compatible`. Accepts `env:` or `file:` references. |
| `provider.openaiCompatible.api_key` | `string` | - | API key for the OpenAI-compatible endpoint. Optional for keyless endpoints. Accepts `env:` or `file:` references. |
| `provider.vertex.project` | `string` | - | Google Cloud project ID hosting the Vertex AI endpoint. |
| `provider.vertex.location` | `string` | - | Vertex AI region (for example `us-east5`). Required when the `vertex` block is present. |

Expand Down
42 changes: 42 additions & 0 deletions docs-site/content/docs/guides/llm-configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,52 @@ Set `llm.provider.backend` to one of these values:
configured `api_key` reference.
- `vertex`: Use Vertex AI Anthropic models through Google Cloud credentials.
- `gateway`: Use AI Gateway-compatible Anthropic model ids.
- `openai-compatible`: Use any OpenAI-compatible chat completions endpoint
(Azure OpenAI, Alibaba Bailian/DashScope, vLLM, LiteLLM, Ollama, and similar)
through a base URL and an optional API key.
- `claude-code`: Use your local Claude Code session through the Claude Agent
SDK. **ktx** strips provider-routing environment variables from child processes.
- `codex`: Use your local Codex authentication through the Codex SDK.

## OpenAI-compatible endpoint

Use `openai-compatible` to route ktx through any endpoint that speaks the OpenAI
chat completions protocol. Set `base_url`; `api_key` is optional for endpoints
that need no key (for example a local Ollama or vLLM server). Because
OpenAI-compatible endpoints expose arbitrary model ids, set one model and reuse
it for every role — override per role by hand if you need to.

```yaml
llm:
provider:
backend: openai-compatible
openaiCompatible:
api_key: env:DASHSCOPE_API_KEY
base_url: https://dashscope.aliyuncs.com/compatible-mode/v1
models:
default: qwen-max
triage: qwen-max
candidateExtraction: qwen-max
curator: qwen-max
reconcile: qwen-max
repair: qwen-max
```

Configure it non-interactively:

```bash
ktx setup \
--llm-backend openai-compatible \
--llm-base-url https://dashscope.aliyuncs.com/compatible-mode/v1 \
--llm-model qwen-max \
--llm-api-key-env DASHSCOPE_API_KEY \
--no-input
```

Drop `--llm-api-key-env` (and `--llm-api-key-file`) for endpoints that require no
key. Anthropic-style `llm.promptCaching` does not apply to OpenAI-compatible
models and is ignored for this backend.

## Claude Code

Use aliases or full Claude model IDs in `llm.models`:
Expand Down
108 changes: 104 additions & 4 deletions docs-site/content/docs/integrations/primary-sources.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Primary Sources
description: Connect ktx to PostgreSQL, Snowflake, BigQuery, MySQL, ClickHouse, SQL Server, SQLite, DuckDB, MongoDB, or Amazon Athena.
description: Connect ktx to PostgreSQL, Hologres, Snowflake, BigQuery, MySQL, ClickHouse, SQL Server, SQLite, DuckDB, MongoDB, or Amazon Athena.
---

**ktx** connects to your data warehouse or database to build schema context,
Expand All @@ -26,13 +26,13 @@ Agents should prefer environment or file references over literal secrets.

| Field | Required | Applies to | Description |
|-------|----------|------------|-------------|
| `driver` | Yes | all connections | Connector driver such as `postgres`, `snowflake`, `bigquery`, `mysql`, `clickhouse`, `sqlserver`, `sqlite`, `duckdb`, `mongodb`, or `athena` |
| `driver` | Yes | all connections | Connector driver such as `postgres`, `hologres`, `snowflake`, `bigquery`, `mysql`, `clickhouse`, `sqlserver`, `sqlite`, `duckdb`, `mongodb`, or `athena` |
| `url` | One of the connection methods | URL-style connectors | Database URL, `env:NAME`, or `file:/path/to/secret` |
| `host`, `port`, `database`, `username`, `password` | One of the connection methods | PostgreSQL, MySQL, SQL Server | Field-by-field connection values |
| `host`, `port`, `database`, `username`, `password` | One of the connection methods | PostgreSQL, Hologres, MySQL, SQL Server | Field-by-field connection values |
| `schema` or `schemas` | No | schema-aware warehouses | Single schema or list of schemas to scan |
| `databases` | No | ClickHouse, MongoDB, Athena | List of databases to scan |
| `sample_size`, `order_by` | No | MongoDB | Schema-inference sampling controls (recent documents, sort field) |
| `context.queryHistory` | No | PostgreSQL, Snowflake, BigQuery | Enables query-history ingestion when the warehouse supports it |
| `context.queryHistory` | No | PostgreSQL, Hologres, Snowflake, BigQuery | Enables query-history ingestion when the warehouse supports it |
| `path` | Yes for path-style SQLite/DuckDB | SQLite, DuckDB | Local SQLite or DuckDB database path or `env:NAME` reference |
| `max_bytes_billed` | No | BigQuery | Maximum bytes billed per query job |
| `query_timeout_ms` | No | all warehouses | Maximum execution time for a single read-only query, in milliseconds (default 30000). A query exceeding it is cancelled server-side (or, for SQLite, by terminating the off-process executor) and returns a `query exceeded Ns` error so the agent can revise. |
Expand Down Expand Up @@ -124,6 +124,106 @@ This helps **ktx** understand how your team actually queries the data.

---

## Hologres

Alibaba Cloud Hologres is PostgreSQL-wire-compatible, so **ktx** reuses the
PostgreSQL connector for connection, schema introspection, foreign key
detection, sampling, and column statistics. Query history comes from Hologres's
own `hologres.hg_query_log` system table rather than `pg_stat_statements`.

**ktx** requires Hologres 4.0 or newer — the first release to support ktx — and
verifies the version with `hg_version()` when testing a connection or scanning.

### Connection config

```yaml title="ktx.yaml"
connections:
my-hologres:
driver: hologres
url: env:HOLOGRES_URL
schemas:
- my_schema
```

Or with individual fields:

```yaml title="ktx.yaml"
connections:
my-hologres:
driver: hologres
host: hgpostcn-xxxx-cn-hangzhou.hologres.aliyuncs.com
port: 80
database: my_db
username: env:HOLOGRES_ACCESS_ID
password: env:HOLOGRES_ACCESS_KEY
schemas:
- my_schema
```

Hologres endpoints commonly use port `80`, which `ktx setup` offers as the
default. Authentication mirrors PostgreSQL (`password`, `url`, and `ssl`
references).

### System schemas

**ktx** automatically excludes the Hologres engine-internal schemas that never
hold user data — `hologres`, `hologres_streaming_mv`, `hologres_statistic`,
`hologres_sample`, `hologres_object_table`, `hg_recyclebin`, and `hg_internal` —
the same way it drops `pg_catalog`. Exclusion is by exact name, so user schemas
that share the `hologres_` prefix (such as a `hologres_dataset_*` sample dataset)
are still scanned.

### Features

| Feature | Supported | Notes |
|---------|-----------|-------|
| Tables & views | Yes | Via `pg_catalog` |
| Primary keys | Yes | Via `information_schema.table_constraints` |
| Foreign keys | Yes | When declared |
| Row count estimates | Yes | Via `pg_class.reltuples` |
| Column statistics | Yes | Via `pg_stats` (`n_distinct`; the `correlation` column is not used) |
| Query history | Yes | Via `hologres.hg_query_log` |
| Table sampling | Yes | `SELECT ... LIMIT n` |

### Query history

Hologres query history aggregates `hologres.hg_query_log` by its `digest`
column — a SQL fingerprint Hologres computes for `SELECT`, `INSERT`, `UPDATE`,
and `DELETE` — over a `query_start` time window, feeding the same unified staged
artifact shape as Postgres, Snowflake, and BigQuery.

```yaml
context:
queryHistory:
enabled: true
windowDays: 90
minExecutions: 5
filters:
dropTrivialProbes: true
```

**Requirements and caveats:**

- A superuser or a member of `pg_read_all_stats` sees every database's log; a
`db_admin` (via SPM/SLPM) sees the current database. Without `pg_read_all_stats`
ingest still runs but sees only the current user's queries, and **ktx** records
a warning noting the partial coverage.
- `hg_query_log` is a slow-query log: by default it records only queries slower
than `log_min_duration_statement` (100ms), so query history is biased toward
the expensive query patterns worth optimizing.
- Hologres retains slow query logs for roughly 30 days, so the effective window
is capped regardless of a larger `windowDays`.

### Dialect notes

- SQL compilation reuses the PostgreSQL dialect (`LIMIT/OFFSET`, `$1`/`$2`
positional parameters, `COUNT(*) FILTER (WHERE ...)`).
- All ingest and query-history reads run as single read-only statements; **ktx**
never wraps them in a transaction, honoring Hologres's restriction against
multi-statement DML and mixed DDL/DML transactions.

---

## Snowflake

Connects via the Snowflake SDK. Supports multi-schema scanning, RSA key authentication, and query-history configuration for Snowflake query history.
Expand Down
1 change: 1 addition & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"@ai-sdk/anthropic": "3.0.78",
"@ai-sdk/devtools": "0.0.18",
"@ai-sdk/google-vertex": "^4.0.134",
"@ai-sdk/openai-compatible": "^2.0.47",
"@anthropic-ai/claude-agent-sdk": "0.3.146",
"@aws-sdk/client-athena": "^3.1068.0",
"@aws-sdk/client-glue": "^3.1068.0",
Expand Down
Loading