The search engine that scales with your data.

Add search that ranks with Elasticsearch, from inside your app or behind its own server: full-text, vector, hybrid, and geo on one typed index, in a single package. When you add AI, the same index backs every answer with the passage it came from.

  • Claude Code
  • Codex
  • Cursor
  • Copilot
  • Gemini CLI
  • Antigravity
  • Grok Build
  • OpenCode
See what your agent does with it

See Narsil in 86 seconds

From install to first query in one file

Create an index with a typed schema, insert documents, and query with filters. The same engine works embedded in Node.js, inside the browser, or behind the bundled HTTP server.

The engine embeds in Node.js, Bun, Deno, and the browser, while the same package also serves a REST API from its own server. Multi-node cluster mode is experimental today, with TCP and gRPC transports between nodes.

Read the getting started guide
search.ts
import { createNarsil } from '@delali/narsil'
 
const narsil = await createNarsil()
 
await narsil.createIndex('products', {
  schema: {
    title: 'string',
    description: 'string',
    price: 'number',
    inStock: 'boolean',
  },
  language: 'english',
})
 
await narsil.insert('products', {
  title: 'Mechanical Keyboard',
  description: 'Cherry MX Brown switches with PBT keycaps',
  price: 129.99,
  inStock: true,
})
 
const results = await narsil.query('products', {
  term: 'mechanical keyboard',
  filters: {
    fields: {
      inStock: { eq: true },
      price: { lte: 200 },
    },
  },
})

The same query works embedded and on the server

The query that you write against an embedded index is the query that you send to the server, even after partitions shard the index behind it. You can move an index between deployments as one .nrsl snapshot, so when you scale, you change the deployment and keep your query code.

An index that you build in your process loads on the server unchanged, because the embedded engine and the server write the same binary format.

One querythree deployments
await narsil.query('products', { term })

In your process

answers with no network hop

embedded

Behind the server

REST API with a write-ahead log

HTTP

Across partitions

workers merge one ranked list

4 shards
The call above reads the same in all threesame .nrsl index

Your AI's answers include their sources

Narsil retrieves the passages that your model writes its answer from. Its highlighting then marks the matched text, so you can trace every claim in the answer back to a document. The server-app example shows this end to end, with a toggle that sends the same question through keyword, semantic, or hybrid retrieval so that you can watch the sources change.

The example numbers each citation and keeps the passage beside the answer.

AskKeywordSemanticHybrid

Does vitamin D supplementation reduce respiratory infections?

The retrieved trials report a modest protective effect, strongest in participants who started with a deficiency and took daily doses rather than large single boluses.[1][2]

Sources

1SciFact #49830.88

...daily vitamin D reduced the risk of acute respiratory infection among all participants...

2SciFact #10270.81

...protective effects were strongest in those with a baseline deficiency...

2 sourceshybrid · 34 ms

Search works inside the page, even offline

Narsil loads its engine and index into the browser and persists the index to IndexedDB, so every search completes on the device. Web Workers keep the search off the main thread. The Cmd+K search on this site and on the main portfolio uses Narsil in this way.

The browser demo indexes a JSON or CSV file of your own inside the page, so the file stays on your machine.

hybrid⌘K

Documentation

Hybrid search

Run keyword and vector retrieval in one query and fuse the rankings.

Vector search

Store embeddings in vector fields and search by similarity.

Pages

Benchmarks

openRuns in-browser on Narsil
See what you can build

At 1M documents, Narsil processes the most vector searches a second

Against Elasticsearch, OpenSearch, Qdrant, and Weaviate, with every engine on its recommended production settings and at the same search accuracy, Narsil processes 1,154 vector searches a second over 1M documents. The benchmark harness recorded every figure below on 28 September 2026.

1M

documents

1,154searches a second

Narsil processes the most vector searches a second over 1M documents.

  • Narsil1,154
  • OpenSearch1,111
  • Elasticsearch1,075
  • Qdrant1,073

Every engine searches the same DBpedia vectors on its recommended production settings and finds at least 99 per cent of the true nearest neighbours.

One dependency covers the whole engine

Keyword, vector, hybrid, and geo queries all search one typed index. The same package also includes partitioning and persistence.

Full-text search
Narsil ranks results with BM25, calibrated against the Anserini reference configuration. Narsil also supports typed schemas, filters, boosts, and highlighting.
Vector search
Narsil answers dense nearest-neighbour queries on a vector field with an exact scan, then moves the field to an HNSW graph as it grows. Embeddings can come from the built-in adapter for OpenAI-compatible APIs or from a companion package that works with local models.
Hybrid ranking
Narsil fuses keyword and vector results through reciprocal rank fusion or a linear blend, which you can tune for each query.
Geosearch
Index coordinates and query by radius or polygon containment alongside text and vector conditions.
Partitions and workers
Narsil shards a large index across partitions and worker threads, then merges the results from every shard into one ranked list for each query.
Durable persistence
Narsil keeps each index durable with a write-ahead log and checkpoints. You can also move an index between Node.js, the browser, and the server as one portable .nrsl snapshot.

Start building with Narsil

Narsil is free and open source under the Apache 2.0 licence.