Local-first photo and video library. It indexes the folders you choose, describes what is actually in the files, and keeps searching while that work continues in the background.
Natural-language search works with no API key. Optional providers — any number of them, including several instances of the same vendor — can plan queries, caption files, embed them, and check the top hits together.
MIT licensed.
- Indexes photos and videos in the folders you add. Other files are ignored.
- Reads pixels, a perceptual hash, color, sharpness, EXIF, and a short English description on this machine.
- Full-text search plus instructional requests such as “sharpest beach photos from last summer without people” or “phone wallpaper”.
- Search stays available while indexing runs.
- Albums, including live albums that are a saved search.
- Moments (a gap in capture time), burst stacks with “keep the sharpest”, favorites, ratings, hidden cull, notes, your own tags, on this day, nearby GPS, and find-similar.
- Optional video keyframes when
ffmpegandffprobeare installed. Without them, videos are still indexed by name. - Export a result set as symlinks, or as copies if symlinks are not allowed.
Every provider is its own row. There is no “one OpenAI” limit. Add three OpenAI instances, or OpenAI plus Anthropic plus a llama.cpp server, and enable all of them.
Presets cover the usual HTTP APIs and local servers:
OpenAI, Azure OpenAI, Anthropic, Google Gemini, xAI Grok, OpenRouter, Mistral, Groq, Together, Fireworks, DeepSeek, Perplexity, Cohere’s OpenAI-compatible endpoint, Ollama, llama.cpp (llama-server), LM Studio, vLLM, LocalAI, and a blank custom preset.
For every preset:
- The endpoint is editable. A vendor preset is only a starting URL.
- The API key is stored exactly as typed. Blank is allowed. Lantern does not check the vendor’s official key shape.
- Request style is one of
openai,anthropic,gemini, orollama. llama.cpp, LM Studio, vLLM, and most hosted gateways useopenai. - Model id, embedding model, extra headers, tier, roles, priority, and in-flight cap are all editable.
- Duplicate makes another instance of the same hookup.
The Index page has three modes:
| Mode | What the pool does |
|---|---|
| Cooperate (default) | The cheapest enabled captioner takes the first look. If it is unsure, or later votes disagree, the other instances are asked in parallel. Planners race and their answers are merged. Every embedding model runs, and search late-fuses those spaces. The top hits are checked by two vision models. |
| Throughput | Work is spread to the least-busy instance. One planner and one embedder answer. Vision re-check is off unless you set a verify count. |
| Deep | Every enabled captioner sees the file. A judge model reconciles disagreements. Every planner and embedder is used. More of the result list is re-checked by every verifier. |
Embeddings from different models are never concatenated. Each model is its own space. A file that one model has not embedded yet is not treated as a zero.
Keys stay in the local SQLite library. Logs redact them.
Start a server with an OpenAI-compatible API, then add the llama.cpp server preset:
llama-server -m your-model.gguf --port 8080The default endpoint is http://127.0.0.1:8080/v1. Change it if the server listens elsewhere. Leave the key blank, or set whatever your server expects. Image captioning needs a multimodal GGUF and the matching projector. A text-only model can still plan searches and judge captions if you turn vision roles off.
You need a recent stable Rust (1.95 or newer; 1.99 is what this was built with) and a C compiler. SQLite is bundled.
On Linux the desktop shell also needs the usual X11, Wayland, and Vulkan runtime libraries. A normal desktop already has them. To compile on a minimal machine:
sudo apt-get install build-essential pkg-config \
libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev \
libxkbcommon-dev libvulkan-devcargo run --releaseHeadless checks, without the GUI:
cargo test --no-default-features
cargo run --no-default-features -- self-testUseful terminal commands:
lantern index --once ~/Pictures
lantern search "quiet outdoor portraits"
lantern search --ai "wallpaper of a teal coastline, not screenshots"
lantern provider add --kind openai --name "OpenAI work" --key "$OPENAI_API_KEY"
lantern provider add --kind openai --name "OpenAI personal" --base-url https://example.test/v1 --key 'not-a-standard-key'
lantern provider add --kind llamacpp --base-url http://127.0.0.1:8080/v1 --key ''
lantern providersThe library database, thumbnails, and AI jpegs live in the per-user data directory (lantern / Lantern under the platform’s project-dirs path). The Index page shows the exact path. The database file is created mode 0600.
Seasons in search (“last summer”) use the northern hemisphere, and the interpreted range is shown with the results.
Pixel analysis never leaves the machine. A provider is contacted only for the roles you enable on that instance: captions, query planning, embeddings, search verification, or judging. You can run Lantern with the provider list empty.
MIT. See LICENSE.