getbased-rag — standalone RAG knowledge server (formerly the Electron-bundled Lens)
Project description
getbased-rag
Installing for the first time? The getbased-agent-stack meta-package bundles this server with the MCP that Claude Code / Hermes / OpenClaw talk to, plus getbased-dashboard for a browser UI. One command and you're up.
A standalone RAG knowledge server — the backend that used to ship inside the getbased Electron desktop app, now just Python. Point any client (the getbased PWA's External server lens backend, the dashboard, or your own) at it.
- Stack: FastAPI + Uvicorn · Qdrant (embedded local mode) · sentence-transformers / ONNX Runtime
- Default port: 8322, loopback only
- Auth: Bearer token, auto-generated on first start
- Stores: every library is its own Qdrant collection, pinned to its own embedding model at creation
Install
Requires Python ≥ 3.10.
pipx install "getbased-rag[full]"
Or from source:
git clone https://github.com/elkimek/getbased-agents.git
cd getbased-agents
uv sync --all-packages --all-extras
Run
lens serve
First start auto-generates an API key at the data dir (see below), prints the bind address, and lazy-loads the embedding model on the first query (~90 MB download for MiniLM).
Copy the API key out when you need to configure a client:
lens key
Smoke test:
curl -s http://127.0.0.1:8322/health
curl -s -H "Authorization: Bearer $(lens key)" http://127.0.0.1:8322/info | jq
Ingest a file or directory from the CLI:
lens ingest ~/Documents/research
lens stats
Or over HTTP (what the dashboard + PWA use):
curl -H "Authorization: Bearer $(lens key)" \
-F "files=@paper.pdf" -F "files=@notes.md" \
http://127.0.0.1:8322/ingest
Per-library embedding models
Every library is pinned to one embedding model at creation time — Qdrant collections are dimension-locked, so you can't swap models on an existing library without re-ingesting. Call GET /models for the curated list (MiniLM-L6-v2 · BGE-small/base/large-en · BGE-M3) with dims and download sizes, then pass embedding_model on create:
curl -H "Authorization: Bearer $(lens key)" \
-H "Content-Type: application/json" \
-d '{"name":"Research","embedding_model":"BAAI/bge-m3"}' \
http://127.0.0.1:8322/libraries
Libraries on the same model share one embedder instance in memory. Two libraries both on BGE-M3 use ~2 GB total, not 4.
Streaming ingest progress
The HTTP POST /ingest endpoint speaks two content types:
- Default (no
Accept): single-shot JSON summary after the run completes Accept: application/x-ndjson: newline-delimited JSON progress stream — onestartevent (with total chunks), per-batchembedevents every ~5 chunks (with current source + index), terminalresultorerrorevent
The dashboard uses the streaming path for its bottom-right pill (chunks/sec rate, cancel button, per-filename status). Cancellation works by client disconnect: aborting the fetch causes the server's worker thread to exit at the next batch boundary with cancelled: true in the result. Partial-commit — whatever was embedded before the cancel stays.
Wiring into the getbased PWA
In the PWA: Settings → AI → Knowledge Base → External server
| Field | Value |
|---|---|
| URL | http://127.0.0.1:8322 |
| API key | output of lens key |
Click Save, then Test connection. rag_ready: false is expected before you ingest anything.
Agent access (Claude Code, Hermes, OpenClaw, etc.)
Pair this server with getbased-mcp to expose knowledge_search, knowledge_list_libraries, knowledge_activate_library, and knowledge_stats as MCP tools. Typical setup: run both the lens server and getbased-mcp on the same VM, point MCP's LENS_URL at http://localhost:8322.
Browser UI
Install getbased-dashboard for a web UI on top of this server — library management, drag-drop ingest with live progress pill, search preview, MCP config generator.
Configuration
Every setting is an environment variable. Defaults in parentheses.
| Variable | Purpose |
|---|---|
LENS_HOST (127.0.0.1) |
Bind interface. Change to 0.0.0.0 only if you really want LAN access |
LENS_PORT (8322) |
TCP port |
LENS_DATA_DIR (platform default) |
Where Qdrant DB, API key, and model cache live |
LENS_EMBEDDING_MODEL (sentence-transformers/all-MiniLM-L6-v2) |
Default model for new libraries (overridable per library) |
LENS_SIMILARITY_FLOOR (0.55) |
Minimum cosine score for a returned chunk |
LENS_ONNX_PROVIDER (auto) |
cuda | rocm | openvino | coreml | cpu |
LENS_RERANKER (false) |
Enable reranking of top candidates |
LENS_MAX_INGEST_BYTES (268435456 — 256 MB) |
Cap on a single ingest upload's total size |
LENS_CHUNK_MAX_SIZE (800) |
Max chunk size in characters |
LENS_CORS_ORIGINS (empty) |
Comma-separated extra CORS origins to allow, in addition to the PWA + loopback defaults |
Default data dir:
- Linux:
$XDG_DATA_HOME/getbased/lensor~/.local/share/getbased/lens - macOS:
~/Library/Application Support/getbased/lens - Windows:
%APPDATA%\getbased\lens
A legacy ~/.getbased/lens is honored if it already exists, so pre-v1.21 installs don't lose their data.
GPU acceleration
Install the matching onnxruntime-* wheel (e.g. onnxruntime-gpu for CUDA), then:
LENS_ONNX_PROVIDER=cuda lens serve
HTTP API
All endpoints except /, /health require Authorization: Bearer <key>.
| Method | Path | Purpose |
|---|---|---|
GET |
/health |
Liveness + rag_ready + chunk count. Public |
GET |
/info |
Embedder engine/model/dim, active library, similarity floor. For UI engine badges |
GET |
/models |
Curated model picker list (id, label, dim, size_mb) plus the server's default |
POST |
/query |
{ query, top_k } → top-k chunks from the active library, encoded with that library's model |
POST |
/ingest |
Multipart upload; accepts streaming NDJSON progress when Accept: application/x-ndjson |
GET |
/stats |
Per-source chunk counts for the active library |
DELETE |
/sources/{source} |
Drop one source from the active library |
DELETE |
/sources |
Clear the active library's chunks (library stays) |
GET |
/libraries |
List libraries + active id. Each row includes chunks, lastIngestAt, embedding_model |
POST |
/libraries |
{ name, embedding_model? } → create. 409 on duplicate name (case-insensitive) |
POST |
/libraries/{id}/activate |
Set active |
PATCH |
/libraries/{id} |
Rename |
DELETE |
/libraries/{id} |
Delete (drops Qdrant collection) |
Security notes
- Default bind is
127.0.0.1— queries never leak to the LAN unless you explicitly setLENS_HOST=0.0.0.0. - The API key file is mode
0600and never exposed over HTTP. Uselens keylocally to read it. - Bearer comparison uses
secrets.compare_digest— constant-time, no timing-leak class of bug. - Upload paths are basename-sanitised server-side (so
../../etc/passwdcan't escape the ingest temp dir). - Zip uploads are zip-slip-guarded — each archive entry must resolve inside its own per-zip subdirectory AND inside the overall ingest root.
- If you expose the server to a LAN or the internet, front it with a reverse proxy that terminates TLS and rate-limits.
CLI
lens serve Start the HTTP server (default)
lens ingest <path> Index files into the active library
lens stats List indexed sources + chunk counts
lens delete <source> Drop chunks belonging to one source
lens clear Wipe the active library
lens info Show config + API key
lens key Print the API key (creates one if missing)
License
GPL-3.0-only.
Lineage
This repo is the Python portion lifted out of getbased after the Electron desktop app was retired. The PWA's external-server lens backend speaks this same HTTP contract unchanged.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file getbased_rag-0.7.0.tar.gz.
File metadata
- Download URL: getbased_rag-0.7.0.tar.gz
- Upload date:
- Size: 49.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
673b4b060fa01744639697ea6306be55e66e140978805ce1066701ba8eb5b2fc
|
|
| MD5 |
bffae040d337a04cf054f5d43bf3699d
|
|
| BLAKE2b-256 |
5ab670cd9a389d18d16d1d0dabb5ec3a1711fe211fac1307a2593e596b5d20f5
|
Provenance
The following attestation bundles were made for getbased_rag-0.7.0.tar.gz:
Publisher:
publish.yml on elkimek/getbased-agents
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
getbased_rag-0.7.0.tar.gz -
Subject digest:
673b4b060fa01744639697ea6306be55e66e140978805ce1066701ba8eb5b2fc - Sigstore transparency entry: 1340495489
- Sigstore integration time:
-
Permalink:
elkimek/getbased-agents@831c8bdc0027bd619df8a93421225366cd908401 -
Branch / Tag:
refs/tags/v0.6.0-dashboard - Owner: https://github.com/elkimek
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@831c8bdc0027bd619df8a93421225366cd908401 -
Trigger Event:
push
-
Statement type:
File details
Details for the file getbased_rag-0.7.0-py3-none-any.whl.
File metadata
- Download URL: getbased_rag-0.7.0-py3-none-any.whl
- Upload date:
- Size: 42.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Pop!_OS","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0979ef2c293bcc14eabebf61390f047e099addde81769f97dfbfbcd9eff9ddd7
|
|
| MD5 |
82a21949c0c432fa7d85bc3e64e561a2
|
|
| BLAKE2b-256 |
f07be6d9327765bab48c02e4899949cd69f99059416d3de3490b5aa0cede08f5
|