lurq

Self-hosting

Run lurq against your own Postgres index.

Everything here runs against your own lurq Postgres index and needs a DATABASE_URL. It's for operators running the hosted service and for self-hosters, not for end users, who only run lurq setup (Quick start).

The two planes

The commands that build an index are not in the published npm package.

lurqrun ships as a read-only oracle: it can query an index, extract API surfaces, scan a codebase, and serve MCP. Everything that ingests, crawls, mines, runs a sandbox, issues keys, or migrates the schema lives on a separate operator binary that is deliberately excluded from the published files, so ingestion code and its heavy dependencies never land on a user's machine.

To run the operator plane, clone the repo:

git clone https://github.com/jadenryu/lurq && cd lurq
npm install
npm run operator -- <command>          # or: npx tsx src/bin/operator.ts <command>

A built checkout can also run node dist-operator/bin/operator.js <command>, which is what the production cron jobs use.

Configuration

Only DATABASE_URL is required; everything else degrades gracefully.

VariableRequiredPurpose
DATABASE_URLyesPostgres connection (pgvector-enabled)
GITHUB_TOKENrecommendedGitHub signals (stars, cadence, issues, archived)
EMBEDDING_PROVIDER / EMBEDDING_API_KEY / EMBEDDING_BASE_URLnoAny OpenAI-compatible /v1/embeddings; falls back to a local embedder
SUMMARY_PROVIDER / SUMMARY_API_KEY / SUMMARY_BASE_URLnoAny OpenAI-compatible chat endpoint for usage guides; falls back to the npm description
LURQ_SYNC_CONCURRENCYnoParallel ingest workers (default 5)
LURQ_SYNC_REFRESH_CAPnoStalest non-seed packages refreshed per sync (default 400)
PORTnoPort for serve-http (defaults to 8080)
LURQ_RATE_LIMIT_MAX / LURQ_IP_RATE_LIMIT_MAX / LURQ_RATE_LIMIT_WINDOW_MSnoPer-key / per-IP rate limits for serve-http
REDIS_URLrecommended for real trafficResponse cache and the shared rate-limit store
LURQ_METRICS_TOKENnoBearer token guarding /metrics; unset disables the endpoint
LURQ_ISSUER_SECRETnoShared secret for the dashboard-authenticated routes
E2B_API_KEY / E2B_TEMPLATEnoVM-isolated sandbox for verifying untrusted packages

Without REDIS_URL the response cache is a transparent pass-through and every request recomputes its search on the database. Fine for one box; set it before serving real traffic, since it also backs the rate limiter across instances.

Set up the index

npm run operator -- db migrate   # pgvector extension + schema + curated seed list
npm run operator -- sync         # compute scores from public APIs (~2 min)

sync is idempotent and tolerant of single-source outages. Run it daily to keep the index fresh.

Optional, to grow coverage beyond the seed list without curation:

npm run operator -- discover --cap 25   # crawl, merit-gate, ingest survivors
npm run operator -- worker              # the autonomous loop (Ctrl-C stops cleanly)
npm run operator -- rescore             # re-derive scores after a weight change

Serve

These two are in the published package:

lurq serve-http   # HTTP MCP server + API-key auth (helmet, rate limits)
lurq serve        # stdio MCP server against your own DB

serve-http fronts the central DB, so DATABASE_URL lives only on the service host. Self-hosters can instead wire an agent to a local stdio server with lurq install-skill --local.

Point your own clients at it with lurq setup --url https://lurq.internal/mcp; the endpoint is stored alongside the key, so a later bare lurq setup stays on your server.

API keys

For operators issuing keys to end users (operator plane, needs DATABASE_URL):

npm run operator -- keys create --label "acme"      # issue a key (shown once)
npm run operator -- keys list                       # prefix, tier, last-used, status
npm run operator -- keys rotate lurq_live_ab12cd    # replace, then revoke the old one
npm run operator -- keys revoke lurq_live_ab12cd    # revoke by prefix or id

Keys are shown once at creation and stored only as hashes. Interactively, the key is wiped from your terminal (screen and scroll-back) after you confirm you've copied it. Capture it when it's printed — it can't be recovered, only rotated or revoked and reissued.

rotate creates the replacement before revoking the original, so a failure part-way through leaves you with a working key rather than none.

On this page