Last Updated: 2026-02-02
Status: Production-ready v4 (with Browser CLI)
SlimArmor is a mini vector database for Val Town that provides semantic search capabilities using SQLite with libSQL/Turso vector extensions.
- Stores text with AI-generated embeddings (4096 dimensions by default)
- Enables semantic search (search by meaning, not keywords)
- Returns distance scores for ranking results
- Supports any OpenAI-compatible embedding API
- NEW: Browser CLI for interactive management
┌─────────────────────────────────────────────────────────────┐
│ Browser CLI (ui.ts) │
│ Terminal-style web UI at /ui │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ HTTP API (api.ts) │
│ /ui, /upsert, /search, /delete, /stats, /calibrate, etc. │
│ + Admin token authentication for write operations │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Vector DB Core (vectordb.ts) │
│ - setup(), upsert(), search(), remove(), stats() │
│ - Content hash check (skip re-embedding unchanged text) │
│ - Dimension assertion (fail fast on mismatch) │
└─────────────────────────────────────────────────────────────┘
│ │
▼ ▼
┌──────────────────────────┐ ┌────────────────────────────────┐
│ Embedding Provider │ │ Val Town SQLite (Turso) │
│ (OpenAI-compatible) │ │ - F32_BLOB vector columns │
│ - Nebius (default) │ │ - libsql_vector_idx (DiskANN)│
│ - OpenAI │ │ - vector_top_k queries │
│ - OpenRouter │ │ - vector_distance_cos │
│ - Custom │ └────────────────────────────────┘
└──────────────────────────┘
A terminal-style web interface for interacting with the vector database.
Features:
- Monospace terminal aesthetic (GitHub dark theme)
- Command history (↑/↓ arrows)
- Clickable IDs in results (auto-fills
get <id>) - Color-coded distance scores (green <0.5, orange 0.5-0.65, red >0.65)
- Session-based auth token storage
- Mobile responsive
- Pretty tables and stats boxes (not raw JSON)
Access: GET /ui
CLI Commands:
| Command | Description |
|---|---|
help | Show all available commands |
stats | Storage & index statistics |
search "query" [-k 10] [--mode balanced] [--max 0.64] | Semantic search |
get <id> | Show record details |
list [--limit 20] [--prefix seed-] | List record IDs |
calibrate "query" | Suggest distance thresholds |
upsert <id> "text..." | Create/update record [AUTH] |
del <id> | Delete record [AUTH] |
seed 100 | Seed synthetic data [AUTH] |
clear --yes | Delete ALL records [AUTH] |
reindex | Recreate vector index [AUTH] |
auth <token> | Set admin token |
logout | Clear auth token |
ping | Health check |
cls | Clear output |
Command aliases: ls → list, delete → del, ? → help
Search modes:
--mode tight→ maxDistance 0.5 (top 3 only)--mode balanced→ maxDistance 0.64 (top 10)--mode loose→ maxDistance 0.7 (include all)
The main library that can be imported into other vals.
Key exports:
setup()- Creates table and indexupsert(id, text, meta?)- Insert/update with smart re-embeddingsearch(query, k?, maxDistance?)- Semantic searchremove(id)- Delete recordstats()- Count and storage estimateget(id)- Get single recordlistIds(limit?)- List all IDsreindex()- Recreate indexgetProviderInfo()- Current embedding config
Configuration via env vars:
EMBEDDING_PROVIDER- Preset: nebius, openai, openrouterEMBEDDING_API_URL- Custom API URLEMBEDDING_API_KEY- API keyEMBEDDING_MODEL- Model nameEMBEDDING_DIM- Vector dimensions
RESTful API layer with Browser CLI and admin token authentication.
UI:
GET /ui- Browser CLI interface
Core endpoints:
POST /upsert- Insert/update record [AUTH]POST /search- Semantic searchPOST /delete- Delete record [AUTH]GET /get?id=...- Get recordGET /list- List IDs
Admin endpoints:
GET /- API info + provider configGET /ping- Health checkGET /stats- Detailed storage statsGET /test- Smoke test [AUTH]GET /seed?n=100- Seed synthetic data [AUTH]GET /calibrate?q=...- Threshold suggestionsPOST /reindex- Recreate index [AUTH]POST /clear?confirm=yes- Delete all [AUTH]
Authentication (NEW in v4):
- Set
ADMIN_TOKENenv var to enable authentication - Pass token via
Authorization: Bearer <token>header - Write operations (
[AUTH]) require auth whenADMIN_TOKENis set - If
ADMIN_TOKENnot set, all operations are open (current default)
CREATE TABLE vectordb (
id TEXT PRIMARY KEY,
text TEXT NOT NULL,
text_hash TEXT NOT NULL, -- SHA-256 for change detection
embedding F32_BLOB(4096), -- Vector column (dimension varies by provider)
meta_json TEXT, -- Optional JSON metadata
updated_at INTEGER NOT NULL -- Unix timestamp ms
);
CREATE INDEX vectordb_embedding_idx
ON vectordb (libsql_vector_idx(embedding, 'metric=cosine', 'max_neighbors=64', 'compress_neighbors=float8'));
We tested and applied these Turso-documented optimizations:
| Setting | Value | Why |
|---|---|---|
metric=cosine | Cosine distance | Standard for text embeddings |
max_neighbors=64 | 64 neighbors | Down from default ~192, saves storage |
compress_neighbors=float8 | 1 byte/dim | 75% less index storage |
Trade-off: Slightly lower recall accuracy, significantly lower storage.
| Metric | Value |
|---|---|
| Storage per record | ~22 KB |
| Estimated max records/GB | ~47,500 |
| Embedding latency (Nebius) | ~460ms |
| Search latency | <100ms |
From calibration with "machine learning" query:
- Min: 0.46 (highly relevant)
- Median: 0.64
- Max: 0.67 (least relevant in top 20)
Recommended thresholds:
- Tight: 0.5 (top 3 only)
- Balanced: 0.64 (top 10)
- Loose: 0.7 (include all)
-
Single embedding dimension - Table created with fixed dimension. Changing providers requires clearing data.
-
No chunking - Each record = one embedding. Long documents should be pre-chunked by the user.
-
No hybrid search - Pure vector search, no FTS fallback. Could be added later.
-
Sync embedding calls - Each upsert calls embedding API synchronously. Batch support not implemented.
-
No pagination - Search returns up to k results, no cursor-based pagination.
If continuing development, consider:
-
Chunking support - Auto-split long documents, store as
docId::chunkN -
Hybrid search - Add FTS5 table, merge vector + keyword results
-
Batch embeddings - Batch multiple texts in one API call
-
Background indexing - Queue-based async embedding
-
Metadata filtering - SQL WHERE clauses on meta_json fields
-
Multi-index - Support different embedding models in same DB
GET /ui
Interactive terminal interface - type help to see commands.
GET /test
Inserts 5 demo records, runs searches, shows results. (Requires auth if ADMIN_TOKEN set)
GET /seed?n=1000
Seeds 1000 synthetic records (takes ~8 minutes). (Requires auth if ADMIN_TOKEN set)
GET /calibrate?q=your+query
Analyzes distance distribution, suggests thresholds.
| Variable | Required | Default | Description |
|---|---|---|---|
ADMIN_TOKEN | No | - | Enable auth for write operations |
EMBEDDING_PROVIDER | No | nebius | Preset: nebius, openai, openrouter |
NEBIUS_API_KEY | If nebius | - | Nebius API key |
OPENAI_API_KEY | If openai | - | OpenAI API key |
OPENROUTER_API_KEY | If openrouter | - | OpenRouter API key |
EMBEDDING_API_URL | No | (from preset) | Custom API URL |
EMBEDDING_API_KEY | No | - | Generic API key fallback |
EMBEDDING_MODEL | No | (from preset) | Override model name |
EMBEDDING_DIM | No | (from preset) | Override dimensions |
Provider returned different dimension than expected. Check EMBEDDING_DIM env var matches your model.
Set the appropriate env var for your provider.
Lower maxDistance (try 0.5 instead of 0.7).
Normal - each insert requires an API call (~460ms). Batch support not implemented.
Clear data with POST /clear?confirm=yes and re-insert.
Set ADMIN_TOKEN env var and use auth <token> in CLI, or pass Authorization: Bearer <token> header in API calls.
- TypeScript throughout
- Proper error handling with typed errors
- Parameterized SQL (no injection risk)
- Content hash prevents unnecessary re-embedding
- Dimension assertion fails fast on mismatch
- 30s timeout on embedding API calls
- AbortController for cancellation
- Admin token auth for write protection
- Verified Val Town SQLite supports vectors - F32_BLOB, libsql_vector_idx, vector_top_k all work
- Tested Nebius embedding API - Qwen3-Embedding-8B returns 4096 dims
- Built core vectordb.ts - upsert, search, delete, stats
- Added optimizations - compress_neighbors=float8, max_neighbors=64
- Added distance scores - Returns cosine distance in results
- Added maxDistance filter - Filter out low-relevance results
- Added admin tools - /seed, /calibrate, /stats, /clear
- Made multi-provider - Nebius, OpenAI, OpenRouter, custom
- Documented everything - README, GUIDE, HANDOVER
- Added Browser CLI (v4) - Terminal-style web UI at /ui with auth support
- Val: https://www.val.town/x/kamenxrider/slimarmor
- Browser CLI: https://kamenxrider--95fbe492ffe111f0bee942dde27851f2.web.val.run/ui
- API Endpoint: https://kamenxrider--95fbe492ffe111f0bee942dde27851f2.web.val.run
- Module: https://esm.town/v/kamenxrider/slimarmor/vectordb.ts
This document is for the next developer/AI continuing work on SlimArmor.