// what the agent sees

Ask digest

When you press ⌘K and ask a question, the agent doesn't read these pages — it reads this. It's committed as .hev-ask/digest.json, rendered here exactly the way the loop discloses it: a map it holds in context, and details it opens on demand.

version
2
sections
86
glossary
15
generated
2026-06-05
content hash
b8987e737da2
  1. level 1 · the map

    Always in the prompt: every section's id, heading, and one-line summary, plus the glossary's aliases for widening a query. This is the collapsed row below.

  2. level 2 · open_section()

    On demand, the agent opens a section to read its verbatim facts — and, for reference sections, the source text. That's what expanding a row reveals.

Expand a row to make the same call the agent does.

Orientation

The compact product overview the build distills — context for the keyword/expansion path.

hev ask

hev ask (@hev/ask) is a ⌘K search overlay for Astro docs sites. It distills the site's content collection into an ask digest — a token-efficient, committed JSON form of the docs — and serves it to readers (an answer overlay) and coding agents (the ask CLI and an MCP server).

Core ideas users ask about:

  • Ask digest (.hev-ask/digest.json): offline-built, committed, reviewable. Nodes hold model-authored summaries plus deterministically extracted verbatim facts; only the distillation is model work, and a content-hash gate skips rebuilds when docs are unchanged. (kg is the digest's historical name, kept in the CLI command group, the path flag, and the virtual module id.)
  • Progressive disclosure: the agentic loop holds a primer and section map in its prompt, opens only the sections it needs, and reads full source text only for reference sections.
  • Two search paths: instant keyless keyword search (token overlap widened by the glossary), and on Enter a bounded Claude loop that streams a grounded answer over SSE with inline deep links.
  • Deep links: every result and citation lands on an exact heading anchor generated with the same slugger Astro uses; a verify command gates drift in CI.
  • Degradation: no key → keyword mode; no digest → plain token overlap; nothing hard-fails.
  • Building: the bundled build-digest skill runs inside a Claude Code subscription (no API key, no token spend on your own key); ask kg build is the one-call fallback for CI.

Users phrase questions as: how do I add search to my Astro site, how does the AI answer work, what happens without an API key, how do I rebuild or verify the digest, how does it compare to Pagefind/Algolia/Orama, what are the limits.

Glossary 15 terms

Aliases that widen a reader's query before retrieval — so k8s finds kubernetes. List the terms; open one for its aliases and definition.

Sections 86 nodes

One node per heading — the map the agent navigates. Collapsed shows the summary it always sees; open a section to reveal its facts, just like the loop's open_section.

API

  • CLI reference
    The ask binary has two command groups: consumer verbs that read the committed digest progressively (skim, find, open, ask, or serve it all to an agent) and producer verbs under the kg group — the digest's historical name — that build and verify it. A deprecated alias binary forwards to the new group with a one-line migration notice.
    facts · quoted verbatim
    @hev/askaskoverviewglossarysearchsectionssection getanswermcpask kgkgbuildcorpusassembleverifyhev-ask-kgask kg ...Callout.astro

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Building the digest reference
    Producer commands run from the site root: a hash-gated one-shot build, a corpus emitter for keyless distillation, an assembler that turns a distillation into the digest, and a verifier for anchors, coverage, and fidelity. The model authors only context, glossary, summaries, and suggestions; chunking, facts, overview, sources, and the content hash are computed in code.
    facts · quoted verbatim
    ask kg build # one-shot build; needs ANTHROPIC_API_KEY only when stale ask kg corpus # emit sections for a keyless skill/model distillation ask kg assemble # assemble .hev-ask/digest.json from that distillation ask kg verify # build the site and verify anchors, coverage, fidelityask kg build.hev-ask/digest.jsonask kg corpus.hev-ask/kg-input.jsonask kg assemble.hev-ask/kg-distill.jsoncontextglossarysummariessuggestionsask kg verify--skip-build--strict

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Claude Code skill reference
    The bundled skill builds the digest inside a Claude Code subscription, so it costs no API tokens on the user's own key. It runs the same deterministic corpus-distill-assemble seam and produces the same artifact shape under the same hash gate.
    facts · quoted verbatim
    ask kg corpus -> .hev-ask/kg-input.json ...writes .hev-ask/kg-distill.json... ask kg assemble -> .hev-ask/digest.jsonbuild-digestANTHROPIC_API_KEYdigest.jsonask kg build

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Distribution reference
    The npm package ships two bins: the main v3 CLI and a deprecated alias that forwards to the kg command group. The launcher resolves an environment override first, then a platform-specific binary package, then checked-out Go source for development.
    facts · quoted verbatim
    askhev-ask-kgask kg ...HEV_ASK_BINARY

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Flags reference
    Reference table of global flags covering the digest path, remote endpoint, JSON output, result caps, collection and base-path selection, content globs, chunk heading depth, the build model, producer input and output paths, the verify build command, skip-build, and strict mode. Global flags come before the command.
    facts · quoted verbatim
    ask --kg-path .hev-ask/digest.json --json search "openapi" ask --endpoint https://askhev.com/api/ask mcp ask kg build --collection docs --collection guides --chunk-heading-depth 2 ask kg verify --skip-build--kg-path <path>.hev-ask/digest.json--endpoint <url>/api/askanswer--json--max-results <n>--collection <name>docs--base-path <path>/docs/--content-glob <glob>--chunk-heading-depth <n>--kg-model <model>claude-opus-4-8ask kg build--out <path>.hev-ask/kg-input.jsonask kg corpus--input <path>.hev-ask/kg-distill.jsonask kg assemble--build-command <cmd>

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Go library reference
    A reusable Go API offers pure helpers and an embeddable, dependency-free command group for mounting the same verbs in another CLI. Helpers cover loading the digest, glossary and section reads, search, an endpoint client, building, anchor verification, and MCP serving.
    facts · quoted verbatim
    group := ask.NewCommandGroup(ask.CommandOptions{ KGPath: ".hev-ask/digest.json", }) err := group.Run(ctx, []string{"search", "read endpoints"}, os.Stdin, os.Stdout, os.Stderr)pkg/askLoadGraphListGlossaryGetSectionSearchGraphNewEndpointClientBuildKnowledgeGraphVerifyAnchorsServeMCP

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • MCP reference
    The CLI runs a stdio MCP server over the same read and search surface. Point it at a local digest for checked-out repos, or at a deployed endpoint when the agent needs the remote digest or streamed answers.
    facts · quoted verbatim
    { "mcpServers": { "docs": { "command": "ask", "args": ["--kg-path", ".hev-ask/digest.json", "mcp"] } } }{ "mcpServers": { "askhev": { "command": "ask", "args": ["--endpoint", "https://askhev.com/api/ask", "mcp"] } } }ask mcpglossary_listglossary_getsections_listsection_getoverviewsearchanswer

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Package scripts reference
    Sites typically wrap the build and verify commands in package scripts. Scripts calling the deprecated alias keep working through the forward, but new scripts should use the kg command group.
    facts · quoted verbatim
    { "scripts": { "kg:build": "ask kg build", "kg:verify": "ask kg verify" } }ask kghev-ask-kg buildhev-ask-kg verify

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Reading the digest reference
    By default the CLI reads the committed digest from the current repo; an endpoint flag switches reads to a deployed site's HTTP API. The answer verb requires the endpoint because it uses the deployed agentic SSE path; local search is the keyless alternative.
    facts · quoted verbatim
    ask glossary list ask glossary get "ask digest" ask sections list --group API ask section get api/endpoint#digest-reads-get ask overview ask search "read endpoints" ask --endpoint https://askhev.com/api/ask answer "what read routes exist?" ask mcpask.hev-ask/digest.json--endpoint <url>ask answer--endpointask search

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Where it runs reference
    Producer commands need filesystem access and run locally or in CI; the Astro integration also triggers the hash-gated build during the site build when a key is present, falling back to the committed artifact. The deployed site reads the digest through a virtual module, and wiring verify into CI is the mechanical guard for anchor correctness.
    facts · quoted verbatim
    ask kg buildastro buildANTHROPIC_API_KEYvirtual:hev-ask/kgask kg verify

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Configuration reference
    The integration is the package's default export and takes one options object. Only the collection list is effectively required; everything else has a default.
    facts · quoted verbatim
    // astro.config.mjs import hevAsk from "@hev/ask"; export default defineConfig({ integrations: [ hevAsk({ collections: ["docs"], basePath: "/docs/", model: "claude-haiku-4-5", maxResults: 6, }), ], });hevAsk()@hev/askcollectionsCallout.astro

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Options reference
    Reference table of every option: collections, base path, endpoint route, the loop and digest-build models, result and answer-token caps, iteration and chunk-depth limits, per-search candidates, the per-document cap, the digest path, and content globs. A changed endpoint must match the overlay component's endpoint prop.
    facts · quoted verbatim
    collectionsstring[]basePathstring'/docs/'basePath + slug#anchorendpoint'/api/ask'model'claude-haiku-4-5'kgModel'claude-opus-4-8'maxResultsnumberanswerMaxTokens1024maxIterationssearchchunkHeadingDepth#####candidatePerSearchperDocCap

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Tuning notes reference
    Practical knobs: heading depth trades finer anchors against too-small sections, the iteration cap bounds agentic latency, the per-document cap controls result spread, and candidates per search trade recall against tokens.
    facts · quoted verbatim
    chunkHeadingDepth###maxIterationsperDocCapcandidatePerSearch

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • TypeScript reference
    The options type is exported for editor help and typed configuration.
    facts · quoted verbatim
    import type { HevAskOptions } from "@hev/ask";

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • What the integration does reference
    At startup the integration injects the on-demand endpoint route, registers virtual modules for the resolved config and the inlined digest, watches the digest path so dev reloads on changes, and warns when collections are missing. At build it runs the hash-gated digest build when a key is present, otherwise warns and keeps the committed artifact — never failing for lack of a key.
    facts · quoted verbatim
    astro:config:setupendpoint@hev/ask/endpointprerender: falsevirtual:hev-ask/configvirtual:hev-ask/kgkgPathcollectionsastro:build:startANTHROPIC_API_KEY

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Search endpoint reference
    One injected on-demand route tree serves the overlay: keyword mode returns JSON, agentic mode streams a grounded answer over Server-Sent Events, and keyless sub-routes expose the digest to CLIs, MCP servers, and generated clients. An OpenAPI 3.1 contract is published alongside.
    facts · quoted verbatim
    /api/asktext/event-stream/openapi.yamlCallout.astro3.1openapi.yaml

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Agentic response (SSE) reference
    With a key and agentic mode the endpoint streams named SSE frames: search activity lines, a one-time sources set sent before any token so clients can validate links, token deltas of the Markdown answer, a done marker, and an error frame for failures after streaming began. Sources carry the deep-link URL; the answer prose carries the substance.
    facts · quoted verbatim
    modeagenticcontent-type: text/event-streamsearch{ query }sources{ sources: Source[], model, mode }token{ text }done{}error{ error }200Source{ title, heading?, url, group? }snippeturl

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Digest reads (GET) reference
    Keyless GET routes read the inlined digest and never call a model: glossary listing and term lookup, section summaries with an optional group filter, full section nodes by id, and the overview-plus-context pair. IDs containing slashes or hashes are URL-encoded in the path, and misses return a JSON 404.
    facts · quoted verbatim
    { "error": "Not found." }virtual:hev-ask/kgGET /api/ask/glossary{ "terms": GlossaryEntry[] }GET /api/ask/glossary/{term}GlossaryEntryGET /api/ask/sections{ "sections": SectionSummary[] }GET /api/ask/sections?group=APIGET /api/ask/sections/{id}KnowledgeNodeGET /api/ask/overview{ "overview": string, "context": string }SectionSummary{ id, title, heading, group, url }/api/ask/sections/api%2Fcli%23flags404

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Errors reference
    Invalid JSON bodies return 400, missing read routes, glossary terms, or section ids return 404, and a failed chunk-index build returns 500. Failures during an agentic stream arrive as a final SSE error event because the HTTP status is already committed.
    facts · quoted verbatim
    400{ "error": "Invalid JSON body." }404{ "error": "…" }500event: error200errore.g

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Index lifecycle reference
    The chunk index builds once per server instance on the first request and is cached for the process lifetime. That first request also compares the live content hash against the digest's and logs a one-time staleness warning — the cue to rebuild.
    facts · quoted verbatim
    ask kg build

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Keyword response (JSON) reference
    Keyword mode returns a JSON envelope of ranked results — title, optional heading and group, the deep-link URL, and a snippet — plus the echoed query, the configured model, the mode that ran, and a warning when an agentic request was downgraded for lack of a key.
    facts · quoted verbatim
    { "results": [ { "title": "Concepts", "heading": "The agentic search loop", "url": "/docs/concepts#the-agentic-search-loop", "group": "Overview", "snippet": "When the reader presses Enter, the query goes to a bounded loop…" } ], "query": "how does agentic search work", "model": "claude-haiku-4-5", "mode": "keyword" }200resultsResult[]titleheading?urlgroup?snippetquerystringmodelmode'keyword'warningstring?#anchor

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • LLM tracing reference
    Setting a PostHog key makes every agentic answer emit a generation trace with model, tokens, latency, and the loop's tool calls; the ingestion host and how much prompt text ships are configurable. Without a key tracing is a no-op, and the answer path never depends on telemetry.
    facts · quoted verbatim
    POSTHOG_KEYPOSTHOG_API_KEY$ai_generationPOSTHOG_HOSTPOSTHOG_CAPTURE_CONTENToffredactedfull

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Mode selection reference
    The endpoint decides the path: empty queries return empty keyword JSON, keyword mode or a missing key returns keyword JSON (with a downgrade warning when agentic was requested), otherwise the agentic SSE stream runs. There is no AI-unavailable error path, and the overlay branches on the response content type.
    facts · quoted verbatim
    { results: [], query: "", model, mode: "keyword" }mode: "keyword"mode: "agentic"warningcontent-type

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Request reference
    Requests are a JSON POST with a query and an optional mode. Empty queries return an empty result set, and omitting the mode behaves like agentic when a key is present.
    facts · quoted verbatim
    { "query": "how does autoscaling work", "mode": "agentic" }POSTquerystringmode'keyword' \| 'agentic'keywordagentic

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Suggested questions (GET) reference
    A keyless GET on the base route returns the digest's baked-in suggested questions and the loop model — no query, no model call. The overlay fetches it once on first open, and an empty list simply means no suggestions are shown.
    facts · quoted verbatim
    { "suggestions": ["How does the digest stay fresh?"], "model": "claude-haiku-4-5" }GET /api/asksuggestions

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • The API key reference
    The endpoint resolves the Anthropic key from the adapter runtime environment first, then the process environment, then the import-time environment. It lives wherever the host injects server secrets and is never sent to the browser.
    facts · quoted verbatim
    ANTHROPIC_API_KEYlocals.runtime.envprocess.envimport.meta.enve.g

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Digest format reference
    The ask digest is a single committed JSON file, built offline and inlined into the site through a virtual module so the running site reads it without filesystem access. It is the agent's view of the docs — a distilled, source-grounded index read progressively — and every node deep-links back to its real section. The kg name survives only in the CLI group, the path flag, and the virtual module id.
    facts · quoted verbatim
    .hev-ask/digest.jsonask kg buildkg--kg-pathvirtual:hev-ask/kgurl#anchorCallout.astro

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Degradation reference
    The digest is read defensively: a missing, malformed, or node-less file degrades the agentic loop to keyword-style search while keyword mode keeps working, and nothing hard-fails. Because it is committed JSON, the deterministic structure reviews in pull requests; only the distillation is model-authored, which is why that step can run inside a Claude Code skill.
    facts · quoted verbatim
    summaryglossarycontextsuggestions

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Fields reference
    Top-level fields: a schema version, a generation timestamp, the content hash that gates freshness, a compact context used as the degradation fallback, the alias-bearing glossary, a deterministic overview map, model-authored suggested questions, the distilled section nodes, and a reserved edges array that ships empty.
    facts · quoted verbatim
    versiongeneratedAtstringcontentHashcontextglossaryGlossaryEntry[]overviewsuggestionsstring[]nodesKnowledgeNode[]edgesKnowledgeEdge[]

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • How each field is used reference
    The overview and nodes are prompt-cached into the loop's system prompt; the glossary widens keyword queries; nodes also lift keyword ranking above incidental mentions; terms back a render-time link-support check; suggestions feed the overlay's empty state; and the content hash lets the build skip model work when nothing changed.
    facts · quoted verbatim
    overviewnodesfactsglossaryk8skubernetessummarytermssuggestionsGETcontentHashbuild

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • KnowledgeNode reference
    Each node pairs the chunk id — mapping one-to-one to a real anchor — with the model's paraphrase, deterministically extracted verbatim facts the model never authors, provenance sources, a mode that marks reference sections as source-primary so the agent reads their source text, and distinctive terms for link validation.
    facts · quoted verbatim
    KnowledgeNodeidstringsummaryfactsFact[]sourcesSourceRef[]urlanchormode'agent-primary' \| 'source-primary'source-primarytermsstring[]

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Regenerating reference
    Rebuild after content changes and commit the result; the hash gate makes this safe to run on every build because model work only happens when content actually changed. Build with the bundled skill or one API call, and run the verifier to gate anchors, coverage, and literal fidelity.
    facts · quoted verbatim
    ask kg buildastro buildask kg verify

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Shape reference
    A worked example of the artifact: version, timestamp, content hash, context, glossary, overview, suggested questions, one fully populated section node with facts and sources, and the empty edges array.
    no verbatim facts in this section

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • MCP server reference
    The MCP command runs a stdio Model Context Protocol server over the same digest reads as the CLI and HTTP API — the zero-glue way to hand a coding agent structured tools for the docs, from a checked-out repo's digest file or a deployed endpoint.
    facts · quoted verbatim
    ask mcp.hev-ask/digest.json/api/ask

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Configure reference
    Two configurations: local keyless reads pointing at the repo's digest file, or a deployed endpoint when the freshest digest or the answer tool matters. Local mode is fully offline, but its answer tool returns an error unless an endpoint is set.
    facts · quoted verbatim
    { "mcpServers": { "docs": { "command": "ask", "args": ["--kg-path", ".hev-ask/digest.json", "mcp"] } } }{ "mcpServers": { "askhev": { "command": "ask", "args": ["--endpoint", "https://askhev.com/api/ask", "mcp"] } } }answer--endpoint

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Data sources reference
    Resolution mirrors the CLI: an endpoint flag routes reads and answers through the deployed HTTP API, otherwise the digest path is read from disk on every tool call — so a just-rebuilt digest is visible without restarting the server.
    facts · quoted verbatim
    ask mcp--endpoint <url>answerPOST /api/ask--kg-path.hev-ask/digest.jsondigest.json

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Protocol surface reference
    The server speaks newline-delimited JSON-RPC over stdio, handling initialization, tool listing, and tool calls. Unknown methods return protocol errors while tool-level failures return MCP error results, and all substantive behavior lives in the shared Go package.
    facts · quoted verbatim
    initializetools/listtools/callisError: truepkg/ask

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Tools reference
    Tools mirror the read surface: glossary listing and lookup, section listing and retrieval, the overview, keyword search, and a streamed answer collapsed into one tool result. Results carry human-readable text plus the original machine shape in structured content.
    facts · quoted verbatim
    glossary_list{ terms: GlossaryEntry[] }glossary_get{ term }sections_list{ group? }{ sections: SectionSummary[] }section_get{ id }overview{ overview, context }search{ query, maxResults? }answer{ query }contentstructuredContent

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • SearchOverlay component reference
    The overlay component renders the ⌘K command palette. Add it once in a global layout; it opens over the page and doesn't affect layout until opened.
    facts · quoted verbatim
    --- import SearchOverlay from "@hev/ask/components/SearchOverlay.astro"; --- <SearchOverlay />SearchOverlay.astro⌘K<dialog>Callout.astro

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Keyboard model reference
    The overlay is ask-first and word count picks the path: one word runs debounced keyword search with an auto-active first result, a second word switches to ask mode where Enter sends the question to the loop, and arrow keys move keyword selection. Without a server key, asking returns keyword results with a surfaced warning instead of breaking.
    facts · quoted verbatim
    Tab

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Keyword results and deep links reference
    Each keyword row shows the document title, an optional heading breadcrumb, and a one-line snippet. The row links to the chunk's URL, which already carries the anchor, so clicking lands on the exact heading.
    facts · quoted verbatim
    Concepts › The agentic loopurl#anchor

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Opening the overlay reference
    Two built-in ways to open the palette: the keyboard shortcut binds automatically once the component is on the page, and any element with the opener data attribute opens it on click — wire up as many triggers as needed.
    facts · quoted verbatim
    <button type="button" data-hev-ask-open> Search <kbd>⌘K</kbd> </button> <a href="#" data-hev-ask-open>Search the docs</a>⌘KCtrl-Kdata-hev-ask-open

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Props reference
    Three props: the endpoint the overlay posts to (which must match the integration's endpoint option), the input placeholder, and the debounce in milliseconds before a keyword query is sent.
    facts · quoted verbatim
    <SearchOverlay endpoint="/api/ask" placeholder="Search hev ask…" debounce={400} />endpointstring'/api/ask'placeholder'Search the docs…'debouncenumber500

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Suggested questions reference
    With AI on, the overlay fetches suggested questions from the endpoint on first open and shows them in the empty state. They come from the digest at build time so rendering costs no model call, and clicking one fills the input and asks immediately.
    facts · quoted verbatim
    GET /api/asksuggestions

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • The mode toggle reference
    An AI-on-Enter preference persists in localStorage. Readers who flip to keyword-only never trigger a model call — a space just searches a phrase, no suggestions are shown, and the choice survives reloads.
    facts · quoted verbatim
    localStoragehev-ask:modeagentickeyword

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • The streamed answer reference
    Asking replaces the keyword rows with an answer panel: the model's sub-queries appear as faint activity lines, then the grounded answer streams token-by-token with accent-styled inline deep links and a sources chip row. Links are validated against the streamed source set, so a hallucinated anchor renders as plain text instead of a dead link.
    facts · quoted verbatim
    searched: …/docs/page#anchor

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗
  • Theming reference
    The overlay reads the page's CSS custom properties for background, text, muted, and accent colors. Because its scoped styles key off those variables, matching a site's look is usually just defining the tokens — no overlay CSS to override.
    facts · quoted verbatim
    :root { --paper: #111111; /* overlay background */ --ink: #fafaf5; /* primary text */ --muted: #6b6b66; /* secondary text */ --signal: #e25822; /* accent / active state */ }as-:root

    Reference section — on open, the agent also receives this section's source text verbatim.

    open section ↗

Overview

  • Concepts summary
    hev ask is three parts: a heading-chunk index with real anchors, an offline ask digest distilling every section, and a bounded agentic loop that reads the digest progressively — primer first, summaries next, full source only when needed. The digest builds offline with a strong model and commits to git; the index and loop run on demand at the edge with no durable state.
    facts · quoted verbatim
    Diagram.astroCallout.astro
    open section ↗
  • Asking is the default summary
    The overlay treats a single word as an instant keyword lookup; a second word switches to ask mode, where Enter sends the question to the agentic loop, and suggested questions baked into the digest make asking the obvious move. Readers can flip to keyword-only, persisted in localStorage, so the model is never called.
    facts · quoted verbatim
    localStorage
    open section ↗
  • Chunks and anchors summary
    Documents are split on headings into section chunks whose URLs carry real anchors, generated with the same slugger Astro's renderer uses so links land on headings that exist. Both the runtime index and the offline build chunk through the same function, so the anchors always agree.
    facts · quoted verbatim
    #####basePath + slug + #anchorgithub-sluggergetCollectiongithub.com
    open section ↗
  • Degradation, by design summary
    Every missing piece degrades instead of failing: no runtime key means keyword-only search, no build key keeps the committed digest with a warning, a missing or node-less digest falls back to plain retrieval with no suggestions, and a stale digest logs a one-line warning but still serves.
    facts · quoted verbatim
    digest.json
    open section ↗
  • Keyword search and the glossary summary
    The instant path is a dependency-free prefilter: query terms expand through glossary aliases, chunks score by token overlap widened by the digest's summaries, terms, and facts, results are capped per document, and snippets excerpt around the first match. It needs no key and no embeddings, and with no digest it degrades to plain token overlap.
    facts · quoted verbatim
    k8skubernetesdigest.jsonsummarytermsfacts
    open section ↗
  • The agentic search loop summary
    Asking sends the query to a bounded tool-use loop that is progressive disclosure over the digest: the primer and section map come free in the prompt, and the model opens only the sections it needs — reading summaries, verbatim facts, and source text for reference sections — up to an iteration cap. The final call drops all tools so the model must stream a grounded answer, citing only sections it opened.
    facts · quoted verbatim
    open_section({ id })factsmaxIterationsurl
    open section ↗
  • The ask digest summary
    The digest is an offline-built, committed artifact holding distilled section nodes with verbatim facts and source links, a deterministic overview map, a compact context and glossary, and suggested questions. Only the distillation is model-authored — structure, facts, overview, and the hash derive in code — which is exactly why the model step fits a Claude Code skill.
    facts · quoted verbatim
    digest.jsonnodessummaryfactssourcesource-primaryoverviewcontextglossarysuggestions
    open section ↗
  • The system prompt is cached summary
    The digest's map and section summaries are injected into the system prompt with a cache marker, so search rounds hit the prompt cache instead of re-sending tokens. The toolless answer turn can't reuse that cache but is the last call anyway, and the loop model defaults to Haiku.
    facts · quoted verbatim
    cache_control4.5
    open section ↗
  • Two ways to build it summary
    The distillation runs two ways into the same deterministic assembler: the recommended Claude Code skill inside an existing subscription with no API key, or a one-call CLI build with Opus for CI. Both are hash-gated so unchanged content does no model work, and the JSON reviews in pull requests like any other change.
    facts · quoted verbatim
    digest.jsonANTHROPIC_API_KEYask kg build4.8
    open section ↗
  • Introduction summary
    hev ask distills an Astro docs site into an ask digest — a token-efficient form of the docs that agents discover progressively through the CLI and readers search through a ⌘K overlay. Build the digest offline with the bundled skill and your subscription, then serve single-turn Q&A for a few cents per query — suited to technical docs, internal wikis, and other medium-sized corpora.
    facts · quoted verbatim
    ask⌘KDiagram.astroCallout.astroastro.build
    open section ↗
  • Build it with your coding agent summary
    The bundled Claude Code skill generates the digest inside an existing coding subscription — no API key, no per-build token spend. Commit the JSON, drop the overlay into a layout, and the site has instant keyword search plus a Claude answer loop, every result deep-linked. The corpus is only the configured collections: no crawler, no external index, nothing to sync.
    facts · quoted verbatim
    .hev-ask/digest.jsonANTHROPIC_API_KEYSearchOverlay.astrodigest.json
    open section ↗
  • Next steps summary
    Pointers onward: the five-minute quick start, the concepts page, tradeoffs and limits, the CLI reference, and the full API reference.
    facts · quoted verbatim
    ask
    open section ↗
  • Who this is for summary
    For maintainers of Astro 5 docs sites with content collections who want search that works without standing up a service, deep-links to the right section, answers questions phrased in the reader's words, and is queryable by coding agents. Static-only keyword needs are better served by Pagefind.
    facts · quoted verbatim
    docs.astro.buildpagefind.app
    open section ↗
  • Limits summary
    The hard boundaries of the current design — corpus scope, recall ceiling, single-call digest build, frontmatter parsing, latency, and adapter requirements — stated as edges of what it covers, not bugs.
    facts · quoted verbatim
    Callout.astro
    open section ↗
  • A server route is required summary
    The search endpoint renders on demand, so a fully static build cannot serve it; a server or hybrid adapter is required, and static-only sites should use a static search tool instead.
    facts · quoted verbatim
    /api/ask
    open section ↗
  • Agentic search adds latency summary
    The agentic path costs up to the iteration cap in Claude round-trips — a few seconds worst case — by nature. The keyword path is the always-available instant lane, and lowering the cap tightens the ceiling.
    facts · quoted verbatim
    maxIterations
    open section ↗
  • Anchors depend on Astro's slugger summary
    Deep links are correct only while generated slugs match Astro's rendered ids. Using the same slugger keeps them aligned, and the verify command fails when any chunk anchor is missing from the built HTML — wire it into CI so a slugging change is caught before a broken link ships.
    facts · quoted verbatim
    idgithub-sluggerask kg verifyverify
    open section ↗
  • Frontmatter parsing is a flat-YAML subset summary
    The offline build parses frontmatter with a small flat-YAML splitter that handles common string and number fields but not nested structures. This only affects disk reads during the offline digest build; the runtime index uses Astro's own collection loader and honors the real schema.
    facts · quoted verbatim
    getCollection
    open section ↗
  • Recall has a keyword ceiling summary
    Retrieval is keyword token overlap widened by the glossary, not embeddings, and the loop cannot ground in what retrieval missed. The glossary recovers most synonym cases, but a query sharing no tokens with the docs can miss entirely; embeddings are the known fix, deliberately unbuilt, and a richer glossary is the cheaper lever.
    facts · quoted verbatim
    k8skubernetes
    open section ↗
  • Secrets live server-side summary
    The agentic path needs the Anthropic key in the server environment that runs the endpoint; it is never exposed to the browser, and without it the endpoint serves keyword results — search degrades rather than breaks.
    facts · quoted verbatim
    ANTHROPIC_API_KEY/api/ask
    open section ↗
  • The corpus is your content collection summary
    Search covers only the configured content collections — no crawler, no sitemap ingestion, and no way to index pages that aren't collection entries. Anything that should be searchable belongs in a collection.
    facts · quoted verbatim
    .astro
    open section ↗
  • The digest build is a single model call summary
    The offline build sends the full cleaned corpus to the model in one call, which fits typical docs sites comfortably but would overflow on a very large corpus. A map-reduce builder is a noted follow-up, not implemented; assume the corpus fits one call.
    no verbatim facts in this section open section ↗
  • Quick start summary
    Add search to an existing Astro 5 collection-based docs site in about five minutes: keyword search first, then an API key to enable agentic answers. The overlay alone gives keyless instant search; adding a server key upgrades Enter into the answer loop, and skipping the key just ships the search UI.
    facts · quoted verbatim
    src/content/docsANTHROPIC_API_KEYSearchOverlay.astroSteps.astroCallout.astro
    open section ↗
  • 1. Install summary
    Install from npm once published, or until then consume the package straight from its subdirectory on GitHub.
    facts · quoted verbatim
    pnpm add @hev/askpnpm add "git+ssh://[email protected]/hev/ask.git#main&path:/packages/ui"
    open section ↗
  • 2. Register the integration summary
    Register the integration in the Astro config with the content collection name(s) — the one required option — and the base path that maps slugs to URLs. Everything else has defaults covered in the configuration reference.
    facts · quoted verbatim
    // astro.config.mjs import { defineConfig } from "astro/config"; import hevAsk from "@hev/ask"; export default defineConfig({ integrations: [ hevAsk({ collections: ["docs"], // your content collection name(s) basePath: "/docs/", // slug → URL prefix: basePath + slug }), ], });collections
    open section ↗
  • 3. Add a server adapter summary
    The search route renders on demand, so add the adapter matching the host. Existing pages stay prerendered; only the search route runs as a function.
    facts · quoted verbatim
    // astro.config.mjs import cloudflare from "@astrojs/cloudflare"; export default defineConfig({ adapter: cloudflare({ platformProxy: { enabled: true } }), // ...integrations as above });/api/ask
    open section ↗
  • 4. Render the overlay summary
    Add the overlay component once somewhere global, like the base layout. Any element with the opener attribute opens the palette, the keyboard shortcut binds automatically, and keyword search works from there.
    facts · quoted verbatim
    --- // src/layouts/Base.astro import SearchOverlay from "@hev/ask/components/SearchOverlay.astro"; --- <button type="button" data-hev-ask-open> Search <kbd>⌘K</kbd> </button> <slot /> <SearchOverlay />data-hev-ask-open⌘Kastro dev
    open section ↗
  • 5. Build the digest summary
    The digest is an offline-built JSON file you commit: it gives the loop context, ranks keyword results, supplies the glossary, and holds the suggested questions. The recommended path is the bundled Claude Code skill — built inside the subscription, no API key — with a one-call CLI build for CI; both are hash-gated, then verify and commit.
    facts · quoted verbatim
    You: build the hev ask digest Claude runs: ask kg corpus # emits the sections to distil …writes context/glossary/summaries/suggestions… ask kg assemble # writes .hev-ask/digest.jsonexport ANTHROPIC_API_KEY=sk-ant-... pnpm exec ask kg build # writes .hev-ask/digest.jsonpnpm exec ask kg verify # builds the site, checks every anchor resolves git add .hev-ask/digest.jsonk8skubernetesastro buildclaude.com
    open section ↗
  • Enable agentic search summary
    Set the Anthropic key in the server environment where the endpoint runs. With it, Enter runs the agentic loop — self-issued sub-queries, a grounded answer, inline deep links; without it, Enter returns keyword results.
    facts · quoted verbatim
    ANTHROPIC_API_KEY/api/ask.env
    open section ↗
  • Prerequisites summary
    Astro 5 with at least one content collection, a server or hybrid adapter for the on-demand route, and an Anthropic key only if agentic search is wanted — keyword search needs none.
    facts · quoted verbatim
    /api/askANTHROPIC_API_KEYdocs.astro.build
    open section ↗
  • Set up keyword search summary
    The keyword path is set up by the install, register, adapter, and overlay steps that follow.
    facts · quoted verbatim
    astro.config.mjsSearchOverlay.astro
    open section ↗
  • Verify it works summary
    Sanity checks: a single heading word should deep-link to its section, a multi-word question should stream a grounded answer with the sub-queries visible, and the verify command — which exits non-zero on any missing anchor — belongs in CI.
    facts · quoted verbatim
    /docs/page#headingask kg verify
    open section ↗
  • Tradeoffs summary
    Every search tool makes choices; this page states honestly what hev ask trades away — its dependency posture, the committed digest, agentic cost and latency — and how it compares to Pagefind, Algolia, and Orama.
    facts · quoted verbatim
    Callout.astro
    open section ↗
  • A committed digest summary
    Generating the digest offline and committing it makes it reviewable in pull requests, deterministic at runtime, free on the request path, and bundleable at the edge with no filesystem access. The cost is staleness when a rebuild is forgotten; the runtime warns on hash divergence, and the hash gate makes rebuild-on-every-change the cheap, intended workflow.
    no verbatim facts in this section open section ↗
  • Cost and latency of agentic search summary
    The agentic path costs real but small money and a few seconds of latency: one bounded loop per query on the default Haiku model with prompt-cached context, plus an Opus-powered offline digest build paid only when content changes. Keyword-only is a first-class mode for keyless deployments, not a fallback afterthought.
    facts · quoted verbatim
    maxIterations
    open section ↗
  • How it compares summary
    A comparison against Pagefind, Algolia DocSearch, and Orama across retrieval, AI ranking, deep links, and hosting. Choose Pagefind for static keyword simplicity, Algolia for a managed service with a crawler, Orama for client-side vector search, and hev ask when docs live in Astro collections and a reader's question — not just keywords — should find the right section.
    no verbatim facts in this section open section ↗
  • Keyword retrieval, not embeddings summary
    Token-overlap retrieval widened by the glossary means nothing to host, nothing to sync, edge-safe, and instant — but paraphrase recall has a ceiling, and the agent grounds only in what retrieval surfaced. Embeddings would do better for token-free phrasing; that upgrade is deferred, not designed out.
    no verbatim facts in this section open section ↗
  • One dependency, deliberately summary
    The package keeps close to zero dependencies with one deliberate exception: the same tiny, edge-safe slugger Astro uses. Hand-rolling anchors risks drifting from the renderer and shipping links that 404 to the top of the page; sharing the slugger guarantees byte-identical anchors.
    facts · quoted verbatim
    github-sluggergithub.com
    open section ↗
  • Two paths instead of one summary
    Running an instant keyword path beside an agentic path keeps the common case instant and keyless while hard questions get a smarter ranker. The cost is a slightly more complex interaction — readers learn that Enter means asking AI — which fits docs, where queries split between jumping to known things and finding the unnameable.
    no verbatim facts in this section open section ↗
Raw digest.json artifact
{
  "version": 2,
  "generatedAt": "2026-06-05T01:49:16.438Z",
  "contentHash": "b8987e737da2dbe8c58216407c6b667d64f24ac18d0997e682cfc450347bef2d",
  "context": "## hev ask\n\nhev ask (`@hev/ask`) is a ⌘K search overlay for Astro docs sites. It distills the site's content collection into an **ask digest** — a token-efficient, committed JSON form of the docs — and serves it to readers (an answer overlay) and coding agents (the ask CLI and an MCP server).\n\nCore ideas users ask about:\n- **Ask digest (`.hev-ask/digest.json`)**: offline-built, committed, reviewable. Nodes hold model-authored summaries plus deterministically extracted verbatim facts; only the distillation is model work, and a content-hash gate skips rebuilds when docs are unchanged. (`kg` is the digest's historical name, kept in the CLI command group, the path flag, and the virtual module id.)\n- **Progressive disclosure**: the agentic loop holds a primer and section map in its prompt, opens only the sections it needs, and reads full source text only for reference sections.\n- **Two search paths**: instant keyless keyword search (token overlap widened by the glossary), and on Enter a bounded Claude loop that streams a grounded answer over SSE with inline deep links.\n- **Deep links**: every result and citation lands on an exact heading anchor generated with the same slugger Astro uses; a verify command gates drift in CI.\n- **Degradation**: no key → keyword mode; no digest → plain token overlap; nothing hard-fails.\n- **Building**: the bundled build-digest skill runs inside a Claude Code subscription (no API key, no token spend on your own key); `ask kg build` is the one-call fallback for CI.\n\nUsers phrase questions as: how do I add search to my Astro site, how does the AI answer work, what happens without an API key, how do I rebuild or verify the digest, how does it compare to Pagefind/Algolia/Orama, what are the limits.",
  "glossary": [
    {
      "term": "ask digest",
      "aliases": [
        "digest",
        "kg",
        "knowledge graph",
        "digest.json"
      ],
      "definition": "The committed JSON artifact distilling every doc section — summaries, verbatim facts, glossary, overview, and suggested questions — that the agentic loop reads progressively."
    },
    {
      "term": "agentic search",
      "aliases": [
        "agentic loop",
        "ask mode",
        "AI search",
        "answer loop",
        "search loop"
      ],
      "definition": "The bounded Claude tool-use loop that opens digest sections and streams a grounded, deep-linked answer over SSE."
    },
    {
      "term": "keyword search",
      "aliases": [
        "keyword mode",
        "instant search",
        "prefilter"
      ],
      "definition": "The keyless instant path: token-overlap scoring over heading chunks, widened by the glossary and the digest's per-section signal."
    },
    {
      "term": "progressive disclosure",
      "aliases": [
        "progressive"
      ],
      "definition": "The loop's reading pattern — primer and section map up front, distilled summaries on open, full source text only for reference sections."
    },
    {
      "term": "chunk",
      "aliases": [
        "heading chunk",
        "section"
      ],
      "definition": "A heading-bounded slice of a document; the unit of indexing, retrieval, and deep linking."
    },
    {
      "term": "anchor",
      "aliases": [
        "deep link",
        "heading anchor"
      ],
      "definition": "The URL fragment generated with the same slugger Astro uses, so results land on the exact rendered heading."
    },
    {
      "term": "glossary",
      "aliases": [
        "aliases",
        "query expansion"
      ],
      "definition": "Digest terms with aliases that widen keyword queries (k8s finds kubernetes) and one-line definitions agents can read."
    },
    {
      "term": "SearchOverlay",
      "aliases": [
        "overlay",
        "command palette",
        "cmd-k",
        "ctrl-k"
      ],
      "definition": "The Astro component rendering the ask-first ⌘K search palette; add it once in a global layout."
    },
    {
      "term": "ask CLI",
      "aliases": [
        "ask",
        "CLI",
        "ask binary"
      ],
      "definition": "The binary with consumer verbs for reading the digest progressively and producer verbs under the kg group for building and verifying it."
    },
    {
      "term": "MCP server",
      "aliases": [
        "ask mcp",
        "MCP",
        "Model Context Protocol"
      ],
      "definition": "The stdio MCP server exposing digest reads, search, and answers as structured tools for coding agents."
    },
    {
      "term": "endpoint",
      "aliases": [
        "/api/ask",
        "search endpoint",
        "API route"
      ],
      "definition": "The injected on-demand route serving keyword JSON, agentic SSE, suggested questions, and keyless digest reads."
    },
    {
      "term": "content hash",
      "aliases": [
        "hash gate",
        "freshness",
        "stale"
      ],
      "definition": "The sha256 of chunk text that lets builds skip model work when docs are unchanged and flags staleness at runtime."
    },
    {
      "term": "build-digest skill",
      "aliases": [
        "build-kg",
        "Claude Code skill",
        "bundled skill"
      ],
      "definition": "The bundled skill that distills the digest inside a Claude Code subscription, costing no API tokens on the user's own key."
    },
    {
      "term": "verify",
      "aliases": [
        "ask kg verify",
        "anchor verification",
        "CI gate"
      ],
      "definition": "The command that builds the site and fails on anchor drift, warning on digest coverage and literal fidelity."
    },
    {
      "term": "degradation",
      "aliases": [
        "fallback",
        "no API key",
        "keyless"
      ],
      "definition": "The design rule that every missing piece downgrades — no key means keyword mode, no digest means plain token overlap — and nothing hard-fails."
    }
  ],
  "overview": "## API\n- CLI — `api/cli`\n- Building the digest — `api/cli#building-the-digest`\n- Claude Code skill — `api/cli#claude-code-skill`\n- Distribution — `api/cli#distribution`\n- Flags — `api/cli#flags`\n- Go library — `api/cli#go-library`\n- MCP — `api/cli#mcp`\n- Package scripts — `api/cli#package-scripts`\n- Reading the digest — `api/cli#reading-the-digest`\n- Where it runs — `api/cli#where-it-runs`\n- Configuration — `api/configuration`\n- Options — `api/configuration#options`\n- Tuning notes — `api/configuration#tuning-notes`\n- TypeScript — `api/configuration#typescript`\n- What the integration does — `api/configuration#what-the-integration-does`\n- Search endpoint — `api/endpoint`\n- Agentic response (SSE) — `api/endpoint#agentic-response-sse`\n- Digest reads (GET) — `api/endpoint#digest-reads-get`\n- Errors — `api/endpoint#errors`\n- Index lifecycle — `api/endpoint#index-lifecycle`\n- Keyword response (JSON) — `api/endpoint#keyword-response-json`\n- LLM tracing — `api/endpoint#llm-tracing`\n- Mode selection — `api/endpoint#mode-selection`\n- Request — `api/endpoint#request`\n- Suggested questions (GET) — `api/endpoint#suggested-questions-get`\n- The API key — `api/endpoint#the-api-key`\n- Digest format — `api/knowledge-graph`\n- Degradation — `api/knowledge-graph#degradation`\n- Fields — `api/knowledge-graph#fields`\n- How each field is used — `api/knowledge-graph#how-each-field-is-used`\n- KnowledgeNode — `api/knowledge-graph#knowledgenode`\n- Regenerating — `api/knowledge-graph#regenerating`\n- Shape — `api/knowledge-graph#shape`\n- MCP server — `api/mcp`\n- Configure — `api/mcp#configure`\n- Data sources — `api/mcp#data-sources`\n- Protocol surface — `api/mcp#protocol-surface`\n- Tools — `api/mcp#tools`\n- SearchOverlay component — `api/search-overlay`\n- Keyboard model — `api/search-overlay#keyboard-model`\n- Keyword results and deep links — `api/search-overlay#keyword-results-and-deep-links`\n- Opening the overlay — `api/search-overlay#opening-the-overlay`\n- Props — `api/search-overlay#props`\n- Suggested questions — `api/search-overlay#suggested-questions`\n- The mode toggle — `api/search-overlay#the-mode-toggle`\n- The streamed answer — `api/search-overlay#the-streamed-answer`\n- Theming — `api/search-overlay#theming`\n## Overview\n- Concepts — `concepts`\n- Asking is the default — `concepts#asking-is-the-default`\n- Chunks and anchors — `concepts#chunks-and-anchors`\n- Degradation, by design — `concepts#degradation-by-design`\n- Keyword search and the glossary — `concepts#keyword-search-and-the-glossary`\n- The agentic search loop — `concepts#the-agentic-search-loop`\n- The ask digest — `concepts#the-ask-digest`\n- The system prompt is cached — `concepts#the-system-prompt-is-cached`\n- Two ways to build it — `concepts#two-ways-to-build-it`\n- Introduction — `index`\n- Build it with your coding agent — `index#build-it-with-your-coding-agent`\n- Next steps — `index#next-steps`\n- Who this is for — `index#who-this-is-for`\n- Limits — `limits`\n- A server route is required — `limits#a-server-route-is-required`\n- Agentic search adds latency — `limits#agentic-search-adds-latency`\n- Anchors depend on Astro's slugger — `limits#anchors-depend-on-astros-slugger`\n- Frontmatter parsing is a flat-YAML subset — `limits#frontmatter-parsing-is-a-flat-yaml-subset`\n- Recall has a keyword ceiling — `limits#recall-has-a-keyword-ceiling`\n- Secrets live server-side — `limits#secrets-live-server-side`\n- The corpus is your content collection — `limits#the-corpus-is-your-content-collection`\n- The digest build is a single model call — `limits#the-digest-build-is-a-single-model-call`\n- Quick start — `quickstart`\n- 1. Install — `quickstart#1-install`\n- 2. Register the integration — `quickstart#2-register-the-integration`\n- 3. Add a server adapter — `quickstart#3-add-a-server-adapter`\n- 4. Render the overlay — `quickstart#4-render-the-overlay`\n- 5. Build the digest — `quickstart#5-build-the-digest`\n- Enable agentic search — `quickstart#enable-agentic-search`\n- Prerequisites — `quickstart#prerequisites`\n- Set up keyword search — `quickstart#set-up-keyword-search`\n- Verify it works — `quickstart#verify-it-works`\n- Tradeoffs — `tradeoffs`\n- A committed digest — `tradeoffs#a-committed-digest`\n- Cost and latency of agentic search — `tradeoffs#cost-and-latency-of-agentic-search`\n- How it compares — `tradeoffs#how-it-compares`\n- Keyword retrieval, not embeddings — `tradeoffs#keyword-retrieval-not-embeddings`\n- One dependency, deliberately — `tradeoffs#one-dependency-deliberately`\n- Two paths instead of one — `tradeoffs#two-paths-instead-of-one`",
  "suggestions": [
    "How do I add hev ask to my Astro docs site?",
    "How does the ask digest stay fresh after docs change?",
    "What happens if I don't set an API key?",
    "How does hev ask compare to Pagefind or Algolia?",
    "How does the agentic answer loop stay grounded?"
  ],
  "nodes": [
    {
      "id": "api/cli",
      "kind": "section",
      "title": "CLI",
      "heading": null,
      "group": "API",
      "url": "/docs/api/cli",
      "summary": "The ask binary has two command groups: consumer verbs that read the committed digest progressively (skim, find, open, ask, or serve it all to an agent) and producer verbs under the kg group — the digest's historical name — that build and verify it. A deprecated alias binary forwards to the new group with a one-line migration notice.",
      "facts": [
        {
          "kind": "code",
          "literal": "@hev/ask",
          "chunkId": "api/cli"
        },
        {
          "kind": "code",
          "literal": "ask",
          "chunkId": "api/cli"
        },
        {
          "kind": "code",
          "literal": "overview",
          "chunkId": "api/cli"
        },
        {
          "kind": "code",
          "literal": "glossary",
          "chunkId": "api/cli"
        },
        {
          "kind": "code",
          "literal": "search",
          "chunkId": "api/cli"
        },
        {
          "kind": "code",
          "literal": "sections",
          "chunkId": "api/cli"
        },
        {
          "kind": "code",
          "literal": "section get",
          "chunkId": "api/cli"
        },
        {
          "kind": "code",
          "literal": "answer",
          "chunkId": "api/cli"
        },
        {
          "kind": "code",
          "literal": "mcp",
          "chunkId": "api/cli"
        },
        {
          "kind": "code",
          "literal": "ask kg",
          "chunkId": "api/cli"
        },
        {
          "kind": "code",
          "literal": "kg",
          "chunkId": "api/cli"
        },
        {
          "kind": "code",
          "literal": "build",
          "chunkId": "api/cli"
        },
        {
          "kind": "code",
          "literal": "corpus",
          "chunkId": "api/cli"
        },
        {
          "kind": "code",
          "literal": "assemble",
          "chunkId": "api/cli"
        },
        {
          "kind": "code",
          "literal": "verify",
          "chunkId": "api/cli"
        },
        {
          "kind": "code",
          "literal": "hev-ask-kg",
          "chunkId": "api/cli"
        },
        {
          "kind": "code",
          "literal": "ask kg ...",
          "chunkId": "api/cli"
        },
        {
          "kind": "value",
          "literal": "Callout.astro",
          "chunkId": "api/cli"
        }
      ],
      "sources": [
        {
          "chunkId": "api/cli",
          "url": "/docs/api/cli",
          "anchor": null
        }
      ],
      "mode": "source-primary",
      "terms": [
        "binary",
        "command",
        "groups",
        "consumer",
        "verbs",
        "read",
        "committed",
        "digest",
        "progressively",
        "skim",
        "find",
        "open",
        "serve",
        "agent",
        "producer",
        "under",
        "group",
        "historical",
        "name",
        "build",
        "verify",
        "deprecated",
        "alias",
        "forwards",
        "line",
        "migration",
        "notice",
        "overview",
        "glossary",
        "search",
        "sections",
        "section",
        "answer",
        "corpus",
        "assemble",
        "callout",
        "astro",
        "reads",
        "builds",
        "verifies"
      ]
    },
    {
      "id": "api/cli#building-the-digest",
      "kind": "section",
      "title": "CLI",
      "heading": "Building the digest",
      "group": "API",
      "url": "/docs/api/cli#building-the-digest",
      "summary": "Producer commands run from the site root: a hash-gated one-shot build, a corpus emitter for keyless distillation, an assembler that turns a distillation into the digest, and a verifier for anchors, coverage, and fidelity. The model authors only context, glossary, summaries, and suggestions; chunking, facts, overview, sources, and the content hash are computed in code.",
      "facts": [
        {
          "kind": "code",
          "literal": "ask kg build        # one-shot build; needs ANTHROPIC_API_KEY only when stale\nask kg corpus       # emit sections for a keyless skill/model distillation\nask kg assemble     # assemble .hev-ask/digest.json from that distillation\nask kg verify       # build the site and verify anchors, coverage, fidelity",
          "chunkId": "api/cli#building-the-digest"
        },
        {
          "kind": "code",
          "literal": "ask kg build",
          "chunkId": "api/cli#building-the-digest"
        },
        {
          "kind": "code",
          "literal": ".hev-ask/digest.json",
          "chunkId": "api/cli#building-the-digest"
        },
        {
          "kind": "code",
          "literal": "ask kg corpus",
          "chunkId": "api/cli#building-the-digest"
        },
        {
          "kind": "code",
          "literal": ".hev-ask/kg-input.json",
          "chunkId": "api/cli#building-the-digest"
        },
        {
          "kind": "code",
          "literal": "ask kg assemble",
          "chunkId": "api/cli#building-the-digest"
        },
        {
          "kind": "code",
          "literal": ".hev-ask/kg-distill.json",
          "chunkId": "api/cli#building-the-digest"
        },
        {
          "kind": "code",
          "literal": "context",
          "chunkId": "api/cli#building-the-digest"
        },
        {
          "kind": "code",
          "literal": "glossary",
          "chunkId": "api/cli#building-the-digest"
        },
        {
          "kind": "code",
          "literal": "summaries",
          "chunkId": "api/cli#building-the-digest"
        },
        {
          "kind": "code",
          "literal": "suggestions",
          "chunkId": "api/cli#building-the-digest"
        },
        {
          "kind": "code",
          "literal": "ask kg verify",
          "chunkId": "api/cli#building-the-digest"
        },
        {
          "kind": "code",
          "literal": "--skip-build",
          "chunkId": "api/cli#building-the-digest"
        },
        {
          "kind": "code",
          "literal": "--strict",
          "chunkId": "api/cli#building-the-digest"
        }
      ],
      "sources": [
        {
          "chunkId": "api/cli#building-the-digest",
          "url": "/docs/api/cli#building-the-digest",
          "anchor": "building-the-digest"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "building",
        "digest",
        "producer",
        "commands",
        "site",
        "root",
        "hash",
        "gated",
        "shot",
        "build",
        "corpus",
        "emitter",
        "keyless",
        "distillation",
        "assembler",
        "turns",
        "verifier",
        "anchors",
        "coverage",
        "fidelity",
        "model",
        "authors",
        "only",
        "context",
        "glossary",
        "summaries",
        "suggestions",
        "chunking",
        "facts",
        "overview",
        "sources",
        "content",
        "computed",
        "code",
        "needs",
        "anthropic",
        "stale",
        "emit",
        "sections",
        "skill"
      ]
    },
    {
      "id": "api/cli#claude-code-skill",
      "kind": "section",
      "title": "CLI",
      "heading": "Claude Code skill",
      "group": "API",
      "url": "/docs/api/cli#claude-code-skill",
      "summary": "The bundled skill builds the digest inside a Claude Code subscription, so it costs no API tokens on the user's own key. It runs the same deterministic corpus-distill-assemble seam and produces the same artifact shape under the same hash gate.",
      "facts": [
        {
          "kind": "code",
          "literal": "ask kg corpus       -> .hev-ask/kg-input.json\n...writes .hev-ask/kg-distill.json...\nask kg assemble     -> .hev-ask/digest.json",
          "chunkId": "api/cli#claude-code-skill"
        },
        {
          "kind": "code",
          "literal": "build-digest",
          "chunkId": "api/cli#claude-code-skill"
        },
        {
          "kind": "code",
          "literal": "ANTHROPIC_API_KEY",
          "chunkId": "api/cli#claude-code-skill"
        },
        {
          "kind": "code",
          "literal": "digest.json",
          "chunkId": "api/cli#claude-code-skill"
        },
        {
          "kind": "code",
          "literal": "ask kg build",
          "chunkId": "api/cli#claude-code-skill"
        }
      ],
      "sources": [
        {
          "chunkId": "api/cli#claude-code-skill",
          "url": "/docs/api/cli#claude-code-skill",
          "anchor": "claude-code-skill"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "claude",
        "code",
        "skill",
        "bundled",
        "builds",
        "digest",
        "inside",
        "subscription",
        "costs",
        "tokens",
        "user",
        "runs",
        "same",
        "deterministic",
        "corpus",
        "distill",
        "assemble",
        "seam",
        "produces",
        "artifact",
        "shape",
        "under",
        "hash",
        "gate",
        "input",
        "json",
        "writes",
        "build",
        "anthropic",
        "without",
        "anthropicapikey",
        "producer",
        "because",
        "model",
        "step",
        "resulting",
        "output",
        "applies"
      ]
    },
    {
      "id": "api/cli#distribution",
      "kind": "section",
      "title": "CLI",
      "heading": "Distribution",
      "group": "API",
      "url": "/docs/api/cli#distribution",
      "summary": "The npm package ships two bins: the main v3 CLI and a deprecated alias that forwards to the kg command group. The launcher resolves an environment override first, then a platform-specific binary package, then checked-out Go source for development.",
      "facts": [
        {
          "kind": "code",
          "literal": "ask",
          "chunkId": "api/cli#distribution"
        },
        {
          "kind": "code",
          "literal": "hev-ask-kg",
          "chunkId": "api/cli#distribution"
        },
        {
          "kind": "code",
          "literal": "ask kg ...",
          "chunkId": "api/cli#distribution"
        },
        {
          "kind": "code",
          "literal": "HEV_ASK_BINARY",
          "chunkId": "api/cli#distribution"
        }
      ],
      "sources": [
        {
          "chunkId": "api/cli#distribution",
          "url": "/docs/api/cli#distribution",
          "anchor": "distribution"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "distribution",
        "package",
        "ships",
        "bins",
        "main",
        "deprecated",
        "alias",
        "forwards",
        "command",
        "group",
        "launcher",
        "resolves",
        "environment",
        "override",
        "first",
        "platform",
        "specific",
        "binary",
        "checked",
        "source",
        "development",
        "exposes",
        "purpose",
        "hevaskbinary",
        "optional",
        "installed",
        "monorepo",
        "fallback",
        "published",
        "installs",
        "packaged",
        "path"
      ]
    },
    {
      "id": "api/cli#flags",
      "kind": "section",
      "title": "CLI",
      "heading": "Flags",
      "group": "API",
      "url": "/docs/api/cli#flags",
      "summary": "Reference table of global flags covering the digest path, remote endpoint, JSON output, result caps, collection and base-path selection, content globs, chunk heading depth, the build model, producer input and output paths, the verify build command, skip-build, and strict mode. Global flags come before the command.",
      "facts": [
        {
          "kind": "code",
          "literal": "ask --kg-path .hev-ask/digest.json --json search \"openapi\"\nask --endpoint https://askhev.com/api/ask mcp\nask kg build --collection docs --collection guides --chunk-heading-depth 2\nask kg verify --skip-build",
          "chunkId": "api/cli#flags"
        },
        {
          "kind": "code",
          "literal": "--kg-path <path>",
          "chunkId": "api/cli#flags"
        },
        {
          "kind": "code",
          "literal": ".hev-ask/digest.json",
          "chunkId": "api/cli#flags"
        },
        {
          "kind": "code",
          "literal": "--endpoint <url>",
          "chunkId": "api/cli#flags"
        },
        {
          "kind": "code",
          "literal": "/api/ask",
          "chunkId": "api/cli#flags"
        },
        {
          "kind": "code",
          "literal": "answer",
          "chunkId": "api/cli#flags"
        },
        {
          "kind": "code",
          "literal": "--json",
          "chunkId": "api/cli#flags"
        },
        {
          "kind": "code",
          "literal": "--max-results <n>",
          "chunkId": "api/cli#flags"
        },
        {
          "kind": "code",
          "literal": "--collection <name>",
          "chunkId": "api/cli#flags"
        },
        {
          "kind": "code",
          "literal": "docs",
          "chunkId": "api/cli#flags"
        },
        {
          "kind": "code",
          "literal": "--base-path <path>",
          "chunkId": "api/cli#flags"
        },
        {
          "kind": "code",
          "literal": "/docs/",
          "chunkId": "api/cli#flags"
        },
        {
          "kind": "code",
          "literal": "--content-glob <glob>",
          "chunkId": "api/cli#flags"
        },
        {
          "kind": "code",
          "literal": "--chunk-heading-depth <n>",
          "chunkId": "api/cli#flags"
        },
        {
          "kind": "code",
          "literal": "--kg-model <model>",
          "chunkId": "api/cli#flags"
        },
        {
          "kind": "code",
          "literal": "claude-opus-4-8",
          "chunkId": "api/cli#flags"
        },
        {
          "kind": "code",
          "literal": "ask kg build",
          "chunkId": "api/cli#flags"
        },
        {
          "kind": "code",
          "literal": "--out <path>",
          "chunkId": "api/cli#flags"
        },
        {
          "kind": "code",
          "literal": ".hev-ask/kg-input.json",
          "chunkId": "api/cli#flags"
        },
        {
          "kind": "code",
          "literal": "ask kg corpus",
          "chunkId": "api/cli#flags"
        },
        {
          "kind": "code",
          "literal": "--input <path>",
          "chunkId": "api/cli#flags"
        },
        {
          "kind": "code",
          "literal": ".hev-ask/kg-distill.json",
          "chunkId": "api/cli#flags"
        },
        {
          "kind": "code",
          "literal": "ask kg assemble",
          "chunkId": "api/cli#flags"
        },
        {
          "kind": "code",
          "literal": "--build-command <cmd>",
          "chunkId": "api/cli#flags"
        }
      ],
      "sources": [
        {
          "chunkId": "api/cli#flags",
          "url": "/docs/api/cli#flags",
          "anchor": "flags"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "flags",
        "reference",
        "table",
        "global",
        "covering",
        "digest",
        "path",
        "remote",
        "endpoint",
        "json",
        "output",
        "result",
        "caps",
        "collection",
        "base",
        "selection",
        "content",
        "globs",
        "chunk",
        "heading",
        "depth",
        "build",
        "model",
        "producer",
        "input",
        "paths",
        "verify",
        "command",
        "skip",
        "strict",
        "mode",
        "come",
        "before",
        "search",
        "openapi",
        "https",
        "askhev",
        "docs",
        "guides",
        "answer"
      ]
    },
    {
      "id": "api/cli#go-library",
      "kind": "section",
      "title": "CLI",
      "heading": "Go library",
      "group": "API",
      "url": "/docs/api/cli#go-library",
      "summary": "A reusable Go API offers pure helpers and an embeddable, dependency-free command group for mounting the same verbs in another CLI. Helpers cover loading the digest, glossary and section reads, search, an endpoint client, building, anchor verification, and MCP serving.",
      "facts": [
        {
          "kind": "code",
          "literal": "group := ask.NewCommandGroup(ask.CommandOptions{\n\tKGPath: \".hev-ask/digest.json\",\n})\nerr := group.Run(ctx, []string{\"search\", \"read endpoints\"}, os.Stdin, os.Stdout, os.Stderr)",
          "chunkId": "api/cli#go-library"
        },
        {
          "kind": "code",
          "literal": "pkg/ask",
          "chunkId": "api/cli#go-library"
        },
        {
          "kind": "code",
          "literal": "LoadGraph",
          "chunkId": "api/cli#go-library"
        },
        {
          "kind": "code",
          "literal": "ListGlossary",
          "chunkId": "api/cli#go-library"
        },
        {
          "kind": "code",
          "literal": "GetSection",
          "chunkId": "api/cli#go-library"
        },
        {
          "kind": "code",
          "literal": "SearchGraph",
          "chunkId": "api/cli#go-library"
        },
        {
          "kind": "code",
          "literal": "NewEndpointClient",
          "chunkId": "api/cli#go-library"
        },
        {
          "kind": "code",
          "literal": "BuildKnowledgeGraph",
          "chunkId": "api/cli#go-library"
        },
        {
          "kind": "code",
          "literal": "VerifyAnchors",
          "chunkId": "api/cli#go-library"
        },
        {
          "kind": "code",
          "literal": "ServeMCP",
          "chunkId": "api/cli#go-library"
        }
      ],
      "sources": [
        {
          "chunkId": "api/cli#go-library",
          "url": "/docs/api/cli#go-library",
          "anchor": "go-library"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "library",
        "reusable",
        "offers",
        "pure",
        "helpers",
        "embeddable",
        "dependency",
        "free",
        "command",
        "group",
        "mounting",
        "same",
        "verbs",
        "another",
        "cover",
        "loading",
        "digest",
        "glossary",
        "section",
        "reads",
        "search",
        "endpoint",
        "client",
        "building",
        "anchor",
        "verification",
        "serving",
        "newcommandgroup",
        "commandoptions",
        "kgpath",
        "json",
        "string",
        "read",
        "endpoints",
        "stdin",
        "stdout",
        "stderr",
        "loadgraph",
        "listglossary",
        "getsection"
      ]
    },
    {
      "id": "api/cli#mcp",
      "kind": "section",
      "title": "CLI",
      "heading": "MCP",
      "group": "API",
      "url": "/docs/api/cli#mcp",
      "summary": "The CLI runs a stdio MCP server over the same read and search surface. Point it at a local digest for checked-out repos, or at a deployed endpoint when the agent needs the remote digest or streamed answers.",
      "facts": [
        {
          "kind": "code",
          "literal": "{\n  \"mcpServers\": {\n    \"docs\": {\n      \"command\": \"ask\",\n      \"args\": [\"--kg-path\", \".hev-ask/digest.json\", \"mcp\"]\n    }\n  }\n}",
          "chunkId": "api/cli#mcp"
        },
        {
          "kind": "code",
          "literal": "{\n  \"mcpServers\": {\n    \"askhev\": {\n      \"command\": \"ask\",\n      \"args\": [\"--endpoint\", \"https://askhev.com/api/ask\", \"mcp\"]\n    }\n  }\n}",
          "chunkId": "api/cli#mcp"
        },
        {
          "kind": "code",
          "literal": "ask mcp",
          "chunkId": "api/cli#mcp"
        },
        {
          "kind": "code",
          "literal": "glossary_list",
          "chunkId": "api/cli#mcp"
        },
        {
          "kind": "code",
          "literal": "glossary_get",
          "chunkId": "api/cli#mcp"
        },
        {
          "kind": "code",
          "literal": "sections_list",
          "chunkId": "api/cli#mcp"
        },
        {
          "kind": "code",
          "literal": "section_get",
          "chunkId": "api/cli#mcp"
        },
        {
          "kind": "code",
          "literal": "overview",
          "chunkId": "api/cli#mcp"
        },
        {
          "kind": "code",
          "literal": "search",
          "chunkId": "api/cli#mcp"
        },
        {
          "kind": "code",
          "literal": "answer",
          "chunkId": "api/cli#mcp"
        }
      ],
      "sources": [
        {
          "chunkId": "api/cli#mcp",
          "url": "/docs/api/cli#mcp",
          "anchor": "mcp"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "runs",
        "stdio",
        "server",
        "same",
        "read",
        "search",
        "surface",
        "point",
        "local",
        "digest",
        "checked",
        "repos",
        "deployed",
        "endpoint",
        "agent",
        "needs",
        "remote",
        "streamed",
        "answers",
        "mcpservers",
        "docs",
        "command",
        "args",
        "path",
        "json",
        "askhev",
        "https",
        "glossary",
        "list",
        "sections",
        "section",
        "overview",
        "answer",
        "glossarylist",
        "glossaryget",
        "sectionslist",
        "sectionget",
        "reads",
        "page",
        "tool"
      ]
    },
    {
      "id": "api/cli#package-scripts",
      "kind": "section",
      "title": "CLI",
      "heading": "Package scripts",
      "group": "API",
      "url": "/docs/api/cli#package-scripts",
      "summary": "Sites typically wrap the build and verify commands in package scripts. Scripts calling the deprecated alias keep working through the forward, but new scripts should use the kg command group.",
      "facts": [
        {
          "kind": "code",
          "literal": "{\n  \"scripts\": {\n    \"kg:build\": \"ask kg build\",\n    \"kg:verify\": \"ask kg verify\"\n  }\n}",
          "chunkId": "api/cli#package-scripts"
        },
        {
          "kind": "code",
          "literal": "ask kg",
          "chunkId": "api/cli#package-scripts"
        },
        {
          "kind": "code",
          "literal": "hev-ask-kg build",
          "chunkId": "api/cli#package-scripts"
        },
        {
          "kind": "code",
          "literal": "hev-ask-kg verify",
          "chunkId": "api/cli#package-scripts"
        }
      ],
      "sources": [
        {
          "chunkId": "api/cli#package-scripts",
          "url": "/docs/api/cli#package-scripts",
          "anchor": "package-scripts"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "package",
        "scripts",
        "sites",
        "typically",
        "wrap",
        "build",
        "verify",
        "commands",
        "calling",
        "deprecated",
        "alias",
        "keep",
        "working",
        "through",
        "forward",
        "should",
        "command",
        "group",
        "site",
        "existing",
        "call"
      ]
    },
    {
      "id": "api/cli#reading-the-digest",
      "kind": "section",
      "title": "CLI",
      "heading": "Reading the digest",
      "group": "API",
      "url": "/docs/api/cli#reading-the-digest",
      "summary": "By default the CLI reads the committed digest from the current repo; an endpoint flag switches reads to a deployed site's HTTP API. The answer verb requires the endpoint because it uses the deployed agentic SSE path; local search is the keyless alternative.",
      "facts": [
        {
          "kind": "code",
          "literal": "ask glossary list\nask glossary get \"ask digest\"\nask sections list --group API\nask section get api/endpoint#digest-reads-get\nask overview\nask search \"read endpoints\"\nask --endpoint https://askhev.com/api/ask answer \"what read routes exist?\"\nask mcp",
          "chunkId": "api/cli#reading-the-digest"
        },
        {
          "kind": "code",
          "literal": "ask",
          "chunkId": "api/cli#reading-the-digest"
        },
        {
          "kind": "code",
          "literal": ".hev-ask/digest.json",
          "chunkId": "api/cli#reading-the-digest"
        },
        {
          "kind": "code",
          "literal": "--endpoint <url>",
          "chunkId": "api/cli#reading-the-digest"
        },
        {
          "kind": "code",
          "literal": "ask answer",
          "chunkId": "api/cli#reading-the-digest"
        },
        {
          "kind": "code",
          "literal": "--endpoint",
          "chunkId": "api/cli#reading-the-digest"
        },
        {
          "kind": "code",
          "literal": "ask search",
          "chunkId": "api/cli#reading-the-digest"
        }
      ],
      "sources": [
        {
          "chunkId": "api/cli#reading-the-digest",
          "url": "/docs/api/cli#reading-the-digest",
          "anchor": "reading-the-digest"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "reading",
        "digest",
        "default",
        "reads",
        "committed",
        "current",
        "repo",
        "endpoint",
        "flag",
        "switches",
        "deployed",
        "site",
        "http",
        "answer",
        "verb",
        "requires",
        "because",
        "uses",
        "agentic",
        "path",
        "local",
        "search",
        "keyless",
        "alternative",
        "glossary",
        "list",
        "sections",
        "group",
        "section",
        "overview",
        "read",
        "endpoints",
        "https",
        "askhev",
        "routes",
        "exist",
        "json",
        "pass",
        "instead",
        "retrieval"
      ]
    },
    {
      "id": "api/cli#where-it-runs",
      "kind": "section",
      "title": "CLI",
      "heading": "Where it runs",
      "group": "API",
      "url": "/docs/api/cli#where-it-runs",
      "summary": "Producer commands need filesystem access and run locally or in CI; the Astro integration also triggers the hash-gated build during the site build when a key is present, falling back to the committed artifact. The deployed site reads the digest through a virtual module, and wiring verify into CI is the mechanical guard for anchor correctness.",
      "facts": [
        {
          "kind": "code",
          "literal": "ask kg build",
          "chunkId": "api/cli#where-it-runs"
        },
        {
          "kind": "code",
          "literal": "astro build",
          "chunkId": "api/cli#where-it-runs"
        },
        {
          "kind": "code",
          "literal": "ANTHROPIC_API_KEY",
          "chunkId": "api/cli#where-it-runs"
        },
        {
          "kind": "code",
          "literal": "virtual:hev-ask/kg",
          "chunkId": "api/cli#where-it-runs"
        },
        {
          "kind": "code",
          "literal": "ask kg verify",
          "chunkId": "api/cli#where-it-runs"
        }
      ],
      "sources": [
        {
          "chunkId": "api/cli#where-it-runs",
          "url": "/docs/api/cli#where-it-runs",
          "anchor": "where-it-runs"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "runs",
        "producer",
        "commands",
        "need",
        "filesystem",
        "access",
        "locally",
        "astro",
        "integration",
        "also",
        "triggers",
        "hash",
        "gated",
        "build",
        "during",
        "site",
        "present",
        "falling",
        "back",
        "committed",
        "artifact",
        "deployed",
        "reads",
        "digest",
        "through",
        "virtual",
        "module",
        "wiring",
        "verify",
        "mechanical",
        "guard",
        "anchor",
        "correctness",
        "anthropic",
        "invokes",
        "anthropicapikey",
        "falls",
        "command",
        "cannot",
        "does"
      ]
    },
    {
      "id": "api/configuration",
      "kind": "section",
      "title": "Configuration",
      "heading": null,
      "group": "API",
      "url": "/docs/api/configuration",
      "summary": "The integration is the package's default export and takes one options object. Only the collection list is effectively required; everything else has a default.",
      "facts": [
        {
          "kind": "code",
          "literal": "// astro.config.mjs\nimport hevAsk from \"@hev/ask\";\n\nexport default defineConfig({\n  integrations: [\n    hevAsk({\n      collections: [\"docs\"],\n      basePath: \"/docs/\",\n      model: \"claude-haiku-4-5\",\n      maxResults: 6,\n    }),\n  ],\n});",
          "chunkId": "api/configuration"
        },
        {
          "kind": "code",
          "literal": "hevAsk()",
          "chunkId": "api/configuration"
        },
        {
          "kind": "code",
          "literal": "@hev/ask",
          "chunkId": "api/configuration"
        },
        {
          "kind": "code",
          "literal": "collections",
          "chunkId": "api/configuration"
        },
        {
          "kind": "value",
          "literal": "Callout.astro",
          "chunkId": "api/configuration"
        }
      ],
      "sources": [
        {
          "chunkId": "api/configuration",
          "url": "/docs/api/configuration",
          "anchor": null
        }
      ],
      "mode": "source-primary",
      "terms": [
        "integration",
        "package",
        "default",
        "export",
        "takes",
        "options",
        "object",
        "only",
        "collection",
        "list",
        "effectively",
        "required",
        "everything",
        "else",
        "astro",
        "config",
        "import",
        "hevask",
        "defineconfig",
        "integrations",
        "collections",
        "docs",
        "basepath",
        "model",
        "claude",
        "haiku",
        "maxresults",
        "callout",
        "every",
        "option",
        "models",
        "endpoint",
        "chunking",
        "depth",
        "retrieval",
        "caps",
        "digest",
        "paths",
        "defaults"
      ]
    },
    {
      "id": "api/configuration#options",
      "kind": "section",
      "title": "Configuration",
      "heading": "Options",
      "group": "API",
      "url": "/docs/api/configuration#options",
      "summary": "Reference table of every option: collections, base path, endpoint route, the loop and digest-build models, result and answer-token caps, iteration and chunk-depth limits, per-search candidates, the per-document cap, the digest path, and content globs. A changed endpoint must match the overlay component's endpoint prop.",
      "facts": [
        {
          "kind": "code",
          "literal": "collections",
          "chunkId": "api/configuration#options"
        },
        {
          "kind": "code",
          "literal": "string[]",
          "chunkId": "api/configuration#options"
        },
        {
          "kind": "code",
          "literal": "basePath",
          "chunkId": "api/configuration#options"
        },
        {
          "kind": "code",
          "literal": "string",
          "chunkId": "api/configuration#options"
        },
        {
          "kind": "code",
          "literal": "'/docs/'",
          "chunkId": "api/configuration#options"
        },
        {
          "kind": "code",
          "literal": "basePath + slug",
          "chunkId": "api/configuration#options"
        },
        {
          "kind": "code",
          "literal": "#anchor",
          "chunkId": "api/configuration#options"
        },
        {
          "kind": "code",
          "literal": "endpoint",
          "chunkId": "api/configuration#options"
        },
        {
          "kind": "code",
          "literal": "'/api/ask'",
          "chunkId": "api/configuration#options"
        },
        {
          "kind": "code",
          "literal": "model",
          "chunkId": "api/configuration#options"
        },
        {
          "kind": "code",
          "literal": "'claude-haiku-4-5'",
          "chunkId": "api/configuration#options"
        },
        {
          "kind": "code",
          "literal": "kgModel",
          "chunkId": "api/configuration#options"
        },
        {
          "kind": "code",
          "literal": "'claude-opus-4-8'",
          "chunkId": "api/configuration#options"
        },
        {
          "kind": "code",
          "literal": "maxResults",
          "chunkId": "api/configuration#options"
        },
        {
          "kind": "code",
          "literal": "number",
          "chunkId": "api/configuration#options"
        },
        {
          "kind": "code",
          "literal": "answerMaxTokens",
          "chunkId": "api/configuration#options"
        },
        {
          "kind": "code",
          "literal": "1024",
          "chunkId": "api/configuration#options"
        },
        {
          "kind": "code",
          "literal": "maxIterations",
          "chunkId": "api/configuration#options"
        },
        {
          "kind": "code",
          "literal": "search",
          "chunkId": "api/configuration#options"
        },
        {
          "kind": "code",
          "literal": "chunkHeadingDepth",
          "chunkId": "api/configuration#options"
        },
        {
          "kind": "code",
          "literal": "##",
          "chunkId": "api/configuration#options"
        },
        {
          "kind": "code",
          "literal": "###",
          "chunkId": "api/configuration#options"
        },
        {
          "kind": "code",
          "literal": "candidatePerSearch",
          "chunkId": "api/configuration#options"
        },
        {
          "kind": "code",
          "literal": "perDocCap",
          "chunkId": "api/configuration#options"
        }
      ],
      "sources": [
        {
          "chunkId": "api/configuration#options",
          "url": "/docs/api/configuration#options",
          "anchor": "options"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "options",
        "reference",
        "table",
        "every",
        "option",
        "collections",
        "base",
        "path",
        "endpoint",
        "route",
        "loop",
        "digest",
        "build",
        "models",
        "result",
        "answer",
        "token",
        "caps",
        "iteration",
        "chunk",
        "depth",
        "limits",
        "search",
        "candidates",
        "document",
        "content",
        "globs",
        "changed",
        "must",
        "match",
        "overlay",
        "component",
        "prop",
        "string",
        "basepath",
        "docs",
        "slug",
        "anchor",
        "model",
        "claude"
      ]
    },
    {
      "id": "api/configuration#tuning-notes",
      "kind": "section",
      "title": "Configuration",
      "heading": "Tuning notes",
      "group": "API",
      "url": "/docs/api/configuration#tuning-notes",
      "summary": "Practical knobs: heading depth trades finer anchors against too-small sections, the iteration cap bounds agentic latency, the per-document cap controls result spread, and candidates per search trade recall against tokens.",
      "facts": [
        {
          "kind": "code",
          "literal": "chunkHeadingDepth",
          "chunkId": "api/configuration#tuning-notes"
        },
        {
          "kind": "code",
          "literal": "###",
          "chunkId": "api/configuration#tuning-notes"
        },
        {
          "kind": "code",
          "literal": "maxIterations",
          "chunkId": "api/configuration#tuning-notes"
        },
        {
          "kind": "code",
          "literal": "perDocCap",
          "chunkId": "api/configuration#tuning-notes"
        },
        {
          "kind": "code",
          "literal": "candidatePerSearch",
          "chunkId": "api/configuration#tuning-notes"
        }
      ],
      "sources": [
        {
          "chunkId": "api/configuration#tuning-notes",
          "url": "/docs/api/configuration#tuning-notes",
          "anchor": "tuning-notes"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "tuning",
        "notes",
        "practical",
        "knobs",
        "heading",
        "depth",
        "trades",
        "finer",
        "anchors",
        "against",
        "small",
        "sections",
        "iteration",
        "bounds",
        "agentic",
        "latency",
        "document",
        "controls",
        "result",
        "spread",
        "candidates",
        "search",
        "trade",
        "recall",
        "tokens",
        "chunkheadingdepth",
        "maxiterations",
        "perdoccap",
        "candidatepersearch",
        "chunk",
        "granularity",
        "raise",
        "default",
        "section",
        "long",
        "pages",
        "drop",
        "stand",
        "alone",
        "results"
      ]
    },
    {
      "id": "api/configuration#typescript",
      "kind": "section",
      "title": "Configuration",
      "heading": "TypeScript",
      "group": "API",
      "url": "/docs/api/configuration#typescript",
      "summary": "The options type is exported for editor help and typed configuration.",
      "facts": [
        {
          "kind": "code",
          "literal": "import type { HevAskOptions } from \"@hev/ask\";",
          "chunkId": "api/configuration#typescript"
        }
      ],
      "sources": [
        {
          "chunkId": "api/configuration#typescript",
          "url": "/docs/api/configuration#typescript",
          "anchor": "typescript"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "typescript",
        "options",
        "type",
        "exported",
        "editor",
        "help",
        "typed",
        "configuration",
        "import",
        "hevaskoptions",
        "config",
        "typing"
      ]
    },
    {
      "id": "api/configuration#what-the-integration-does",
      "kind": "section",
      "title": "Configuration",
      "heading": "What the integration does",
      "group": "API",
      "url": "/docs/api/configuration#what-the-integration-does",
      "summary": "At startup the integration injects the on-demand endpoint route, registers virtual modules for the resolved config and the inlined digest, watches the digest path so dev reloads on changes, and warns when collections are missing. At build it runs the hash-gated digest build when a key is present, otherwise warns and keeps the committed artifact — never failing for lack of a key.",
      "facts": [
        {
          "kind": "code",
          "literal": "astro:config:setup",
          "chunkId": "api/configuration#what-the-integration-does"
        },
        {
          "kind": "code",
          "literal": "endpoint",
          "chunkId": "api/configuration#what-the-integration-does"
        },
        {
          "kind": "code",
          "literal": "@hev/ask/endpoint",
          "chunkId": "api/configuration#what-the-integration-does"
        },
        {
          "kind": "code",
          "literal": "prerender: false",
          "chunkId": "api/configuration#what-the-integration-does"
        },
        {
          "kind": "code",
          "literal": "virtual:hev-ask/config",
          "chunkId": "api/configuration#what-the-integration-does"
        },
        {
          "kind": "code",
          "literal": "virtual:hev-ask/kg",
          "chunkId": "api/configuration#what-the-integration-does"
        },
        {
          "kind": "code",
          "literal": "kgPath",
          "chunkId": "api/configuration#what-the-integration-does"
        },
        {
          "kind": "code",
          "literal": "collections",
          "chunkId": "api/configuration#what-the-integration-does"
        },
        {
          "kind": "code",
          "literal": "astro:build:start",
          "chunkId": "api/configuration#what-the-integration-does"
        },
        {
          "kind": "code",
          "literal": "ANTHROPIC_API_KEY",
          "chunkId": "api/configuration#what-the-integration-does"
        }
      ],
      "sources": [
        {
          "chunkId": "api/configuration#what-the-integration-does",
          "url": "/docs/api/configuration#what-the-integration-does",
          "anchor": "what-the-integration-does"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "integration",
        "does",
        "startup",
        "injects",
        "demand",
        "endpoint",
        "route",
        "registers",
        "virtual",
        "modules",
        "resolved",
        "config",
        "inlined",
        "digest",
        "watches",
        "path",
        "reloads",
        "changes",
        "warns",
        "collections",
        "missing",
        "build",
        "runs",
        "hash",
        "gated",
        "present",
        "otherwise",
        "keeps",
        "committed",
        "artifact",
        "never",
        "failing",
        "lack",
        "astro",
        "setup",
        "prerender",
        "false",
        "kgpath",
        "start",
        "anthropic"
      ]
    },
    {
      "id": "api/endpoint",
      "kind": "section",
      "title": "Search endpoint",
      "heading": null,
      "group": "API",
      "url": "/docs/api/endpoint",
      "summary": "One injected on-demand route tree serves the overlay: keyword mode returns JSON, agentic mode streams a grounded answer over Server-Sent Events, and keyless sub-routes expose the digest to CLIs, MCP servers, and generated clients. An OpenAPI 3.1 contract is published alongside.",
      "facts": [
        {
          "kind": "code",
          "literal": "/api/ask",
          "chunkId": "api/endpoint"
        },
        {
          "kind": "code",
          "literal": "text/event-stream",
          "chunkId": "api/endpoint"
        },
        {
          "kind": "code",
          "literal": "/openapi.yaml",
          "chunkId": "api/endpoint"
        },
        {
          "kind": "value",
          "literal": "Callout.astro",
          "chunkId": "api/endpoint"
        },
        {
          "kind": "value",
          "literal": "3.1",
          "chunkId": "api/endpoint"
        },
        {
          "kind": "value",
          "literal": "openapi.yaml",
          "chunkId": "api/endpoint"
        }
      ],
      "sources": [
        {
          "chunkId": "api/endpoint",
          "url": "/docs/api/endpoint",
          "anchor": null
        }
      ],
      "mode": "source-primary",
      "terms": [
        "injected",
        "demand",
        "route",
        "tree",
        "serves",
        "overlay",
        "keyword",
        "mode",
        "returns",
        "json",
        "agentic",
        "streams",
        "grounded",
        "answer",
        "server",
        "sent",
        "events",
        "keyless",
        "routes",
        "expose",
        "digest",
        "clis",
        "servers",
        "generated",
        "clients",
        "openapi",
        "contract",
        "published",
        "alongside",
        "text",
        "event",
        "stream",
        "yaml",
        "callout",
        "astro",
        "suggestions",
        "reads",
        "selection",
        "error",
        "responses"
      ]
    },
    {
      "id": "api/endpoint#agentic-response-sse",
      "kind": "section",
      "title": "Search endpoint",
      "heading": "Agentic response (SSE)",
      "group": "API",
      "url": "/docs/api/endpoint#agentic-response-sse",
      "summary": "With a key and agentic mode the endpoint streams named SSE frames: search activity lines, a one-time sources set sent before any token so clients can validate links, token deltas of the Markdown answer, a done marker, and an error frame for failures after streaming began. Sources carry the deep-link URL; the answer prose carries the substance.",
      "facts": [
        {
          "kind": "code",
          "literal": "mode",
          "chunkId": "api/endpoint#agentic-response-sse"
        },
        {
          "kind": "code",
          "literal": "agentic",
          "chunkId": "api/endpoint#agentic-response-sse"
        },
        {
          "kind": "code",
          "literal": "content-type: text/event-stream",
          "chunkId": "api/endpoint#agentic-response-sse"
        },
        {
          "kind": "code",
          "literal": "search",
          "chunkId": "api/endpoint#agentic-response-sse"
        },
        {
          "kind": "code",
          "literal": "{ query }",
          "chunkId": "api/endpoint#agentic-response-sse"
        },
        {
          "kind": "code",
          "literal": "sources",
          "chunkId": "api/endpoint#agentic-response-sse"
        },
        {
          "kind": "code",
          "literal": "{ sources: Source[], model, mode }",
          "chunkId": "api/endpoint#agentic-response-sse"
        },
        {
          "kind": "code",
          "literal": "token",
          "chunkId": "api/endpoint#agentic-response-sse"
        },
        {
          "kind": "code",
          "literal": "{ text }",
          "chunkId": "api/endpoint#agentic-response-sse"
        },
        {
          "kind": "code",
          "literal": "done",
          "chunkId": "api/endpoint#agentic-response-sse"
        },
        {
          "kind": "code",
          "literal": "{}",
          "chunkId": "api/endpoint#agentic-response-sse"
        },
        {
          "kind": "code",
          "literal": "error",
          "chunkId": "api/endpoint#agentic-response-sse"
        },
        {
          "kind": "code",
          "literal": "{ error }",
          "chunkId": "api/endpoint#agentic-response-sse"
        },
        {
          "kind": "code",
          "literal": "200",
          "chunkId": "api/endpoint#agentic-response-sse"
        },
        {
          "kind": "code",
          "literal": "Source",
          "chunkId": "api/endpoint#agentic-response-sse"
        },
        {
          "kind": "code",
          "literal": "{ title, heading?, url, group? }",
          "chunkId": "api/endpoint#agentic-response-sse"
        },
        {
          "kind": "code",
          "literal": "snippet",
          "chunkId": "api/endpoint#agentic-response-sse"
        },
        {
          "kind": "code",
          "literal": "url",
          "chunkId": "api/endpoint#agentic-response-sse"
        }
      ],
      "sources": [
        {
          "chunkId": "api/endpoint#agentic-response-sse",
          "url": "/docs/api/endpoint#agentic-response-sse",
          "anchor": "agentic-response-sse"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "agentic",
        "response",
        "mode",
        "endpoint",
        "streams",
        "named",
        "frames",
        "search",
        "activity",
        "lines",
        "time",
        "sources",
        "sent",
        "before",
        "token",
        "clients",
        "validate",
        "links",
        "deltas",
        "markdown",
        "answer",
        "done",
        "marker",
        "error",
        "frame",
        "failures",
        "after",
        "streaming",
        "began",
        "carry",
        "deep",
        "link",
        "prose",
        "carries",
        "substance",
        "content",
        "type",
        "text",
        "event",
        "stream"
      ]
    },
    {
      "id": "api/endpoint#digest-reads-get",
      "kind": "section",
      "title": "Search endpoint",
      "heading": "Digest reads (GET)",
      "group": "API",
      "url": "/docs/api/endpoint#digest-reads-get",
      "summary": "Keyless GET routes read the inlined digest and never call a model: glossary listing and term lookup, section summaries with an optional group filter, full section nodes by id, and the overview-plus-context pair. IDs containing slashes or hashes are URL-encoded in the path, and misses return a JSON 404.",
      "facts": [
        {
          "kind": "code",
          "literal": "{ \"error\": \"Not found.\" }",
          "chunkId": "api/endpoint#digest-reads-get"
        },
        {
          "kind": "code",
          "literal": "virtual:hev-ask/kg",
          "chunkId": "api/endpoint#digest-reads-get"
        },
        {
          "kind": "code",
          "literal": "GET /api/ask/glossary",
          "chunkId": "api/endpoint#digest-reads-get"
        },
        {
          "kind": "code",
          "literal": "{ \"terms\": GlossaryEntry[] }",
          "chunkId": "api/endpoint#digest-reads-get"
        },
        {
          "kind": "code",
          "literal": "GET /api/ask/glossary/{term}",
          "chunkId": "api/endpoint#digest-reads-get"
        },
        {
          "kind": "code",
          "literal": "GlossaryEntry",
          "chunkId": "api/endpoint#digest-reads-get"
        },
        {
          "kind": "code",
          "literal": "GET /api/ask/sections",
          "chunkId": "api/endpoint#digest-reads-get"
        },
        {
          "kind": "code",
          "literal": "{ \"sections\": SectionSummary[] }",
          "chunkId": "api/endpoint#digest-reads-get"
        },
        {
          "kind": "code",
          "literal": "GET /api/ask/sections?group=API",
          "chunkId": "api/endpoint#digest-reads-get"
        },
        {
          "kind": "code",
          "literal": "GET /api/ask/sections/{id}",
          "chunkId": "api/endpoint#digest-reads-get"
        },
        {
          "kind": "code",
          "literal": "KnowledgeNode",
          "chunkId": "api/endpoint#digest-reads-get"
        },
        {
          "kind": "code",
          "literal": "GET /api/ask/overview",
          "chunkId": "api/endpoint#digest-reads-get"
        },
        {
          "kind": "code",
          "literal": "{ \"overview\": string, \"context\": string }",
          "chunkId": "api/endpoint#digest-reads-get"
        },
        {
          "kind": "code",
          "literal": "SectionSummary",
          "chunkId": "api/endpoint#digest-reads-get"
        },
        {
          "kind": "code",
          "literal": "{ id, title, heading, group, url }",
          "chunkId": "api/endpoint#digest-reads-get"
        },
        {
          "kind": "code",
          "literal": "/api/ask/sections/api%2Fcli%23flags",
          "chunkId": "api/endpoint#digest-reads-get"
        },
        {
          "kind": "code",
          "literal": "404",
          "chunkId": "api/endpoint#digest-reads-get"
        }
      ],
      "sources": [
        {
          "chunkId": "api/endpoint#digest-reads-get",
          "url": "/docs/api/endpoint#digest-reads-get",
          "anchor": "digest-reads-get"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "digest",
        "reads",
        "keyless",
        "routes",
        "read",
        "inlined",
        "never",
        "call",
        "model",
        "glossary",
        "listing",
        "term",
        "lookup",
        "section",
        "summaries",
        "optional",
        "group",
        "filter",
        "full",
        "nodes",
        "overview",
        "plus",
        "context",
        "pair",
        "containing",
        "slashes",
        "hashes",
        "encoded",
        "path",
        "misses",
        "return",
        "json",
        "error",
        "found",
        "virtual",
        "terms",
        "glossaryentry",
        "sections",
        "sectionsummary",
        "knowledgenode"
      ]
    },
    {
      "id": "api/endpoint#errors",
      "kind": "section",
      "title": "Search endpoint",
      "heading": "Errors",
      "group": "API",
      "url": "/docs/api/endpoint#errors",
      "summary": "Invalid JSON bodies return 400, missing read routes, glossary terms, or section ids return 404, and a failed chunk-index build returns 500. Failures during an agentic stream arrive as a final SSE error event because the HTTP status is already committed.",
      "facts": [
        {
          "kind": "code",
          "literal": "400",
          "chunkId": "api/endpoint#errors"
        },
        {
          "kind": "code",
          "literal": "{ \"error\": \"Invalid JSON body.\" }",
          "chunkId": "api/endpoint#errors"
        },
        {
          "kind": "code",
          "literal": "404",
          "chunkId": "api/endpoint#errors"
        },
        {
          "kind": "code",
          "literal": "{ \"error\": \"…\" }",
          "chunkId": "api/endpoint#errors"
        },
        {
          "kind": "code",
          "literal": "500",
          "chunkId": "api/endpoint#errors"
        },
        {
          "kind": "code",
          "literal": "event: error",
          "chunkId": "api/endpoint#errors"
        },
        {
          "kind": "code",
          "literal": "200",
          "chunkId": "api/endpoint#errors"
        },
        {
          "kind": "code",
          "literal": "error",
          "chunkId": "api/endpoint#errors"
        },
        {
          "kind": "value",
          "literal": "e.g",
          "chunkId": "api/endpoint#errors"
        }
      ],
      "sources": [
        {
          "chunkId": "api/endpoint#errors",
          "url": "/docs/api/endpoint#errors",
          "anchor": "errors"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "errors",
        "invalid",
        "json",
        "bodies",
        "return",
        "missing",
        "read",
        "routes",
        "glossary",
        "terms",
        "section",
        "failed",
        "chunk",
        "index",
        "build",
        "returns",
        "failures",
        "during",
        "agentic",
        "stream",
        "arrive",
        "final",
        "error",
        "event",
        "because",
        "http",
        "status",
        "already",
        "committed",
        "body",
        "cause",
        "request",
        "wasn",
        "valid",
        "digest",
        "route",
        "term",
        "found",
        "misconfigured",
        "collection"
      ]
    },
    {
      "id": "api/endpoint#index-lifecycle",
      "kind": "section",
      "title": "Search endpoint",
      "heading": "Index lifecycle",
      "group": "API",
      "url": "/docs/api/endpoint#index-lifecycle",
      "summary": "The chunk index builds once per server instance on the first request and is cached for the process lifetime. That first request also compares the live content hash against the digest's and logs a one-time staleness warning — the cue to rebuild.",
      "facts": [
        {
          "kind": "code",
          "literal": "ask kg build",
          "chunkId": "api/endpoint#index-lifecycle"
        }
      ],
      "sources": [
        {
          "chunkId": "api/endpoint#index-lifecycle",
          "url": "/docs/api/endpoint#index-lifecycle",
          "anchor": "index-lifecycle"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "index",
        "lifecycle",
        "chunk",
        "builds",
        "once",
        "server",
        "instance",
        "first",
        "request",
        "cached",
        "process",
        "lifetime",
        "also",
        "compares",
        "live",
        "content",
        "hash",
        "against",
        "digest",
        "logs",
        "time",
        "staleness",
        "warning",
        "rebuild",
        "build",
        "built",
        "endpoint",
        "differ"
      ]
    },
    {
      "id": "api/endpoint#keyword-response-json",
      "kind": "section",
      "title": "Search endpoint",
      "heading": "Keyword response (JSON)",
      "group": "API",
      "url": "/docs/api/endpoint#keyword-response-json",
      "summary": "Keyword mode returns a JSON envelope of ranked results — title, optional heading and group, the deep-link URL, and a snippet — plus the echoed query, the configured model, the mode that ran, and a warning when an agentic request was downgraded for lack of a key.",
      "facts": [
        {
          "kind": "code",
          "literal": "{\n  \"results\": [\n    {\n      \"title\": \"Concepts\",\n      \"heading\": \"The agentic search loop\",\n      \"url\": \"/docs/concepts#the-agentic-search-loop\",\n      \"group\": \"Overview\",\n      \"snippet\": \"When the reader presses Enter, the query goes to a bounded loop…\"\n    }\n  ],\n  \"query\": \"how does agentic search work\",\n  \"model\": \"claude-haiku-4-5\",\n  \"mode\": \"keyword\"\n}",
          "chunkId": "api/endpoint#keyword-response-json"
        },
        {
          "kind": "code",
          "literal": "200",
          "chunkId": "api/endpoint#keyword-response-json"
        },
        {
          "kind": "code",
          "literal": "results",
          "chunkId": "api/endpoint#keyword-response-json"
        },
        {
          "kind": "code",
          "literal": "Result[]",
          "chunkId": "api/endpoint#keyword-response-json"
        },
        {
          "kind": "code",
          "literal": "title",
          "chunkId": "api/endpoint#keyword-response-json"
        },
        {
          "kind": "code",
          "literal": "heading?",
          "chunkId": "api/endpoint#keyword-response-json"
        },
        {
          "kind": "code",
          "literal": "url",
          "chunkId": "api/endpoint#keyword-response-json"
        },
        {
          "kind": "code",
          "literal": "group?",
          "chunkId": "api/endpoint#keyword-response-json"
        },
        {
          "kind": "code",
          "literal": "snippet",
          "chunkId": "api/endpoint#keyword-response-json"
        },
        {
          "kind": "code",
          "literal": "query",
          "chunkId": "api/endpoint#keyword-response-json"
        },
        {
          "kind": "code",
          "literal": "string",
          "chunkId": "api/endpoint#keyword-response-json"
        },
        {
          "kind": "code",
          "literal": "model",
          "chunkId": "api/endpoint#keyword-response-json"
        },
        {
          "kind": "code",
          "literal": "mode",
          "chunkId": "api/endpoint#keyword-response-json"
        },
        {
          "kind": "code",
          "literal": "'keyword'",
          "chunkId": "api/endpoint#keyword-response-json"
        },
        {
          "kind": "code",
          "literal": "warning",
          "chunkId": "api/endpoint#keyword-response-json"
        },
        {
          "kind": "code",
          "literal": "string?",
          "chunkId": "api/endpoint#keyword-response-json"
        },
        {
          "kind": "code",
          "literal": "#anchor",
          "chunkId": "api/endpoint#keyword-response-json"
        }
      ],
      "sources": [
        {
          "chunkId": "api/endpoint#keyword-response-json",
          "url": "/docs/api/endpoint#keyword-response-json",
          "anchor": "keyword-response-json"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "keyword",
        "response",
        "json",
        "mode",
        "returns",
        "envelope",
        "ranked",
        "results",
        "title",
        "optional",
        "heading",
        "group",
        "deep",
        "link",
        "snippet",
        "plus",
        "echoed",
        "query",
        "configured",
        "model",
        "warning",
        "agentic",
        "request",
        "downgraded",
        "lack",
        "concepts",
        "search",
        "loop",
        "docs",
        "overview",
        "reader",
        "presses",
        "enter",
        "goes",
        "bounded",
        "does",
        "work",
        "claude",
        "haiku",
        "result"
      ]
    },
    {
      "id": "api/endpoint#llm-tracing",
      "kind": "section",
      "title": "Search endpoint",
      "heading": "LLM tracing",
      "group": "API",
      "url": "/docs/api/endpoint#llm-tracing",
      "summary": "Setting a PostHog key makes every agentic answer emit a generation trace with model, tokens, latency, and the loop's tool calls; the ingestion host and how much prompt text ships are configurable. Without a key tracing is a no-op, and the answer path never depends on telemetry.",
      "facts": [
        {
          "kind": "code",
          "literal": "POSTHOG_KEY",
          "chunkId": "api/endpoint#llm-tracing"
        },
        {
          "kind": "code",
          "literal": "POSTHOG_API_KEY",
          "chunkId": "api/endpoint#llm-tracing"
        },
        {
          "kind": "code",
          "literal": "$ai_generation",
          "chunkId": "api/endpoint#llm-tracing"
        },
        {
          "kind": "code",
          "literal": "POSTHOG_HOST",
          "chunkId": "api/endpoint#llm-tracing"
        },
        {
          "kind": "code",
          "literal": "POSTHOG_CAPTURE_CONTENT",
          "chunkId": "api/endpoint#llm-tracing"
        },
        {
          "kind": "code",
          "literal": "off",
          "chunkId": "api/endpoint#llm-tracing"
        },
        {
          "kind": "code",
          "literal": "redacted",
          "chunkId": "api/endpoint#llm-tracing"
        },
        {
          "kind": "code",
          "literal": "full",
          "chunkId": "api/endpoint#llm-tracing"
        }
      ],
      "sources": [
        {
          "chunkId": "api/endpoint#llm-tracing",
          "url": "/docs/api/endpoint#llm-tracing",
          "anchor": "llm-tracing"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "tracing",
        "setting",
        "posthog",
        "makes",
        "every",
        "agentic",
        "answer",
        "emit",
        "generation",
        "trace",
        "model",
        "tokens",
        "latency",
        "loop",
        "tool",
        "calls",
        "ingestion",
        "host",
        "much",
        "prompt",
        "text",
        "ships",
        "configurable",
        "without",
        "path",
        "never",
        "depends",
        "telemetry",
        "capture",
        "content",
        "redacted",
        "full",
        "posthogkey",
        "posthogapikey",
        "same",
        "environment",
        "emits",
        "aigeneration",
        "posthoghost",
        "overrides"
      ]
    },
    {
      "id": "api/endpoint#mode-selection",
      "kind": "section",
      "title": "Search endpoint",
      "heading": "Mode selection",
      "group": "API",
      "url": "/docs/api/endpoint#mode-selection",
      "summary": "The endpoint decides the path: empty queries return empty keyword JSON, keyword mode or a missing key returns keyword JSON (with a downgrade warning when agentic was requested), otherwise the agentic SSE stream runs. There is no AI-unavailable error path, and the overlay branches on the response content type.",
      "facts": [
        {
          "kind": "code",
          "literal": "{ results: [], query: \"\", model, mode: \"keyword\" }",
          "chunkId": "api/endpoint#mode-selection"
        },
        {
          "kind": "code",
          "literal": "mode: \"keyword\"",
          "chunkId": "api/endpoint#mode-selection"
        },
        {
          "kind": "code",
          "literal": "mode: \"agentic\"",
          "chunkId": "api/endpoint#mode-selection"
        },
        {
          "kind": "code",
          "literal": "warning",
          "chunkId": "api/endpoint#mode-selection"
        },
        {
          "kind": "code",
          "literal": "content-type",
          "chunkId": "api/endpoint#mode-selection"
        }
      ],
      "sources": [
        {
          "chunkId": "api/endpoint#mode-selection",
          "url": "/docs/api/endpoint#mode-selection",
          "anchor": "mode-selection"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "mode",
        "selection",
        "endpoint",
        "decides",
        "path",
        "empty",
        "queries",
        "return",
        "keyword",
        "json",
        "missing",
        "returns",
        "downgrade",
        "warning",
        "agentic",
        "requested",
        "otherwise",
        "stream",
        "runs",
        "there",
        "unavailable",
        "error",
        "overlay",
        "branches",
        "response",
        "content",
        "type",
        "results",
        "query",
        "model",
        "plus",
        "downgrades",
        "request",
        "says",
        "reader",
        "still",
        "gets",
        "handles",
        "both",
        "shapes"
      ]
    },
    {
      "id": "api/endpoint#request",
      "kind": "section",
      "title": "Search endpoint",
      "heading": "Request",
      "group": "API",
      "url": "/docs/api/endpoint#request",
      "summary": "Requests are a JSON POST with a query and an optional mode. Empty queries return an empty result set, and omitting the mode behaves like agentic when a key is present.",
      "facts": [
        {
          "kind": "code",
          "literal": "{\n  \"query\": \"how does autoscaling work\",\n  \"mode\": \"agentic\"\n}",
          "chunkId": "api/endpoint#request"
        },
        {
          "kind": "code",
          "literal": "POST",
          "chunkId": "api/endpoint#request"
        },
        {
          "kind": "code",
          "literal": "query",
          "chunkId": "api/endpoint#request"
        },
        {
          "kind": "code",
          "literal": "string",
          "chunkId": "api/endpoint#request"
        },
        {
          "kind": "code",
          "literal": "mode",
          "chunkId": "api/endpoint#request"
        },
        {
          "kind": "code",
          "literal": "'keyword' \\| 'agentic'",
          "chunkId": "api/endpoint#request"
        },
        {
          "kind": "code",
          "literal": "keyword",
          "chunkId": "api/endpoint#request"
        },
        {
          "kind": "code",
          "literal": "agentic",
          "chunkId": "api/endpoint#request"
        }
      ],
      "sources": [
        {
          "chunkId": "api/endpoint#request",
          "url": "/docs/api/endpoint#request",
          "anchor": "request"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "request",
        "requests",
        "json",
        "post",
        "query",
        "optional",
        "mode",
        "empty",
        "queries",
        "return",
        "result",
        "omitting",
        "behaves",
        "like",
        "agentic",
        "present",
        "does",
        "autoscaling",
        "work",
        "string",
        "keyword",
        "body",
        "field",
        "type",
        "description",
        "search",
        "whitespace",
        "returns",
        "forces",
        "instant",
        "path",
        "loop",
        "omitted"
      ]
    },
    {
      "id": "api/endpoint#suggested-questions-get",
      "kind": "section",
      "title": "Search endpoint",
      "heading": "Suggested questions (GET)",
      "group": "API",
      "url": "/docs/api/endpoint#suggested-questions-get",
      "summary": "A keyless GET on the base route returns the digest's baked-in suggested questions and the loop model — no query, no model call. The overlay fetches it once on first open, and an empty list simply means no suggestions are shown.",
      "facts": [
        {
          "kind": "code",
          "literal": "{\n  \"suggestions\": [\"How does the digest stay fresh?\"],\n  \"model\": \"claude-haiku-4-5\"\n}",
          "chunkId": "api/endpoint#suggested-questions-get"
        },
        {
          "kind": "code",
          "literal": "GET /api/ask",
          "chunkId": "api/endpoint#suggested-questions-get"
        },
        {
          "kind": "code",
          "literal": "suggestions",
          "chunkId": "api/endpoint#suggested-questions-get"
        }
      ],
      "sources": [
        {
          "chunkId": "api/endpoint#suggested-questions-get",
          "url": "/docs/api/endpoint#suggested-questions-get",
          "anchor": "suggested-questions-get"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "suggested",
        "questions",
        "keyless",
        "base",
        "route",
        "returns",
        "digest",
        "baked",
        "loop",
        "model",
        "query",
        "call",
        "overlay",
        "fetches",
        "once",
        "first",
        "open",
        "empty",
        "list",
        "simply",
        "means",
        "suggestions",
        "shown",
        "does",
        "stay",
        "fresh",
        "claude",
        "haiku",
        "populate",
        "array",
        "graph",
        "without",
        "just",
        "shows",
        "none"
      ]
    },
    {
      "id": "api/endpoint#the-api-key",
      "kind": "section",
      "title": "Search endpoint",
      "heading": "The API key",
      "group": "API",
      "url": "/docs/api/endpoint#the-api-key",
      "summary": "The endpoint resolves the Anthropic key from the adapter runtime environment first, then the process environment, then the import-time environment. It lives wherever the host injects server secrets and is never sent to the browser.",
      "facts": [
        {
          "kind": "code",
          "literal": "ANTHROPIC_API_KEY",
          "chunkId": "api/endpoint#the-api-key"
        },
        {
          "kind": "code",
          "literal": "locals.runtime.env",
          "chunkId": "api/endpoint#the-api-key"
        },
        {
          "kind": "code",
          "literal": "process.env",
          "chunkId": "api/endpoint#the-api-key"
        },
        {
          "kind": "code",
          "literal": "import.meta.env",
          "chunkId": "api/endpoint#the-api-key"
        },
        {
          "kind": "value",
          "literal": "e.g",
          "chunkId": "api/endpoint#the-api-key"
        }
      ],
      "sources": [
        {
          "chunkId": "api/endpoint#the-api-key",
          "url": "/docs/api/endpoint#the-api-key",
          "anchor": "the-api-key"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "endpoint",
        "resolves",
        "anthropic",
        "adapter",
        "runtime",
        "environment",
        "first",
        "process",
        "import",
        "time",
        "lives",
        "wherever",
        "host",
        "injects",
        "server",
        "secrets",
        "never",
        "sent",
        "browser",
        "locals",
        "meta",
        "anthropicapikey",
        "order",
        "cloudflare"
      ]
    },
    {
      "id": "api/knowledge-graph",
      "kind": "section",
      "title": "Digest format",
      "heading": null,
      "group": "API",
      "url": "/docs/api/knowledge-graph",
      "summary": "The ask digest is a single committed JSON file, built offline and inlined into the site through a virtual module so the running site reads it without filesystem access. It is the agent's view of the docs — a distilled, source-grounded index read progressively — and every node deep-links back to its real section. The kg name survives only in the CLI group, the path flag, and the virtual module id.",
      "facts": [
        {
          "kind": "code",
          "literal": ".hev-ask/digest.json",
          "chunkId": "api/knowledge-graph"
        },
        {
          "kind": "code",
          "literal": "ask kg build",
          "chunkId": "api/knowledge-graph"
        },
        {
          "kind": "code",
          "literal": "kg",
          "chunkId": "api/knowledge-graph"
        },
        {
          "kind": "code",
          "literal": "--kg-path",
          "chunkId": "api/knowledge-graph"
        },
        {
          "kind": "code",
          "literal": "virtual:hev-ask/kg",
          "chunkId": "api/knowledge-graph"
        },
        {
          "kind": "code",
          "literal": "url#anchor",
          "chunkId": "api/knowledge-graph"
        },
        {
          "kind": "value",
          "literal": "Callout.astro",
          "chunkId": "api/knowledge-graph"
        }
      ],
      "sources": [
        {
          "chunkId": "api/knowledge-graph",
          "url": "/docs/api/knowledge-graph",
          "anchor": null
        }
      ],
      "mode": "source-primary",
      "terms": [
        "digest",
        "single",
        "committed",
        "json",
        "file",
        "built",
        "offline",
        "inlined",
        "site",
        "through",
        "virtual",
        "module",
        "running",
        "reads",
        "without",
        "filesystem",
        "access",
        "agent",
        "view",
        "docs",
        "distilled",
        "source",
        "grounded",
        "index",
        "read",
        "progressively",
        "every",
        "node",
        "deep",
        "links",
        "back",
        "real",
        "section",
        "name",
        "survives",
        "only",
        "group",
        "path",
        "flag",
        "build"
      ]
    },
    {
      "id": "api/knowledge-graph#degradation",
      "kind": "section",
      "title": "Digest format",
      "heading": "Degradation",
      "group": "API",
      "url": "/docs/api/knowledge-graph#degradation",
      "summary": "The digest is read defensively: a missing, malformed, or node-less file degrades the agentic loop to keyword-style search while keyword mode keeps working, and nothing hard-fails. Because it is committed JSON, the deterministic structure reviews in pull requests; only the distillation is model-authored, which is why that step can run inside a Claude Code skill.",
      "facts": [
        {
          "kind": "code",
          "literal": "summary",
          "chunkId": "api/knowledge-graph#degradation"
        },
        {
          "kind": "code",
          "literal": "glossary",
          "chunkId": "api/knowledge-graph#degradation"
        },
        {
          "kind": "code",
          "literal": "context",
          "chunkId": "api/knowledge-graph#degradation"
        },
        {
          "kind": "code",
          "literal": "suggestions",
          "chunkId": "api/knowledge-graph#degradation"
        }
      ],
      "sources": [
        {
          "chunkId": "api/knowledge-graph#degradation",
          "url": "/docs/api/knowledge-graph#degradation",
          "anchor": "degradation"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "degradation",
        "digest",
        "read",
        "defensively",
        "missing",
        "malformed",
        "node",
        "less",
        "file",
        "degrades",
        "agentic",
        "loop",
        "keyword",
        "style",
        "search",
        "while",
        "mode",
        "keeps",
        "working",
        "nothing",
        "hard",
        "fails",
        "because",
        "committed",
        "json",
        "deterministic",
        "structure",
        "reviews",
        "pull",
        "requests",
        "only",
        "distillation",
        "model",
        "authored",
        "step",
        "inside",
        "claude",
        "code",
        "skill",
        "summary"
      ]
    },
    {
      "id": "api/knowledge-graph#fields",
      "kind": "section",
      "title": "Digest format",
      "heading": "Fields",
      "group": "API",
      "url": "/docs/api/knowledge-graph#fields",
      "summary": "Top-level fields: a schema version, a generation timestamp, the content hash that gates freshness, a compact context used as the degradation fallback, the alias-bearing glossary, a deterministic overview map, model-authored suggested questions, the distilled section nodes, and a reserved edges array that ships empty.",
      "facts": [
        {
          "kind": "code",
          "literal": "version",
          "chunkId": "api/knowledge-graph#fields"
        },
        {
          "kind": "code",
          "literal": "generatedAt",
          "chunkId": "api/knowledge-graph#fields"
        },
        {
          "kind": "code",
          "literal": "string",
          "chunkId": "api/knowledge-graph#fields"
        },
        {
          "kind": "code",
          "literal": "contentHash",
          "chunkId": "api/knowledge-graph#fields"
        },
        {
          "kind": "code",
          "literal": "context",
          "chunkId": "api/knowledge-graph#fields"
        },
        {
          "kind": "code",
          "literal": "glossary",
          "chunkId": "api/knowledge-graph#fields"
        },
        {
          "kind": "code",
          "literal": "GlossaryEntry[]",
          "chunkId": "api/knowledge-graph#fields"
        },
        {
          "kind": "code",
          "literal": "overview",
          "chunkId": "api/knowledge-graph#fields"
        },
        {
          "kind": "code",
          "literal": "suggestions",
          "chunkId": "api/knowledge-graph#fields"
        },
        {
          "kind": "code",
          "literal": "string[]",
          "chunkId": "api/knowledge-graph#fields"
        },
        {
          "kind": "code",
          "literal": "nodes",
          "chunkId": "api/knowledge-graph#fields"
        },
        {
          "kind": "code",
          "literal": "KnowledgeNode[]",
          "chunkId": "api/knowledge-graph#fields"
        },
        {
          "kind": "code",
          "literal": "edges",
          "chunkId": "api/knowledge-graph#fields"
        },
        {
          "kind": "code",
          "literal": "KnowledgeEdge[]",
          "chunkId": "api/knowledge-graph#fields"
        }
      ],
      "sources": [
        {
          "chunkId": "api/knowledge-graph#fields",
          "url": "/docs/api/knowledge-graph#fields",
          "anchor": "fields"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "fields",
        "level",
        "schema",
        "version",
        "generation",
        "timestamp",
        "content",
        "hash",
        "gates",
        "freshness",
        "compact",
        "context",
        "degradation",
        "fallback",
        "alias",
        "bearing",
        "glossary",
        "deterministic",
        "overview",
        "model",
        "authored",
        "suggested",
        "questions",
        "distilled",
        "section",
        "nodes",
        "reserved",
        "edges",
        "array",
        "ships",
        "empty",
        "generatedat",
        "string",
        "contenthash",
        "glossaryentry",
        "suggestions",
        "knowledgenode",
        "knowledgeedge",
        "field",
        "type"
      ]
    },
    {
      "id": "api/knowledge-graph#how-each-field-is-used",
      "kind": "section",
      "title": "Digest format",
      "heading": "How each field is used",
      "group": "API",
      "url": "/docs/api/knowledge-graph#how-each-field-is-used",
      "summary": "The overview and nodes are prompt-cached into the loop's system prompt; the glossary widens keyword queries; nodes also lift keyword ranking above incidental mentions; terms back a render-time link-support check; suggestions feed the overlay's empty state; and the content hash lets the build skip model work when nothing changed.",
      "facts": [
        {
          "kind": "code",
          "literal": "overview",
          "chunkId": "api/knowledge-graph#how-each-field-is-used"
        },
        {
          "kind": "code",
          "literal": "nodes",
          "chunkId": "api/knowledge-graph#how-each-field-is-used"
        },
        {
          "kind": "code",
          "literal": "facts",
          "chunkId": "api/knowledge-graph#how-each-field-is-used"
        },
        {
          "kind": "code",
          "literal": "glossary",
          "chunkId": "api/knowledge-graph#how-each-field-is-used"
        },
        {
          "kind": "code",
          "literal": "k8s",
          "chunkId": "api/knowledge-graph#how-each-field-is-used"
        },
        {
          "kind": "code",
          "literal": "kubernetes",
          "chunkId": "api/knowledge-graph#how-each-field-is-used"
        },
        {
          "kind": "code",
          "literal": "summary",
          "chunkId": "api/knowledge-graph#how-each-field-is-used"
        },
        {
          "kind": "code",
          "literal": "terms",
          "chunkId": "api/knowledge-graph#how-each-field-is-used"
        },
        {
          "kind": "code",
          "literal": "suggestions",
          "chunkId": "api/knowledge-graph#how-each-field-is-used"
        },
        {
          "kind": "code",
          "literal": "GET",
          "chunkId": "api/knowledge-graph#how-each-field-is-used"
        },
        {
          "kind": "code",
          "literal": "contentHash",
          "chunkId": "api/knowledge-graph#how-each-field-is-used"
        },
        {
          "kind": "code",
          "literal": "build",
          "chunkId": "api/knowledge-graph#how-each-field-is-used"
        }
      ],
      "sources": [
        {
          "chunkId": "api/knowledge-graph#how-each-field-is-used",
          "url": "/docs/api/knowledge-graph#how-each-field-is-used",
          "anchor": "how-each-field-is-used"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "field",
        "overview",
        "nodes",
        "prompt",
        "cached",
        "loop",
        "system",
        "glossary",
        "widens",
        "keyword",
        "queries",
        "also",
        "lift",
        "ranking",
        "above",
        "incidental",
        "mentions",
        "terms",
        "back",
        "render",
        "time",
        "link",
        "support",
        "check",
        "suggestions",
        "feed",
        "overlay",
        "empty",
        "state",
        "content",
        "hash",
        "lets",
        "build",
        "skip",
        "model",
        "work",
        "nothing",
        "changed",
        "facts",
        "kubernetes"
      ]
    },
    {
      "id": "api/knowledge-graph#knowledgenode",
      "kind": "section",
      "title": "Digest format",
      "heading": "KnowledgeNode",
      "group": "API",
      "url": "/docs/api/knowledge-graph#knowledgenode",
      "summary": "Each node pairs the chunk id — mapping one-to-one to a real anchor — with the model's paraphrase, deterministically extracted verbatim facts the model never authors, provenance sources, a mode that marks reference sections as source-primary so the agent reads their source text, and distinctive terms for link validation.",
      "facts": [
        {
          "kind": "code",
          "literal": "KnowledgeNode",
          "chunkId": "api/knowledge-graph#knowledgenode"
        },
        {
          "kind": "code",
          "literal": "id",
          "chunkId": "api/knowledge-graph#knowledgenode"
        },
        {
          "kind": "code",
          "literal": "string",
          "chunkId": "api/knowledge-graph#knowledgenode"
        },
        {
          "kind": "code",
          "literal": "summary",
          "chunkId": "api/knowledge-graph#knowledgenode"
        },
        {
          "kind": "code",
          "literal": "facts",
          "chunkId": "api/knowledge-graph#knowledgenode"
        },
        {
          "kind": "code",
          "literal": "Fact[]",
          "chunkId": "api/knowledge-graph#knowledgenode"
        },
        {
          "kind": "code",
          "literal": "sources",
          "chunkId": "api/knowledge-graph#knowledgenode"
        },
        {
          "kind": "code",
          "literal": "SourceRef[]",
          "chunkId": "api/knowledge-graph#knowledgenode"
        },
        {
          "kind": "code",
          "literal": "url",
          "chunkId": "api/knowledge-graph#knowledgenode"
        },
        {
          "kind": "code",
          "literal": "anchor",
          "chunkId": "api/knowledge-graph#knowledgenode"
        },
        {
          "kind": "code",
          "literal": "mode",
          "chunkId": "api/knowledge-graph#knowledgenode"
        },
        {
          "kind": "code",
          "literal": "'agent-primary' \\| 'source-primary'",
          "chunkId": "api/knowledge-graph#knowledgenode"
        },
        {
          "kind": "code",
          "literal": "source-primary",
          "chunkId": "api/knowledge-graph#knowledgenode"
        },
        {
          "kind": "code",
          "literal": "terms",
          "chunkId": "api/knowledge-graph#knowledgenode"
        },
        {
          "kind": "code",
          "literal": "string[]",
          "chunkId": "api/knowledge-graph#knowledgenode"
        }
      ],
      "sources": [
        {
          "chunkId": "api/knowledge-graph#knowledgenode",
          "url": "/docs/api/knowledge-graph#knowledgenode",
          "anchor": "knowledgenode"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "knowledgenode",
        "node",
        "pairs",
        "chunk",
        "mapping",
        "real",
        "anchor",
        "model",
        "paraphrase",
        "deterministically",
        "extracted",
        "verbatim",
        "facts",
        "never",
        "authors",
        "provenance",
        "sources",
        "mode",
        "marks",
        "reference",
        "sections",
        "source",
        "primary",
        "agent",
        "reads",
        "their",
        "text",
        "distinctive",
        "terms",
        "link",
        "validation",
        "string",
        "summary",
        "fact",
        "sourceref",
        "field",
        "type",
        "description",
        "equals",
        "maps"
      ]
    },
    {
      "id": "api/knowledge-graph#regenerating",
      "kind": "section",
      "title": "Digest format",
      "heading": "Regenerating",
      "group": "API",
      "url": "/docs/api/knowledge-graph#regenerating",
      "summary": "Rebuild after content changes and commit the result; the hash gate makes this safe to run on every build because model work only happens when content actually changed. Build with the bundled skill or one API call, and run the verifier to gate anchors, coverage, and literal fidelity.",
      "facts": [
        {
          "kind": "code",
          "literal": "ask kg build",
          "chunkId": "api/knowledge-graph#regenerating"
        },
        {
          "kind": "code",
          "literal": "astro build",
          "chunkId": "api/knowledge-graph#regenerating"
        },
        {
          "kind": "code",
          "literal": "ask kg verify",
          "chunkId": "api/knowledge-graph#regenerating"
        }
      ],
      "sources": [
        {
          "chunkId": "api/knowledge-graph#regenerating",
          "url": "/docs/api/knowledge-graph#regenerating",
          "anchor": "regenerating"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "regenerating",
        "rebuild",
        "after",
        "content",
        "changes",
        "commit",
        "result",
        "hash",
        "gate",
        "makes",
        "safe",
        "every",
        "build",
        "because",
        "model",
        "work",
        "only",
        "happens",
        "actually",
        "changed",
        "bundled",
        "skill",
        "call",
        "verifier",
        "anchors",
        "coverage",
        "literal",
        "fidelity",
        "astro",
        "verify",
        "spends",
        "claude",
        "code",
        "integration",
        "also",
        "runs",
        "during",
        "present"
      ]
    },
    {
      "id": "api/knowledge-graph#shape",
      "kind": "section",
      "title": "Digest format",
      "heading": "Shape",
      "group": "API",
      "url": "/docs/api/knowledge-graph#shape",
      "summary": "A worked example of the artifact: version, timestamp, content hash, context, glossary, overview, suggested questions, one fully populated section node with facts and sources, and the empty edges array.",
      "facts": [],
      "sources": [
        {
          "chunkId": "api/knowledge-graph#shape",
          "url": "/docs/api/knowledge-graph#shape",
          "anchor": "shape"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "shape",
        "worked",
        "example",
        "artifact",
        "version",
        "timestamp",
        "content",
        "hash",
        "context",
        "glossary",
        "overview",
        "suggested",
        "questions",
        "fully",
        "populated",
        "section",
        "node",
        "facts",
        "sources",
        "empty",
        "edges",
        "array",
        "generatedat",
        "2026",
        "30t12",
        "000z",
        "contenthash",
        "a1b2c3",
        "search",
        "overlay",
        "astro",
        "docs",
        "term",
        "digest",
        "aliases",
        "definition",
        "offline",
        "built",
        "distilled",
        "kubernetes"
      ]
    },
    {
      "id": "api/mcp",
      "kind": "section",
      "title": "MCP server",
      "heading": null,
      "group": "API",
      "url": "/docs/api/mcp",
      "summary": "The MCP command runs a stdio Model Context Protocol server over the same digest reads as the CLI and HTTP API — the zero-glue way to hand a coding agent structured tools for the docs, from a checked-out repo's digest file or a deployed endpoint.",
      "facts": [
        {
          "kind": "code",
          "literal": "ask mcp",
          "chunkId": "api/mcp"
        },
        {
          "kind": "code",
          "literal": ".hev-ask/digest.json",
          "chunkId": "api/mcp"
        },
        {
          "kind": "code",
          "literal": "/api/ask",
          "chunkId": "api/mcp"
        }
      ],
      "sources": [
        {
          "chunkId": "api/mcp",
          "url": "/docs/api/mcp",
          "anchor": null
        }
      ],
      "mode": "source-primary",
      "terms": [
        "command",
        "runs",
        "stdio",
        "model",
        "context",
        "protocol",
        "server",
        "same",
        "digest",
        "reads",
        "http",
        "zero",
        "glue",
        "hand",
        "coding",
        "agent",
        "structured",
        "tools",
        "docs",
        "checked",
        "repo",
        "file",
        "deployed",
        "endpoint",
        "json",
        "expose",
        "committed",
        "agents",
        "graph",
        "path",
        "point",
        "gets"
      ]
    },
    {
      "id": "api/mcp#configure",
      "kind": "section",
      "title": "MCP server",
      "heading": "Configure",
      "group": "API",
      "url": "/docs/api/mcp#configure",
      "summary": "Two configurations: local keyless reads pointing at the repo's digest file, or a deployed endpoint when the freshest digest or the answer tool matters. Local mode is fully offline, but its answer tool returns an error unless an endpoint is set.",
      "facts": [
        {
          "kind": "code",
          "literal": "{\n  \"mcpServers\": {\n    \"docs\": {\n      \"command\": \"ask\",\n      \"args\": [\"--kg-path\", \".hev-ask/digest.json\", \"mcp\"]\n    }\n  }\n}",
          "chunkId": "api/mcp#configure"
        },
        {
          "kind": "code",
          "literal": "{\n  \"mcpServers\": {\n    \"askhev\": {\n      \"command\": \"ask\",\n      \"args\": [\"--endpoint\", \"https://askhev.com/api/ask\", \"mcp\"]\n    }\n  }\n}",
          "chunkId": "api/mcp#configure"
        },
        {
          "kind": "code",
          "literal": "answer",
          "chunkId": "api/mcp#configure"
        },
        {
          "kind": "code",
          "literal": "--endpoint",
          "chunkId": "api/mcp#configure"
        }
      ],
      "sources": [
        {
          "chunkId": "api/mcp#configure",
          "url": "/docs/api/mcp#configure",
          "anchor": "configure"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "configure",
        "configurations",
        "local",
        "keyless",
        "reads",
        "pointing",
        "repo",
        "digest",
        "file",
        "deployed",
        "endpoint",
        "freshest",
        "answer",
        "tool",
        "matters",
        "mode",
        "fully",
        "offline",
        "returns",
        "error",
        "unless",
        "mcpservers",
        "docs",
        "command",
        "args",
        "path",
        "json",
        "askhev",
        "https",
        "graph",
        "site",
        "form",
        "want"
      ]
    },
    {
      "id": "api/mcp#data-sources",
      "kind": "section",
      "title": "MCP server",
      "heading": "Data sources",
      "group": "API",
      "url": "/docs/api/mcp#data-sources",
      "summary": "Resolution mirrors the CLI: an endpoint flag routes reads and answers through the deployed HTTP API, otherwise the digest path is read from disk on every tool call — so a just-rebuilt digest is visible without restarting the server.",
      "facts": [
        {
          "kind": "code",
          "literal": "ask mcp",
          "chunkId": "api/mcp#data-sources"
        },
        {
          "kind": "code",
          "literal": "--endpoint <url>",
          "chunkId": "api/mcp#data-sources"
        },
        {
          "kind": "code",
          "literal": "answer",
          "chunkId": "api/mcp#data-sources"
        },
        {
          "kind": "code",
          "literal": "POST /api/ask",
          "chunkId": "api/mcp#data-sources"
        },
        {
          "kind": "code",
          "literal": "--kg-path",
          "chunkId": "api/mcp#data-sources"
        },
        {
          "kind": "code",
          "literal": ".hev-ask/digest.json",
          "chunkId": "api/mcp#data-sources"
        },
        {
          "kind": "code",
          "literal": "digest.json",
          "chunkId": "api/mcp#data-sources"
        }
      ],
      "sources": [
        {
          "chunkId": "api/mcp#data-sources",
          "url": "/docs/api/mcp#data-sources",
          "anchor": "data-sources"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "data",
        "sources",
        "resolution",
        "mirrors",
        "endpoint",
        "flag",
        "routes",
        "reads",
        "answers",
        "through",
        "deployed",
        "http",
        "otherwise",
        "digest",
        "path",
        "read",
        "disk",
        "every",
        "tool",
        "call",
        "just",
        "rebuilt",
        "visible",
        "without",
        "restarting",
        "server",
        "answer",
        "post",
        "json",
        "uses",
        "same",
        "calls",
        "streams",
        "defaulting",
        "local",
        "load"
      ]
    },
    {
      "id": "api/mcp#protocol-surface",
      "kind": "section",
      "title": "MCP server",
      "heading": "Protocol surface",
      "group": "API",
      "url": "/docs/api/mcp#protocol-surface",
      "summary": "The server speaks newline-delimited JSON-RPC over stdio, handling initialization, tool listing, and tool calls. Unknown methods return protocol errors while tool-level failures return MCP error results, and all substantive behavior lives in the shared Go package.",
      "facts": [
        {
          "kind": "code",
          "literal": "initialize",
          "chunkId": "api/mcp#protocol-surface"
        },
        {
          "kind": "code",
          "literal": "tools/list",
          "chunkId": "api/mcp#protocol-surface"
        },
        {
          "kind": "code",
          "literal": "tools/call",
          "chunkId": "api/mcp#protocol-surface"
        },
        {
          "kind": "code",
          "literal": "isError: true",
          "chunkId": "api/mcp#protocol-surface"
        },
        {
          "kind": "code",
          "literal": "pkg/ask",
          "chunkId": "api/mcp#protocol-surface"
        }
      ],
      "sources": [
        {
          "chunkId": "api/mcp#protocol-surface",
          "url": "/docs/api/mcp#protocol-surface",
          "anchor": "protocol-surface"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "protocol",
        "surface",
        "server",
        "speaks",
        "newline",
        "delimited",
        "json",
        "stdio",
        "handling",
        "initialization",
        "tool",
        "listing",
        "calls",
        "unknown",
        "methods",
        "return",
        "errors",
        "while",
        "level",
        "failures",
        "error",
        "results",
        "substantive",
        "behavior",
        "lives",
        "shared",
        "package",
        "initialize",
        "tools",
        "list",
        "call",
        "iserror",
        "true",
        "handles",
        "plus",
        "initialized",
        "notification",
        "result",
        "keeps",
        "small"
      ]
    },
    {
      "id": "api/mcp#tools",
      "kind": "section",
      "title": "MCP server",
      "heading": "Tools",
      "group": "API",
      "url": "/docs/api/mcp#tools",
      "summary": "Tools mirror the read surface: glossary listing and lookup, section listing and retrieval, the overview, keyword search, and a streamed answer collapsed into one tool result. Results carry human-readable text plus the original machine shape in structured content.",
      "facts": [
        {
          "kind": "code",
          "literal": "glossary_list",
          "chunkId": "api/mcp#tools"
        },
        {
          "kind": "code",
          "literal": "{ terms: GlossaryEntry[] }",
          "chunkId": "api/mcp#tools"
        },
        {
          "kind": "code",
          "literal": "glossary_get",
          "chunkId": "api/mcp#tools"
        },
        {
          "kind": "code",
          "literal": "{ term }",
          "chunkId": "api/mcp#tools"
        },
        {
          "kind": "code",
          "literal": "sections_list",
          "chunkId": "api/mcp#tools"
        },
        {
          "kind": "code",
          "literal": "{ group? }",
          "chunkId": "api/mcp#tools"
        },
        {
          "kind": "code",
          "literal": "{ sections: SectionSummary[] }",
          "chunkId": "api/mcp#tools"
        },
        {
          "kind": "code",
          "literal": "section_get",
          "chunkId": "api/mcp#tools"
        },
        {
          "kind": "code",
          "literal": "{ id }",
          "chunkId": "api/mcp#tools"
        },
        {
          "kind": "code",
          "literal": "overview",
          "chunkId": "api/mcp#tools"
        },
        {
          "kind": "code",
          "literal": "{ overview, context }",
          "chunkId": "api/mcp#tools"
        },
        {
          "kind": "code",
          "literal": "search",
          "chunkId": "api/mcp#tools"
        },
        {
          "kind": "code",
          "literal": "{ query, maxResults? }",
          "chunkId": "api/mcp#tools"
        },
        {
          "kind": "code",
          "literal": "answer",
          "chunkId": "api/mcp#tools"
        },
        {
          "kind": "code",
          "literal": "{ query }",
          "chunkId": "api/mcp#tools"
        },
        {
          "kind": "code",
          "literal": "content",
          "chunkId": "api/mcp#tools"
        },
        {
          "kind": "code",
          "literal": "structuredContent",
          "chunkId": "api/mcp#tools"
        }
      ],
      "sources": [
        {
          "chunkId": "api/mcp#tools",
          "url": "/docs/api/mcp#tools",
          "anchor": "tools"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "tools",
        "mirror",
        "read",
        "surface",
        "glossary",
        "listing",
        "lookup",
        "section",
        "retrieval",
        "overview",
        "keyword",
        "search",
        "streamed",
        "answer",
        "collapsed",
        "tool",
        "result",
        "results",
        "carry",
        "human",
        "readable",
        "text",
        "plus",
        "original",
        "machine",
        "shape",
        "structured",
        "content",
        "list",
        "terms",
        "glossaryentry",
        "term",
        "sections",
        "group",
        "sectionsummary",
        "context",
        "query",
        "maxresults",
        "structuredcontent",
        "arguments"
      ]
    },
    {
      "id": "api/search-overlay",
      "kind": "section",
      "title": "SearchOverlay component",
      "heading": null,
      "group": "API",
      "url": "/docs/api/search-overlay",
      "summary": "The overlay component renders the ⌘K command palette. Add it once in a global layout; it opens over the page and doesn't affect layout until opened.",
      "facts": [
        {
          "kind": "code",
          "literal": "---\nimport SearchOverlay from \"@hev/ask/components/SearchOverlay.astro\";\n---\n<SearchOverlay />",
          "chunkId": "api/search-overlay"
        },
        {
          "kind": "code",
          "literal": "SearchOverlay.astro",
          "chunkId": "api/search-overlay"
        },
        {
          "kind": "code",
          "literal": "⌘K",
          "chunkId": "api/search-overlay"
        },
        {
          "kind": "code",
          "literal": "<dialog>",
          "chunkId": "api/search-overlay"
        },
        {
          "kind": "value",
          "literal": "Callout.astro",
          "chunkId": "api/search-overlay"
        }
      ],
      "sources": [
        {
          "chunkId": "api/search-overlay",
          "url": "/docs/api/search-overlay",
          "anchor": null
        }
      ],
      "mode": "source-primary",
      "terms": [
        "overlay",
        "component",
        "renders",
        "command",
        "palette",
        "once",
        "global",
        "layout",
        "opens",
        "page",
        "doesn",
        "affect",
        "until",
        "opened",
        "import",
        "searchoverlay",
        "components",
        "astro",
        "dialog",
        "callout",
        "props",
        "data",
        "open",
        "opener",
        "attribute",
        "keyboard",
        "model",
        "mode",
        "toggle",
        "theming",
        "through",
        "variables"
      ]
    },
    {
      "id": "api/search-overlay#keyboard-model",
      "kind": "section",
      "title": "SearchOverlay component",
      "heading": "Keyboard model",
      "group": "API",
      "url": "/docs/api/search-overlay#keyboard-model",
      "summary": "The overlay is ask-first and word count picks the path: one word runs debounced keyword search with an auto-active first result, a second word switches to ask mode where Enter sends the question to the loop, and arrow keys move keyword selection. Without a server key, asking returns keyword results with a surfaced warning instead of breaking.",
      "facts": [
        {
          "kind": "code",
          "literal": "Tab",
          "chunkId": "api/search-overlay#keyboard-model"
        }
      ],
      "sources": [
        {
          "chunkId": "api/search-overlay#keyboard-model",
          "url": "/docs/api/search-overlay#keyboard-model",
          "anchor": "keyboard-model"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "keyboard",
        "model",
        "overlay",
        "first",
        "word",
        "count",
        "picks",
        "path",
        "runs",
        "debounced",
        "keyword",
        "search",
        "auto",
        "active",
        "result",
        "second",
        "switches",
        "mode",
        "enter",
        "sends",
        "question",
        "loop",
        "arrow",
        "keys",
        "move",
        "selection",
        "without",
        "server",
        "asking",
        "returns",
        "results",
        "surfaced",
        "warning",
        "instead",
        "breaking",
        "number",
        "words",
        "typed",
        "decides",
        "open"
      ]
    },
    {
      "id": "api/search-overlay#keyword-results-and-deep-links",
      "kind": "section",
      "title": "SearchOverlay component",
      "heading": "Keyword results and deep links",
      "group": "API",
      "url": "/docs/api/search-overlay#keyword-results-and-deep-links",
      "summary": "Each keyword row shows the document title, an optional heading breadcrumb, and a one-line snippet. The row links to the chunk's URL, which already carries the anchor, so clicking lands on the exact heading.",
      "facts": [
        {
          "kind": "code",
          "literal": "Concepts › The agentic loop",
          "chunkId": "api/search-overlay#keyword-results-and-deep-links"
        },
        {
          "kind": "code",
          "literal": "url",
          "chunkId": "api/search-overlay#keyword-results-and-deep-links"
        },
        {
          "kind": "code",
          "literal": "#anchor",
          "chunkId": "api/search-overlay#keyword-results-and-deep-links"
        }
      ],
      "sources": [
        {
          "chunkId": "api/search-overlay#keyword-results-and-deep-links",
          "url": "/docs/api/search-overlay#keyword-results-and-deep-links",
          "anchor": "keyword-results-and-deep-links"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "keyword",
        "results",
        "deep",
        "links",
        "shows",
        "document",
        "title",
        "optional",
        "heading",
        "breadcrumb",
        "line",
        "snippet",
        "chunk",
        "already",
        "carries",
        "anchor",
        "clicking",
        "lands",
        "exact",
        "concepts",
        "agentic",
        "loop",
        "result",
        "renders",
        "link"
      ]
    },
    {
      "id": "api/search-overlay#opening-the-overlay",
      "kind": "section",
      "title": "SearchOverlay component",
      "heading": "Opening the overlay",
      "group": "API",
      "url": "/docs/api/search-overlay#opening-the-overlay",
      "summary": "Two built-in ways to open the palette: the keyboard shortcut binds automatically once the component is on the page, and any element with the opener data attribute opens it on click — wire up as many triggers as needed.",
      "facts": [
        {
          "kind": "code",
          "literal": "<button type=\"button\" data-hev-ask-open>\n  Search <kbd>⌘K</kbd>\n</button>\n\n<a href=\"#\" data-hev-ask-open>Search the docs</a>",
          "chunkId": "api/search-overlay#opening-the-overlay"
        },
        {
          "kind": "code",
          "literal": "⌘K",
          "chunkId": "api/search-overlay#opening-the-overlay"
        },
        {
          "kind": "code",
          "literal": "Ctrl-K",
          "chunkId": "api/search-overlay#opening-the-overlay"
        },
        {
          "kind": "code",
          "literal": "data-hev-ask-open",
          "chunkId": "api/search-overlay#opening-the-overlay"
        }
      ],
      "sources": [
        {
          "chunkId": "api/search-overlay#opening-the-overlay",
          "url": "/docs/api/search-overlay#opening-the-overlay",
          "anchor": "opening-the-overlay"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "opening",
        "overlay",
        "built",
        "ways",
        "open",
        "palette",
        "keyboard",
        "shortcut",
        "binds",
        "automatically",
        "once",
        "component",
        "page",
        "element",
        "opener",
        "data",
        "attribute",
        "opens",
        "click",
        "wire",
        "many",
        "triggers",
        "needed",
        "button",
        "type",
        "search",
        "href",
        "docs",
        "ctrl",
        "both",
        "bound",
        "like",
        "header",
        "sidebar",
        "inline",
        "links"
      ]
    },
    {
      "id": "api/search-overlay#props",
      "kind": "section",
      "title": "SearchOverlay component",
      "heading": "Props",
      "group": "API",
      "url": "/docs/api/search-overlay#props",
      "summary": "Three props: the endpoint the overlay posts to (which must match the integration's endpoint option), the input placeholder, and the debounce in milliseconds before a keyword query is sent.",
      "facts": [
        {
          "kind": "code",
          "literal": "<SearchOverlay\n  endpoint=\"/api/ask\"\n  placeholder=\"Search hev ask…\"\n  debounce={400}\n/>",
          "chunkId": "api/search-overlay#props"
        },
        {
          "kind": "code",
          "literal": "endpoint",
          "chunkId": "api/search-overlay#props"
        },
        {
          "kind": "code",
          "literal": "string",
          "chunkId": "api/search-overlay#props"
        },
        {
          "kind": "code",
          "literal": "'/api/ask'",
          "chunkId": "api/search-overlay#props"
        },
        {
          "kind": "code",
          "literal": "placeholder",
          "chunkId": "api/search-overlay#props"
        },
        {
          "kind": "code",
          "literal": "'Search the docs…'",
          "chunkId": "api/search-overlay#props"
        },
        {
          "kind": "code",
          "literal": "debounce",
          "chunkId": "api/search-overlay#props"
        },
        {
          "kind": "code",
          "literal": "number",
          "chunkId": "api/search-overlay#props"
        },
        {
          "kind": "code",
          "literal": "500",
          "chunkId": "api/search-overlay#props"
        }
      ],
      "sources": [
        {
          "chunkId": "api/search-overlay#props",
          "url": "/docs/api/search-overlay#props",
          "anchor": "props"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "props",
        "three",
        "endpoint",
        "overlay",
        "posts",
        "must",
        "match",
        "integration",
        "option",
        "input",
        "placeholder",
        "debounce",
        "milliseconds",
        "before",
        "keyword",
        "query",
        "sent",
        "searchoverlay",
        "search",
        "string",
        "docs",
        "number",
        "prop",
        "type",
        "default",
        "description",
        "queries",
        "text",
        "after",
        "typing",
        "stops"
      ]
    },
    {
      "id": "api/search-overlay#suggested-questions",
      "kind": "section",
      "title": "SearchOverlay component",
      "heading": "Suggested questions",
      "group": "API",
      "url": "/docs/api/search-overlay#suggested-questions",
      "summary": "With AI on, the overlay fetches suggested questions from the endpoint on first open and shows them in the empty state. They come from the digest at build time so rendering costs no model call, and clicking one fills the input and asks immediately.",
      "facts": [
        {
          "kind": "code",
          "literal": "GET /api/ask",
          "chunkId": "api/search-overlay#suggested-questions"
        },
        {
          "kind": "code",
          "literal": "suggestions",
          "chunkId": "api/search-overlay#suggested-questions"
        }
      ],
      "sources": [
        {
          "chunkId": "api/search-overlay#suggested-questions",
          "url": "/docs/api/search-overlay#suggested-questions",
          "anchor": "suggested-questions"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "suggested",
        "questions",
        "overlay",
        "fetches",
        "endpoint",
        "first",
        "open",
        "shows",
        "empty",
        "state",
        "come",
        "digest",
        "build",
        "time",
        "rendering",
        "costs",
        "model",
        "call",
        "clicking",
        "fills",
        "input",
        "asks",
        "immediately",
        "suggestions",
        "short",
        "list",
        "opens",
        "baked",
        "there",
        "render",
        "none",
        "simply",
        "nothing",
        "extra",
        "suggestion"
      ]
    },
    {
      "id": "api/search-overlay#the-mode-toggle",
      "kind": "section",
      "title": "SearchOverlay component",
      "heading": "The mode toggle",
      "group": "API",
      "url": "/docs/api/search-overlay#the-mode-toggle",
      "summary": "An AI-on-Enter preference persists in localStorage. Readers who flip to keyword-only never trigger a model call — a space just searches a phrase, no suggestions are shown, and the choice survives reloads.",
      "facts": [
        {
          "kind": "code",
          "literal": "localStorage",
          "chunkId": "api/search-overlay#the-mode-toggle"
        },
        {
          "kind": "code",
          "literal": "hev-ask:mode",
          "chunkId": "api/search-overlay#the-mode-toggle"
        },
        {
          "kind": "code",
          "literal": "agentic",
          "chunkId": "api/search-overlay#the-mode-toggle"
        },
        {
          "kind": "code",
          "literal": "keyword",
          "chunkId": "api/search-overlay#the-mode-toggle"
        }
      ],
      "sources": [
        {
          "chunkId": "api/search-overlay#the-mode-toggle",
          "url": "/docs/api/search-overlay#the-mode-toggle",
          "anchor": "the-mode-toggle"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "mode",
        "toggle",
        "enter",
        "preference",
        "persists",
        "localstorage",
        "readers",
        "flip",
        "keyword",
        "only",
        "never",
        "trigger",
        "model",
        "call",
        "space",
        "just",
        "searches",
        "phrase",
        "suggestions",
        "shown",
        "choice",
        "survives",
        "reloads",
        "agentic",
        "overlay",
        "under",
        "suggested",
        "questions"
      ]
    },
    {
      "id": "api/search-overlay#the-streamed-answer",
      "kind": "section",
      "title": "SearchOverlay component",
      "heading": "The streamed answer",
      "group": "API",
      "url": "/docs/api/search-overlay#the-streamed-answer",
      "summary": "Asking replaces the keyword rows with an answer panel: the model's sub-queries appear as faint activity lines, then the grounded answer streams token-by-token with accent-styled inline deep links and a sources chip row. Links are validated against the streamed source set, so a hallucinated anchor renders as plain text instead of a dead link.",
      "facts": [
        {
          "kind": "code",
          "literal": "searched: …",
          "chunkId": "api/search-overlay#the-streamed-answer"
        },
        {
          "kind": "code",
          "literal": "/docs/page#anchor",
          "chunkId": "api/search-overlay#the-streamed-answer"
        }
      ],
      "sources": [
        {
          "chunkId": "api/search-overlay#the-streamed-answer",
          "url": "/docs/api/search-overlay#the-streamed-answer",
          "anchor": "the-streamed-answer"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "streamed",
        "answer",
        "asking",
        "replaces",
        "keyword",
        "rows",
        "panel",
        "model",
        "queries",
        "appear",
        "faint",
        "activity",
        "lines",
        "grounded",
        "streams",
        "token",
        "accent",
        "styled",
        "inline",
        "deep",
        "links",
        "sources",
        "chip",
        "validated",
        "against",
        "source",
        "hallucinated",
        "anchor",
        "renders",
        "plain",
        "text",
        "instead",
        "dead",
        "link",
        "searched",
        "docs",
        "page",
        "pressing",
        "enter",
        "configured"
      ]
    },
    {
      "id": "api/search-overlay#theming",
      "kind": "section",
      "title": "SearchOverlay component",
      "heading": "Theming",
      "group": "API",
      "url": "/docs/api/search-overlay#theming",
      "summary": "The overlay reads the page's CSS custom properties for background, text, muted, and accent colors. Because its scoped styles key off those variables, matching a site's look is usually just defining the tokens — no overlay CSS to override.",
      "facts": [
        {
          "kind": "code",
          "literal": ":root {\n  --paper: #111111;       /* overlay background */\n  --ink: #fafaf5;         /* primary text */\n  --muted: #6b6b66;       /* secondary text */\n  --signal: #e25822;      /* accent / active state */\n}",
          "chunkId": "api/search-overlay#theming"
        },
        {
          "kind": "code",
          "literal": "as-",
          "chunkId": "api/search-overlay#theming"
        },
        {
          "kind": "code",
          "literal": ":root",
          "chunkId": "api/search-overlay#theming"
        }
      ],
      "sources": [
        {
          "chunkId": "api/search-overlay#theming",
          "url": "/docs/api/search-overlay#theming",
          "anchor": "theming"
        }
      ],
      "mode": "source-primary",
      "terms": [
        "theming",
        "overlay",
        "reads",
        "page",
        "custom",
        "properties",
        "background",
        "text",
        "muted",
        "accent",
        "colors",
        "because",
        "scoped",
        "styles",
        "those",
        "variables",
        "matching",
        "site",
        "look",
        "usually",
        "just",
        "defining",
        "tokens",
        "override",
        "root",
        "paper",
        "111111",
        "fafaf5",
        "primary",
        "6b6b66",
        "secondary",
        "signal",
        "e25822",
        "active",
        "state",
        "markup",
        "uses",
        "class",
        "prefix",
        "define"
      ]
    },
    {
      "id": "concepts",
      "kind": "section",
      "title": "Concepts",
      "heading": null,
      "group": "Overview",
      "url": "/docs/concepts",
      "summary": "hev ask is three parts: a heading-chunk index with real anchors, an offline ask digest distilling every section, and a bounded agentic loop that reads the digest progressively — primer first, summaries next, full source only when needed. The digest builds offline with a strong model and commits to git; the index and loop run on demand at the edge with no durable state.",
      "facts": [
        {
          "kind": "value",
          "literal": "Diagram.astro",
          "chunkId": "concepts"
        },
        {
          "kind": "value",
          "literal": "Callout.astro",
          "chunkId": "concepts"
        }
      ],
      "sources": [
        {
          "chunkId": "concepts",
          "url": "/docs/concepts",
          "anchor": null
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "three",
        "parts",
        "heading",
        "chunk",
        "index",
        "real",
        "anchors",
        "offline",
        "digest",
        "distilling",
        "every",
        "section",
        "bounded",
        "agentic",
        "loop",
        "reads",
        "progressively",
        "primer",
        "first",
        "summaries",
        "next",
        "full",
        "source",
        "only",
        "needed",
        "builds",
        "strong",
        "model",
        "commits",
        "demand",
        "edge",
        "durable",
        "state",
        "diagram",
        "astro",
        "callout",
        "works",
        "indexing",
        "keyword",
        "prefiltering"
      ]
    },
    {
      "id": "concepts#asking-is-the-default",
      "kind": "section",
      "title": "Concepts",
      "heading": "Asking is the default",
      "group": "Overview",
      "url": "/docs/concepts#asking-is-the-default",
      "summary": "The overlay treats a single word as an instant keyword lookup; a second word switches to ask mode, where Enter sends the question to the agentic loop, and suggested questions baked into the digest make asking the obvious move. Readers can flip to keyword-only, persisted in localStorage, so the model is never called.",
      "facts": [
        {
          "kind": "code",
          "literal": "localStorage",
          "chunkId": "concepts#asking-is-the-default"
        }
      ],
      "sources": [
        {
          "chunkId": "concepts#asking-is-the-default",
          "url": "/docs/concepts#asking-is-the-default",
          "anchor": "asking-is-the-default"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "asking",
        "default",
        "overlay",
        "treats",
        "single",
        "word",
        "instant",
        "keyword",
        "lookup",
        "second",
        "switches",
        "mode",
        "enter",
        "sends",
        "question",
        "agentic",
        "loop",
        "suggested",
        "questions",
        "baked",
        "digest",
        "make",
        "obvious",
        "move",
        "readers",
        "flip",
        "only",
        "persisted",
        "localstorage",
        "model",
        "never",
        "called",
        "first",
        "treated",
        "answered",
        "instantly",
        "index",
        "moment",
        "query",
        "grows"
      ]
    },
    {
      "id": "concepts#chunks-and-anchors",
      "kind": "section",
      "title": "Concepts",
      "heading": "Chunks and anchors",
      "group": "Overview",
      "url": "/docs/concepts#chunks-and-anchors",
      "summary": "Documents are split on headings into section chunks whose URLs carry real anchors, generated with the same slugger Astro's renderer uses so links land on headings that exist. Both the runtime index and the offline build chunk through the same function, so the anchors always agree.",
      "facts": [
        {
          "kind": "code",
          "literal": "##",
          "chunkId": "concepts#chunks-and-anchors"
        },
        {
          "kind": "code",
          "literal": "###",
          "chunkId": "concepts#chunks-and-anchors"
        },
        {
          "kind": "code",
          "literal": "basePath + slug + #anchor",
          "chunkId": "concepts#chunks-and-anchors"
        },
        {
          "kind": "code",
          "literal": "github-slugger",
          "chunkId": "concepts#chunks-and-anchors"
        },
        {
          "kind": "code",
          "literal": "getCollection",
          "chunkId": "concepts#chunks-and-anchors"
        },
        {
          "kind": "value",
          "literal": "github.com",
          "chunkId": "concepts#chunks-and-anchors"
        }
      ],
      "sources": [
        {
          "chunkId": "concepts#chunks-and-anchors",
          "url": "/docs/concepts#chunks-and-anchors",
          "anchor": "chunks-and-anchors"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "chunks",
        "anchors",
        "documents",
        "split",
        "headings",
        "section",
        "whose",
        "urls",
        "carry",
        "real",
        "generated",
        "same",
        "slugger",
        "astro",
        "renderer",
        "uses",
        "links",
        "land",
        "exist",
        "both",
        "runtime",
        "index",
        "offline",
        "build",
        "chunk",
        "through",
        "function",
        "always",
        "agree",
        "basepath",
        "slug",
        "anchor",
        "github",
        "getcollection",
        "does",
        "pages",
        "indexes",
        "sections",
        "document",
        "configurable"
      ]
    },
    {
      "id": "concepts#degradation-by-design",
      "kind": "section",
      "title": "Concepts",
      "heading": "Degradation, by design",
      "group": "Overview",
      "url": "/docs/concepts#degradation-by-design",
      "summary": "Every missing piece degrades instead of failing: no runtime key means keyword-only search, no build key keeps the committed digest with a warning, a missing or node-less digest falls back to plain retrieval with no suggestions, and a stale digest logs a one-line warning but still serves.",
      "facts": [
        {
          "kind": "code",
          "literal": "digest.json",
          "chunkId": "concepts#degradation-by-design"
        }
      ],
      "sources": [
        {
          "chunkId": "concepts#degradation-by-design",
          "url": "/docs/concepts#degradation-by-design",
          "anchor": "degradation-by-design"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "degradation",
        "design",
        "every",
        "missing",
        "piece",
        "degrades",
        "instead",
        "failing",
        "runtime",
        "means",
        "keyword",
        "only",
        "search",
        "build",
        "keeps",
        "committed",
        "digest",
        "warning",
        "node",
        "less",
        "falls",
        "back",
        "plain",
        "retrieval",
        "suggestions",
        "stale",
        "logs",
        "line",
        "still",
        "serves",
        "json",
        "built",
        "keep",
        "working",
        "pieces",
        "drop",
        "away",
        "mode",
        "overlay",
        "searches"
      ]
    },
    {
      "id": "concepts#keyword-search-and-the-glossary",
      "kind": "section",
      "title": "Concepts",
      "heading": "Keyword search and the glossary",
      "group": "Overview",
      "url": "/docs/concepts#keyword-search-and-the-glossary",
      "summary": "The instant path is a dependency-free prefilter: query terms expand through glossary aliases, chunks score by token overlap widened by the digest's summaries, terms, and facts, results are capped per document, and snippets excerpt around the first match. It needs no key and no embeddings, and with no digest it degrades to plain token overlap.",
      "facts": [
        {
          "kind": "code",
          "literal": "k8s",
          "chunkId": "concepts#keyword-search-and-the-glossary"
        },
        {
          "kind": "code",
          "literal": "kubernetes",
          "chunkId": "concepts#keyword-search-and-the-glossary"
        },
        {
          "kind": "code",
          "literal": "digest.json",
          "chunkId": "concepts#keyword-search-and-the-glossary"
        },
        {
          "kind": "code",
          "literal": "summary",
          "chunkId": "concepts#keyword-search-and-the-glossary"
        },
        {
          "kind": "code",
          "literal": "terms",
          "chunkId": "concepts#keyword-search-and-the-glossary"
        },
        {
          "kind": "code",
          "literal": "facts",
          "chunkId": "concepts#keyword-search-and-the-glossary"
        }
      ],
      "sources": [
        {
          "chunkId": "concepts#keyword-search-and-the-glossary",
          "url": "/docs/concepts#keyword-search-and-the-glossary",
          "anchor": "keyword-search-and-the-glossary"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "keyword",
        "search",
        "glossary",
        "instant",
        "path",
        "dependency",
        "free",
        "prefilter",
        "query",
        "terms",
        "expand",
        "through",
        "aliases",
        "chunks",
        "score",
        "token",
        "overlap",
        "widened",
        "digest",
        "summaries",
        "facts",
        "results",
        "capped",
        "document",
        "snippets",
        "excerpt",
        "around",
        "first",
        "match",
        "needs",
        "embeddings",
        "degrades",
        "plain",
        "kubernetes",
        "json",
        "summary",
        "reader",
        "types",
        "single",
        "term"
      ]
    },
    {
      "id": "concepts#the-agentic-search-loop",
      "kind": "section",
      "title": "Concepts",
      "heading": "The agentic search loop",
      "group": "Overview",
      "url": "/docs/concepts#the-agentic-search-loop",
      "summary": "Asking sends the query to a bounded tool-use loop that is progressive disclosure over the digest: the primer and section map come free in the prompt, and the model opens only the sections it needs — reading summaries, verbatim facts, and source text for reference sections — up to an iteration cap. The final call drops all tools so the model must stream a grounded answer, citing only sections it opened.",
      "facts": [
        {
          "kind": "code",
          "literal": "open_section({ id })",
          "chunkId": "concepts#the-agentic-search-loop"
        },
        {
          "kind": "code",
          "literal": "facts",
          "chunkId": "concepts#the-agentic-search-loop"
        },
        {
          "kind": "code",
          "literal": "maxIterations",
          "chunkId": "concepts#the-agentic-search-loop"
        },
        {
          "kind": "code",
          "literal": "url",
          "chunkId": "concepts#the-agentic-search-loop"
        }
      ],
      "sources": [
        {
          "chunkId": "concepts#the-agentic-search-loop",
          "url": "/docs/concepts#the-agentic-search-loop",
          "anchor": "the-agentic-search-loop"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "agentic",
        "search",
        "loop",
        "asking",
        "sends",
        "query",
        "bounded",
        "tool",
        "progressive",
        "disclosure",
        "digest",
        "primer",
        "section",
        "come",
        "free",
        "prompt",
        "model",
        "opens",
        "only",
        "sections",
        "needs",
        "reading",
        "summaries",
        "verbatim",
        "facts",
        "source",
        "text",
        "reference",
        "iteration",
        "final",
        "call",
        "drops",
        "tools",
        "must",
        "stream",
        "grounded",
        "answer",
        "citing",
        "opened",
        "open"
      ]
    },
    {
      "id": "concepts#the-ask-digest",
      "kind": "section",
      "title": "Concepts",
      "heading": "The ask digest",
      "group": "Overview",
      "url": "/docs/concepts#the-ask-digest",
      "summary": "The digest is an offline-built, committed artifact holding distilled section nodes with verbatim facts and source links, a deterministic overview map, a compact context and glossary, and suggested questions. Only the distillation is model-authored — structure, facts, overview, and the hash derive in code — which is exactly why the model step fits a Claude Code skill.",
      "facts": [
        {
          "kind": "code",
          "literal": "digest.json",
          "chunkId": "concepts#the-ask-digest"
        },
        {
          "kind": "code",
          "literal": "nodes",
          "chunkId": "concepts#the-ask-digest"
        },
        {
          "kind": "code",
          "literal": "summary",
          "chunkId": "concepts#the-ask-digest"
        },
        {
          "kind": "code",
          "literal": "facts",
          "chunkId": "concepts#the-ask-digest"
        },
        {
          "kind": "code",
          "literal": "source",
          "chunkId": "concepts#the-ask-digest"
        },
        {
          "kind": "code",
          "literal": "source-primary",
          "chunkId": "concepts#the-ask-digest"
        },
        {
          "kind": "code",
          "literal": "overview",
          "chunkId": "concepts#the-ask-digest"
        },
        {
          "kind": "code",
          "literal": "context",
          "chunkId": "concepts#the-ask-digest"
        },
        {
          "kind": "code",
          "literal": "glossary",
          "chunkId": "concepts#the-ask-digest"
        },
        {
          "kind": "code",
          "literal": "suggestions",
          "chunkId": "concepts#the-ask-digest"
        }
      ],
      "sources": [
        {
          "chunkId": "concepts#the-ask-digest",
          "url": "/docs/concepts#the-ask-digest",
          "anchor": "the-ask-digest"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "digest",
        "offline",
        "built",
        "committed",
        "artifact",
        "holding",
        "distilled",
        "section",
        "nodes",
        "verbatim",
        "facts",
        "source",
        "links",
        "deterministic",
        "overview",
        "compact",
        "context",
        "glossary",
        "suggested",
        "questions",
        "only",
        "distillation",
        "model",
        "authored",
        "structure",
        "hash",
        "derive",
        "code",
        "exactly",
        "step",
        "fits",
        "claude",
        "skill",
        "json",
        "summary",
        "primary",
        "suggestions",
        "repo",
        "reviewable",
        "agent"
      ]
    },
    {
      "id": "concepts#the-system-prompt-is-cached",
      "kind": "section",
      "title": "Concepts",
      "heading": "The system prompt is cached",
      "group": "Overview",
      "url": "/docs/concepts#the-system-prompt-is-cached",
      "summary": "The digest's map and section summaries are injected into the system prompt with a cache marker, so search rounds hit the prompt cache instead of re-sending tokens. The toolless answer turn can't reuse that cache but is the last call anyway, and the loop model defaults to Haiku.",
      "facts": [
        {
          "kind": "code",
          "literal": "cache_control",
          "chunkId": "concepts#the-system-prompt-is-cached"
        },
        {
          "kind": "value",
          "literal": "4.5",
          "chunkId": "concepts#the-system-prompt-is-cached"
        }
      ],
      "sources": [
        {
          "chunkId": "concepts#the-system-prompt-is-cached",
          "url": "/docs/concepts#the-system-prompt-is-cached",
          "anchor": "the-system-prompt-is-cached"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "system",
        "prompt",
        "cached",
        "digest",
        "section",
        "summaries",
        "injected",
        "cache",
        "marker",
        "search",
        "rounds",
        "instead",
        "sending",
        "tokens",
        "toolless",
        "answer",
        "turn",
        "reuse",
        "last",
        "call",
        "anyway",
        "loop",
        "model",
        "defaults",
        "haiku",
        "control",
        "cachecontrol",
        "across",
        "rather",
        "sent",
        "changes",
        "tool",
        "none",
        "claude",
        "configurable"
      ]
    },
    {
      "id": "concepts#two-ways-to-build-it",
      "kind": "section",
      "title": "Concepts",
      "heading": "Two ways to build it",
      "group": "Overview",
      "url": "/docs/concepts#two-ways-to-build-it",
      "summary": "The distillation runs two ways into the same deterministic assembler: the recommended Claude Code skill inside an existing subscription with no API key, or a one-call CLI build with Opus for CI. Both are hash-gated so unchanged content does no model work, and the JSON reviews in pull requests like any other change.",
      "facts": [
        {
          "kind": "code",
          "literal": "digest.json",
          "chunkId": "concepts#two-ways-to-build-it"
        },
        {
          "kind": "code",
          "literal": "ANTHROPIC_API_KEY",
          "chunkId": "concepts#two-ways-to-build-it"
        },
        {
          "kind": "code",
          "literal": "ask kg build",
          "chunkId": "concepts#two-ways-to-build-it"
        },
        {
          "kind": "value",
          "literal": "4.8",
          "chunkId": "concepts#two-ways-to-build-it"
        }
      ],
      "sources": [
        {
          "chunkId": "concepts#two-ways-to-build-it",
          "url": "/docs/concepts#two-ways-to-build-it",
          "anchor": "two-ways-to-build-it"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "ways",
        "build",
        "distillation",
        "runs",
        "same",
        "deterministic",
        "assembler",
        "recommended",
        "claude",
        "code",
        "skill",
        "inside",
        "existing",
        "subscription",
        "call",
        "opus",
        "both",
        "hash",
        "gated",
        "unchanged",
        "content",
        "does",
        "model",
        "work",
        "json",
        "reviews",
        "pull",
        "requests",
        "like",
        "other",
        "change",
        "digest",
        "anthropic",
        "step",
        "feed",
        "walks",
        "through",
        "reading",
        "corpus",
        "writing"
      ]
    },
    {
      "id": "index",
      "kind": "section",
      "title": "Introduction",
      "heading": null,
      "group": "Overview",
      "url": "/docs",
      "summary": "hev ask distills an Astro docs site into an ask digest — a token-efficient form of the docs that agents discover progressively through the CLI and readers search through a ⌘K overlay. Build the digest offline with the bundled skill and your subscription, then serve single-turn Q&A for a few cents per query — suited to technical docs, internal wikis, and other medium-sized corpora.",
      "facts": [
        {
          "kind": "code",
          "literal": "ask",
          "chunkId": "index"
        },
        {
          "kind": "code",
          "literal": "⌘K",
          "chunkId": "index"
        },
        {
          "kind": "value",
          "literal": "Diagram.astro",
          "chunkId": "index"
        },
        {
          "kind": "value",
          "literal": "Callout.astro",
          "chunkId": "index"
        },
        {
          "kind": "value",
          "literal": "astro.build",
          "chunkId": "index"
        }
      ],
      "sources": [
        {
          "chunkId": "index",
          "url": "/docs",
          "anchor": null
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "distills",
        "astro",
        "docs",
        "site",
        "digest",
        "token",
        "efficient",
        "form",
        "agents",
        "discover",
        "progressively",
        "through",
        "readers",
        "search",
        "overlay",
        "build",
        "offline",
        "bundled",
        "skill",
        "subscription",
        "serve",
        "single",
        "turn",
        "cents",
        "query",
        "suited",
        "technical",
        "internal",
        "wikis",
        "other",
        "medium",
        "sized",
        "corpora",
        "diagram",
        "callout",
        "committed",
        "serves",
        "ways",
        "answer",
        "server"
      ]
    },
    {
      "id": "index#build-it-with-your-coding-agent",
      "kind": "section",
      "title": "Introduction",
      "heading": "Build it with your coding agent",
      "group": "Overview",
      "url": "/docs#build-it-with-your-coding-agent",
      "summary": "The bundled Claude Code skill generates the digest inside an existing coding subscription — no API key, no per-build token spend. Commit the JSON, drop the overlay into a layout, and the site has instant keyword search plus a Claude answer loop, every result deep-linked. The corpus is only the configured collections: no crawler, no external index, nothing to sync.",
      "facts": [
        {
          "kind": "code",
          "literal": ".hev-ask/digest.json",
          "chunkId": "index#build-it-with-your-coding-agent"
        },
        {
          "kind": "code",
          "literal": "ANTHROPIC_API_KEY",
          "chunkId": "index#build-it-with-your-coding-agent"
        },
        {
          "kind": "code",
          "literal": "SearchOverlay.astro",
          "chunkId": "index#build-it-with-your-coding-agent"
        },
        {
          "kind": "code",
          "literal": "digest.json",
          "chunkId": "index#build-it-with-your-coding-agent"
        }
      ],
      "sources": [
        {
          "chunkId": "index#build-it-with-your-coding-agent",
          "url": "/docs#build-it-with-your-coding-agent",
          "anchor": "build-it-with-your-coding-agent"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "build",
        "coding",
        "agent",
        "bundled",
        "claude",
        "code",
        "skill",
        "generates",
        "digest",
        "inside",
        "existing",
        "subscription",
        "token",
        "spend",
        "commit",
        "json",
        "drop",
        "overlay",
        "layout",
        "site",
        "instant",
        "keyword",
        "search",
        "plus",
        "answer",
        "loop",
        "every",
        "result",
        "deep",
        "linked",
        "corpus",
        "only",
        "configured",
        "collections",
        "crawler",
        "external",
        "index",
        "nothing",
        "sync",
        "anthropic"
      ]
    },
    {
      "id": "index#next-steps",
      "kind": "section",
      "title": "Introduction",
      "heading": "Next steps",
      "group": "Overview",
      "url": "/docs#next-steps",
      "summary": "Pointers onward: the five-minute quick start, the concepts page, tradeoffs and limits, the CLI reference, and the full API reference.",
      "facts": [
        {
          "kind": "code",
          "literal": "ask",
          "chunkId": "index#next-steps"
        }
      ],
      "sources": [
        {
          "chunkId": "index#next-steps",
          "url": "/docs#next-steps",
          "anchor": "next-steps"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "next",
        "steps",
        "pointers",
        "onward",
        "five",
        "minute",
        "quick",
        "start",
        "concepts",
        "page",
        "tradeoffs",
        "limits",
        "reference",
        "full",
        "search",
        "site",
        "minutes",
        "chunks",
        "anchors",
        "agentic",
        "loop",
        "digest",
        "choosing",
        "deliberately",
        "doesn",
        "build",
        "verify",
        "query",
        "every",
        "option",
        "component",
        "props",
        "endpoint",
        "contract"
      ]
    },
    {
      "id": "index#who-this-is-for",
      "kind": "section",
      "title": "Introduction",
      "heading": "Who this is for",
      "group": "Overview",
      "url": "/docs#who-this-is-for",
      "summary": "For maintainers of Astro 5 docs sites with content collections who want search that works without standing up a service, deep-links to the right section, answers questions phrased in the reader's words, and is queryable by coding agents. Static-only keyword needs are better served by Pagefind.",
      "facts": [
        {
          "kind": "value",
          "literal": "docs.astro.build",
          "chunkId": "index#who-this-is-for"
        },
        {
          "kind": "value",
          "literal": "pagefind.app",
          "chunkId": "index#who-this-is-for"
        }
      ],
      "sources": [
        {
          "chunkId": "index#who-this-is-for",
          "url": "/docs#who-this-is-for",
          "anchor": "who-this-is-for"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "maintainers",
        "astro",
        "docs",
        "sites",
        "content",
        "collections",
        "want",
        "search",
        "works",
        "without",
        "standing",
        "service",
        "deep",
        "links",
        "right",
        "section",
        "answers",
        "questions",
        "phrased",
        "reader",
        "words",
        "queryable",
        "coding",
        "agents",
        "static",
        "only",
        "keyword",
        "needs",
        "better",
        "served",
        "pagefind",
        "build",
        "building",
        "maintaining",
        "site",
        "whose",
        "lives",
        "collection",
        "markdown",
        "work"
      ]
    },
    {
      "id": "limits",
      "kind": "section",
      "title": "Limits",
      "heading": null,
      "group": "Overview",
      "url": "/docs/limits",
      "summary": "The hard boundaries of the current design — corpus scope, recall ceiling, single-call digest build, frontmatter parsing, latency, and adapter requirements — stated as edges of what it covers, not bugs.",
      "facts": [
        {
          "kind": "value",
          "literal": "Callout.astro",
          "chunkId": "limits"
        }
      ],
      "sources": [
        {
          "chunkId": "limits",
          "url": "/docs/limits",
          "anchor": null
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "hard",
        "boundaries",
        "current",
        "design",
        "corpus",
        "scope",
        "recall",
        "ceiling",
        "single",
        "call",
        "digest",
        "build",
        "frontmatter",
        "parsing",
        "latency",
        "adapter",
        "requirements",
        "stated",
        "edges",
        "covers",
        "bugs",
        "callout",
        "astro",
        "deliberately",
        "does",
        "these",
        "should",
        "know",
        "before",
        "adopting",
        "none"
      ]
    },
    {
      "id": "limits#a-server-route-is-required",
      "kind": "section",
      "title": "Limits",
      "heading": "A server route is required",
      "group": "Overview",
      "url": "/docs/limits#a-server-route-is-required",
      "summary": "The search endpoint renders on demand, so a fully static build cannot serve it; a server or hybrid adapter is required, and static-only sites should use a static search tool instead.",
      "facts": [
        {
          "kind": "code",
          "literal": "/api/ask",
          "chunkId": "limits#a-server-route-is-required"
        }
      ],
      "sources": [
        {
          "chunkId": "limits#a-server-route-is-required",
          "url": "/docs/limits#a-server-route-is-required",
          "anchor": "a-server-route-is-required"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "server",
        "route",
        "required",
        "search",
        "endpoint",
        "renders",
        "demand",
        "fully",
        "static",
        "build",
        "cannot",
        "serve",
        "hybrid",
        "adapter",
        "only",
        "sites",
        "should",
        "tool",
        "instead",
        "need",
        "node",
        "cloudflare",
        "vercel",
        "tradeoffs"
      ]
    },
    {
      "id": "limits#agentic-search-adds-latency",
      "kind": "section",
      "title": "Limits",
      "heading": "Agentic search adds latency",
      "group": "Overview",
      "url": "/docs/limits#agentic-search-adds-latency",
      "summary": "The agentic path costs up to the iteration cap in Claude round-trips — a few seconds worst case — by nature. The keyword path is the always-available instant lane, and lowering the cap tightens the ceiling.",
      "facts": [
        {
          "kind": "code",
          "literal": "maxIterations",
          "chunkId": "limits#agentic-search-adds-latency"
        }
      ],
      "sources": [
        {
          "chunkId": "limits#agentic-search-adds-latency",
          "url": "/docs/limits#agentic-search-adds-latency",
          "anchor": "agentic-search-adds-latency"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "agentic",
        "search",
        "adds",
        "latency",
        "path",
        "costs",
        "iteration",
        "claude",
        "round",
        "trips",
        "seconds",
        "worst",
        "case",
        "nature",
        "keyword",
        "always",
        "available",
        "instant",
        "lane",
        "lowering",
        "tightens",
        "ceiling",
        "maxiterations",
        "bounded",
        "default",
        "considered",
        "tune",
        "down",
        "need",
        "tighter"
      ]
    },
    {
      "id": "limits#anchors-depend-on-astros-slugger",
      "kind": "section",
      "title": "Limits",
      "heading": "Anchors depend on Astro's slugger",
      "group": "Overview",
      "url": "/docs/limits#anchors-depend-on-astros-slugger",
      "summary": "Deep links are correct only while generated slugs match Astro's rendered ids. Using the same slugger keeps them aligned, and the verify command fails when any chunk anchor is missing from the built HTML — wire it into CI so a slugging change is caught before a broken link ships.",
      "facts": [
        {
          "kind": "code",
          "literal": "id",
          "chunkId": "limits#anchors-depend-on-astros-slugger"
        },
        {
          "kind": "code",
          "literal": "github-slugger",
          "chunkId": "limits#anchors-depend-on-astros-slugger"
        },
        {
          "kind": "code",
          "literal": "ask kg verify",
          "chunkId": "limits#anchors-depend-on-astros-slugger"
        },
        {
          "kind": "code",
          "literal": "verify",
          "chunkId": "limits#anchors-depend-on-astros-slugger"
        }
      ],
      "sources": [
        {
          "chunkId": "limits#anchors-depend-on-astros-slugger",
          "url": "/docs/limits#anchors-depend-on-astros-slugger",
          "anchor": "anchors-depend-on-astros-slugger"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "anchors",
        "depend",
        "astro",
        "slugger",
        "deep",
        "links",
        "correct",
        "only",
        "while",
        "generated",
        "slugs",
        "match",
        "rendered",
        "same",
        "keeps",
        "aligned",
        "verify",
        "command",
        "fails",
        "chunk",
        "anchor",
        "missing",
        "built",
        "html",
        "wire",
        "slugging",
        "change",
        "caught",
        "before",
        "broken",
        "link",
        "ships",
        "github",
        "long",
        "heading",
        "generates",
        "attributes",
        "uses",
        "stay",
        "ever"
      ]
    },
    {
      "id": "limits#frontmatter-parsing-is-a-flat-yaml-subset",
      "kind": "section",
      "title": "Limits",
      "heading": "Frontmatter parsing is a flat-YAML subset",
      "group": "Overview",
      "url": "/docs/limits#frontmatter-parsing-is-a-flat-yaml-subset",
      "summary": "The offline build parses frontmatter with a small flat-YAML splitter that handles common string and number fields but not nested structures. This only affects disk reads during the offline digest build; the runtime index uses Astro's own collection loader and honors the real schema.",
      "facts": [
        {
          "kind": "code",
          "literal": "getCollection",
          "chunkId": "limits#frontmatter-parsing-is-a-flat-yaml-subset"
        }
      ],
      "sources": [
        {
          "chunkId": "limits#frontmatter-parsing-is-a-flat-yaml-subset",
          "url": "/docs/limits#frontmatter-parsing-is-a-flat-yaml-subset",
          "anchor": "frontmatter-parsing-is-a-flat-yaml-subset"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "frontmatter",
        "parsing",
        "flat",
        "yaml",
        "subset",
        "offline",
        "build",
        "parses",
        "small",
        "splitter",
        "handles",
        "common",
        "string",
        "number",
        "fields",
        "nested",
        "structures",
        "only",
        "affects",
        "disk",
        "reads",
        "during",
        "digest",
        "runtime",
        "index",
        "uses",
        "astro",
        "collection",
        "loader",
        "honors",
        "real",
        "schema",
        "getcollection",
        "full",
        "parser",
        "docs",
        "aren",
        "supported",
        "time",
        "reading"
      ]
    },
    {
      "id": "limits#recall-has-a-keyword-ceiling",
      "kind": "section",
      "title": "Limits",
      "heading": "Recall has a keyword ceiling",
      "group": "Overview",
      "url": "/docs/limits#recall-has-a-keyword-ceiling",
      "summary": "Retrieval is keyword token overlap widened by the glossary, not embeddings, and the loop cannot ground in what retrieval missed. The glossary recovers most synonym cases, but a query sharing no tokens with the docs can miss entirely; embeddings are the known fix, deliberately unbuilt, and a richer glossary is the cheaper lever.",
      "facts": [
        {
          "kind": "code",
          "literal": "k8s",
          "chunkId": "limits#recall-has-a-keyword-ceiling"
        },
        {
          "kind": "code",
          "literal": "kubernetes",
          "chunkId": "limits#recall-has-a-keyword-ceiling"
        }
      ],
      "sources": [
        {
          "chunkId": "limits#recall-has-a-keyword-ceiling",
          "url": "/docs/limits#recall-has-a-keyword-ceiling",
          "anchor": "recall-has-a-keyword-ceiling"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "recall",
        "keyword",
        "ceiling",
        "retrieval",
        "token",
        "overlap",
        "widened",
        "glossary",
        "embeddings",
        "loop",
        "cannot",
        "ground",
        "missed",
        "recovers",
        "most",
        "synonym",
        "cases",
        "query",
        "sharing",
        "tokens",
        "docs",
        "miss",
        "entirely",
        "known",
        "deliberately",
        "unbuilt",
        "richer",
        "cheaper",
        "lever",
        "kubernetes",
        "agentic",
        "grounds",
        "answer",
        "surfaces",
        "link",
        "practice",
        "abbreviations",
        "product",
        "aliases",
        "reader"
      ]
    },
    {
      "id": "limits#secrets-live-server-side",
      "kind": "section",
      "title": "Limits",
      "heading": "Secrets live server-side",
      "group": "Overview",
      "url": "/docs/limits#secrets-live-server-side",
      "summary": "The agentic path needs the Anthropic key in the server environment that runs the endpoint; it is never exposed to the browser, and without it the endpoint serves keyword results — search degrades rather than breaks.",
      "facts": [
        {
          "kind": "code",
          "literal": "ANTHROPIC_API_KEY",
          "chunkId": "limits#secrets-live-server-side"
        },
        {
          "kind": "code",
          "literal": "/api/ask",
          "chunkId": "limits#secrets-live-server-side"
        }
      ],
      "sources": [
        {
          "chunkId": "limits#secrets-live-server-side",
          "url": "/docs/limits#secrets-live-server-side",
          "anchor": "secrets-live-server-side"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "secrets",
        "live",
        "server",
        "side",
        "agentic",
        "path",
        "needs",
        "anthropic",
        "environment",
        "runs",
        "endpoint",
        "never",
        "exposed",
        "browser",
        "without",
        "serves",
        "keyword",
        "results",
        "search",
        "degrades",
        "rather",
        "breaks",
        "anthropicapikey",
        "present",
        "runtime",
        "doesn",
        "break"
      ]
    },
    {
      "id": "limits#the-corpus-is-your-content-collection",
      "kind": "section",
      "title": "Limits",
      "heading": "The corpus is your content collection",
      "group": "Overview",
      "url": "/docs/limits#the-corpus-is-your-content-collection",
      "summary": "Search covers only the configured content collections — no crawler, no sitemap ingestion, and no way to index pages that aren't collection entries. Anything that should be searchable belongs in a collection.",
      "facts": [
        {
          "kind": "code",
          "literal": ".astro",
          "chunkId": "limits#the-corpus-is-your-content-collection"
        }
      ],
      "sources": [
        {
          "chunkId": "limits#the-corpus-is-your-content-collection",
          "url": "/docs/limits#the-corpus-is-your-content-collection",
          "anchor": "the-corpus-is-your-content-collection"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "corpus",
        "content",
        "collection",
        "search",
        "covers",
        "only",
        "configured",
        "collections",
        "crawler",
        "sitemap",
        "ingestion",
        "index",
        "pages",
        "aren",
        "entries",
        "anything",
        "should",
        "searchable",
        "belongs",
        "astro",
        "searches",
        "configure",
        "nothing",
        "else",
        "there",
        "external",
        "hand",
        "written",
        "example",
        "appear",
        "want"
      ]
    },
    {
      "id": "limits#the-digest-build-is-a-single-model-call",
      "kind": "section",
      "title": "Limits",
      "heading": "The digest build is a single model call",
      "group": "Overview",
      "url": "/docs/limits#the-digest-build-is-a-single-model-call",
      "summary": "The offline build sends the full cleaned corpus to the model in one call, which fits typical docs sites comfortably but would overflow on a very large corpus. A map-reduce builder is a noted follow-up, not implemented; assume the corpus fits one call.",
      "facts": [],
      "sources": [
        {
          "chunkId": "limits#the-digest-build-is-a-single-model-call",
          "url": "/docs/limits#the-digest-build-is-a-single-model-call",
          "anchor": "the-digest-build-is-a-single-model-call"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "digest",
        "build",
        "single",
        "model",
        "call",
        "offline",
        "sends",
        "full",
        "cleaned",
        "corpus",
        "fits",
        "typical",
        "docs",
        "sites",
        "comfortably",
        "would",
        "overflow",
        "very",
        "large",
        "reduce",
        "builder",
        "noted",
        "follow",
        "implemented",
        "assume",
        "site",
        "dozens",
        "pages",
        "exceed",
        "context",
        "window",
        "summaries",
        "merged",
        "graph",
        "today"
      ]
    },
    {
      "id": "quickstart",
      "kind": "section",
      "title": "Quick start",
      "heading": null,
      "group": "Overview",
      "url": "/docs/quickstart",
      "summary": "Add search to an existing Astro 5 collection-based docs site in about five minutes: keyword search first, then an API key to enable agentic answers. The overlay alone gives keyless instant search; adding a server key upgrades Enter into the answer loop, and skipping the key just ships the search UI.",
      "facts": [
        {
          "kind": "code",
          "literal": "src/content/docs",
          "chunkId": "quickstart"
        },
        {
          "kind": "code",
          "literal": "ANTHROPIC_API_KEY",
          "chunkId": "quickstart"
        },
        {
          "kind": "code",
          "literal": "SearchOverlay.astro",
          "chunkId": "quickstart"
        },
        {
          "kind": "value",
          "literal": "Steps.astro",
          "chunkId": "quickstart"
        },
        {
          "kind": "value",
          "literal": "Callout.astro",
          "chunkId": "quickstart"
        }
      ],
      "sources": [
        {
          "chunkId": "quickstart",
          "url": "/docs/quickstart",
          "anchor": null
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "search",
        "existing",
        "astro",
        "collection",
        "based",
        "docs",
        "site",
        "about",
        "five",
        "minutes",
        "keyword",
        "first",
        "enable",
        "agentic",
        "answers",
        "overlay",
        "alone",
        "gives",
        "keyless",
        "instant",
        "adding",
        "server",
        "upgrades",
        "enter",
        "answer",
        "loop",
        "skipping",
        "just",
        "ships",
        "content",
        "anthropic",
        "searchoverlay",
        "steps",
        "callout",
        "install",
        "integration",
        "drop",
        "build",
        "digest",
        "whose"
      ]
    },
    {
      "id": "quickstart#1-install",
      "kind": "section",
      "title": "Quick start",
      "heading": "1. Install",
      "group": "Overview",
      "url": "/docs/quickstart#1-install",
      "summary": "Install from npm once published, or until then consume the package straight from its subdirectory on GitHub.",
      "facts": [
        {
          "kind": "code",
          "literal": "pnpm add @hev/ask",
          "chunkId": "quickstart#1-install"
        },
        {
          "kind": "code",
          "literal": "pnpm add \"git+ssh://[email protected]/hev/ask.git#main&path:/packages/ui\"",
          "chunkId": "quickstart#1-install"
        }
      ],
      "sources": [
        {
          "chunkId": "quickstart#1-install",
          "url": "/docs/quickstart#1-install",
          "anchor": "1-install"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "install",
        "once",
        "published",
        "until",
        "consume",
        "package",
        "straight",
        "subdirectory",
        "github",
        "pnpm",
        "main",
        "path",
        "packages"
      ]
    },
    {
      "id": "quickstart#2-register-the-integration",
      "kind": "section",
      "title": "Quick start",
      "heading": "2. Register the integration",
      "group": "Overview",
      "url": "/docs/quickstart#2-register-the-integration",
      "summary": "Register the integration in the Astro config with the content collection name(s) — the one required option — and the base path that maps slugs to URLs. Everything else has defaults covered in the configuration reference.",
      "facts": [
        {
          "kind": "code",
          "literal": "// astro.config.mjs\nimport { defineConfig } from \"astro/config\";\nimport hevAsk from \"@hev/ask\";\n\nexport default defineConfig({\n  integrations: [\n    hevAsk({\n      collections: [\"docs\"],   // your content collection name(s)\n      basePath: \"/docs/\",      // slug → URL prefix: basePath + slug\n    }),\n  ],\n});",
          "chunkId": "quickstart#2-register-the-integration"
        },
        {
          "kind": "code",
          "literal": "collections",
          "chunkId": "quickstart#2-register-the-integration"
        }
      ],
      "sources": [
        {
          "chunkId": "quickstart#2-register-the-integration",
          "url": "/docs/quickstart#2-register-the-integration",
          "anchor": "2-register-the-integration"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "register",
        "integration",
        "astro",
        "config",
        "content",
        "collection",
        "name",
        "required",
        "option",
        "base",
        "path",
        "maps",
        "slugs",
        "urls",
        "everything",
        "else",
        "defaults",
        "covered",
        "configuration",
        "reference",
        "import",
        "defineconfig",
        "hevask",
        "export",
        "default",
        "integrations",
        "collections",
        "docs",
        "basepath",
        "slug",
        "prefix",
        "must"
      ]
    },
    {
      "id": "quickstart#3-add-a-server-adapter",
      "kind": "section",
      "title": "Quick start",
      "heading": "3. Add a server adapter",
      "group": "Overview",
      "url": "/docs/quickstart#3-add-a-server-adapter",
      "summary": "The search route renders on demand, so add the adapter matching the host. Existing pages stay prerendered; only the search route runs as a function.",
      "facts": [
        {
          "kind": "code",
          "literal": "// astro.config.mjs\nimport cloudflare from \"@astrojs/cloudflare\";\n\nexport default defineConfig({\n  adapter: cloudflare({ platformProxy: { enabled: true } }),\n  // ...integrations as above\n});",
          "chunkId": "quickstart#3-add-a-server-adapter"
        },
        {
          "kind": "code",
          "literal": "/api/ask",
          "chunkId": "quickstart#3-add-a-server-adapter"
        }
      ],
      "sources": [
        {
          "chunkId": "quickstart#3-add-a-server-adapter",
          "url": "/docs/quickstart#3-add-a-server-adapter",
          "anchor": "3-add-a-server-adapter"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "server",
        "adapter",
        "search",
        "route",
        "renders",
        "demand",
        "matching",
        "host",
        "existing",
        "pages",
        "stay",
        "prerendered",
        "only",
        "runs",
        "function",
        "astro",
        "config",
        "import",
        "cloudflare",
        "astrojs",
        "export",
        "default",
        "defineconfig",
        "platformproxy",
        "enabled",
        "true",
        "integrations",
        "above",
        "whichever",
        "matches",
        "site",
        "uses"
      ]
    },
    {
      "id": "quickstart#4-render-the-overlay",
      "kind": "section",
      "title": "Quick start",
      "heading": "4. Render the overlay",
      "group": "Overview",
      "url": "/docs/quickstart#4-render-the-overlay",
      "summary": "Add the overlay component once somewhere global, like the base layout. Any element with the opener attribute opens the palette, the keyboard shortcut binds automatically, and keyword search works from there.",
      "facts": [
        {
          "kind": "code",
          "literal": "---\n// src/layouts/Base.astro\nimport SearchOverlay from \"@hev/ask/components/SearchOverlay.astro\";\n---\n<button type=\"button\" data-hev-ask-open>\n  Search <kbd>⌘K</kbd>\n</button>\n\n<slot />\n\n<SearchOverlay />",
          "chunkId": "quickstart#4-render-the-overlay"
        },
        {
          "kind": "code",
          "literal": "data-hev-ask-open",
          "chunkId": "quickstart#4-render-the-overlay"
        },
        {
          "kind": "code",
          "literal": "⌘K",
          "chunkId": "quickstart#4-render-the-overlay"
        },
        {
          "kind": "code",
          "literal": "astro dev",
          "chunkId": "quickstart#4-render-the-overlay"
        }
      ],
      "sources": [
        {
          "chunkId": "quickstart#4-render-the-overlay",
          "url": "/docs/quickstart#4-render-the-overlay",
          "anchor": "4-render-the-overlay"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "render",
        "overlay",
        "component",
        "once",
        "somewhere",
        "global",
        "like",
        "base",
        "layout",
        "element",
        "opener",
        "attribute",
        "opens",
        "palette",
        "keyboard",
        "shortcut",
        "binds",
        "automatically",
        "keyword",
        "search",
        "works",
        "there",
        "layouts",
        "astro",
        "import",
        "searchoverlay",
        "components",
        "button",
        "type",
        "data",
        "open",
        "slot",
        "bound",
        "press"
      ]
    },
    {
      "id": "quickstart#5-build-the-digest",
      "kind": "section",
      "title": "Quick start",
      "heading": "5. Build the digest",
      "group": "Overview",
      "url": "/docs/quickstart#5-build-the-digest",
      "summary": "The digest is an offline-built JSON file you commit: it gives the loop context, ranks keyword results, supplies the glossary, and holds the suggested questions. The recommended path is the bundled Claude Code skill — built inside the subscription, no API key — with a one-call CLI build for CI; both are hash-gated, then verify and commit.",
      "facts": [
        {
          "kind": "code",
          "literal": "You: build the hev ask digest\n\nClaude runs:\n  ask kg corpus       # emits the sections to distil\n  …writes context/glossary/summaries/suggestions…\n  ask kg assemble     # writes .hev-ask/digest.json",
          "chunkId": "quickstart#5-build-the-digest"
        },
        {
          "kind": "code",
          "literal": "export ANTHROPIC_API_KEY=sk-ant-...\npnpm exec ask kg build      # writes .hev-ask/digest.json",
          "chunkId": "quickstart#5-build-the-digest"
        },
        {
          "kind": "code",
          "literal": "pnpm exec ask kg verify     # builds the site, checks every anchor resolves\ngit add .hev-ask/digest.json",
          "chunkId": "quickstart#5-build-the-digest"
        },
        {
          "kind": "code",
          "literal": "k8s",
          "chunkId": "quickstart#5-build-the-digest"
        },
        {
          "kind": "code",
          "literal": "kubernetes",
          "chunkId": "quickstart#5-build-the-digest"
        },
        {
          "kind": "code",
          "literal": "astro build",
          "chunkId": "quickstart#5-build-the-digest"
        },
        {
          "kind": "value",
          "literal": "claude.com",
          "chunkId": "quickstart#5-build-the-digest"
        }
      ],
      "sources": [
        {
          "chunkId": "quickstart#5-build-the-digest",
          "url": "/docs/quickstart#5-build-the-digest",
          "anchor": "5-build-the-digest"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "build",
        "digest",
        "offline",
        "built",
        "json",
        "file",
        "commit",
        "gives",
        "loop",
        "context",
        "ranks",
        "keyword",
        "results",
        "supplies",
        "glossary",
        "holds",
        "suggested",
        "questions",
        "recommended",
        "path",
        "bundled",
        "claude",
        "code",
        "skill",
        "inside",
        "subscription",
        "call",
        "both",
        "hash",
        "gated",
        "verify",
        "runs",
        "corpus",
        "emits",
        "sections",
        "distil",
        "writes",
        "summaries",
        "suggestions",
        "assemble"
      ]
    },
    {
      "id": "quickstart#enable-agentic-search",
      "kind": "section",
      "title": "Quick start",
      "heading": "Enable agentic search",
      "group": "Overview",
      "url": "/docs/quickstart#enable-agentic-search",
      "summary": "Set the Anthropic key in the server environment where the endpoint runs. With it, Enter runs the agentic loop — self-issued sub-queries, a grounded answer, inline deep links; without it, Enter returns keyword results.",
      "facts": [
        {
          "kind": "code",
          "literal": "ANTHROPIC_API_KEY",
          "chunkId": "quickstart#enable-agentic-search"
        },
        {
          "kind": "code",
          "literal": "/api/ask",
          "chunkId": "quickstart#enable-agentic-search"
        },
        {
          "kind": "code",
          "literal": ".env",
          "chunkId": "quickstart#enable-agentic-search"
        }
      ],
      "sources": [
        {
          "chunkId": "quickstart#enable-agentic-search",
          "url": "/docs/quickstart#enable-agentic-search",
          "anchor": "enable-agentic-search"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "enable",
        "agentic",
        "search",
        "anthropic",
        "server",
        "environment",
        "endpoint",
        "runs",
        "enter",
        "loop",
        "self",
        "issued",
        "queries",
        "grounded",
        "answer",
        "inline",
        "deep",
        "links",
        "without",
        "returns",
        "keyword",
        "results",
        "anthropicapikey",
        "host",
        "secrets",
        "local",
        "present",
        "pressing",
        "overlay"
      ]
    },
    {
      "id": "quickstart#prerequisites",
      "kind": "section",
      "title": "Quick start",
      "heading": "Prerequisites",
      "group": "Overview",
      "url": "/docs/quickstart#prerequisites",
      "summary": "Astro 5 with at least one content collection, a server or hybrid adapter for the on-demand route, and an Anthropic key only if agentic search is wanted — keyword search needs none.",
      "facts": [
        {
          "kind": "code",
          "literal": "/api/ask",
          "chunkId": "quickstart#prerequisites"
        },
        {
          "kind": "code",
          "literal": "ANTHROPIC_API_KEY",
          "chunkId": "quickstart#prerequisites"
        },
        {
          "kind": "value",
          "literal": "docs.astro.build",
          "chunkId": "quickstart#prerequisites"
        }
      ],
      "sources": [
        {
          "chunkId": "quickstart#prerequisites",
          "url": "/docs/quickstart#prerequisites",
          "anchor": "prerequisites"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "prerequisites",
        "astro",
        "least",
        "content",
        "collection",
        "server",
        "hybrid",
        "adapter",
        "demand",
        "route",
        "anthropic",
        "only",
        "agentic",
        "search",
        "wanted",
        "keyword",
        "needs",
        "none",
        "docs",
        "build",
        "node",
        "cloudflare",
        "vercel",
        "renders",
        "fully",
        "static",
        "serve",
        "anthropicapikey",
        "enable"
      ]
    },
    {
      "id": "quickstart#set-up-keyword-search",
      "kind": "section",
      "title": "Quick start",
      "heading": "Set up keyword search",
      "group": "Overview",
      "url": "/docs/quickstart#set-up-keyword-search",
      "summary": "The keyword path is set up by the install, register, adapter, and overlay steps that follow.",
      "facts": [
        {
          "kind": "value",
          "literal": "astro.config.mjs",
          "chunkId": "quickstart#set-up-keyword-search"
        },
        {
          "kind": "value",
          "literal": "SearchOverlay.astro",
          "chunkId": "quickstart#set-up-keyword-search"
        }
      ],
      "sources": [
        {
          "chunkId": "quickstart#set-up-keyword-search",
          "url": "/docs/quickstart#set-up-keyword-search",
          "anchor": "set-up-keyword-search"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "keyword",
        "search",
        "path",
        "install",
        "register",
        "adapter",
        "overlay",
        "steps",
        "follow",
        "astro",
        "config",
        "searchoverlay"
      ]
    },
    {
      "id": "quickstart#verify-it-works",
      "kind": "section",
      "title": "Quick start",
      "heading": "Verify it works",
      "group": "Overview",
      "url": "/docs/quickstart#verify-it-works",
      "summary": "Sanity checks: a single heading word should deep-link to its section, a multi-word question should stream a grounded answer with the sub-queries visible, and the verify command — which exits non-zero on any missing anchor — belongs in CI.",
      "facts": [
        {
          "kind": "code",
          "literal": "/docs/page#heading",
          "chunkId": "quickstart#verify-it-works"
        },
        {
          "kind": "code",
          "literal": "ask kg verify",
          "chunkId": "quickstart#verify-it-works"
        }
      ],
      "sources": [
        {
          "chunkId": "quickstart#verify-it-works",
          "url": "/docs/quickstart#verify-it-works",
          "anchor": "verify-it-works"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "verify",
        "works",
        "sanity",
        "checks",
        "single",
        "heading",
        "word",
        "should",
        "deep",
        "link",
        "section",
        "multi",
        "question",
        "stream",
        "grounded",
        "answer",
        "queries",
        "visible",
        "command",
        "exits",
        "zero",
        "missing",
        "anchor",
        "belongs",
        "docs",
        "page",
        "keyword",
        "type",
        "result",
        "agentic",
        "click",
        "suggested",
        "press",
        "enter",
        "footer",
        "shows",
        "model",
        "streams",
        "inline",
        "links"
      ]
    },
    {
      "id": "tradeoffs",
      "kind": "section",
      "title": "Tradeoffs",
      "heading": null,
      "group": "Overview",
      "url": "/docs/tradeoffs",
      "summary": "Every search tool makes choices; this page states honestly what hev ask trades away — its dependency posture, the committed digest, agentic cost and latency — and how it compares to Pagefind, Algolia, and Orama.",
      "facts": [
        {
          "kind": "value",
          "literal": "Callout.astro",
          "chunkId": "tradeoffs"
        }
      ],
      "sources": [
        {
          "chunkId": "tradeoffs",
          "url": "/docs/tradeoffs",
          "anchor": null
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "every",
        "search",
        "tool",
        "makes",
        "choices",
        "page",
        "states",
        "honestly",
        "trades",
        "away",
        "dependency",
        "posture",
        "committed",
        "digest",
        "agentic",
        "cost",
        "latency",
        "compares",
        "pagefind",
        "algolia",
        "orama",
        "callout",
        "astro",
        "choosing",
        "adopting",
        "honest",
        "version",
        "gives",
        "decide",
        "whether",
        "trade",
        "fits",
        "docs"
      ]
    },
    {
      "id": "tradeoffs#a-committed-digest",
      "kind": "section",
      "title": "Tradeoffs",
      "heading": "A committed digest",
      "group": "Overview",
      "url": "/docs/tradeoffs#a-committed-digest",
      "summary": "Generating the digest offline and committing it makes it reviewable in pull requests, deterministic at runtime, free on the request path, and bundleable at the edge with no filesystem access. The cost is staleness when a rebuild is forgotten; the runtime warns on hash divergence, and the hash gate makes rebuild-on-every-change the cheap, intended workflow.",
      "facts": [],
      "sources": [
        {
          "chunkId": "tradeoffs#a-committed-digest",
          "url": "/docs/tradeoffs#a-committed-digest",
          "anchor": "a-committed-digest"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "committed",
        "digest",
        "generating",
        "offline",
        "committing",
        "makes",
        "reviewable",
        "pull",
        "requests",
        "deterministic",
        "runtime",
        "free",
        "request",
        "path",
        "bundleable",
        "edge",
        "filesystem",
        "access",
        "cost",
        "staleness",
        "rebuild",
        "forgotten",
        "warns",
        "hash",
        "divergence",
        "gate",
        "every",
        "change",
        "cheap",
        "intended",
        "workflow",
        "generated",
        "json",
        "rather",
        "computed",
        "hidden",
        "service",
        "upside",
        "read",
        "model"
      ]
    },
    {
      "id": "tradeoffs#cost-and-latency-of-agentic-search",
      "kind": "section",
      "title": "Tradeoffs",
      "heading": "Cost and latency of agentic search",
      "group": "Overview",
      "url": "/docs/tradeoffs#cost-and-latency-of-agentic-search",
      "summary": "The agentic path costs real but small money and a few seconds of latency: one bounded loop per query on the default Haiku model with prompt-cached context, plus an Opus-powered offline digest build paid only when content changes. Keyword-only is a first-class mode for keyless deployments, not a fallback afterthought.",
      "facts": [
        {
          "kind": "code",
          "literal": "maxIterations",
          "chunkId": "tradeoffs#cost-and-latency-of-agentic-search"
        }
      ],
      "sources": [
        {
          "chunkId": "tradeoffs#cost-and-latency-of-agentic-search",
          "url": "/docs/tradeoffs#cost-and-latency-of-agentic-search",
          "anchor": "cost-and-latency-of-agentic-search"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "cost",
        "latency",
        "agentic",
        "search",
        "path",
        "costs",
        "real",
        "small",
        "money",
        "seconds",
        "bounded",
        "loop",
        "query",
        "default",
        "haiku",
        "model",
        "prompt",
        "cached",
        "context",
        "plus",
        "opus",
        "powered",
        "offline",
        "digest",
        "build",
        "paid",
        "only",
        "content",
        "changes",
        "keyword",
        "first",
        "class",
        "mode",
        "keyless",
        "deployments",
        "fallback",
        "afterthought",
        "maxiterations",
        "calls",
        "claude"
      ]
    },
    {
      "id": "tradeoffs#how-it-compares",
      "kind": "section",
      "title": "Tradeoffs",
      "heading": "How it compares",
      "group": "Overview",
      "url": "/docs/tradeoffs#how-it-compares",
      "summary": "A comparison against Pagefind, Algolia DocSearch, and Orama across retrieval, AI ranking, deep links, and hosting. Choose Pagefind for static keyword simplicity, Algolia for a managed service with a crawler, Orama for client-side vector search, and hev ask when docs live in Astro collections and a reader's question — not just keywords — should find the right section.",
      "facts": [],
      "sources": [
        {
          "chunkId": "tradeoffs#how-it-compares",
          "url": "/docs/tradeoffs#how-it-compares",
          "anchor": "how-it-compares"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "compares",
        "comparison",
        "against",
        "pagefind",
        "algolia",
        "docsearch",
        "orama",
        "across",
        "retrieval",
        "ranking",
        "deep",
        "links",
        "hosting",
        "choose",
        "static",
        "keyword",
        "simplicity",
        "managed",
        "service",
        "crawler",
        "client",
        "side",
        "vector",
        "search",
        "docs",
        "live",
        "astro",
        "collections",
        "reader",
        "question",
        "just",
        "keywords",
        "should",
        "find",
        "right",
        "section",
        "tool",
        "glossary",
        "enter",
        "heading"
      ]
    },
    {
      "id": "tradeoffs#keyword-retrieval-not-embeddings",
      "kind": "section",
      "title": "Tradeoffs",
      "heading": "Keyword retrieval, not embeddings",
      "group": "Overview",
      "url": "/docs/tradeoffs#keyword-retrieval-not-embeddings",
      "summary": "Token-overlap retrieval widened by the glossary means nothing to host, nothing to sync, edge-safe, and instant — but paraphrase recall has a ceiling, and the agent grounds only in what retrieval surfaced. Embeddings would do better for token-free phrasing; that upgrade is deferred, not designed out.",
      "facts": [],
      "sources": [
        {
          "chunkId": "tradeoffs#keyword-retrieval-not-embeddings",
          "url": "/docs/tradeoffs#keyword-retrieval-not-embeddings",
          "anchor": "keyword-retrieval-not-embeddings"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "keyword",
        "retrieval",
        "embeddings",
        "token",
        "overlap",
        "widened",
        "glossary",
        "means",
        "nothing",
        "host",
        "sync",
        "edge",
        "safe",
        "instant",
        "paraphrase",
        "recall",
        "ceiling",
        "agent",
        "grounds",
        "only",
        "surfaced",
        "would",
        "better",
        "free",
        "phrasing",
        "upgrade",
        "deferred",
        "designed",
        "dependency",
        "vector",
        "store",
        "upside",
        "keep",
        "recovers",
        "synonym",
        "give",
        "cost",
        "answers",
        "well",
        "ground"
      ]
    },
    {
      "id": "tradeoffs#one-dependency-deliberately",
      "kind": "section",
      "title": "Tradeoffs",
      "heading": "One dependency, deliberately",
      "group": "Overview",
      "url": "/docs/tradeoffs#one-dependency-deliberately",
      "summary": "The package keeps close to zero dependencies with one deliberate exception: the same tiny, edge-safe slugger Astro uses. Hand-rolling anchors risks drifting from the renderer and shipping links that 404 to the top of the page; sharing the slugger guarantees byte-identical anchors.",
      "facts": [
        {
          "kind": "code",
          "literal": "github-slugger",
          "chunkId": "tradeoffs#one-dependency-deliberately"
        },
        {
          "kind": "value",
          "literal": "github.com",
          "chunkId": "tradeoffs#one-dependency-deliberately"
        }
      ],
      "sources": [
        {
          "chunkId": "tradeoffs#one-dependency-deliberately",
          "url": "/docs/tradeoffs#one-dependency-deliberately",
          "anchor": "one-dependency-deliberately"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "dependency",
        "deliberately",
        "package",
        "keeps",
        "close",
        "zero",
        "dependencies",
        "deliberate",
        "exception",
        "same",
        "tiny",
        "edge",
        "safe",
        "slugger",
        "astro",
        "uses",
        "hand",
        "rolling",
        "anchors",
        "risks",
        "drifting",
        "renderer",
        "shipping",
        "links",
        "page",
        "sharing",
        "guarantees",
        "byte",
        "identical",
        "github",
        "aims",
        "pure",
        "generating",
        "heading",
        "link",
        "404s",
        "took",
        "purpose"
      ]
    },
    {
      "id": "tradeoffs#two-paths-instead-of-one",
      "kind": "section",
      "title": "Tradeoffs",
      "heading": "Two paths instead of one",
      "group": "Overview",
      "url": "/docs/tradeoffs#two-paths-instead-of-one",
      "summary": "Running an instant keyword path beside an agentic path keeps the common case instant and keyless while hard questions get a smarter ranker. The cost is a slightly more complex interaction — readers learn that Enter means asking AI — which fits docs, where queries split between jumping to known things and finding the unnameable.",
      "facts": [],
      "sources": [
        {
          "chunkId": "tradeoffs#two-paths-instead-of-one",
          "url": "/docs/tradeoffs#two-paths-instead-of-one",
          "anchor": "two-paths-instead-of-one"
        }
      ],
      "mode": "agent-primary",
      "terms": [
        "paths",
        "instead",
        "running",
        "instant",
        "keyword",
        "path",
        "beside",
        "agentic",
        "keeps",
        "common",
        "case",
        "keyless",
        "while",
        "hard",
        "questions",
        "smarter",
        "ranker",
        "cost",
        "slightly",
        "more",
        "complex",
        "interaction",
        "readers",
        "learn",
        "enter",
        "means",
        "asking",
        "fits",
        "docs",
        "queries",
        "split",
        "between",
        "jumping",
        "known",
        "things",
        "finding",
        "unnameable",
        "runs",
        "asks",
        "reader"
      ]
    }
  ],
  "edges": []
}
esc