Chat with your own files. Private, self-hosted, with sources. Runs free on your own hardware. Answers from your stuff, in 100+ languages, and shows you exactly where every answer came from.
Quickstart Β· How it works Β· Features Β· Screenshots Β· Configuration
Status: active development. The retrieval pipeline, streaming chat, source viewer, multi-format ingestion, multilingual search, and one-command Docker deploy all work. Polishing toward a public release.
Asking ChatGPT is like asking a clever stranger who has never read your notes. heystack is like asking a librarian who has read everything you wrote and points you to the exact page.
- It knows your stuff. Answers come from your own documents, not the public internet.
- It does not make things up. Every answer is built from your files and cites them, so you can click and verify. If it is not in your documents, it says so.
- It is private. Your data never leaves your machine. Nothing uploaded, logged, or trained on.
- It is free. The AI runs locally via Ollama. No subscription, no cost per question.
- It is multilingual. Ask in any language and find content in any language, by meaning. (English question, Greek document? No problem.)
- You own it. Works offline. Self-hosted with Docker or k3s.
| π Quality retrieval | Hybrid search (semantic + keyword) fused with RRF, then an LLM reranker picks the best passages |
| π Multilingual & cross-lingual | bge-m3 embeddings (100+ languages) + language-agnostic keyword search |
| π Many formats | PDF, Word, Excel, PowerPoint, Markdown/MDX, and plain text |
| π§Ύ Trustworthy answers | Streamed token-by-token with clickable [n] citations |
| ποΈ Open the source | Click any citation to open the real document β PDFs embedded, spreadsheets as tables, the cited passage highlighted |
| π₯οΈ Scan my computer | Point it at your Desktop/Documents/Downloads and it indexes everything supported |
| πͺΆ Obsidian connector | Live-sync a vault (wiki-links, tags, deletions) |
| π¨ Beautiful UI | Light/dark themes, responsive, clean |
| π³ One-command deploy | docker compose up β app + Postgres, optional Ollama |
Captured from the bundled demo data. Regenerate with scripts/screenshots.mjs.
| Ask, with sources | Open the cited source |
|---|---|
![]() |
![]() |
| Scan your computer | Dark theme |
|---|---|
![]() |
![]() |
retrieval + generation = RAG. Search alone just lists files. AI alone makes things up. Together you get trustworthy answers from your own knowledge.
flowchart LR
Q["Your question"] --> H["Hybrid search<br/>vector + keyword (RRF)"]
H --> RR["Rerank<br/>best passages"]
RR --> LLM["Local LLM<br/>grounded answer"]
LLM --> A["Answer with<br/>clickable citations"]
D[("Your documents")] -. indexed .-> H
TypeScript end to end. One Postgres holds vectors and full-text. Ollama runs the models locally.
flowchart TB
subgraph Browser
UI["Next.js UI<br/>chat, sources, scan"]
end
subgraph Server["heystack server (Next.js)"]
API["API routes"]
RAG["RAG pipeline<br/>chunk, embed, retrieve, rerank"]
end
PG[("Postgres + pgvector<br/>vectors + full-text")]
OLL["Ollama<br/>bge-m3 + llama3.1"]
UI <--> API
API --> RAG
RAG <--> PG
RAG <--> OLL
Requirements: Docker, and Ollama running locally.
# 1. Pull the models (bge-m3 = multilingual embeddings, llama3.1 = chat)
ollama pull bge-m3
ollama pull llama3.1:8b
# 2. Configure and start
cp .env.example .env
docker compose up -d
# 3. Add some documents (a file or a whole folder)
npm install
npm run ingest -- "/path/to/your/docs" "My Docs"
# 4. Open the app
# http://localhost:3000Prefer Ollama in a container too? docker compose --profile ollama up -d and set OLLAMA_BASE_URL=http://ollama:11434 in .env.
Load a small, neutral demo knowledge base (a multilingual coffee guide in Markdown, CSV, and PDF) so you have something to chat with right away:
npm run seed # loads demo/ into a "Demo" collectionThen open the app and try, for example, "where does coffee come from?" (the answer is in a Spanish document) or "how much caffeine is in a cup?" (German) β heystack finds them across languages.
# Any file or folder (PDF, Word, Excel, PowerPoint, Markdown, text)
npm run ingest -- "C:/path/to/folder" "My Docs"
# An Obsidian vault, kept in sync as you edit
npm run obsidian -- "C:/path/to/Vault" "My Vault" --watchOr open the app and use Scan my computer (top-right) to index your Desktop, Documents, and Downloads.
npm install
docker compose up -d db # just Postgres
npm run dev # http://localhost:3000| Type | Extensions | How it is read |
|---|---|---|
| Markdown | .md, .mdx |
Structure-aware, frontmatter parsed, MDX import noise stripped |
.pdf |
Text extracted; embedded as-is in the viewer | |
| Word | .docx |
Text via mammoth |
| Excel | .xlsx, .xls |
One section per sheet (CSV), rendered as tables |
| PowerPoint | .pptx |
Text via officeparser |
| CSV | .csv |
Rendered as a table |
| Text | .txt |
As-is |
All via environment (.env). Sensible local defaults.
| Variable | Default | Notes |
|---|---|---|
OLLAMA_BASE_URL |
http://localhost:11434 |
Where Ollama runs |
EMBEDDING_MODEL |
bge-m3 |
Multilingual, 1024-dim. Use nomic-embed-text for English-only (768) |
EMBEDDING_DIM |
1024 |
Must match the model and the vector(...) column in db/init.sql |
CHAT_MODEL |
llama3.1:8b |
Any Ollama chat model |
RERANK_MODEL |
(chat model) | Model used to rerank passages |
ENABLE_RERANK |
true |
Set false to skip reranking (faster, slightly lower quality) |
SCAN_ROOTS |
Desktop/Documents/Downloads | Comma-separated folders for "Scan my computer" |
DATABASE_URL |
local Postgres | Postgres + pgvector connection |
OPENAI_API_KEY |
(empty) | Optional cloud fallback; leave empty to stay fully local |
Docker (prebuilt image). A multi-stage image is published to GHCR on every
push to main:
docker pull ghcr.io/heystack-app/heystack:latestOr build and run the whole stack locally with the included compose file:
docker compose up -dKubernetes / k3s. Manifests live in k8s/:
kubectl create namespace heystack
kubectl apply -n heystack -f k8s/heystack.yamlSet the database password and point OLLAMA_BASE_URL at an Ollama instance
(k3s nodes usually have no GPU, so use a machine that does).
heystack runs the models locally, so a public demo needs a host that can run Ollama (a GPU box is much faster). To make a shared instance safe:
- Set
NEXT_PUBLIC_DEMO_MODE=trueβ hides "Scan my computer" and disables the scan API, so it cannot read the server's filesystem. - Seed it with neutral content:
npm run seed. - Put it behind a reverse proxy with rate limiting β every question runs an LLM.
For a personal instance on your own machine, leave demo mode off and enjoy the full feature set.
src/
app/ Next.js UI + API routes (chat, collections, documents, scan)
components/ theme toggle, collection picker, source viewer, scan modal
db/ Drizzle schema + client
lib/
ollama.ts local embeddings + chat (streaming)
scan.ts "scan my computer" engine
rag/
extract.ts read pdf/docx/xlsx/pptx/md/txt -> text
chunk.ts structural, markdown-aware chunking
ingest.ts chunk -> embed -> store (NFKC normalized)
retrieve.ts hybrid search (vector + full-text) fused with RRF
rerank.ts LLM reranker
ask.ts retrieve -> rerank -> grounded, streamed answer + citations
connectors/obsidian.ts vault sync (wiki-links, tags, live watch)
scripts/ ingest + obsidian CLIs
db/init.sql schema + pgvector (HNSW) and full-text (GIN) indexes
docker-compose.yml app + Postgres (+ optional Ollama)
Shipped
- Hybrid retrieval + reranker, streaming answers, and clickable, openable sources
- Ingestion of PDF, Word, Excel, PowerPoint, Markdown, CSV, and text
- Multilingual & cross-lingual search (bge-m3)
- Obsidian connector, collection picker, and scan-my-computer
- One-command Docker, a published image, and Kubernetes manifests
Planned β contributions very welcome, see the open issues:
- A hosted public demo
- OCR for scanned PDFs
- Multi-user accounts and authentication
- A Helm chart
Issues and PRs are welcome. It is a standard Next.js + TypeScript app: npm install, run Postgres with docker compose up -d db, then npm run dev.
Quality checks. CI runs lint, typecheck, and build on every push and PR.
There is also a retrieval eval that measures recall@k over the demo data:
npm run seed # needs Ollama + a running Postgres
npm run eval # PASS/FAIL per case + recall@k, fails under 80%


