Classics
Most search makes you guess the right keywords. Classics lets you bring a question instead. Ask "how do I grow my business?" or "how do I stop fearing death?" and it returns the passages that mean that, ranked across the whole library and cited by author, title, and chapter. A passage can score high even when it shares no words with your query, because matching is by meaning, not text.
Highlight any text in a result and Classics renders it as a shareable card: the question you asked, the passage that answered it, and a full citation back to the source. You can also pick several passages and download them as a typeset PDF, or copy any one to the clipboard.
The PDF is typeset for reading: your question as the title, each passage under its citation, and the matching span underlined.
How it works
Books come from Project Gutenberg. Each one is split into ~600-word passages tagged with their book and chapter, embedded once with a local all-mpnet-base-v2 model, and cached to disk. At query time only your question is embedded (one small vector), then matched against the cached library matrix with plain NumPy cosine similarity. No API keys, no network calls at query time, and the corpus is never re-embedded.
The build
The same core (chunk, embed, search) is exposed two ways: a CLI and a thin FastAPI shell that serves the browser UI. The library matrix is loaded once and cached in memory, so only the query embedding is computed per request. Searches and saved quotes are recorded to local SQLite via SQLModel.
It is a small, sharp Python project: a clean separation between core logic, the web shell, and storage, with no heavyweight vector database in sight. The README has the full architecture diagram and setup.