Introduction

An AI chat assistant you embed on any website. It answers from your own pages, cites every claim, and runs either in the reader's browser or on your server.

Introduction ​

DocPilot is an AI chat assistant you embed on a website. Put it on a documentation site, a landing page, a help centre or an app you already ship. It answers from your own pages, numbers every claim with a link to its source, and says so when your pages do not cover the question.

Choose first where a turn runs. In the static install, the default, the reader's browser downloads the index and runs the search, the gate and the prompt, and your server only attaches the model key. In the server install (runtime: 'server'), the turn runs on your server: the index, the prompt, the thresholds and the keys stay there, and the page receives a stream. The reader sees the same chat in both.

Use static if your pages are public and you want nothing extra to run. Use server if the corpus or the prompt must stay private, or you need rate limits and metrics. Choose your install has the comparison.

It mounts on any platform: VitePress, Docusaurus, Vue, React, plain JavaScript or TypeScript, or one <script> tag on any HTML page. The config, the index and the commands are the same on all of them.

sh
npm i @cloflin/docpilot
npx docpilot init

Built on current technology ​

  • Hybrid search in the browser. BM25 word matching and embedding similarity, fused by reciprocal rank. No vector database, no search service.
  • 1-bit vectors. One sign bit per dimension: the index is small enough to download on the first question.
  • An agent, not a template. The model calls tools — search, read a section, list pages — then answers through a typed answer call that the browser validates.
  • Streaming everywhere. Answers type in as server-sent events; reasoning models show their thinking.
  • Any model. 15 providers — OpenAI, Anthropic, Gemini, Mistral, DeepSeek, OpenRouter and others — or a local model through Ollama.
  • Modern packaging. ESM-only TypeScript, a Vite plugin, Node 20 or newer, MIT licence.

From your pages to answers ​

The index is built once, at deploy time, by a CLI. Then you measure it and improve it with the same CLI. Press a step to see what it reads and writes.

terminal
$ npx docpilot init
Scaffolds the loop: .env.example, a starter golden set and calibration set, agent skills.
readsyour answers to four questions
writesdocpilot/ · .env.example · skills

The first three steps are enough to ship. The rest is how the assistant gets better: eval tells you which questions it gets wrong, improve names the edit for each, tune and new pages fix them, and feedback pull turns your readers' thumbs-down into the next set of test questions. Measure explains the numbers, and Improve answers the loop. Every command is in the CLI reference.

RAG, in plain words ​

RAG — retrieval-augmented generation — means the model does not answer from memory. It answers from passages that a search found in your content a second earlier.

  1. At build time, every page is cut into chunks of 350–500 tokens, split at its headings. Each chunk becomes a vector: a list of numbers that places its meaning in space.
  2. When a reader asks, the question becomes a vector too. The browser finds the chunks closest to it, and the chunks that share its words, and merges both lists.
  3. The model gets the question plus those passages, and an instruction to use nothing else and to cite each claim.
  4. The browser checks the answer. A citation that points at a passage nobody retrieved is removed, and so is a link to a page that does not exist.

In the static install, steps 1 and 2 run without a server, so the only thing your server does is forward the model call. In the server install, your server runs all four. See Security for what each install makes public.

How small the index is ​

An embedding model returns 4,096 numbers per chunk, each a 32-bit float. DocPilot keeps one bit of each: its sign. This site's own index is 430 KB for 859 chunks at 4096 dimensions — the whole documentation you are reading.

float32what the embedder returns
13.4 MB
int8a byte per dimension
3.4 MB
1-bitwhat the browser downloads
430 KB
859 chunks × 4096 dims × 1 bit = 439,808 bytes · 32× smaller than float32, 8× smaller than int8

The bit costs almost nothing in quality. Measured on this corpus, the average error in similarity is under 0.01, and the build refuses to write an index whose error passes 0.03. If your embedder does not survive the bit, --quantize=auto falls back to one byte per dimension. The details are in Building the index.

What it costs ​

DocPilot is MIT-licensed: no plan, no seat, no per-answer fee. You pay your model provider for tokens, and nothing else.

A question on this site uses about 5.9k input and 0.7k output tokens. With the model this site runs, 1,000 questions cost about $0.66. Building the index costs a fraction of a cent, and a rebuild only re-embeds the chunks that changed.

1k10k50k100k500k1M
$0.66
a month for 1,000 questions on deepseek/deepseek-v4-flash
5.9k in × $0.091/M + 0.7k out × $0.182/M
+ 10 tokens to embed the question

Prices are OpenRouter list prices from October 2026. The measurement behind the token counts, and what makes them grow, is in What it costs.

What the reader gets ​

Each feature has its own page with a live mock-up and the config that turns it on.

Where to go next ​