langolier.

Langolier Wiki

infinition.github.io/langolier

Langolier is a local knowledge studio. You give it documents, code, videos and voice notes; it indexes them and answers your questions with citations pointing at the exact passage that backed each claim. Nothing leaves the machine unless you point it at a cloud API.

New here? Start with Installation, then First steps.

Getting started

Guides

Reference

Language

The interface ships in English and French. The switch sits at the bottom of the sidebar and the choice persists. This wiki is written in English; the README carries a full French section.

License

MPL 2.0.

Installation

Download a build

Builds are published on the releases page.

PlatformFile
macOS (Apple Silicon).dmg
Windows.exe installer
Linux.AppImage, .deb or .rpm

macOS builds are ad hoc signed. On first launch, right click the app and pick Open, otherwise Gatekeeper refuses it.

What else you need

Langolier answers out of the box with its embedded engine. Some sources need external tools, and the application tells you which one is missing when it needs it.

ToolNeeded for
PopplerPDF page counts and rendering scanned pages
TesseractOCR on scanned pages
FFmpegaudio and video
whisper.cpptranscription
yt-dlpadding a video by URL

On macOS, Install-Mac.command installs all of them through Homebrew and fetches the transcription model. On Windows, Install-Windows.bat does the same.

Build from source

Requires the Tauri prerequisites, Rust stable, Node 20 or newer, and cmake for the embedded llama.cpp.

git clone https://github.com/infinition/langolier.git
cd langolier
npm ci
npm run tauri build

For development, npm run desktop starts Vite and the Tauri shell with hot reload.

llama.cpp tunes itself for the processor that compiles it, so build on the machine that will run it.

Where your data lives

One SQLite file in the application data folder, holding sources, passages, vectors and conversations. Original files stay where they are: removing a source drops its passages and vectors from the index, never the file.

SystemPath
macOS~/Library/Application Support/local.langolier.studio
Windows%APPDATA%\local.langolier.studio
Linux~/.local/share/local.langolier.studio

Back up that folder and you have backed up everything.

First steps

Add your first sources

Open Sources and press Add sources. You can drop a folder, pick files, paste a piece of text, or give the address of a video.

Supported without any extra tool: PDF, DOCX, PPTX, XLSX, ODT, ODP, ODS, Markdown, plain text, CSV, JSON, notebooks, source files and subtitles. Audio and video go through transcription, which needs whisper.cpp and FFmpeg.

Each file is read, cut into passages, and turned into vectors. The table shows where each source stands: its language, its passage count, and how many of those passages already carry a vector. A source is usable for word search as soon as its passages exist, before the vectors are finished.

Ask a question

Open Conversation and ask. The answer carries numbered citations, and the chips below it open the exact passage behind each claim.

The mode selector under the question decides how the memory is searched:

ModeWhat it does
HybridWords and meaning, fused. The default, and the right answer most of the time
LexicalWords only, through BM25. No model needed to search
SemanticMeaning only, through vectors
GeneralAnswers from the model alone, without your sources

When it says it does not know

In strict mode, an answer with no supporting passage is refused rather than guessed. That refusal is a feature: it means the corpus does not hold what you asked for.

Three things usually explain it. The source may not be indexed yet, which the Sources table tells you. The question may use words absent from your documents, which hybrid search handles better than lexical. Or the abstention threshold may be set high, under

Engines > La rigueur.

The abstention sentence is yours to write. Change it to something that sounds like you.

What to do next

  • Point Langolier at a folder that keeps filling, with Watches
  • Give a subject its own profile, with Assistants
  • Ask from outside the app, with the local API

Choosing an engine

Langolier separates the brain from the memory. The model that writes answers and the model that turns text into vectors are configured independently, so a cloud chat model can sit next to a local embedder.

The embedded engine

llama.cpp, built into the application. Pick a curated tag under Engines, press Install, and the GGUF lands in the application cache.

