mirror of
https://github.com/Kaelio/ktx.git
synced 2026-06-07 07:55:13 +02:00
Merge pull request #24 from Kaelio/luca-martial/agent-friendly-docs-site
feat(docs-site): add agent-readable docs routes and AI resources
This commit is contained in:
commit
01585e5d4a
40 changed files with 1774 additions and 18 deletions
|
|
@ -5,14 +5,26 @@ import {
|
|||
DocsTitle,
|
||||
DocsDescription,
|
||||
} from "fumadocs-ui/page";
|
||||
import { notFound } from "next/navigation";
|
||||
import { notFound, redirect } from "next/navigation";
|
||||
import defaultMdxComponents from "fumadocs-ui/mdx";
|
||||
import { CodeBlock } from "@/components/code-block";
|
||||
import { DocsPageActions } from "@/components/docs-page-actions";
|
||||
|
||||
const docsIndexPath = "/docs/getting-started/introduction";
|
||||
const docsIndexSlug = ["getting-started", "introduction"] as const;
|
||||
|
||||
function isDocsIndex(slug: string[] | undefined) {
|
||||
return slug === undefined || slug.length === 0 || slug.join("/") === "";
|
||||
}
|
||||
|
||||
export default async function Page(props: {
|
||||
params: Promise<{ slug?: string[] }>;
|
||||
}) {
|
||||
const params = await props.params;
|
||||
if (isDocsIndex(params.slug)) {
|
||||
redirect(docsIndexPath);
|
||||
}
|
||||
|
||||
const page = source.getPage(params.slug);
|
||||
if (!page) notFound();
|
||||
|
||||
|
|
@ -22,6 +34,10 @@ export default async function Page(props: {
|
|||
<DocsPage toc={page.data.toc}>
|
||||
<DocsTitle>{page.data.title}</DocsTitle>
|
||||
<DocsDescription>{page.data.description}</DocsDescription>
|
||||
<DocsPageActions
|
||||
markdownUrl={`${page.url}.md`}
|
||||
mdxSource={page.data.content}
|
||||
/>
|
||||
<DocsBody>
|
||||
<MDX components={{ ...defaultMdxComponents, pre: CodeBlock }} />
|
||||
</DocsBody>
|
||||
|
|
@ -30,14 +46,16 @@ export default async function Page(props: {
|
|||
}
|
||||
|
||||
export function generateStaticParams() {
|
||||
return source.generateParams();
|
||||
return [{ slug: [""] }, ...source.generateParams()];
|
||||
}
|
||||
|
||||
export async function generateMetadata(props: {
|
||||
params: Promise<{ slug?: string[] }>;
|
||||
}) {
|
||||
const params = await props.params;
|
||||
const page = source.getPage(params.slug);
|
||||
const page = source.getPage(
|
||||
isDocsIndex(params.slug) ? [...docsIndexSlug] : params.slug,
|
||||
);
|
||||
if (!page) notFound();
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -188,6 +188,24 @@ pre {
|
|||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
.ktx-code code {
|
||||
display: grid;
|
||||
min-width: max-content;
|
||||
padding: 0 !important;
|
||||
border: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
background: transparent !important;
|
||||
font-size: inherit !important;
|
||||
line-height: inherit !important;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.ktx-code .line {
|
||||
display: block;
|
||||
min-height: 1.7em;
|
||||
padding-inline: 0 !important;
|
||||
}
|
||||
|
||||
/* Neutralize the outer figure styling that our wrapper now owns */
|
||||
figure:has(> .ktx-code),
|
||||
figure[data-rehype-pretty-code-figure]:has(.ktx-code) {
|
||||
|
|
|
|||
11
docs-site/app/llms-full.txt/route.ts
Normal file
11
docs-site/app/llms-full.txt/route.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { buildLlmsFullTxt } from "@/lib/llm-docs";
|
||||
|
||||
export const dynamic = "force-static";
|
||||
|
||||
export async function GET() {
|
||||
return new Response(await buildLlmsFullTxt(), {
|
||||
headers: {
|
||||
"Content-Type": "text/plain; charset=utf-8",
|
||||
},
|
||||
});
|
||||
}
|
||||
33
docs-site/app/llms.mdx/docs/[[...slug]]/route.ts
Normal file
33
docs-site/app/llms.mdx/docs/[[...slug]]/route.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import {
|
||||
getLlmDocsPage,
|
||||
getLlmDocsPages,
|
||||
getPageMarkdown,
|
||||
} from "@/lib/llm-docs";
|
||||
|
||||
export const dynamic = "force-static";
|
||||
|
||||
export async function GET(
|
||||
_request: Request,
|
||||
props: { params: Promise<{ slug?: string[] }> },
|
||||
) {
|
||||
const params = await props.params;
|
||||
const page = getLlmDocsPage(params.slug);
|
||||
if (!page) {
|
||||
return new Response("Documentation page not found.\n", {
|
||||
status: 404,
|
||||
headers: {
|
||||
"Content-Type": "text/plain; charset=utf-8",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return new Response(await getPageMarkdown(page), {
|
||||
headers: {
|
||||
"Content-Type": "text/markdown; charset=utf-8",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function generateStaticParams() {
|
||||
return getLlmDocsPages().map((page) => ({ slug: page.slug }));
|
||||
}
|
||||
11
docs-site/app/llms.txt/route.ts
Normal file
11
docs-site/app/llms.txt/route.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { buildLlmsTxt } from "@/lib/llm-docs";
|
||||
|
||||
export const dynamic = "force-static";
|
||||
|
||||
export function GET() {
|
||||
return new Response(buildLlmsTxt(), {
|
||||
headers: {
|
||||
"Content-Type": "text/plain; charset=utf-8",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
@ -60,7 +60,7 @@ export function CodeBlock(props: Props) {
|
|||
// Mode A — Terminal
|
||||
if (isTerminal) {
|
||||
return (
|
||||
<div className="ktx-code ktx-code-terminal group">
|
||||
<div className="not-prose ktx-code ktx-code-terminal group">
|
||||
<div className="ktx-code-terminal-head">
|
||||
<span className="ktx-tl-dot" style={{ background: "#ff5f57" }} />
|
||||
<span className="ktx-tl-dot" style={{ background: "#febc2e" }} />
|
||||
|
|
@ -83,7 +83,7 @@ export function CodeBlock(props: Props) {
|
|||
// Mode B — VS Code tab (filename present)
|
||||
if (hasTitle) {
|
||||
return (
|
||||
<div className="ktx-code ktx-code-tab group">
|
||||
<div className="not-prose ktx-code ktx-code-tab group">
|
||||
<div className="ktx-code-tab-head">
|
||||
<span className="ktx-file-glyph" data-lang={language ?? ""} />
|
||||
<span className="ktx-code-tab-filename">{title}</span>
|
||||
|
|
@ -99,7 +99,7 @@ export function CodeBlock(props: Props) {
|
|||
|
||||
// Mode C — Minimal default
|
||||
return (
|
||||
<div className="ktx-code ktx-code-minimal group relative">
|
||||
<div className="not-prose ktx-code ktx-code-minimal group relative">
|
||||
{language && <span className="ktx-code-minimal-lang">{language}</span>}
|
||||
<CopyButton text={codeText} className="ktx-code-minimal-copy" />
|
||||
<pre {...rest} className="ktx-code-body ktx-code-body-minimal">
|
||||
|
|
|
|||
110
docs-site/components/docs-page-actions.tsx
Normal file
110
docs-site/components/docs-page-actions.tsx
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
|
||||
type CopyState = "idle" | "copied" | "error";
|
||||
|
||||
type Props = {
|
||||
markdownUrl: string;
|
||||
mdxSource: string;
|
||||
};
|
||||
|
||||
export function DocsPageActions({ markdownUrl, mdxSource }: Props) {
|
||||
return (
|
||||
<div className="not-prose mt-4 mb-8 flex flex-wrap items-center gap-2 border-b border-fd-border pb-6 text-xs">
|
||||
<CopyMarkdownButton markdownUrl={markdownUrl} />
|
||||
<a
|
||||
href={markdownUrl}
|
||||
className="inline-flex h-8 items-center rounded-md border border-fd-border bg-fd-background px-3 font-medium text-fd-muted-foreground transition-colors hover:border-fd-primary/40 hover:text-fd-foreground"
|
||||
>
|
||||
View MD
|
||||
</a>
|
||||
<CopyTextButton label="Copy MDX" text={mdxSource} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function CopyMarkdownButton({ markdownUrl }: { markdownUrl: string }) {
|
||||
const [state, setState] = useState<CopyState>("idle");
|
||||
|
||||
const onClick = async () => {
|
||||
try {
|
||||
const response = await fetch(markdownUrl, {
|
||||
headers: { Accept: "text/markdown" },
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch ${markdownUrl}`);
|
||||
}
|
||||
|
||||
await navigator.clipboard.writeText(await response.text());
|
||||
flash(setState, "copied");
|
||||
} catch {
|
||||
flash(setState, "error");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<ActionButton
|
||||
label={labelForState(state, "Copy MD")}
|
||||
onClick={onClick}
|
||||
state={state}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function CopyTextButton({ label, text }: { label: string; text: string }) {
|
||||
const [state, setState] = useState<CopyState>("idle");
|
||||
|
||||
const onClick = async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
flash(setState, "copied");
|
||||
} catch {
|
||||
flash(setState, "error");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<ActionButton
|
||||
label={labelForState(state, label)}
|
||||
onClick={onClick}
|
||||
state={state}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function ActionButton({
|
||||
label,
|
||||
onClick,
|
||||
state,
|
||||
}: {
|
||||
label: string;
|
||||
onClick: () => void;
|
||||
state: CopyState;
|
||||
}) {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClick}
|
||||
className="inline-flex h-8 items-center rounded-md border border-fd-border bg-fd-background px-3 font-medium text-fd-muted-foreground transition-colors hover:border-fd-primary/40 hover:text-fd-foreground data-[state=copied]:border-emerald-500/40 data-[state=copied]:text-emerald-600 data-[state=error]:border-red-500/40 data-[state=error]:text-red-600"
|
||||
data-state={state}
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
function labelForState(state: CopyState, label: string) {
|
||||
if (state === "copied") return "Copied";
|
||||
if (state === "error") return "Copy failed";
|
||||
return label;
|
||||
}
|
||||
|
||||
function flash(
|
||||
setState: (state: CopyState) => void,
|
||||
state: Exclude<CopyState, "idle">,
|
||||
) {
|
||||
setState(state);
|
||||
window.setTimeout(() => setState("idle"), 1500);
|
||||
}
|
||||
40
docs-site/content/docs/ai-resources/agent-instructions.mdx
Normal file
40
docs-site/content/docs/ai-resources/agent-instructions.mdx
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
title: Agent Instructions
|
||||
description: Suggested instructions for coding assistants that need to read and cite KTX docs.
|
||||
---
|
||||
|
||||
Use these instructions when a coding assistant needs to answer questions from the KTX documentation.
|
||||
|
||||
```text
|
||||
When answering KTX docs questions:
|
||||
|
||||
1. Start with https://docs.kaelio.com/ktx/llms.txt.
|
||||
2. Fetch the smallest relevant Markdown page from the index.
|
||||
3. Prefer /docs/<path>.md over rendered HTML.
|
||||
4. Use https://docs.kaelio.com/ktx/llms-full.txt only when the task needs broad docs context.
|
||||
5. Quote commands exactly from docs pages.
|
||||
6. If docs and local repository behavior disagree, say what differs and prefer local verified output for code changes.
|
||||
```
|
||||
|
||||
## What this is for
|
||||
|
||||
This page is for documentation consumption only:
|
||||
|
||||
- answering questions about KTX
|
||||
- finding the right docs page
|
||||
- citing setup or CLI guidance
|
||||
- helping an assistant avoid stale or invented commands
|
||||
|
||||
It does not describe local tool configuration.
|
||||
|
||||
## Minimal project prompt
|
||||
|
||||
```text
|
||||
You are helping with KTX. Read https://docs.kaelio.com/ktx/llms.txt first, then fetch only the Markdown pages needed for the task. Do not scrape the rendered docs site when a .md route exists.
|
||||
```
|
||||
|
||||
## Repository prompt
|
||||
|
||||
```text
|
||||
Before editing KTX docs, read /llms.txt and the affected .md docs pages. Keep AI Resources focused on docs consumption. After editing, verify /llms.txt, /llms-full.txt, and any changed .md routes.
|
||||
```
|
||||
50
docs-site/content/docs/ai-resources/agent-quickstart.mdx
Normal file
50
docs-site/content/docs/ai-resources/agent-quickstart.mdx
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
---
|
||||
title: Agent Quickstart
|
||||
description: A task-first route for coding agents that need to understand KTX docs.
|
||||
---
|
||||
|
||||
This page is for coding assistants reading or citing the KTX docs. It is intentionally limited to documentation lookup, docs navigation, and safe command discovery.
|
||||
|
||||
## First read
|
||||
|
||||
Agents should start with the smallest source that answers the task:
|
||||
|
||||
1. [`/llms.txt`](/llms.txt) - discover the docs and preferred entry points.
|
||||
2. The relevant per-page Markdown URL, for example `/docs/getting-started/quickstart.md`.
|
||||
3. [`/llms-full.txt`](/llms-full.txt) - use only when the task needs broad context across many pages.
|
||||
|
||||
## Task router
|
||||
|
||||
| User asks the agent to explain... | Read first | Then read |
|
||||
|------------------------------------|------------|-----------|
|
||||
| What KTX does | [Introduction](/docs/getting-started/introduction) | [The Context Layer](/docs/concepts/the-context-layer) |
|
||||
| How to start from a checkout | [Quickstart](/docs/getting-started/quickstart) | [ktx setup](/docs/cli-reference/ktx-setup) |
|
||||
| How to check project readiness | [ktx status](/docs/cli-reference/ktx-status) | [Quickstart](/docs/getting-started/quickstart) |
|
||||
| How context gets built | [Building Context](/docs/guides/building-context) | [ktx ingest](/docs/cli-reference/ktx-ingest) |
|
||||
| How semantic YAML works | [Writing Context](/docs/guides/writing-context) | [ktx sl](/docs/cli-reference/ktx-sl) |
|
||||
| How machine-readable CLI output is shaped | [ktx agent](/docs/cli-reference/ktx-agent) | [Markdown Access](/docs/ai-resources/markdown-access) |
|
||||
|
||||
## Operating workflow
|
||||
|
||||
Use this workflow when the user asks an assistant to answer a KTX docs question:
|
||||
|
||||
1. Read [`/llms.txt`](/llms.txt).
|
||||
2. Pick the smallest relevant `.md` page.
|
||||
3. Use [`/llms-full.txt`](/llms-full.txt) only if the answer needs multiple sections of the docs.
|
||||
4. Quote commands exactly from the docs page.
|
||||
5. If a command affects a local project, ask the user before assuming credentials or live services are available.
|
||||
|
||||
## Docs lookup from a shell
|
||||
|
||||
```bash
|
||||
curl https://docs.kaelio.com/ktx/llms.txt
|
||||
curl https://docs.kaelio.com/ktx/docs/getting-started/quickstart.md
|
||||
```
|
||||
|
||||
## Guardrails
|
||||
|
||||
- Do not invent CLI flags. Fetch the relevant CLI reference page.
|
||||
- Do not scrape rendered HTML when a `.md` route exists.
|
||||
- Do not assume docs lookup requires agent-client configuration.
|
||||
- Do not include credentials or secrets in prompts, URLs, or copied docs snippets.
|
||||
- When docs and local CLI behavior disagree, prefer the local CLI output and mention the mismatch.
|
||||
38
docs-site/content/docs/ai-resources/index.mdx
Normal file
38
docs-site/content/docs/ai-resources/index.mdx
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
---
|
||||
title: AI Resources
|
||||
description: Machine-readable docs and prompt recipes for coding assistants reading KTX documentation.
|
||||
---
|
||||
|
||||
Use this section when a coding assistant, IDE agent, or automation system needs to understand the KTX documentation.
|
||||
|
||||
> **Documentation index**
|
||||
>
|
||||
> Start with [`/llms.txt`](/llms.txt) to discover the available docs. Use [`/llms-full.txt`](/llms-full.txt) when the assistant needs the complete docs corpus in one Markdown response.
|
||||
|
||||
## Choose the right path
|
||||
|
||||
| Goal | Use this page |
|
||||
|------|---------------|
|
||||
| Tell a coding assistant how to approach KTX docs | [Agent Quickstart](/docs/ai-resources/agent-quickstart) |
|
||||
| Fetch docs as Markdown instead of HTML | [Markdown Access](/docs/ai-resources/markdown-access) |
|
||||
| Add lightweight instructions to an assistant prompt | [Agent Instructions](/docs/ai-resources/agent-instructions) |
|
||||
| Copy prompts for common agent workflows | [Prompt Recipes](/docs/ai-resources/prompt-recipes) |
|
||||
|
||||
## Available resources
|
||||
|
||||
| Resource | What it gives agents |
|
||||
|----------|----------------------|
|
||||
| [`/llms.txt`](/llms.txt) | Curated index of high-value KTX docs and Markdown endpoints |
|
||||
| [`/llms-full.txt`](/llms-full.txt) | Complete docs corpus in one plain-text Markdown response |
|
||||
| `/docs/<path>.md` | Per-page Markdown for any docs page |
|
||||
| Page-level actions | Copy Markdown, view Markdown, or copy MDX from rendered docs pages |
|
||||
| Prompt recipes | Reusable prompts for docs lookup, setup help, and docs editing |
|
||||
|
||||
## Agent usage notes
|
||||
|
||||
When an assistant is unsure where to begin, use this order:
|
||||
|
||||
1. Read [`/llms.txt`](/llms.txt).
|
||||
2. Fetch the specific Markdown page for the task.
|
||||
3. Use [Agent Quickstart](/docs/ai-resources/agent-quickstart) to choose the next command or page.
|
||||
4. Use page-level copy actions when the user wants the exact Markdown or MDX source.
|
||||
75
docs-site/content/docs/ai-resources/markdown-access.mdx
Normal file
75
docs-site/content/docs/ai-resources/markdown-access.mdx
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
---
|
||||
title: Markdown Access
|
||||
description: Fetch KTX docs as llms.txt, llms-full.txt, or per-page Markdown.
|
||||
---
|
||||
|
||||
KTX docs are available as plain Markdown so assistants do not need to parse the rendered HTML site.
|
||||
|
||||
## Index
|
||||
|
||||
Fetch the curated index:
|
||||
|
||||
```text
|
||||
https://docs.kaelio.com/ktx/llms.txt
|
||||
```
|
||||
|
||||
Use this file to discover high-value pages, task-specific entry points, and Markdown URLs.
|
||||
|
||||
## Full corpus
|
||||
|
||||
Fetch the complete docs corpus:
|
||||
|
||||
```text
|
||||
https://docs.kaelio.com/ktx/llms-full.txt
|
||||
```
|
||||
|
||||
Use this when an assistant needs broad context across setup, concepts, CLI reference, integrations, and troubleshooting. Prefer the smaller per-page Markdown route for narrow tasks.
|
||||
|
||||
## Per-page Markdown
|
||||
|
||||
Every docs page has a Markdown route:
|
||||
|
||||
```text
|
||||
https://docs.kaelio.com/ktx/docs/getting-started/quickstart.md
|
||||
https://docs.kaelio.com/ktx/docs/cli-reference/ktx-agent.md
|
||||
https://docs.kaelio.com/ktx/docs/guides/building-context.md
|
||||
```
|
||||
|
||||
Requests that ask for Markdown can also use the normal docs URL with `Accept: text/markdown`:
|
||||
|
||||
```bash
|
||||
curl -H "Accept: text/markdown" https://docs.kaelio.com/ktx/docs/getting-started/quickstart
|
||||
```
|
||||
|
||||
## Recommended retrieval order
|
||||
|
||||
1. Fetch `/llms.txt`.
|
||||
2. Select one or two relevant page Markdown URLs.
|
||||
3. Fetch `/llms-full.txt` only when page-level docs are not enough.
|
||||
|
||||
## Output contract
|
||||
|
||||
Markdown responses are designed for agent consumption:
|
||||
|
||||
- Frontmatter is removed.
|
||||
- Each page includes a title, description, canonical URL, and Markdown URL.
|
||||
- Code blocks stay as code blocks.
|
||||
- Tables stay as Markdown tables.
|
||||
- Missing docs pages return a plain-text `404` instead of silently falling back to HTML.
|
||||
|
||||
## Page actions
|
||||
|
||||
Rendered docs pages include page-level actions near the title:
|
||||
|
||||
- **Copy MD** copies the generated Markdown for the current page.
|
||||
- **View MD** opens the generated Markdown route.
|
||||
- **Copy MDX** copies the source MDX for the current page.
|
||||
|
||||
## Common mistakes
|
||||
|
||||
| Mistake | Better path |
|
||||
|---------|-------------|
|
||||
| Scraping the HTML page for a docs answer | Fetch the `.md` route instead |
|
||||
| Loading `/llms-full.txt` for a single CLI flag lookup | Fetch the relevant CLI reference page |
|
||||
| Treating `/llms.txt` as complete documentation | Use it as an index, then fetch linked pages |
|
||||
| Copying rendered text by hand | Use **Copy MD** or **Copy MDX** from the page actions |
|
||||
11
docs-site/content/docs/ai-resources/meta.json
Normal file
11
docs-site/content/docs/ai-resources/meta.json
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"title": "AI Resources",
|
||||
"defaultOpen": true,
|
||||
"pages": [
|
||||
"index",
|
||||
"agent-quickstart",
|
||||
"markdown-access",
|
||||
"agent-instructions",
|
||||
"prompt-recipes"
|
||||
]
|
||||
}
|
||||
54
docs-site/content/docs/ai-resources/prompt-recipes.mdx
Normal file
54
docs-site/content/docs/ai-resources/prompt-recipes.mdx
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
---
|
||||
title: Prompt Recipes
|
||||
description: Copyable prompts for common KTX agent workflows.
|
||||
---
|
||||
|
||||
Use these prompts when asking a coding assistant to work with KTX. Replace project names, connection ids, and business terms with your own values.
|
||||
|
||||
## Learn the docs
|
||||
|
||||
```text
|
||||
Read https://docs.kaelio.com/ktx/llms.txt first. Then fetch only the KTX Markdown pages needed for this task. Do not scrape rendered HTML unless no Markdown route exists.
|
||||
```
|
||||
|
||||
## Set up a project
|
||||
|
||||
```text
|
||||
Set up KTX in this repository. Start by reading /docs/ai-resources/agent-quickstart.md and /docs/getting-started/quickstart.md. Use pnpm, not npm. After setup, run ktx status and summarize which steps are complete, which files changed, and what still needs credentials or user input.
|
||||
```
|
||||
|
||||
## Find a command
|
||||
|
||||
```text
|
||||
Find the correct KTX command for this task: <task>. Start with /llms.txt, then fetch the smallest relevant CLI reference .md page. Quote the exact command and flags from the docs.
|
||||
```
|
||||
|
||||
## Explain setup
|
||||
|
||||
```text
|
||||
Explain how to set up KTX for this repo. Read /docs/getting-started/quickstart.md and the relevant CLI reference pages. Summarize prerequisites, commands, generated files, and any credentials the user must provide manually.
|
||||
```
|
||||
|
||||
## Compare concepts
|
||||
|
||||
```text
|
||||
Explain the difference between these KTX concepts: <concepts>. Start from /llms.txt, fetch the relevant concept and guide pages as Markdown, and answer with links to the source pages.
|
||||
```
|
||||
|
||||
## Review semantic changes
|
||||
|
||||
```text
|
||||
Review the KTX semantic-layer and knowledge changes in this branch. Check that measures have clear definitions, joins use valid keys, hidden/internal columns are not exposed to agents, and validation passes. List concrete file and line issues first.
|
||||
```
|
||||
|
||||
## Copy exact docs source
|
||||
|
||||
```text
|
||||
Open the relevant KTX docs page and use the page action to copy the generated Markdown or source MDX. Preserve code fences and tables exactly.
|
||||
```
|
||||
|
||||
## Update docs
|
||||
|
||||
```text
|
||||
Update the KTX docs for agent readability. Keep AI Resources focused on docs consumption. After editing, verify /llms.txt, /llms-full.txt, and the affected .md routes.
|
||||
```
|
||||
|
|
@ -5,6 +5,17 @@ description: How KTX's relationship detection performs on real-world schemas.
|
|||
|
||||
KTX infers foreign key relationships between tables even when the database declares no primary keys or foreign key constraints. This is critical for analytics warehouses, where constraints are rarely enforced. This page documents the methodology, scoring pipeline, and a reproducible benchmark you can run yourself.
|
||||
|
||||
## Agent usage notes
|
||||
|
||||
Use this page when an agent needs to explain, tune, or verify relationship detection.
|
||||
|
||||
| Agent task | Relevant section | Command |
|
||||
|------------|------------------|---------|
|
||||
| Explain why KTX inferred a join | Detection pipeline | `ktx dev scan relationships <run-id> --status all` |
|
||||
| Decide whether to accept or reject a candidate | Scoring and threshold configuration | `ktx dev scan relationships <run-id> --accept <candidate-id>` |
|
||||
| Tune thresholds from reviewed decisions | Broader benchmark suite and calibration | `ktx dev scan relationship-thresholds --connection <connection-id>` |
|
||||
| Reproduce the bundled benchmark | Reproducing the benchmark | `pnpm run relationships:verify-orbit` |
|
||||
|
||||
## What this measures
|
||||
|
||||
Most analytics warehouses — Snowflake, BigQuery, Redshift — don't enforce referential integrity constraints. Tables like `fct_product_events` reference `dim_accounts` by convention (`account_id` → `id`), but nothing in the schema says so.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ Hidden commands that provide machine-readable JSON output for coding agents. The
|
|||
|
||||
All `ktx agent` subcommands require `--json` and produce structured JSON output on stdout.
|
||||
|
||||
## Usage
|
||||
## Command signature
|
||||
|
||||
```bash
|
||||
ktx agent <subcommand> --json [options]
|
||||
|
|
@ -124,3 +124,25 @@ ktx agent sql execute --json \
|
|||
--sql-file /tmp/query.sql \
|
||||
--max-rows 500
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
Every `ktx agent` command writes JSON to stdout and diagnostic text to stderr. Agents should parse stdout as JSON and treat a non-zero exit code as a failed tool call.
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"data": {
|
||||
"type": "agent-response"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Common errors
|
||||
|
||||
| Error | Cause | Recovery |
|
||||
|-------|-------|----------|
|
||||
| Missing JSON output | `--json` was omitted | Re-run the same subcommand with `--json` |
|
||||
| Unknown connection id | The requested connection is not configured in `ktx.yaml` | Call `ktx agent context --json` or `ktx connection list` to discover valid ids |
|
||||
| Query file cannot be read | `--query-file` points to a missing or invalid JSON file | Write the query payload to a real file and pass its absolute path |
|
||||
| SQL execution rejected | SQL is not read-only or `--max-rows` is missing | Use semantic-layer queries first; for direct SQL, pass read-only SQL and an explicit row limit |
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ description: "Add, list, test, and map data sources."
|
|||
|
||||
Manage database and source connections in your KTX project. Connections define how KTX reaches your data warehouse, BI tools, and context sources.
|
||||
|
||||
## Usage
|
||||
## Command signature
|
||||
|
||||
```bash
|
||||
ktx connection <subcommand> [options]
|
||||
|
|
@ -147,3 +147,28 @@ ktx connection mapping refresh metabase-prod --auto-accept
|
|||
# Pick Notion root pages interactively
|
||||
ktx connection notion pick my-notion
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
Interactive commands render prompts and status text. Commands with `--json` return machine-readable JSON suitable for scripts and agents.
|
||||
|
||||
```json
|
||||
{
|
||||
"connections": [
|
||||
{
|
||||
"id": "my-warehouse",
|
||||
"driver": "postgres",
|
||||
"readonly": false
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Common errors
|
||||
|
||||
| Error | Cause | Recovery |
|
||||
|-------|-------|----------|
|
||||
| Connection test fails | Credentials, network access, database, warehouse, or schema is invalid | Verify the same URL with the database's native client, then rerun `ktx connection add ... --force` |
|
||||
| Literal credentials rejected | KTX avoids writing raw secrets to `ktx.yaml` by default | Use `env:NAME` or `file:/path/to/secret`; use `--allow-literal-credentials` only for local throwaway projects |
|
||||
| Mapping validation fails | BI database mappings do not point at valid warehouse connections | Run `ktx connection mapping refresh <connectionId> --auto-accept`, then set invalid mappings explicitly |
|
||||
| Notion pick cannot run non-interactively | `--no-input` was used without root page or database ids | Pass `--root-page-id`, `--root-database-id`, or `--root-data-source-id` with `--no-input` |
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ description: "Low-level diagnostics, scans, adapter commands, and mapping tools.
|
|||
|
||||
Hidden commands for low-level project management, diagnostics, direct adapter control, and shell completion. Most users interact with these through higher-level commands like [`ktx ingest`](/docs/cli-reference/ktx-ingest) and [`ktx setup`](/docs/cli-reference/ktx-setup), but `ktx dev` provides direct access when you need fine-grained control.
|
||||
|
||||
## Usage
|
||||
## Command signature
|
||||
|
||||
```bash
|
||||
ktx dev <subcommand> [options]
|
||||
|
|
@ -145,3 +145,22 @@ ktx dev completion zsh
|
|||
# Install zsh completions
|
||||
ktx dev completion zsh --install
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
`ktx dev` commands are diagnostic and may print plain text, JSON, or visual reports depending on the selected flags.
|
||||
|
||||
| Mode | How to request it | Use case |
|
||||
|------|-------------------|----------|
|
||||
| Plain text | `--plain` or default diagnostic output | Human-readable terminal inspection |
|
||||
| JSON | `--json` | Agent parsing and automation |
|
||||
| Visual report | `--viz` | Interactive memory-flow and ingest debugging |
|
||||
|
||||
## Common errors
|
||||
|
||||
| Error | Cause | Recovery |
|
||||
|-------|-------|----------|
|
||||
| Doctor reports missing runtime pieces | Packages, Python environment, or linked CLI are not ready | Run `pnpm install`, `pnpm run setup:dev`, and `uv sync --all-groups` |
|
||||
| Ingest run cannot find adapter | `--adapter` does not match a supported source adapter | Use configured source names from `ktx.yaml` or run higher-level `ktx ingest` |
|
||||
| Replay/report file cannot be read | The report path is wrong or the run id is not stored locally | Run `ktx dev ingest status --json` to discover stored run ids and report files |
|
||||
| Visual output fails in CI | TUI rendering requires an interactive terminal | Use `--plain --no-input` or `--json --no-input` |
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ description: "Build and refresh context from configured sources."
|
|||
|
||||
Ingest context from your configured sources — dbt, Looker, Metabase, MetricFlow, LookML, or Notion. The ingest process extracts metadata from your tools, then uses an LLM agent to reconcile it with existing context, writing semantic sources and knowledge pages to your project.
|
||||
|
||||
## Usage
|
||||
## Command signature
|
||||
|
||||
```bash
|
||||
ktx ingest [connectionId] [options]
|
||||
|
|
@ -68,3 +68,28 @@ ktx ingest status --json
|
|||
## Low-level ingest commands
|
||||
|
||||
For adapter-level control, use `ktx dev ingest`. See [`ktx dev`](/docs/cli-reference/ktx-dev) for the full low-level ingest surface including `run`, `status`, `watch`, and `replay` with output mode options (`--plain`, `--json`, `--viz`).
|
||||
|
||||
## Output
|
||||
|
||||
Ingest run commands print progress and create a stored ingest report. `ktx ingest status --json` returns the run state, adapter, connection, and summary information.
|
||||
|
||||
```json
|
||||
{
|
||||
"runId": "ingest-local-abc123",
|
||||
"status": "completed",
|
||||
"connectionId": "dbt-main",
|
||||
"summary": {
|
||||
"semanticSourcesChanged": 4,
|
||||
"knowledgePagesChanged": 2
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Common errors
|
||||
|
||||
| Error | Cause | Recovery |
|
||||
|-------|-------|----------|
|
||||
| No eligible sources | `ktx.yaml` has no configured context source for ingest | Add a source with `ktx setup` or `ktx connection add`, then rerun ingest |
|
||||
| Ingest needs credentials | The source adapter requires API or git access | Configure the referenced environment variable or secret file |
|
||||
| Latest run not found | No ingest run has been started in this project | Run `ktx ingest <connectionId>` or `ktx ingest --all` first |
|
||||
| Report watch fails in a non-interactive shell | Visual report needs a terminal | Use `ktx ingest status --json` for agent and CI workflows |
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ Discover your database schema — tables, columns, types, constraints, and relat
|
|||
|
||||
Scan commands live under `ktx dev scan`. See also the [Building Context](/docs/guides/building-context) guide for a walkthrough.
|
||||
|
||||
## Usage
|
||||
## Command signature
|
||||
|
||||
```bash
|
||||
ktx dev scan <connectionId> [options]
|
||||
|
|
@ -143,3 +143,27 @@ ktx dev scan relationship-calibration --accept-threshold 0.9 --review-threshold
|
|||
# Get threshold advice based on review decisions
|
||||
ktx dev scan relationship-thresholds
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
Scan commands write scan artifacts under the KTX project directory and print status or report summaries. Use `--json` on report and relationship commands when an agent needs structured output.
|
||||
|
||||
```json
|
||||
{
|
||||
"runId": "scan-local-abc123",
|
||||
"status": "completed",
|
||||
"mode": "structural",
|
||||
"changes": {
|
||||
"tablesAdded": 42
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Common errors
|
||||
|
||||
| Error | Cause | Recovery |
|
||||
|-------|-------|----------|
|
||||
| Scan cannot connect | Connection credentials or network access are invalid | Run `ktx connection test <connectionId>` and update the connection before scanning |
|
||||
| Enriched scan cannot describe columns | LLM credentials are missing or invalid | Complete LLM setup with `ktx setup` before enriched scans |
|
||||
| Relationship apply writes nothing | No accepted candidates match the provided run id or candidate ids | Inspect `ktx dev scan relationships <runId> --status accepted` first |
|
||||
| Calibration is not ready | Too few reviewed relationship labels exist | Review and accept/reject more candidates, then rerun calibration |
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ description: "Run the MCP stdio server."
|
|||
|
||||
Start a Model Context Protocol (MCP) server that exposes your KTX project's context to coding agents. The server runs over stdio and provides tools for querying semantic sources, searching knowledge, managing connections, and running ingests.
|
||||
|
||||
## Usage
|
||||
## Command signature
|
||||
|
||||
```bash
|
||||
ktx serve --mcp stdio [options]
|
||||
|
|
@ -49,3 +49,26 @@ ktx serve --mcp stdio --project-dir /path/to/my-project
|
|||
## Agent integration
|
||||
|
||||
The MCP server is typically configured through `ktx setup --agents` rather than started manually. See the [Serving Agents](/docs/guides/serving-agents) guide and [Agent Clients](/docs/integrations/agent-clients) integration page for per-tool configuration.
|
||||
|
||||
## Output
|
||||
|
||||
`ktx serve --mcp stdio` communicates through MCP messages on stdio. It is meant to be launched by an agent client, not read directly by a human terminal session.
|
||||
|
||||
```json
|
||||
{
|
||||
"command": "ktx",
|
||||
"args": ["serve", "--mcp", "stdio", "--semantic-compute", "--execute-queries"],
|
||||
"env": {
|
||||
"KTX_PROJECT_DIR": "/home/user/analytics"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Common errors
|
||||
|
||||
| Error | Cause | Recovery |
|
||||
|-------|-------|----------|
|
||||
| Agent cannot start server | The agent config cannot find the `ktx` binary | Run `pnpm run link:dev` or use an absolute command path in the agent config |
|
||||
| Semantic tools are unavailable | Server was started without `--semantic-compute` | Add `--semantic-compute` or `--semantic-compute-url` to the server args |
|
||||
| Query execution is denied | Server was started without `--execute-queries` | Add `--execute-queries` only for trusted projects where read-only execution is intended |
|
||||
| Context resolves to wrong project | `KTX_PROJECT_DIR` is missing or points elsewhere | Set `KTX_PROJECT_DIR` to the project containing the intended `ktx.yaml` |
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ description: "Set up or resume a local KTX project."
|
|||
|
||||
Interactive wizard that walks you through configuring LLM credentials, embeddings, database connections, context sources, and agent integrations. When run without flags in a directory that has no `ktx.yaml`, it launches the full guided flow. When run in an existing project, it resumes from the first incomplete step.
|
||||
|
||||
## Usage
|
||||
## Command signature
|
||||
|
||||
```bash
|
||||
ktx setup [options]
|
||||
|
|
@ -173,3 +173,27 @@ ktx setup context watch
|
|||
# Run the packaged demo
|
||||
ktx setup demo
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
Interactive setup renders prompts and progress messages. `ktx setup status` is the best command for agents because it summarizes readiness in one response.
|
||||
|
||||
```text
|
||||
KTX project: /home/user/analytics
|
||||
Project ready: yes
|
||||
LLM ready: yes (claude-sonnet-4-6)
|
||||
Embeddings ready: yes (text-embedding-3-small)
|
||||
Primary sources configured: yes (postgres-warehouse)
|
||||
Context sources configured: yes (dbt-main)
|
||||
KTX context built: yes
|
||||
Agent integration ready: yes (codex:project)
|
||||
```
|
||||
|
||||
## Common errors
|
||||
|
||||
| Error | Cause | Recovery |
|
||||
|-------|-------|----------|
|
||||
| Setup resumes an unexpected project | `KTX_PROJECT_DIR` or nearest `ktx.yaml` points to another directory | Pass `--project-dir <path>` explicitly |
|
||||
| Health check for model fails | Provider key or model id is invalid | Set the correct environment variable or secret file and rerun setup |
|
||||
| Setup cannot run in CI | Interactive prompts need a TTY | Use `--yes --no-input` with explicit flags for required values |
|
||||
| Agent integration missing | Setup skipped the agents step | Run `ktx setup --agents --target <target> --agent-install-mode both` |
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ description: "List, read, validate, query, or write semantic-layer sources."
|
|||
|
||||
Interact with your project's semantic layer. Semantic sources are YAML definitions that describe your tables, columns, measures, joins, and grain — the vocabulary agents use to generate correct SQL.
|
||||
|
||||
## Usage
|
||||
## Command signature
|
||||
|
||||
```bash
|
||||
ktx sl <subcommand> [options]
|
||||
|
|
@ -120,3 +120,28 @@ ktx sl query \
|
|||
--execute \
|
||||
--max-rows 1000
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
Semantic-layer commands return human-readable output by default. Use `--json` or `--format json` when an agent needs structured output; use `--format sql` to inspect generated SQL before execution.
|
||||
|
||||
```json
|
||||
{
|
||||
"sql": "SELECT orders.status, SUM(orders.total_amount) AS total_revenue FROM public.orders GROUP BY orders.status",
|
||||
"rows": [
|
||||
{
|
||||
"orders.status": "completed",
|
||||
"total_revenue": 125000
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Common errors
|
||||
|
||||
| Error | Cause | Recovery |
|
||||
|-------|-------|----------|
|
||||
| Source not found | Source name or connection id is wrong | Run `ktx sl list --json` and retry with an exact source name and connection id |
|
||||
| Validation fails | YAML references missing columns, invalid joins, or invalid SQL expressions | Fix the source YAML and rerun `ktx sl validate` |
|
||||
| Query compile fails | Measure, dimension, filter, or segment name is invalid | Read the source with `ktx sl read`, then retry using declared fields |
|
||||
| Execution returns too many rows | `--max-rows` is missing or too high | Add `--max-rows` with a bounded value before executing |
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ description: "Show current project status."
|
|||
|
||||
Print the current setup status of your KTX project — which steps are complete, which need attention, and whether the project is ready for agents.
|
||||
|
||||
## Usage
|
||||
## Command signature
|
||||
|
||||
```bash
|
||||
ktx status [options]
|
||||
|
|
@ -26,3 +26,26 @@ ktx status
|
|||
# Get status as JSON (useful for scripting)
|
||||
ktx status --json
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
`ktx status` prints readiness for each setup area. Agents should use `ktx status --json` when they need to branch on readiness state.
|
||||
|
||||
```json
|
||||
{
|
||||
"projectReady": true,
|
||||
"llmReady": true,
|
||||
"embeddingsReady": true,
|
||||
"primarySourcesConfigured": true,
|
||||
"contextBuilt": true,
|
||||
"agentIntegrationReady": true
|
||||
}
|
||||
```
|
||||
|
||||
## Common errors
|
||||
|
||||
| Error | Cause | Recovery |
|
||||
|-------|-------|----------|
|
||||
| No KTX project found | Current directory has no `ktx.yaml` and `KTX_PROJECT_DIR` is unset | Run from a KTX project or set `KTX_PROJECT_DIR` |
|
||||
| Project ready is false | One or more setup steps are incomplete | Run `ktx setup` to resume setup |
|
||||
| Agent integration ready is false | No agent target has been installed | Run `ktx setup --agents --target <target>` |
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ description: "List, read, search, or write knowledge pages."
|
|||
|
||||
Manage knowledge pages in your KTX project. Knowledge pages are Markdown documents that capture business definitions, rules, and gotchas. Agents search them for context when answering questions about your data.
|
||||
|
||||
## Usage
|
||||
## Command signature
|
||||
|
||||
```bash
|
||||
ktx wiki <subcommand> [options]
|
||||
|
|
@ -90,3 +90,28 @@ ktx wiki write data-freshness \
|
|||
--content "The orders table refreshes every 15 minutes..." \
|
||||
--ref "https://wiki.example.com/data-pipelines"
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
Wiki commands print local knowledge pages and search results. Agents should search first, then read the most relevant page by key.
|
||||
|
||||
```json
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"key": "revenue-definitions",
|
||||
"summary": "Canonical revenue metric definitions",
|
||||
"score": 0.92
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Common errors
|
||||
|
||||
| Error | Cause | Recovery |
|
||||
|-------|-------|----------|
|
||||
| Search returns no results | The query terms do not match summaries, tags, or content | Retry with business synonyms, then create a page if the knowledge is missing |
|
||||
| Read fails for a key | The page key is wrong or scoped to a different user | Run `ktx wiki list` or search again to get the exact key |
|
||||
| Write fails due to missing fields | `--summary` or `--content` was omitted | Pass both fields, and keep the summary short enough for search results |
|
||||
| Agent writes duplicate pages | It did not search existing pages first | Always run `ktx wiki search` before `ktx wiki write` |
|
||||
|
|
|
|||
|
|
@ -220,3 +220,17 @@ Before submitting a pull request:
|
|||
5. **Don't commit artifacts** — `node_modules/`, `.venv/`, `dist/`, coverage output, and local databases should not be committed.
|
||||
|
||||
For larger features or architectural changes, open an issue first to discuss the approach.
|
||||
|
||||
## Agent usage notes
|
||||
|
||||
Use this page when an agent is modifying the KTX repository itself rather than using KTX in an analytics project.
|
||||
|
||||
| Agent task | Command or section |
|
||||
|------------|--------------------|
|
||||
| Prepare the workspace | `pnpm install`, `pnpm run setup:dev`, `uv sync --all-groups` |
|
||||
| Verify TypeScript changes | `pnpm run type-check`, `pnpm run test`, or package-filtered equivalents |
|
||||
| Verify Python changes | `uv run pytest -q` and `uv run pre-commit run --files <files>` |
|
||||
| Add a connector | Adding a connector |
|
||||
| Check style expectations | Code conventions |
|
||||
|
||||
Common recovery path: if a check fails because generated files or local runtimes are missing, run the setup commands first. If a check fails because of a real type, lint, or test error, fix the source file and rerun the smallest failing check before broadening verification.
|
||||
|
|
|
|||
|
|
@ -80,3 +80,14 @@ This matters for three reasons.
|
|||
**Reproducibility.** Because ingestion sessions are recorded as structured transcripts (tool calls and responses, not just logs), they can be replayed for testing and validation. If you change your ingestion configuration or upgrade the LLM, you can replay previous sessions to see how the output would differ. This gives you a safety net for changes that affect how context is generated.
|
||||
|
||||
The transcript is stored with local ingest run state and can be reviewed or replayed when you need to audit a decision. Commit the resulting YAML and Markdown changes; commit reports or transcripts only when they are part of your team's review workflow.
|
||||
|
||||
## Agent usage notes
|
||||
|
||||
Use this page when an agent needs to explain review workflows, ingestion diffs, replayability, or why KTX writes YAML and Markdown instead of hiding context in a hosted service.
|
||||
|
||||
| Agent task | Relevant section | Next page |
|
||||
|------------|------------------|-----------|
|
||||
| Explain how generated context should be reviewed | The git workflow | [Building Context](/docs/guides/building-context) |
|
||||
| Diagnose why ingestion changed a semantic source | Auto-ingestion and Deterministic replay | [ktx ingest](/docs/cli-reference/ktx-ingest) |
|
||||
| Explain how context improves over time | Feedback loops | [Link Detection](/docs/benchmarks/link-detection) |
|
||||
| Tell a user what to commit | The git workflow | [Writing Context](/docs/guides/writing-context) |
|
||||
|
|
|
|||
|
|
@ -145,3 +145,14 @@ my-project/
|
|||
Semantic sources and knowledge pages are committed to git. The SQLite database holds ephemeral state — scan results, embedding indexes, session logs — and is git-ignored. If you delete it, KTX rebuilds it on the next run.
|
||||
|
||||
This means your analytics context travels with your code. You can fork it, branch it, review it in a PR, and merge it with the same tools you use for dbt models. There's no sync problem between a remote server and your local state. There's no migration to run. The files are the source of truth.
|
||||
|
||||
## Agent usage notes
|
||||
|
||||
Use this page when an agent needs to explain why KTX exists, why schema-only database access is not enough, or how KTX differs from MetricFlow, Cube, Malloy, and traditional semantic layers.
|
||||
|
||||
| Agent task | Relevant section | Next page |
|
||||
|------------|------------------|-----------|
|
||||
| Explain why a database agent made a plausible but wrong query | The problem | [Writing Context](/docs/guides/writing-context) |
|
||||
| Decide whether a metric belongs in YAML or Markdown | What a context layer is | [Writing Context](/docs/guides/writing-context) |
|
||||
| Compare KTX to another semantic layer | How KTX compares | [Primary Sources](/docs/integrations/primary-sources) |
|
||||
| Explain reviewability and source of truth | The plain-files philosophy | [Context as Code](/docs/concepts/context-as-code) |
|
||||
|
|
|
|||
|
|
@ -39,6 +39,9 @@ If you've ever watched an agent confidently generate a query that joins on the w
|
|||
<Card title="Quickstart" href="/docs/getting-started/quickstart">
|
||||
Set up KTX and build your first context in under 10 minutes.
|
||||
</Card>
|
||||
<Card title="AI Resources" href="/docs/ai-resources">
|
||||
Machine-readable docs and prompt recipes for coding assistants.
|
||||
</Card>
|
||||
<Card title="Concepts" href="/docs/concepts/the-context-layer">
|
||||
Understand what a context layer is, why agents need one, and how KTX compares to other semantic layers.
|
||||
</Card>
|
||||
|
|
@ -56,4 +59,19 @@ If you've ever watched an agent confidently generate a query that joins on the w
|
|||
## Next steps
|
||||
|
||||
- **Get hands-on** — follow the [Quickstart](/docs/getting-started/quickstart) to set up KTX with your own database in under 10 minutes.
|
||||
- **Help a coding agent use the docs** — start with [AI Resources](/docs/ai-resources) or fetch [`/llms.txt`](/llms.txt).
|
||||
- **Understand the theory** — read [The Context Layer](/docs/concepts/the-context-layer) to learn why schema access alone breaks on real analytics and how KTX addresses it.
|
||||
|
||||
## Agent usage notes
|
||||
|
||||
Use this page as the high-level routing document for KTX docs.
|
||||
|
||||
| Agent task | Read next |
|
||||
|------------|-----------|
|
||||
| Discover machine-readable docs | [AI Resources](/docs/ai-resources) |
|
||||
| Learn how a coding assistant should approach KTX | [Agent Quickstart](/docs/ai-resources/agent-quickstart) |
|
||||
| Set up a new KTX project | [Quickstart](/docs/getting-started/quickstart) |
|
||||
| Explain what problem KTX solves | [The Context Layer](/docs/concepts/the-context-layer) |
|
||||
| Scan a database and ingest metadata | [Building Context](/docs/guides/building-context) |
|
||||
| Edit semantic sources or knowledge pages | [Writing Context](/docs/guides/writing-context) |
|
||||
| Look up exact command flags | [CLI Reference](/docs/cli-reference/ktx-setup) |
|
||||
|
|
|
|||
|
|
@ -5,6 +5,22 @@ description: Set up KTX and build your first context in under 10 minutes.
|
|||
|
||||
This guide walks you through `ktx setup` — an interactive wizard that configures your LLM provider, connects your database, optionally ingests from your existing tools, builds context, and installs agent integration.
|
||||
|
||||
If you are a coding assistant trying to decide which KTX docs page to read, start with the [Agent Quickstart](/docs/ai-resources/agent-quickstart). This page is the human setup walkthrough.
|
||||
|
||||
## Workflow summary
|
||||
|
||||
Use this sequence when an agent needs to set up KTX from a fresh checkout:
|
||||
|
||||
1. `pnpm install` — install workspace dependencies.
|
||||
2. `pnpm run setup:dev` — build local packages and prepare the development CLI.
|
||||
3. `pnpm run link:dev` — link the `ktx` command for local use.
|
||||
4. `ktx setup` — create or resume a KTX project.
|
||||
5. `ktx status` — verify project readiness.
|
||||
6. `ktx sl list` — confirm semantic-layer sources are available.
|
||||
7. `ktx sl query ... --format sql` — compile a semantic query without executing it.
|
||||
|
||||
The setup wizard is stateful. If it exits before completion, rerun `ktx setup` in the same project directory to resume from the first incomplete step.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **Node.js 22+** and **pnpm**
|
||||
|
|
@ -198,6 +214,20 @@ Then select which agents to install for:
|
|||
|
||||
**MCP mode** writes an MCP server configuration (e.g., `.mcp.json`) that lets the agent call KTX tools like `sl_query`, `knowledge_search`, and `sl_write_source` over the Model Context Protocol.
|
||||
|
||||
## Generated files
|
||||
|
||||
KTX writes project state as plain files so agents can inspect and edit changes in git.
|
||||
|
||||
| Path | Created by | Purpose |
|
||||
|------|------------|---------|
|
||||
| `ktx.yaml` | `ktx setup` | Main project configuration: connections, LLM settings, embeddings, and context sources |
|
||||
| `.ktx/secrets/*` | `ktx setup` when file-backed secrets are selected | Local secret files referenced from `ktx.yaml`; do not commit these |
|
||||
| `semantic-layer/<connection-id>/*.yaml` | context build, ingestion, or `ktx sl write` | Semantic source definitions agents use for SQL generation |
|
||||
| `knowledge/global/*.md` | ingestion or `ktx wiki write --scope global` | Shared business context and metric definitions |
|
||||
| `knowledge/user/<user-id>/*.md` | `ktx wiki write --scope user` | User-scoped notes for one agent/user context |
|
||||
| `.mcp.json`, `.cursor/mcp.json`, `.agents/mcp/ktx.json`, `.opencode/mcp.json` | agent integration setup | MCP server configuration for supported agent clients |
|
||||
| `.claude/skills/ktx/SKILL.md`, `.agents/skills/ktx/SKILL.md` | CLI-mode agent integration setup | Agent instructions for calling `ktx agent` commands |
|
||||
|
||||
## Verify it worked
|
||||
|
||||
Check your project status:
|
||||
|
|
@ -247,6 +277,18 @@ ktx sl query \
|
|||
--execute --max-rows 10
|
||||
```
|
||||
|
||||
## Common errors
|
||||
|
||||
| Error or symptom | Likely cause | Recovery |
|
||||
|------------------|--------------|----------|
|
||||
| `ktx: command not found` | The local CLI has not been linked | Run `pnpm run setup:dev` and `pnpm run link:dev` from the KTX checkout, then open a new shell |
|
||||
| LLM health check fails | Missing, invalid, or unauthorized Anthropic API key | Export `ANTHROPIC_API_KEY` or rerun `ktx setup` and choose the file-backed secret option |
|
||||
| OpenAI embedding check fails | `OPENAI_API_KEY` is missing when OpenAI embeddings are selected | Export `OPENAI_API_KEY`, or rerun setup and choose local sentence-transformers embeddings |
|
||||
| Local embeddings hang or fail | The Python daemon cannot start or the local model runtime is unavailable | Run `uv sync --all-groups`, then start `ktx-daemon serve-http --host 127.0.0.1 --port 8765` and rerun setup |
|
||||
| Database connection test fails | Credentials, network access, warehouse, database, or schema value is wrong | Test the same URL with the database's native client, then rerun `ktx connection add ... --force` or rerun setup |
|
||||
| `KTX context built: no` in `ktx status` | Setup saved configuration but did not build context | Run `ktx setup context build` or rerun `ktx setup` and choose to build context now |
|
||||
| Agent integration is incomplete | Setup skipped the agents step or the target was not installed | Run `ktx setup --agents --target codex --agent-install-mode both --project` using the target you need |
|
||||
|
||||
## Next steps
|
||||
|
||||
- **Build more context** — learn about [scanning](/docs/guides/building-context), relationship detection, and ingestion workflows in the Building Context guide.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,17 @@ description: Write and refine semantic sources and knowledge pages.
|
|||
|
||||
After building context through scanning and ingestion, you'll want to refine it — edit semantic sources to match your business logic, add knowledge pages that capture tribal knowledge, and query your data through the semantic layer to verify everything works.
|
||||
|
||||
## Agent workflow summary
|
||||
|
||||
Agents should refine context in this order:
|
||||
|
||||
1. `ktx sl list --json` — discover available sources and connection ids.
|
||||
2. `ktx sl read <source> --connection-id <id>` — inspect the current YAML.
|
||||
3. Edit the source YAML directly or use `ktx sl write`.
|
||||
4. `ktx sl validate <source> --connection-id <id>` — verify columns, joins, and table references.
|
||||
5. `ktx sl query ... --format sql` — compile a representative query without executing it.
|
||||
6. `ktx wiki search ...` and `ktx wiki write ...` — add business context that does not belong in schema YAML.
|
||||
|
||||
## Semantic Sources
|
||||
|
||||
Semantic sources are YAML files that describe your tables, columns, measures, and joins. They're the core of the context layer — the structured definitions that agents use to generate correct SQL.
|
||||
|
|
@ -108,6 +119,26 @@ Key fields:
|
|||
| `segments` | No | Named filter conditions |
|
||||
| `inherits_columns_from` | No | Inherit column metadata from a manifest entry |
|
||||
|
||||
Source component fields:
|
||||
|
||||
| Component | Field | Required | Description |
|
||||
|-----------|-------|----------|-------------|
|
||||
| Column | `name` | Yes | Column identifier as used in SQL expressions |
|
||||
| Column | `type` | Yes | Agent-facing type: `string`, `number`, `time`, or `boolean` |
|
||||
| Column | `role` | No | Special role such as `time` for default time dimensions |
|
||||
| Column | `visibility` | No | `public`, `internal`, or `hidden` |
|
||||
| Column | `description` | Strongly recommended | Human-readable business meaning |
|
||||
| Measure | `name` | Yes | Queryable metric name |
|
||||
| Measure | `expr` | Yes | SQL aggregation expression at the source grain |
|
||||
| Measure | `filter` | No | SQL predicate applied only to this measure |
|
||||
| Measure | `description` | Strongly recommended | Definition agents can cite and compare |
|
||||
| Segment | `name` | Yes | Reusable filter name |
|
||||
| Segment | `expr` | Yes | SQL predicate for the segment |
|
||||
| Join | `to` | Yes | Target semantic source name |
|
||||
| Join | `on` | Yes | SQL join condition using source names or aliases |
|
||||
| Join | `relationship` | Yes | `many_to_one`, `one_to_many`, or `one_to_one` |
|
||||
| Join | `alias` | No | Query alias for repeated or clearer joins |
|
||||
|
||||
Column visibility controls what agents see:
|
||||
|
||||
| Visibility | Behavior |
|
||||
|
|
@ -192,6 +223,16 @@ Query flags:
|
|||
|
||||
The query planner is grain-aware — it understands the cardinality of joins and avoids chasm traps (double-counting caused by many-to-many fan-outs). When you query measures that span multiple sources, KTX generates sub-queries at the correct grain before joining.
|
||||
|
||||
### Workflow: edit and validate a source
|
||||
|
||||
1. `ktx sl read orders --connection-id my-postgres > /tmp/orders.yaml` — capture the current definition.
|
||||
2. Edit `/tmp/orders.yaml` to add columns, measures, joins, or descriptions.
|
||||
3. `ktx sl write orders --connection-id my-postgres --yaml "$(cat /tmp/orders.yaml)"` — write the updated source.
|
||||
4. `ktx sl validate orders --connection-id my-postgres` — check the definition against the live schema.
|
||||
5. `ktx sl query --connection-id my-postgres --measure total_revenue --dimension order_date --format sql` — compile a representative query.
|
||||
|
||||
If validation fails, fix the YAML before asking an agent to use the source. Common validation failures are missing columns, invalid join targets, and measure expressions that reference fields outside the source.
|
||||
|
||||
## Knowledge Pages
|
||||
|
||||
Knowledge pages are Markdown files that capture business context — definitions, rules, gotchas, and anything an agent needs to understand beyond what the schema tells it.
|
||||
|
|
@ -250,6 +291,18 @@ Write flags:
|
|||
| `--ref <ref>` | Reference to external resources (repeatable) |
|
||||
| `--sl-ref <ref>` | Link to a semantic source (repeatable) |
|
||||
|
||||
Knowledge page fields:
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| Key | Yes | Stable page identifier passed to `ktx wiki read` |
|
||||
| Summary | Yes | Short text shown in search results |
|
||||
| Content | Yes | Full Markdown business context |
|
||||
| Scope | No | `global` for shared context or `user` for user-scoped notes |
|
||||
| Tags | No | Search and organization labels |
|
||||
| External refs | No | Links or identifiers for source-of-truth systems |
|
||||
| Semantic-layer refs | No | Source names the page explains or constrains |
|
||||
|
||||
You can also create and edit knowledge pages directly as Markdown files in the `knowledge/` directory.
|
||||
|
||||
### Listing pages
|
||||
|
|
@ -271,3 +324,21 @@ ktx wiki search "revenue recognition"
|
|||
```
|
||||
|
||||
Search uses both full-text matching and semantic similarity — it finds relevant pages even when the exact terms don't match. Agents call this automatically when they need business context to answer a question.
|
||||
|
||||
### Workflow: add searchable business context
|
||||
|
||||
1. Search first: `ktx wiki search "order status definitions"`.
|
||||
2. If no page already covers the rule, write a page with `ktx wiki write`.
|
||||
3. Include a concise `--summary`; agents see this before loading full content.
|
||||
4. Add `--tag` values for the business area and `--sl-ref` values for related semantic sources.
|
||||
5. Search again with the user's likely wording to confirm the page is discoverable.
|
||||
|
||||
## Common errors
|
||||
|
||||
| Error or symptom | Likely cause | Recovery |
|
||||
|------------------|--------------|----------|
|
||||
| `ktx sl validate` reports a missing column | YAML references a column that is absent from the scanned table | Run a fresh scan or update the YAML to match the warehouse schema |
|
||||
| Query compilation double-counts a measure | Join relationship or grain is missing or wrong | Add `grain` and explicit `relationship` values, then validate and recompile |
|
||||
| Agent cannot find a metric | Measure name or description does not match business terminology | Add a measure description and a knowledge page with common synonyms |
|
||||
| Knowledge search misses a page | Summary and tags do not include likely user wording | Rewrite the summary and add relevant tags, then search again |
|
||||
| `ktx sl write` changes are hard to review | Large YAML was passed inline | Edit the source file directly or write from a temporary file, then review the git diff |
|
||||
|
|
|
|||
|
|
@ -7,6 +7,29 @@ Context sources feed your existing analytics tooling into KTX. During ingestion,
|
|||
|
||||
All context sources are configured in `ktx.yaml` under `connections` with their respective `driver` value.
|
||||
|
||||
## Ingestion workflow
|
||||
|
||||
Agents should configure and ingest context sources in this order:
|
||||
|
||||
1. Add the context source connection in `ktx.yaml` or with `ktx setup`.
|
||||
2. Store tokens as `env:NAME` or `file:/path/to/secret`.
|
||||
3. Run `ktx ingest <connectionId>` for one source or `ktx ingest --all`.
|
||||
4. Check progress with `ktx ingest status --json`.
|
||||
5. Review generated `semantic-layer/` YAML and `knowledge/` Markdown files in git.
|
||||
6. Validate changed semantic sources with `ktx sl validate`.
|
||||
|
||||
## Shared source fields
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `driver` | Yes | Source adapter: `dbt`, `metricflow`, `lookml`, `metabase`, `looker`, or `notion` |
|
||||
| `readonly` | Strongly recommended | Marks the source as read-only for KTX |
|
||||
| `source_dir` | For local file sources | Absolute or project-relative source directory |
|
||||
| `repo_url` | For Git-hosted sources | Git repository URL |
|
||||
| `branch` | No | Git branch to read |
|
||||
| `path` | No | Subdirectory inside a monorepo |
|
||||
| `auth_token_ref` | For private APIs/repos | `env:NAME` or `file:/path/to/secret` token reference |
|
||||
|
||||
## dbt
|
||||
|
||||
Ingests schema definitions, model descriptions, column metadata, and test coverage from a dbt project.
|
||||
|
|
@ -351,3 +374,13 @@ Create an integration at [notion.so/my-integrations](https://www.notion.so/my-in
|
|||
- Notion is knowledge-only — it does not produce semantic layer sources
|
||||
- Rate limits apply; large workspaces may require multiple ingestion runs
|
||||
- `last_successful_cursor` is auto-managed for incremental sync
|
||||
|
||||
## Common errors
|
||||
|
||||
| Error or symptom | Likely cause | Recovery |
|
||||
|------------------|--------------|----------|
|
||||
| Adapter cannot read source files | `source_dir`, `repo_url`, `branch`, or `path` is wrong | Verify the path locally or clone the repo manually with the same credentials |
|
||||
| Private repo/API authentication fails | Token env var or secret file is missing | Export the env var or update `auth_token_ref` to a readable file |
|
||||
| Ingest creates duplicate context | Existing source names or knowledge pages do not match imported terminology | Review the diff, rename duplicates, and add knowledge pages with canonical names |
|
||||
| Notion ingest skips pages | Integration lacks access or root ids are missing | Share pages with the Notion integration and set `root_page_ids` or use `all_accessible` carefully |
|
||||
| Generated semantic sources fail validation | Tool metadata does not match the live warehouse schema | Map BI/source databases to primary warehouse connections and rerun validation |
|
||||
|
|
|
|||
|
|
@ -11,6 +11,20 @@ All connectors share these conventions:
|
|||
- Connections are read-only — KTX never writes to your database
|
||||
- Schema scanning discovers tables, columns, types, and constraints automatically
|
||||
|
||||
## Connection field reference
|
||||
|
||||
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`, `clickhouse`, `mysql`, `sqlserver`, or `sqlite` |
|
||||
| `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, ClickHouse, SQL Server | Field-by-field connection values |
|
||||
| `schema` or `schemas` | No | schema-aware warehouses | Single schema or list of schemas to scan |
|
||||
| `readonly` | Strongly recommended | all primary sources | Marks the connection as read-only in KTX config |
|
||||
| `historicSql` | No | supported warehouses | Enables query-history ingestion when the warehouse supports it |
|
||||
| `path` | Yes for path-style SQLite | SQLite | Local SQLite database path or `env:NAME` reference |
|
||||
|
||||
## PostgreSQL
|
||||
|
||||
The most full-featured connector. Supports schema introspection, foreign key detection, column statistics, and historic SQL via `pg_stat_statements`.
|
||||
|
|
@ -488,3 +502,13 @@ No authentication required — SQLite is file-based. The file must be readable b
|
|||
- SQLite type affinity system: `TEXT`, `NUMERIC`, `INTEGER`, `REAL`, `BLOB`
|
||||
- Foreign key enforcement requires explicit `PRAGMA foreign_keys = ON`
|
||||
- In-memory databases supported with `path: ":memory:"` (for testing)
|
||||
|
||||
## Common errors
|
||||
|
||||
| Error or symptom | Likely cause | Recovery |
|
||||
|------------------|--------------|----------|
|
||||
| Connection URL appears in git diff | A literal credential URL was written to `ktx.yaml` | Replace it with `env:NAME` or `file:/path/to/secret` and rotate exposed credentials |
|
||||
| Scan returns no tables | Schema/database/project filter is wrong or the user lacks metadata permissions | Verify the schema list and grant metadata read permissions |
|
||||
| Historic SQL is empty | Query history extension or warehouse history view is unavailable | Enable the warehouse-specific history feature, then rerun scan or setup |
|
||||
| Column statistics are missing | Connector cannot access stats tables or the warehouse does not expose them | Grant stats permissions where supported; otherwise rely on structural scan output |
|
||||
| SQL execution fails through agents | Connection is missing, unreachable, or execution is disabled in the server | Run `ktx connection test <id>` and check `ktx serve` flags |
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
"integrations",
|
||||
"benchmarks",
|
||||
"cli-reference",
|
||||
"ai-resources",
|
||||
"community"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
159
docs-site/lib/llm-docs.ts
Normal file
159
docs-site/lib/llm-docs.ts
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
import { source } from "@/lib/source";
|
||||
|
||||
const siteOrigin = "https://docs.kaelio.com/ktx";
|
||||
|
||||
export type LlmDocsPage = {
|
||||
title: string;
|
||||
description?: string;
|
||||
url: string;
|
||||
markdownUrl: string;
|
||||
slug: string[];
|
||||
getMarkdown: () => Promise<string>;
|
||||
};
|
||||
|
||||
export function getLlmDocsPages(): LlmDocsPage[] {
|
||||
return source.getPages().map(toLlmDocsPage);
|
||||
}
|
||||
|
||||
export function getLlmDocsPage(slug: string[] | undefined) {
|
||||
const page = source.getPage(slug);
|
||||
return page ? toLlmDocsPage(page) : null;
|
||||
}
|
||||
|
||||
export async function getPageMarkdown(page: LlmDocsPage) {
|
||||
const description = page.description ? `\n\n> ${page.description}` : "";
|
||||
const body = await page.getMarkdown();
|
||||
|
||||
return normalizeMarkdown(`# ${page.title}${description}
|
||||
|
||||
Canonical URL: ${absoluteUrl(page.url)}
|
||||
Markdown URL: ${absoluteUrl(page.markdownUrl)}
|
||||
|
||||
${body}
|
||||
`);
|
||||
}
|
||||
|
||||
export function buildLlmsTxt() {
|
||||
const pages = getLlmDocsPages();
|
||||
const byUrl = new Map(pages.map((page) => [page.url, page]));
|
||||
const link = (url: string, label: string, fallbackDescription: string) => {
|
||||
const page = byUrl.get(url);
|
||||
const description = page?.description ?? fallbackDescription;
|
||||
const markdownUrl = page?.markdownUrl ?? `${url}.md`;
|
||||
return `- [${label}](${absoluteUrl(markdownUrl)}): ${description}`;
|
||||
};
|
||||
|
||||
return `# KTX
|
||||
|
||||
> Agent-native context layer for analytics engineering and database agents.
|
||||
|
||||
KTX provides semantic-layer files, warehouse scans, knowledge pages, provenance, and agent-facing tools that help coding agents answer analytics questions without inventing metrics or joins.
|
||||
|
||||
## Agent Entry Points
|
||||
|
||||
${link("/docs/ai-resources", "AI Resources", "Machine-readable docs, prompt recipes, and agent setup paths")}
|
||||
${link("/docs/ai-resources/agent-quickstart", "Agent Quickstart", "Task-first route for coding assistants using KTX")}
|
||||
${link("/docs/ai-resources/markdown-access", "Markdown Access", "Fetch KTX docs as llms.txt, llms-full.txt, or per-page Markdown")}
|
||||
${link("/docs/ai-resources/agent-instructions", "Agent Instructions", "Suggested instructions for coding assistants that need to read and cite KTX docs")}
|
||||
|
||||
## Start Here
|
||||
|
||||
${link("/docs/getting-started/introduction", "Introduction", "What KTX is and who it is for")}
|
||||
${link("/docs/getting-started/quickstart", "Quickstart", "Set up KTX and build your first context")}
|
||||
${link("/docs/guides/writing-context", "Writing Context", "Write semantic sources and knowledge pages")}
|
||||
|
||||
## Machine-Readable Documentation
|
||||
|
||||
- [Full documentation](${absoluteUrl("/llms-full.txt")}): All docs pages in one plain-text markdown response
|
||||
- [Markdown access guide](${absoluteUrl("/docs/ai-resources/markdown-access.md")}): How to fetch llms.txt, llms-full.txt, and per-page Markdown
|
||||
- [Quickstart markdown](${absoluteUrl("/docs/getting-started/quickstart.md")}): Human setup walkthrough
|
||||
- [Agent CLI markdown](${absoluteUrl("/docs/cli-reference/ktx-agent.md")}): Machine-readable agent commands
|
||||
|
||||
## CLI Reference
|
||||
|
||||
${link("/docs/cli-reference/ktx-setup", "ktx setup", "Interactive project setup")}
|
||||
${link("/docs/cli-reference/ktx-agent", "ktx agent", "Machine-readable commands for coding agents")}
|
||||
${link("/docs/cli-reference/ktx-sl", "ktx sl", "Semantic-layer commands")}
|
||||
${link("/docs/cli-reference/ktx-wiki", "ktx wiki", "Knowledge page commands")}
|
||||
${link("/docs/cli-reference/ktx-connection", "ktx connection", "Connection management commands")}
|
||||
|
||||
## Integrations
|
||||
|
||||
${link("/docs/integrations/primary-sources", "Primary Sources", "Connect KTX to databases and warehouses")}
|
||||
${link("/docs/integrations/context-sources", "Context Sources", "Ingest dbt, LookML, Metabase, Looker, MetricFlow, and Notion")}
|
||||
|
||||
## All Documentation
|
||||
|
||||
${buildPageIndex(pages)}
|
||||
`;
|
||||
}
|
||||
|
||||
export async function buildLlmsFullTxt() {
|
||||
const rendered = await Promise.all(getLlmDocsPages().map(getPageMarkdown));
|
||||
return [`# KTX Full Documentation`, `Source: ${siteOrigin}`, ...rendered].join(
|
||||
"\n\n---\n\n",
|
||||
);
|
||||
}
|
||||
|
||||
function toLlmDocsPage(page: ReturnType<typeof source.getPages>[number]) {
|
||||
return {
|
||||
title: page.data.title,
|
||||
description: page.data.description,
|
||||
url: page.url,
|
||||
markdownUrl: `${page.url}.md`,
|
||||
slug: page.slugs,
|
||||
getMarkdown: async () => normalizeMarkdown(page.data.content),
|
||||
} satisfies LlmDocsPage;
|
||||
}
|
||||
|
||||
function normalizeMarkdown(markdown: string) {
|
||||
return markdown
|
||||
.trim()
|
||||
.replace(/^---\n[\s\S]*?\n---\n?/, "")
|
||||
.trim()
|
||||
.replace(/\n{3,}/g, "\n\n");
|
||||
}
|
||||
|
||||
function buildPageIndex(pages: LlmDocsPage[]) {
|
||||
const grouped = new Map<string, LlmDocsPage[]>();
|
||||
|
||||
for (const page of pages) {
|
||||
const category = page.slug[0] ?? "general";
|
||||
grouped.set(category, [...(grouped.get(category) ?? []), page]);
|
||||
}
|
||||
|
||||
return [...grouped.entries()]
|
||||
.map(([category, categoryPages]) => {
|
||||
const links = categoryPages
|
||||
.map((page) => {
|
||||
const description = page.description ? `: ${page.description}` : "";
|
||||
return `- [${page.title}](${absoluteUrl(page.markdownUrl)})${description}`;
|
||||
})
|
||||
.join("\n");
|
||||
|
||||
return `### ${formatCategoryName(category)}
|
||||
|
||||
${links}`;
|
||||
})
|
||||
.join("\n\n");
|
||||
}
|
||||
|
||||
function absoluteUrl(path: string) {
|
||||
return `${siteOrigin}${path}`;
|
||||
}
|
||||
|
||||
function formatCategoryName(category: string) {
|
||||
const labels: Record<string, string> = {
|
||||
"ai-resources": "AI Resources",
|
||||
"cli-reference": "CLI Reference",
|
||||
};
|
||||
|
||||
if (labels[category]) {
|
||||
return labels[category];
|
||||
}
|
||||
|
||||
return category
|
||||
.split("-")
|
||||
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
.join(" ");
|
||||
}
|
||||
51
docs-site/middleware.ts
Normal file
51
docs-site/middleware.ts
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import { NextResponse, type NextRequest } from "next/server";
|
||||
|
||||
const markdownMimeTypes = new Set([
|
||||
"text/markdown",
|
||||
"text/x-markdown",
|
||||
"application/markdown",
|
||||
]);
|
||||
|
||||
export function middleware(request: NextRequest) {
|
||||
if (!isMarkdownPreferred(request.headers.get("accept"))) {
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
||||
const { pathname } = request.nextUrl;
|
||||
if (!pathname.startsWith("/docs/") || pathname.endsWith(".md")) {
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
||||
const rewriteUrl = request.nextUrl.clone();
|
||||
rewriteUrl.pathname = `/llms.mdx${pathname}`;
|
||||
|
||||
return NextResponse.rewrite(rewriteUrl);
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: ["/docs/:path*"],
|
||||
};
|
||||
|
||||
function isMarkdownPreferred(acceptHeader: string | null) {
|
||||
if (!acceptHeader) return false;
|
||||
|
||||
const accepted = acceptHeader
|
||||
.split(",")
|
||||
.map((entry, index) => {
|
||||
const [type = "", ...parameters] = entry.trim().split(";");
|
||||
const quality = parameters
|
||||
.map((parameter) => parameter.trim())
|
||||
.find((parameter) => parameter.startsWith("q="));
|
||||
|
||||
return {
|
||||
type: type.trim().toLowerCase(),
|
||||
quality: quality ? Number.parseFloat(quality.slice(2)) : 1,
|
||||
index,
|
||||
};
|
||||
})
|
||||
.filter((entry) => Number.isFinite(entry.quality) && entry.quality > 0)
|
||||
.sort((a, b) => b.quality - a.quality || a.index - b.index);
|
||||
|
||||
const preferred = accepted[0]?.type;
|
||||
return preferred ? markdownMimeTypes.has(preferred) : false;
|
||||
}
|
||||
|
|
@ -3,6 +3,15 @@ import { createMDX } from "fumadocs-mdx/next";
|
|||
const withMDX = createMDX();
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const config = {};
|
||||
const config = {
|
||||
async rewrites() {
|
||||
return [
|
||||
{
|
||||
source: "/docs/:path*.md",
|
||||
destination: "/llms.mdx/docs/:path*",
|
||||
},
|
||||
];
|
||||
},
|
||||
};
|
||||
|
||||
export default withMDX(config);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@
|
|||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start"
|
||||
"start": "next start",
|
||||
"test": "node --test tests/*.test.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"fumadocs-core": "15.7.13",
|
||||
|
|
|
|||
14
docs-site/tests/docs-index-route.test.mjs
Normal file
14
docs-site/tests/docs-index-route.test.mjs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
|
||||
const docsSiteUrl = process.env.DOCS_SITE_URL ?? "http://localhost:3000";
|
||||
|
||||
test("/docs redirects to the docs introduction", async () => {
|
||||
const response = await fetch(`${docsSiteUrl}/docs`, { redirect: "manual" });
|
||||
|
||||
assert.equal(response.status, 307);
|
||||
assert.equal(
|
||||
response.headers.get("location"),
|
||||
"/docs/getting-started/introduction",
|
||||
);
|
||||
});
|
||||
411
docs/superpowers/plans/2026-05-11-agent-friendly-docs-site.md
Normal file
411
docs/superpowers/plans/2026-05-11-agent-friendly-docs-site.md
Normal file
|
|
@ -0,0 +1,411 @@
|
|||
# Agent-Friendly Docs Site Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Make `docs-site` discoverable and readable by coding agents through `llms.txt`, bundled markdown, per-page markdown routes, markdown negotiation, and stricter agent-friendly docs content.
|
||||
|
||||
**Architecture:** Keep the existing Next 15 + Fumadocs app. Add a small `lib/llm-docs.ts` module that reads Fumadocs pages and builds machine-readable markdown responses, then expose those responses through route handlers and a markdown negotiation proxy. Rewrite existing MDX pages in place so the rendered UI and machine-readable routes share one source of truth.
|
||||
|
||||
**Tech Stack:** Next.js 15 App Router, Fumadocs, MDX, TypeScript, pnpm, Node 22.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Machine-Readable Docs Routes
|
||||
|
||||
**Files:**
|
||||
- Create: `docs-site/lib/llm-docs.ts`
|
||||
- Create: `docs-site/app/llms.txt/route.ts`
|
||||
- Create: `docs-site/app/llms-full.txt/route.ts`
|
||||
- Create: `docs-site/app/llms.mdx/docs/[[...slug]]/route.ts`
|
||||
- Modify: `docs-site/next.config.mjs`
|
||||
|
||||
- [ ] **Step 1: Add the LLM docs utility**
|
||||
|
||||
Create `docs-site/lib/llm-docs.ts` with functions that:
|
||||
|
||||
```ts
|
||||
import { source } from "@/lib/source";
|
||||
|
||||
const SITE_ORIGIN = "https://ktx.dev";
|
||||
|
||||
export type LlmDocsPage = {
|
||||
title: string;
|
||||
description?: string;
|
||||
url: string;
|
||||
markdownUrl: string;
|
||||
slug: string[];
|
||||
getMarkdown: () => Promise<string>;
|
||||
};
|
||||
|
||||
export function getLlmDocsPages(): LlmDocsPage[] {
|
||||
return source.getPages().map((page) => ({
|
||||
title: page.data.title,
|
||||
description: page.data.description,
|
||||
url: page.url,
|
||||
markdownUrl: `${page.url}.md`,
|
||||
slug: page.slugs,
|
||||
getMarkdown: async () => normalizeMarkdown(await page.data.getText("raw")),
|
||||
}));
|
||||
}
|
||||
|
||||
export function getLlmDocsPage(slug: string[] | undefined) {
|
||||
const page = source.getPage(slug);
|
||||
if (!page) return null;
|
||||
|
||||
return {
|
||||
title: page.data.title,
|
||||
description: page.data.description,
|
||||
url: page.url,
|
||||
markdownUrl: `${page.url}.md`,
|
||||
slug: page.slugs,
|
||||
getMarkdown: async () => normalizeMarkdown(await page.data.getText("raw")),
|
||||
} satisfies LlmDocsPage;
|
||||
}
|
||||
|
||||
export async function getPageMarkdown(page: LlmDocsPage) {
|
||||
const body = await page.getMarkdown();
|
||||
const description = page.description ? `\n\n> ${page.description}` : "";
|
||||
|
||||
return `# ${page.title}${description}\n\nCanonical URL: ${page.url}\nMarkdown URL: ${page.markdownUrl}\n\n${body}`;
|
||||
}
|
||||
|
||||
export function buildLlmsTxt() {
|
||||
const pages = getLlmDocsPages();
|
||||
const byUrl = new Map(pages.map((page) => [page.url, page]));
|
||||
const link = (url: string, label: string, fallbackDescription: string) => {
|
||||
const page = byUrl.get(url);
|
||||
const description = page?.description ?? fallbackDescription;
|
||||
return `- [${label}](${url}): ${description}`;
|
||||
};
|
||||
|
||||
return `# KTX
|
||||
|
||||
> Agent-native context layer for analytics engineering and database agents.
|
||||
|
||||
KTX provides semantic-layer files, warehouse scans, knowledge pages, provenance, and agent-facing tools that help coding agents answer analytics questions without inventing metrics or joins.
|
||||
|
||||
## Start Here
|
||||
|
||||
${link("/docs/getting-started/introduction", "Introduction", "What KTX is and who it is for")}
|
||||
${link("/docs/getting-started/quickstart", "Quickstart", "Set up KTX and build your first context")}
|
||||
${link("/docs/guides/serving-agents", "Serving Agents", "Expose KTX context through MCP and CLI tools")}
|
||||
${link("/docs/guides/writing-context", "Writing Context", "Write semantic sources and knowledge pages")}
|
||||
|
||||
## Machine-Readable Documentation
|
||||
|
||||
- [Full documentation](/llms-full.txt): All docs pages in one plain-text markdown response
|
||||
- [Quickstart markdown](/docs/getting-started/quickstart.md): Raw markdown for the setup guide
|
||||
- [Agent CLI markdown](/docs/cli-reference/ktx-agent.md): Raw markdown for machine-readable agent commands
|
||||
- [Serving Agents markdown](/docs/guides/serving-agents.md): Raw markdown for MCP and CLI workflows
|
||||
|
||||
## CLI Reference
|
||||
|
||||
${link("/docs/cli-reference/ktx-setup", "ktx setup", "Interactive project setup")}
|
||||
${link("/docs/cli-reference/ktx-agent", "ktx agent", "Machine-readable commands for coding agents")}
|
||||
${link("/docs/cli-reference/ktx-sl", "ktx sl", "Semantic-layer commands")}
|
||||
${link("/docs/cli-reference/ktx-wiki", "ktx wiki", "Knowledge page commands")}
|
||||
${link("/docs/cli-reference/ktx-connection", "ktx connection", "Connection management commands")}
|
||||
|
||||
## Integrations
|
||||
|
||||
${link("/docs/integrations/agent-clients", "Agent Clients", "Configure Claude Code, Cursor, Codex, and OpenCode")}
|
||||
${link("/docs/integrations/primary-sources", "Primary Sources", "Connect KTX to databases and warehouses")}
|
||||
${link("/docs/integrations/context-sources", "Context Sources", "Ingest dbt, LookML, Metabase, Looker, MetricFlow, and Notion")}
|
||||
`;
|
||||
}
|
||||
|
||||
export async function buildLlmsFullTxt() {
|
||||
const pages = getLlmDocsPages();
|
||||
const rendered = await Promise.all(pages.map(getPageMarkdown));
|
||||
return [`# KTX Full Documentation`, `Source: ${SITE_ORIGIN}`, ...rendered].join("\n\n---\n\n");
|
||||
}
|
||||
|
||||
function normalizeMarkdown(markdown: string) {
|
||||
return markdown.trim().replace(/\n{3,}/g, "\n\n");
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Add route handlers**
|
||||
|
||||
Create route files:
|
||||
|
||||
```ts
|
||||
import { buildLlmsTxt } from "@/lib/llm-docs";
|
||||
|
||||
export const dynamic = "force-static";
|
||||
|
||||
export function GET() {
|
||||
return new Response(buildLlmsTxt(), {
|
||||
headers: { "Content-Type": "text/plain; charset=utf-8" },
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
import { buildLlmsFullTxt } from "@/lib/llm-docs";
|
||||
|
||||
export const dynamic = "force-static";
|
||||
|
||||
export async function GET() {
|
||||
return new Response(await buildLlmsFullTxt(), {
|
||||
headers: { "Content-Type": "text/plain; charset=utf-8" },
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
import { getLlmDocsPage, getPageMarkdown } from "@/lib/llm-docs";
|
||||
import { notFound } from "next/navigation";
|
||||
|
||||
export const dynamic = "force-static";
|
||||
|
||||
export async function GET(
|
||||
_request: Request,
|
||||
props: { params: Promise<{ slug?: string[] }> },
|
||||
) {
|
||||
const params = await props.params;
|
||||
const page = getLlmDocsPage(params.slug);
|
||||
if (!page) notFound();
|
||||
|
||||
return new Response(await getPageMarkdown(page), {
|
||||
headers: { "Content-Type": "text/markdown; charset=utf-8" },
|
||||
});
|
||||
}
|
||||
|
||||
export function generateStaticParams() {
|
||||
return getLlmDocsPages().map((page) => ({ slug: page.slug }));
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Add `.md` rewrite**
|
||||
|
||||
Modify `docs-site/next.config.mjs`:
|
||||
|
||||
```js
|
||||
import { createMDX } from "fumadocs-mdx/next";
|
||||
|
||||
const withMDX = createMDX();
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const config = {
|
||||
async rewrites() {
|
||||
return [
|
||||
{
|
||||
source: "/docs/:path*.md",
|
||||
destination: "/llms.mdx/docs/:path*",
|
||||
},
|
||||
];
|
||||
},
|
||||
};
|
||||
|
||||
export default withMDX(config);
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Build check**
|
||||
|
||||
Run: `pnpm --filter ktx-docs build`
|
||||
|
||||
Expected: Next build completes and static routes include `llms.txt`, `llms-full.txt`, and the LLM markdown route.
|
||||
|
||||
### Task 2: Markdown Negotiation
|
||||
|
||||
**Files:**
|
||||
- Create: `docs-site/proxy.ts`
|
||||
|
||||
- [ ] **Step 1: Add markdown negotiation proxy**
|
||||
|
||||
Create `docs-site/proxy.ts`:
|
||||
|
||||
```ts
|
||||
import { isMarkdownPreferred, rewritePath } from "fumadocs-core/negotiation";
|
||||
import { NextResponse, type NextRequest } from "next/server";
|
||||
|
||||
const { rewrite } = rewritePath("/docs/*path", "/llms.mdx/docs/*path");
|
||||
|
||||
export function proxy(request: NextRequest) {
|
||||
if (!isMarkdownPreferred(request)) {
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
||||
const rewrittenPath = rewrite(request.nextUrl.pathname);
|
||||
if (!rewrittenPath) {
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
||||
return NextResponse.rewrite(new URL(rewrittenPath, request.nextUrl));
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: ["/docs/:path*"],
|
||||
};
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Verify build**
|
||||
|
||||
Run: `pnpm --filter ktx-docs build`
|
||||
|
||||
Expected: Build passes with the proxy included.
|
||||
|
||||
### Task 3: Agent-Friendly High-Priority Guides
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs-site/content/docs/getting-started/quickstart.mdx`
|
||||
- Modify: `docs-site/content/docs/guides/serving-agents.mdx`
|
||||
- Modify: `docs-site/content/docs/guides/writing-context.mdx`
|
||||
|
||||
- [ ] **Step 1: Rewrite quickstart structure**
|
||||
|
||||
Add sections for:
|
||||
|
||||
- Workflow summary
|
||||
- Generated files
|
||||
- Common errors and recovery
|
||||
|
||||
Keep existing setup detail, but make each command block copy-pasteable and each expected output complete enough for agents to recognize success.
|
||||
|
||||
- [ ] **Step 2: Rewrite Serving Agents as API reference**
|
||||
|
||||
Add tables for MCP tool inputs and CLI command inputs. Add workflows:
|
||||
|
||||
- Answer an analytics question through MCP
|
||||
- Answer an analytics question through CLI
|
||||
- Safely execute SQL with row limits
|
||||
|
||||
- [ ] **Step 3: Rewrite Writing Context with schemas and workflows**
|
||||
|
||||
Add semantic-source field tables, knowledge-page field tables, and workflows:
|
||||
|
||||
- Inspect a source
|
||||
- Edit and validate a source
|
||||
- Query through the semantic layer
|
||||
- Write and search a knowledge page
|
||||
|
||||
- [ ] **Step 4: Build check**
|
||||
|
||||
Run: `pnpm --filter ktx-docs build`
|
||||
|
||||
Expected: MDX compiles without syntax errors.
|
||||
|
||||
### Task 4: CLI Reference Normalization
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs-site/content/docs/cli-reference/*.mdx`
|
||||
|
||||
- [ ] **Step 1: Normalize every CLI page**
|
||||
|
||||
For each CLI reference page, ensure this structure exists:
|
||||
|
||||
```md
|
||||
## Command signature
|
||||
|
||||
```bash
|
||||
ktx <command> [subcommand] [options]
|
||||
```
|
||||
|
||||
## Subcommands
|
||||
|
||||
| Subcommand | Description |
|
||||
|---|---|
|
||||
|
||||
## Options
|
||||
|
||||
| Flag | Type | Required | Description | Default |
|
||||
|---|---|---|---|---|
|
||||
|
||||
## Examples
|
||||
|
||||
```bash
|
||||
ktx <real-command> --real-flag realistic-value
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
```text
|
||||
complete expected output shape
|
||||
```
|
||||
|
||||
## Common errors
|
||||
|
||||
| Error | Cause | Recovery |
|
||||
|---|---|---|
|
||||
```
|
||||
|
||||
Only add sections that are relevant to the command; do not invent output for commands whose output is intentionally interactive.
|
||||
|
||||
- [ ] **Step 2: Build check**
|
||||
|
||||
Run: `pnpm --filter ktx-docs build`
|
||||
|
||||
Expected: MDX compiles without syntax errors.
|
||||
|
||||
### Task 5: Integration and Concept Page Polish
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs-site/content/docs/integrations/agent-clients.mdx`
|
||||
- Modify: `docs-site/content/docs/integrations/primary-sources.mdx`
|
||||
- Modify: `docs-site/content/docs/integrations/context-sources.mdx`
|
||||
- Modify: `docs-site/content/docs/concepts/*.mdx`
|
||||
- Modify: `docs-site/content/docs/benchmarks/link-detection.mdx`
|
||||
|
||||
- [ ] **Step 1: Normalize integrations**
|
||||
|
||||
Add structured sections for supported values, config snippets, authentication, generated files, and recovery notes. Keep existing examples aligned with current KTX commands.
|
||||
|
||||
- [ ] **Step 2: Add agent usage notes**
|
||||
|
||||
For concept and benchmark pages, add a compact `## Agent usage notes` section that tells agents when the page is relevant and which concrete page to read next.
|
||||
|
||||
- [ ] **Step 3: Build check**
|
||||
|
||||
Run: `pnpm --filter ktx-docs build`
|
||||
|
||||
Expected: MDX compiles without syntax errors.
|
||||
|
||||
### Task 6: Route Verification and Final Checks
|
||||
|
||||
**Files:**
|
||||
- No required source changes unless verification finds a bug.
|
||||
|
||||
- [ ] **Step 1: Run production build**
|
||||
|
||||
Run: `pnpm --filter ktx-docs build`
|
||||
|
||||
Expected: Build succeeds.
|
||||
|
||||
- [ ] **Step 2: Run TypeScript check**
|
||||
|
||||
Run: `pnpm --filter ktx-docs exec tsc --noEmit`
|
||||
|
||||
Expected: TypeScript exits successfully.
|
||||
|
||||
- [ ] **Step 3: Start local server**
|
||||
|
||||
Run: `pnpm --filter ktx-docs start`
|
||||
|
||||
Expected: Server starts on an available port.
|
||||
|
||||
- [ ] **Step 4: Verify machine-readable routes**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
curl -i http://localhost:3000/llms.txt
|
||||
curl -i http://localhost:3000/llms-full.txt
|
||||
curl -i http://localhost:3000/docs/getting-started/quickstart.md
|
||||
curl -i -H "Accept: text/markdown" http://localhost:3000/docs/getting-started/quickstart
|
||||
curl -i http://localhost:3000/docs/not-a-page.md
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `/llms.txt`: `200`, `Content-Type: text/plain; charset=utf-8`
|
||||
- `/llms-full.txt`: `200`, `Content-Type: text/plain; charset=utf-8`
|
||||
- `/docs/getting-started/quickstart.md`: `200`, `Content-Type: text/markdown; charset=utf-8`
|
||||
- `/docs/getting-started/quickstart` with `Accept: text/markdown`: `200`, `Content-Type: text/markdown; charset=utf-8`
|
||||
- `/docs/not-a-page.md`: `404`
|
||||
|
||||
- [ ] **Step 5: Inspect final diff**
|
||||
|
||||
Run: `git diff --stat && git diff --check`
|
||||
|
||||
Expected: Diff contains only docs-site and plan changes, with no whitespace errors.
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
# Agent-Friendly Docs Site Design
|
||||
|
||||
## Goal
|
||||
|
||||
Make `docs-site` easier for coding agents and LLM readers to discover, ingest,
|
||||
and use. The work applies the Vercel Academy agent-friendly docs patterns to the
|
||||
KTX documentation site while preserving the current Fumadocs + Next.js
|
||||
architecture.
|
||||
|
||||
Success means agents can:
|
||||
|
||||
- Discover the documentation from well-known root files.
|
||||
- Fetch all documentation in one plain-text response.
|
||||
- Fetch any docs page as markdown without parsing the HTML UI.
|
||||
- Follow CLI, MCP, setup, integration, and semantic-layer workflows from
|
||||
structured examples.
|
||||
- Recover from common setup and command failures using explicit troubleshooting
|
||||
notes.
|
||||
|
||||
## Current State
|
||||
|
||||
`docs-site` is a Next 15 app using Fumadocs. Source pages live under
|
||||
`docs-site/content/docs`, and rendered docs are served under `/docs`.
|
||||
|
||||
The site currently has good human-facing MDX pages, but it does not expose:
|
||||
|
||||
- `/llms.txt`
|
||||
- `/llms-full.txt`
|
||||
- raw markdown routes such as `/docs/getting-started/quickstart.md`
|
||||
- markdown content negotiation
|
||||
|
||||
Many docs pages already use tables and code blocks, but the structure is not
|
||||
consistently optimized for literal agent parsing. CLI and agent-facing pages are
|
||||
the highest-priority content because agents are most likely to copy commands and
|
||||
JSON examples directly.
|
||||
|
||||
## Design
|
||||
|
||||
### Machine-readable access
|
||||
|
||||
Add a small LLM docs utility layer inside `docs-site`:
|
||||
|
||||
- `docs-site/lib/llm-docs.ts`
|
||||
- Converts Fumadocs pages to raw or LLM-readable markdown.
|
||||
- Builds a stable ordered list of docs pages from `source.getPages()`.
|
||||
- Produces the `llms.txt` index content.
|
||||
- Produces the `llms-full.txt` bundled content.
|
||||
|
||||
Add routes:
|
||||
|
||||
- `docs-site/app/llms.txt/route.ts`
|
||||
- Returns `text/plain; charset=utf-8`.
|
||||
- Includes `# KTX`, a blockquote summary, a short description, and sections
|
||||
linking to key docs, markdown docs, CLI reference pages, integration pages,
|
||||
and `/llms-full.txt`.
|
||||
|
||||
- `docs-site/app/llms-full.txt/route.ts`
|
||||
- Returns `text/plain; charset=utf-8`.
|
||||
- Concatenates all docs pages in source order.
|
||||
- Prefixes each page with a stable heading and canonical `/docs/...` URL.
|
||||
|
||||
- `docs-site/app/llms.mdx/docs/[[...slug]]/route.ts`
|
||||
- Returns one docs page as `text/markdown; charset=utf-8`.
|
||||
- Uses the same slug shape as `/docs/[[...slug]]`.
|
||||
- Returns 404 for unknown pages.
|
||||
|
||||
Add a Next rewrite in `docs-site/next.config.mjs`:
|
||||
|
||||
- `/docs/:path*.md` rewrites to `/llms.mdx/docs/:path*`
|
||||
|
||||
Add a markdown negotiation proxy for `/docs/...` requests:
|
||||
|
||||
- Requests whose `Accept` header prefers markdown are rewritten to the matching
|
||||
LLM markdown route.
|
||||
- Normal browser requests continue to render the existing Fumadocs UI.
|
||||
- The proxy must leave `/llms.txt`, `/llms-full.txt`, assets, and non-docs
|
||||
routes unchanged.
|
||||
|
||||
### Content rewrite pass
|
||||
|
||||
Rewrite the existing MDX content in a bounded, high-impact pass. The intent is
|
||||
not to expand every page; it is to make every page more literal and consistent
|
||||
for agents.
|
||||
|
||||
Apply these patterns across docs:
|
||||
|
||||
- Put command signatures in fenced code blocks.
|
||||
- Use tables for flags, options, inputs, outputs, supported values, and
|
||||
environment variables.
|
||||
- Use realistic values in copy-paste examples.
|
||||
- Show complete expected command output when output shape matters.
|
||||
- Add explicit "Common errors" or "Recovery" sections for workflows where a
|
||||
command can fail for predictable reasons.
|
||||
- Add workflow sections that chain commands in the order an agent should use
|
||||
them.
|
||||
- Avoid placeholders that an agent could copy literally, unless the placeholder
|
||||
is clearly marked as a value to replace.
|
||||
|
||||
Priority pages:
|
||||
|
||||
1. `getting-started/quickstart.mdx`
|
||||
- Add a compact workflow summary.
|
||||
- Make prerequisites and generated files explicit.
|
||||
- Add troubleshooting for missing API keys, failed connection tests, daemon
|
||||
startup, and unbuilt context.
|
||||
|
||||
2. `guides/serving-agents.mdx`
|
||||
- Treat MCP tools and `ktx agent` commands as agent-facing API references.
|
||||
- Add tool/command input tables, output expectations, safety constraints, and
|
||||
workflows for answering analytics questions.
|
||||
|
||||
3. `guides/writing-context.mdx`
|
||||
- Add semantic-source schema tables.
|
||||
- Add workflows for listing, reading, editing, validating, querying, and
|
||||
writing wiki knowledge.
|
||||
|
||||
4. `cli-reference/*.mdx`
|
||||
- Normalize every command page to: command signature, subcommands table,
|
||||
option tables, examples, output modes, common errors, and related workflows
|
||||
where useful.
|
||||
|
||||
5. `integrations/agent-clients.mdx`, `integrations/primary-sources.mdx`, and
|
||||
`integrations/context-sources.mdx`
|
||||
- Normalize integration setup sections into structured config tables,
|
||||
copy-paste examples, authentication requirements, and recovery notes.
|
||||
|
||||
6. Concept and benchmark pages
|
||||
- Keep narrative content, but add compact "Agent usage notes" where it helps
|
||||
agents decide when to read or cite the page.
|
||||
|
||||
### Documentation boundaries
|
||||
|
||||
The first pass should not introduce a separate public docs tree or a generated
|
||||
API reference system. It should work with the existing MDX source files and
|
||||
Fumadocs loader.
|
||||
|
||||
Do not add stale compatibility aliases or rename KTX concepts. Keep examples
|
||||
aligned with commands and files that exist in the standalone KTX repository.
|
||||
|
||||
### Testing
|
||||
|
||||
Verification commands:
|
||||
|
||||
- `pnpm --filter ktx-docs build`
|
||||
- `pnpm --filter ktx-docs exec tsc --noEmit` after generated Fumadocs source
|
||||
files exist.
|
||||
- Route checks against a local docs server:
|
||||
- `GET /llms.txt` returns 200 and `text/plain`.
|
||||
- `GET /llms-full.txt` returns 200 and `text/plain`.
|
||||
- `GET /docs/getting-started/quickstart.md` returns 200 and
|
||||
`text/markdown`.
|
||||
- unknown markdown docs paths return 404.
|
||||
|
||||
For content checks, inspect the generated markdown responses to confirm they
|
||||
contain:
|
||||
|
||||
- realistic command examples,
|
||||
- tables,
|
||||
- full output examples where documented,
|
||||
- workflow sections,
|
||||
- recovery/error sections.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- `/llms.txt` gives agents a concise index with links to key KTX docs and
|
||||
`/llms-full.txt`.
|
||||
- `/llms-full.txt` returns all docs content in source order as plain text.
|
||||
- Every Fumadocs page can be fetched through a `.md` URL.
|
||||
- High-priority docs pages use consistent agent-friendly structure.
|
||||
- The docs site builds successfully.
|
||||
- Verification results and any skipped checks are reported clearly.
|
||||
Loading…
Add table
Add a link
Reference in a new issue