diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index de9d056d..fbfe41d5 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -191,9 +191,8 @@ jobs:
coverage:
name: Coverage
runs-on: ubuntu-latest
- permissions:
- contents: read
- id-token: write
+ env:
+ CODECOV_TOKEN_CONFIGURED: ${{ secrets.CODECOV_TOKEN != '' }}
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@@ -232,25 +231,39 @@ jobs:
run: pnpm run test:coverage:ts
- name: Upload TypeScript coverage
+ if: env.CODECOV_TOKEN_CONFIGURED == 'true'
uses: codecov/codecov-action@75cd11691c0faa626561e295848008c8a7dddffe # v5.5.4
with:
- use_oidc: true
+ token: ${{ secrets.CODECOV_TOKEN }}
+ slug: Kaelio/ktx
files: ./packages/cli/coverage/lcov.info,./packages/connector-bigquery/coverage/lcov.info,./packages/connector-clickhouse/coverage/lcov.info,./packages/connector-mysql/coverage/lcov.info,./packages/connector-postgres/coverage/lcov.info,./packages/connector-snowflake/coverage/lcov.info,./packages/connector-sqlite/coverage/lcov.info,./packages/connector-sqlserver/coverage/lcov.info,./packages/context/coverage/lcov.info,./packages/llm/coverage/lcov.info
flags: typescript
name: typescript
- fail_ci_if_error: false
+ disable_search: true
+ fail_ci_if_error: true
+
+ - name: Warn when Codecov token is missing for TypeScript
+ if: env.CODECOV_TOKEN_CONFIGURED != 'true'
+ run: echo "::warning::CODECOV_TOKEN is not configured; skipping TypeScript coverage upload"
- name: Generate Python coverage
run: pnpm run test:coverage:py
- name: Upload Python coverage
+ if: env.CODECOV_TOKEN_CONFIGURED == 'true'
uses: codecov/codecov-action@75cd11691c0faa626561e295848008c8a7dddffe # v5.5.4
with:
- use_oidc: true
+ token: ${{ secrets.CODECOV_TOKEN }}
+ slug: Kaelio/ktx
files: ./coverage/python.xml
flags: python
name: python
- fail_ci_if_error: false
+ disable_search: true
+ fail_ci_if_error: true
+
+ - name: Warn when Codecov token is missing for Python
+ if: env.CODECOV_TOKEN_CONFIGURED != 'true'
+ run: echo "::warning::CODECOV_TOKEN is not configured; skipping Python coverage upload"
artifact-checks:
name: Artifact checks
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 95fdf9d4..d00a8fdd 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -7,10 +7,10 @@ on:
description: "Release kind: rc publishes to next, stable publishes to latest"
required: true
type: choice
- default: "rc"
+ default: "stable"
options:
- - rc
- stable
+ - rc
force_release:
description: "Force a patch release even if semantic-release finds no releasable commits"
required: false
@@ -20,7 +20,7 @@ on:
description: "Create the release and publish @kaelio/ktx to npm instead of running a dry-run"
required: true
type: boolean
- default: false
+ default: true
permissions:
contents: write
@@ -90,6 +90,26 @@ jobs:
env:
KTX_PRERELEASE_BRANCH: next
+ - name: Prepare npm package root for release verification
+ run: |
+ set -euo pipefail
+
+ mkdir -p dist/public-npm-package
+ node --input-type=module <<'EOF'
+ import { writeFile } from 'node:fs/promises';
+
+ const packageJson = {
+ name: '@kaelio/ktx',
+ version: '0.0.0',
+ private: false
+ };
+
+ await writeFile(
+ 'dist/public-npm-package/package.json',
+ `${JSON.stringify(packageJson, null, 2)}\n`
+ );
+ EOF
+
- name: Dry-run semantic release
if: ${{ !inputs.publish_live }}
run: |
diff --git a/.gitignore b/.gitignore
index d1098953..0ad46067 100644
--- a/.gitignore
+++ b/.gitignore
@@ -57,6 +57,7 @@ yarn-error.log*
.agents
.claude
.superpowers
+docs/superpowers
# Editors and OS files
.idea/
diff --git a/AGENTS.md b/AGENTS.md
index 15b9c8aa..a5447c9d 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -72,8 +72,9 @@ KTX is a pnpm + uv workspace.
- Python daemon: `python/ktx-daemon`
- Examples and fixtures: `examples/`
- Workspace scripts: `scripts/`
-- Local agent skills are private overlays. Do not commit `.agents/` or
- `.claude/` to this public repository.
+- Local agent skills and internal planning docs are private overlays. Do not
+ commit `.agents/`, `.claude/`, or `docs/superpowers/` to this public
+ repository.
Some package names still contain `ktx` during the split. Do not mass-rename
symbols, package names, paths, or docs to `ktx` unless the task asks for that
diff --git a/README.md b/README.md
index e058b828..d3d55d03 100644
--- a/README.md
+++ b/README.md
@@ -6,35 +6,68 @@
The context layer for analytics agents
-
by Kaelio
-
-
+
+
+
-
---
-KTX turns warehouse metadata, semantic definitions, and business knowledge into
-reviewable project files that agents can use to plan, query, and update
-analytics work.
+KTX is a self-improving context layer that teaches agents how to query your
+warehouse accurately - from approved metric definitions, joinable columns, and
+business knowledge it builds and maintains for you.
-Use KTX when you want agents to:
+Works with PostgreSQL, Snowflake, BigQuery, ClickHouse, MySQL, SQL Server, and
+SQLite. Integrates with dbt, MetricFlow, LookML, Looker, Metabase, and Notion.
-- Generate SQL from approved measures and joins
-- Repair semantic definitions through reviewable diffs
-- Explain metric provenance with warehouse evidence
-- Work alongside dbt, MetricFlow, LookML, Looker, Metabase, and Notion
+## Why KTX
-Supports PostgreSQL, Snowflake, BigQuery, ClickHouse, MySQL, SQL Server, and
-SQLite.
+General-purpose agents struggle on data tasks. They re-explore your warehouse
+on every question, invent their own metric logic, and return numbers that
+don't match approved definitions.
+
+Traditional semantic layers don't fix this. They demand constant manual
+upkeep and don't absorb the rest of your company's knowledge.
+
+KTX does both, automatically:
+
+- **Learns from company knowledge.** Ingests wiki content, organizes it,
+ removes duplicates, and flags contradictions for human review.
+- **Maps the data stack.** Samples tables, captures metadata and usage
+ patterns, detects joinable columns, and annotates sources so agents write
+ better queries.
+- **Builds a semantic layer.** Combines raw tables and high-level metrics
+ through a join graph that automatically resolves chasm and fan traps, so
+ agents fetch metrics declaratively instead of rewriting canonical SQL each
+ time.
+- **Serves agents at execution.** Exposes CLI and MCP tools with combined
+ full-text and semantic search across wiki and semantic-layer entities.
+
+Agents can run raw SQL when they need it, or compose semantic-layer queries
+when they want approved metrics with reliable joins.
+
+
+
+
+
+## Agent Setup
+
+Ask an agent such as Claude Code, Codex, Cursor, or OpenCode to install and
+configure KTX from your project directory:
+
+```text
+Follow instructions from
+https://docs.kaelio.com/ktx/docs/agents-setup.md
+to install and configure ktx
+```
## Quick Start
```bash
-pnpm add --global @kaelio/ktx
+npm install -g @kaelio/ktx
ktx setup
ktx status
```
@@ -49,8 +82,8 @@ KTX project: /home/user/analytics
Project ready: yes
LLM ready: yes (claude-sonnet-4-6)
Embeddings ready: yes (text-embedding-3-small)
-Databases configured: yes (postgres-warehouse)
-Context sources configured: yes (dbt-main)
+Databases configured: yes (warehouse)
+Context sources configured: yes (dbt_main)
KTX context built: yes
Agent integration ready: yes (codex:project)
```
@@ -65,7 +98,7 @@ Agent integration ready: yes (codex:project)
| `ktx connection test ` | Test one connection |
| `ktx ingest ` | Build context for one connection |
| `ktx ingest --all` | Build context for every configured connection |
-| `ktx ingest text ` | Capture free-form notes into memory |
+| `ktx ingest text --connection-id ` | Capture free-form notes into memory |
| `ktx sl list` | List semantic-layer sources |
| `ktx sl search "revenue"` | Search semantic-layer sources |
| `ktx sl validate --connection-id ` | Validate a semantic source |
@@ -93,14 +126,17 @@ Commit `ktx.yaml`, `semantic-layer/`, and `wiki/`. Keep `.ktx/` local.
## Agent Usage
-Setup can install KTX instructions for Claude Code, Codex, Cursor, OpenCode,
-and universal `.agents` clients:
+Install KTX integration for Claude Code, Claude Desktop, Codex, Cursor,
+OpenCode, and generic `.agents` clients:
```bash
-ktx setup --agents --target codex
+ktx setup --agents
```
-Agent-facing workflows typically start with:
+Pass `--target ` to install or repair one specific integration.
+
+A typical agent workflow combines wiki and semantic-layer search before
+querying:
```bash
ktx sl search "revenue" --json
@@ -108,31 +144,14 @@ ktx wiki search "refund policy" --json
ktx sl query --connection-id warehouse --measure orders.revenue --format sql
```
-During agent setup, choose **MCP tools + analytics skill** for client agents.
-Choose **MCP tools + analytics skill + admin CLI skill** only when a developer
-or operator agent also needs pinned `ktx` admin commands.
+During setup, choose **Ask data questions with KTX MCP** for client agents.
+Choose **Ask data questions + manage KTX with CLI commands** when an operator
+agent also needs pinned `ktx` admin commands.
-The analytics skill teaches client agents the MCP workflow: discover data,
-prefer semantic-layer measures, inspect entity details before raw SQL, and
-capture durable learnings. Admin CLI skills call `ktx` commands directly
-through a skill file installed in your agent's config:
-
-```bash
-ktx sl query --measure orders.revenue --dimension orders.status --format sql
-ktx wiki search "revenue definition"
-ktx sl validate orders
-```
-
-Supported client agents: Claude Code, Claude Desktop, Codex, Cursor, OpenCode,
-and clients that can use the printed MCP endpoint or `.agents` admin skills.
-Claude Desktop setup registers a local `ktx mcp stdio` server in Claude
-Desktop's config and generates `.ktx/agents/claude/ktx-plugin.zip` with the
-analytics skill.
-
-The release artifact manifest contains the public npm tarball and the bundled
-`kaelio-ktx` runtime wheel. The `python/ktx-sl` and `python/ktx-daemon`
-directories remain source packages for development, not public release
-artifacts.
+After setup, KTX prints **Required before using agents** with the exact
+commands to run. If the output includes `ktx mcp start --project-dir ...`, run
+it before opening your agent. Claude Desktop uses its own launcher and prints
+separate skill upload steps under `.ktx/agents/claude/`.
## Workspace packages
@@ -189,7 +208,7 @@ uv run pytest -q
## Docs
- [Quickstart](docs-site/content/docs/getting-started/quickstart.mdx)
-- [CLI Reference](docs-site/content/docs/cli-reference/index.mdx)
+- [CLI Reference](docs-site/content/docs/cli-reference/ktx.mdx)
- [Building Context](docs-site/content/docs/guides/building-context.mdx)
- [Contributing](docs-site/content/docs/community/contributing.mdx)
diff --git a/codecov.yml b/codecov.yml
new file mode 100644
index 00000000..0ff83e2f
--- /dev/null
+++ b/codecov.yml
@@ -0,0 +1,109 @@
+codecov:
+ branch: main
+ require_ci_to_pass: true
+ notify:
+ after_n_builds: 2
+
+coverage:
+ precision: 2
+ round: down
+ range: "70...100"
+ status:
+ project:
+ default:
+ target: auto
+ threshold: 1%
+ if_ci_failed: error
+ typescript:
+ target: auto
+ threshold: 1%
+ flags:
+ - typescript
+ if_ci_failed: error
+ python:
+ target: auto
+ threshold: 1%
+ flags:
+ - python
+ if_ci_failed: error
+ patch:
+ default:
+ target: 75%
+ threshold: 5%
+ if_ci_failed: error
+ informational: true
+
+comment:
+ layout: "header, diff, flags, components, files"
+ behavior: default
+ require_changes: false
+ require_base: false
+ require_head: true
+
+flags:
+ typescript:
+ paths:
+ - packages/
+ carryforward: false
+ python:
+ paths:
+ - python/
+ carryforward: false
+
+component_management:
+ individual_components:
+ - component_id: pkg_cli
+ name: CLI
+ paths:
+ - packages/cli/src/**
+ - component_id: pkg_context
+ name: Context engine
+ paths:
+ - packages/context/src/**
+ - component_id: pkg_llm
+ name: LLM
+ paths:
+ - packages/llm/src/**
+ - component_id: connector_bigquery
+ name: BigQuery connector
+ paths:
+ - packages/connector-bigquery/src/**
+ - component_id: connector_clickhouse
+ name: ClickHouse connector
+ paths:
+ - packages/connector-clickhouse/src/**
+ - component_id: connector_mysql
+ name: MySQL connector
+ paths:
+ - packages/connector-mysql/src/**
+ - component_id: connector_postgres
+ name: Postgres connector
+ paths:
+ - packages/connector-postgres/src/**
+ - component_id: connector_snowflake
+ name: Snowflake connector
+ paths:
+ - packages/connector-snowflake/src/**
+ - component_id: connector_sqlite
+ name: SQLite connector
+ paths:
+ - packages/connector-sqlite/src/**
+ - component_id: connector_sqlserver
+ name: SQL Server connector
+ paths:
+ - packages/connector-sqlserver/src/**
+ - component_id: py_semantic_layer
+ name: Python semantic layer
+ paths:
+ - python/ktx-sl/semantic_layer/**
+ - component_id: py_daemon
+ name: Python daemon
+ paths:
+ - python/ktx-daemon/src/ktx_daemon/**
+
+ignore:
+ - docs-site/**
+ - examples/**
+ - packages/*/coverage/**
+ - packages/*/dist/**
+ - python/ktx-sl/demos/**
diff --git a/docs-site/app/api/search/route.ts b/docs-site/app/api/search/route.ts
new file mode 100644
index 00000000..d86bfc5b
--- /dev/null
+++ b/docs-site/app/api/search/route.ts
@@ -0,0 +1,4 @@
+import { source } from "@/lib/source";
+import { createFromSource } from "fumadocs-core/search/server";
+
+export const { GET } = createFromSource(source);
diff --git a/docs-site/app/docs/[[...slug]]/page.tsx b/docs-site/app/docs/[[...slug]]/page.tsx
index dd5d944c..e0677c9e 100644
--- a/docs-site/app/docs/[[...slug]]/page.tsx
+++ b/docs-site/app/docs/[[...slug]]/page.tsx
@@ -51,10 +51,7 @@ export default async function Page(props: {
<>