ModelSizeNotes
qwen3:4b-instruct2.5 GBRecommended, around 30 tokens per second
qwen3:8b5.0 GBSurer, around 17 tokens per second
qwen3:1.7b1.4 GBVery fast, may drift into English

Any GGUF path works too. Weights already pulled by Ollama are linked into the cache rather than downloaded again.

Idle models are unloaded after a configurable pause, five minutes by default, so memory comes back without quitting the application.

Prefer qwen3:4b-instruct over the bare qwen3:4b: the latter reasons out loud and lets its thinking leak into the answer.

Apple, on this Mac

On macOS 26 and newer, Langolier can ask the model the system already carries, through the framework Apple publishes for applications. The entry appears under Engines only on a Mac.

Nothing is downloaded, nothing has to be started, no port is opened, and no disk space is used: the model belongs to the system and is shared with every other application that asks for it. On an M series Mac it writes around 25 tokens per second, with the first token after a second and a half.

Two limits decide whether it suits you.

Its context is 8192 tokens, and that budget covers the passages, the conversation so far and the answer together. Langolier trims the oldest turns to stay inside it, so a long thread keeps working but carries less history than it would on the embedded engine.

It writes answers only. Apple exposes no embeddings, so the memory keeps running on the engine compiled into the application whatever you choose here.

If the model cannot answer, the page says which of three things is in the way: Apple Intelligence is turned off in System Settings, the Mac cannot run it, or the model is still downloading.

Ollama, LM Studio and compatible servers

Point the address at a local server. Ollama on http://127.0.0.1:11434, LM Studio on its own port. The model has to be pulled on that side first.

If you use Ollama for embeddings, it has to be running when Langolier searches, or hybrid search falls back to words only. The embedded engine has no such dependency, since it starts with the application.

A cloud provider

Supported providers are listed in the settings. Your API key is stored in the application database, and your questions and the retrieved passages travel to the provider. The interface states this next to the setting.

Token caps on an assistant profile bound the bill.

Changing the embedding model

Vectors produced by one model cannot be compared with vectors produced by another. Langolier refuses to mix them: it says so, falls back to word search, and offers to reindex the sources.

Word search keeps working throughout, so the application stays usable while vectors are rebuilt.

Assistants

An assistant is a named profile: a mission, a scope of knowledge, an engine, a set of caps and a theme. Langolier without a profile answers from everything with the global settings; a profile narrows and specialises that.

Creating one

Open Assistants and create a profile. What each field changes:

FieldEffect
MissionPrepended to the instructions, so the assistant knows what it is for
WelcomeThe first message a visitor sees on the exported chat page
ScopeWhich sources it may answer from: everything, or a chosen set
EngineIts own model and provider, overriding the global one
CapsA ceiling on tokens per conversation and per day
ThemeThe colours of its exported page
LanguageEnglish, French, or the visitor's own

Scope

Scope is the difference between a general assistant and a useful one. A profile bound to a handful of folders answers about those folders and abstains elsewhere, which is usually what you want when you hand it to someone else.

Sources outside the scope are not searched at all. They are not hidden after the fact, they never enter the retrieval.

Caps and privacy

Token caps bound an API bill. When a conversation reaches its cap, the assistant says so instead of silently continuing to spend.

Hide source names keeps document titles out of the answers. The citations still work and still point at real passages, but the reader does not learn that your 2024-negotiation-notes.pdf exists.

Exporting

Export produces a folder holding a .langolier bundle, a window launcher, a web launcher and server scripts. See Exporting a chatbot.

The profile travels with its scope, its engine and its caps. What does not travel: your other sources, your other profiles, your conversations.

Watches

A watch is a folder that feeds itself into the memory. You point Langolier at it, it is scanned on a timer, and anything supported that lands there is ingested on its own.

Adding one

Open Vigies and pick a folder. It can be local, or a mounted network volume such as a NAS share.

Two modes, and the difference is not reversible for your files:

ModeWhat happens to the files
SyncThey stay where they are. Langolier reads them in place
HooverThey are moved into Langolier's own folder once ingested

Sync is the safe default. Hoover suits an inbox you want emptied, a scanner output folder for instance.

The interval

The page carries a global interval, applied to every watch that does not set its own. A single watch can override it: a fast folder every minute, an archive once a day.

Network folders are polled rather than notified. An unmounted volume is flagged on the card and picked up again as soon as it reappears, without losing what it already knew.

Reading a card

Each card shows what is ready, what is queued, what failed, and when it was last scanned. A failed source names its reason, and the See details link shows the error in full.

A watch can be paused without losing anything. What it already indexed stays, and it resumes where it stopped.

While Langolier is in the menu bar

By default, scanning stands down when Langolier runs without its window, which spares the disk and the battery. A folder filled in the meantime is picked up when you open the window again.

To keep scanning anyway, turn on Keep watching folders in the menu bar, on this same page.

Duplicates

A file whose content is already indexed is not ingested twice. It gets its own status, Duplicate, naming the source that already holds those bytes. It is not an error, and the library lets you filter those rows and remove them in one go.

Telegram

An exported assistant can answer in a Telegram chat. The bridge uses long polling, so no port is opened on your machine and no domain is needed.

Setting it up

  1. Talk to @BotFather on Telegram and create a bot. It gives

you a token.

  1. Paste the token into the assistant profile, under its Telegram section.
  2. Press the test button. It confirms the token reaches a real bot.
  3. Export the assistant, then run it. The bridge starts with the server.

Who may talk to it

The whitelist accepts numeric ids or @handles, comma separated. Leave it empty and anyone who finds the bot can talk to it.

How conversations map

One Telegram chat maps to one conversation, so the assistant remembers the thread. /new starts another.

Caps and source privacy apply exactly as they do on the web page: a token cap reached in Telegram stops the same way, and hidden source names stay hidden.

What to keep in mind

Messages travel through Telegram's servers. Whatever your assistant answers there leaves your machine, citations included. Keep it to content that may go there.

For a test or a second instance, LANGOLIER_DISABLE_TELEGRAM=1 keeps the server from polling the bot, so two copies do not steal each other's updates.

Local API, Shortcuts and Siri

Langolier can answer over a local HTTP API, so Shortcuts, Siri or any local agent can query your memory without opening the application.

Switching it on

Under Engines > Local API, turn on Answer local requests. A token is generated on the spot, and the address appears next to it. Use Test the API to confirm it answers.

What the API is, precisely:

  • It listens on 127.0.0.1 only. Nothing is exposed to your network, ever.
  • It answers POST only, so a question never travels in a URL.
  • Every request needs Authorization: Bearer <token>. Without a token configured, the

endpoint refuses everything, including a lucky guess.

  • Twelve questions a minute per address.
  • Answering takes the same lock as the window, so a question from Siri and a question

typed in the app never generate at the same time.

Starting and stopping takes effect immediately, without restarting the application.

Two endpoints

/api/ask writes the answer. That takes a model, local or remote, the same one the application uses.

POST http://127.0.0.1:8787/api/ask
Authorization: Bearer <token>

{ "question": "How do you purify water?" }
{
  "content": "Boiling is the surest method [1]...",
  "text": "Boiling is the surest method [1]...\n\nSources\n[1] Guide.pdf, Page 222",
  "sources": [ { "name": "Guide.pdf", "locator": "Page 222", "text": "..." } ],
  "status": "ok",
  "warning": null
}

content is the answer alone, which is what you want read out loud. text is the same answer with its sources listed underneath, which is what you want displayed. One request gives you both.

/api/search stops before the writing and returns the passages, so whatever called it can write instead.

POST http://127.0.0.1:8787/api/search
Authorization: Bearer <token>

{ "question": "How do you purify water?", "mode": "lexical" }
{
  "sources": [
    { "n": 1, "name": "Guide.pdf", "locator": "Page 222", "text": "...", "score": 0.81 }
  ],
  "warning": null
}

What each mode costs

This matters if you want Langolier to run without any model at all.

ModeWhat it needs
exact, lexicalNothing. Retrieval is pure SQLite, no model involved
hybrid, semanticThe embedding engine, to turn your question into a vector

The relevance judge, when left on under Engines > La rigueur, uses a model on top of that. Turn it off if you want retrieval to stay free of any model.

So a shortcut calling /api/search in lexical mode asks nothing of any engine: it reads your index and hands back passages. Whoever called it does the writing.

Wiring it to Siri

In the Shortcuts app, create a shortcut named Search my memory:

  1. Ask for input, text, with a prompt such as "What are you looking for?"
  2. Get contents of URL on http://127.0.0.1:8787/api/ask

- Method POST - Header Authorization set to Bearer followed by your token - Request body JSON, one field question, holding the provided input

  1. Get dictionary value for text, then Show result
  2. Optionally, a second Get dictionary value for content feeding Speak text,

so the source list is displayed but not read aloud

Then say the shortcut's name to Siri. Siri asks your question, the shortcut calls Langolier, and the answer comes back with its citations.

Troubleshooting

Nothing answers. Check the application is running and the switch is on. The API lives in the application process, so quitting Langolier stops it. The menu bar mode keeps it alive without a window.

401. The token in the shortcut no longer matches the one in the settings. Regenerating the token invalidates the old one.

The answer mentions lexical search only. The embedding engine is out of reach, so hybrid search fell back to words. If you use Ollama for embeddings, it has to be running.

Exporting a chatbot

Export turns an assistant into something that runs on another machine: a folder holding a .langolier bundle, a window launcher, a web launcher and server scripts.

What travels

The bundle carries the profile, the sources in its scope, their passages and their vectors, and the settings it needs. It does not carry your other sources, your other profiles, or your conversations.

Running it

./server.sh                 # chat page on 0.0.0.0:8080
./chatbotweb --serve --port 8787 --data ./state

The window launcher opens a real window instead of a browser tab. It can sit in the menu bar or system tray, start hidden, and pop a floating question bar on a global shortcut, on macOS, Windows and Linux.

The page speaks the visitor's language, English or French, or the one pinned in the profile.

Updating a deployed bot

Drop a new .langolier next to the launcher. It is picked up in under thirty seconds without a restart, and conversations survive the swap.

When you have no file access

Turn on Remote administration in the profile before exporting, with a secret. A gear then sits in the chat page footer: with the secret, you can import a bundle from the browser, pick any earlier version from a list and restore it, or delete versions you no longer need.

Every bundle the chatbot ever ran is kept, twenty at most, named, timestamped and deduplicated. The running version and the one the kit shipped with cannot be deleted.

Five wrong secrets pause the admin routes for fifteen minutes. When administration is off, the routes do not exist at all.

There is deliberately no export from the page: nothing leaves the server through it, so the corpus and the API key stay where you put them.

Docker

The server build needs no desktop libraries. docker/ holds a Dockerfile and a Compose file.

mkdir -p docker/data docker/state
cp ~/Desktop/my-assistant/my-assistant.langolier docker/data/
cd docker && docker compose up -d --build
curl -fsS http://localhost:8787/api/health
MountContents
./dataThe .langolier, and for an embedded export, models/*.gguf. Replace the bundle here to update
./stateThe working database and the conversations. Back this up

llama.cpp tunes itself for the processor that compiles it, so build the image on the host that will run it. On a NAS or a small VPS, a cloud provider profile is lighter: the container then only embeds text, and a 2 GB memory cap is enough. With network_mode: host, the Telegram bridge works without extra plumbing.

Settings

Where each setting lives, and what it actually changes. A setting sits on the page of the thing it governs; what governs the engine itself stays under Engines.

Sources > Processing

SettingEffect
Pause processingHolds the whole queue. Watches keep spotting files, nothing is ingested, nothing is lost
Keep processing sources in the menu barOff by default. OCR, transcription and vectors are what heat the machine
Passage lengthHow long a passage is cut, in characters. Applies to sources indexed from then on
Overlap between passagesHow much two consecutive passages share

Vigies

SettingEffect
Scan everyThe interval every watch falls back to. A watch can override it
Keep watching folders in the menu barOff by default. A folder filled meanwhile is picked up when the window reopens

Engines > Le cerveau

The model that writes. Provider, address, model, answer length, and how long an idle model stays in memory before it is unloaded.

Pointing the brain at a cloud provider sends your questions and the retrieved passages to it. The interface says so next to the setting.

Engines > La mémoire

The embedding engine, and how much is retrieved.

SettingEffect
Embedding server and modelWhat turns text into vectors. Changing it invalidates existing vectors
Passages retrievedHow many passages reach the answer
Candidates per search armHow many each arm brings back before fusion
Passages per sourceCaps what one document may contribute. Zero lifts the cap

Engines > La rigueur

SettingEffect
Answer only from the sourcesStrict mode. Without a supporting passage, the abstention sentence is used
Abstention sentenceYours to write. What it says when it does not know
Relevance judgeA model rereads the candidates and scores them. Below the threshold, it abstains
Judge modelEmpty means the conversation model
Verify the answer after writingA second call checks each claim. Safer, doubles the time
Minimum cosine, minimum BM25Raw floors, applied before the judge

Engines > La palette

The global shortcut that opens the floating question bar from anywhere.

Engines > In the background

SettingEffect
Icon in the menu barClosing the window then releases it, and the app leaves the Dock
Start hiddenOpens without a window; the icon and the shortcut are there
Launch at loginStarts hidden at login

Engines > Local API

SettingEffect
Answer local requestsStarts the loopback server. See Local API
PortDefault 8787
Access tokenRequired on every request. Regenerating it invalidates the old one

Where settings are stored

In the same SQLite file as everything else, so they survive reinstalling the application. Launch at login is the exception: it writes a system file, a LaunchAgent on macOS, a registry key on Windows, a .desktop entry on Linux, because nothing inside the application could start it.

How retrieval works

Every answer starts by finding passages. Understanding this explains most of what the settings do.

Cutting sources into passages

A source is read, then cut into overlapping passages. The cut lands on a sentence boundary when one is within reach, so a passage does not start mid-word.

Length and overlap are set under Sources > Processing. They apply to sources indexed from then on; existing passages keep the length they were cut with until a reindex.

Two searches, fused

ArmWhat it finds
BM25, through SQLite FTS5The passages holding your words
Dense vectorsThe passages holding your meaning, whatever the words

Both arms bring back candidates, and the two lists are fused with Reciprocal Rank Fusion: a passage ranked high by either arm survives, a passage ranked high by both wins.

Vectors are stored normalised, so comparing two of them is a plain dot product.

Candidates per search arm decides how many each arm brings back before fusion. Wider catches more and costs more to rerank.

Passages per source keeps one talkative document from filling the whole answer.

The judge

With the relevance judge on, a model reads the surviving candidates and scores each one. Below the threshold, the assistant abstains before writing anything.

This is the difference between an answer that quotes a vaguely related paragraph and one that admits the corpus does not cover the question. It costs one extra model call.

Grounding

In strict mode, the model may only use the retrieved passages for factual claims, and must cite them inline. Citation markers are checked against the passages that were actually supplied: a reference to a source that does not exist is caught.

That check is about reference bounds, not about truth. It confirms [2] points at a real passage, not that the sentence faithfully reflects it.

Verify the answer after writing adds a second call that checks each claim against the passages. Safer, and it doubles the response time.

When vectors are missing

Changing the embedding model makes existing vectors incomparable: they were produced by a different model. Langolier does not mix them. It says so, falls back to word search, and offers to reindex.

Word search keeps working the whole time.