Skip to main content

sift

CI PyPI Python Downloads Coverage License Ruff pre-commit CodeQL

Fast local search over your text and Markdown files, built for AI agents.

sift indexes folders of .md and .txt files, embeds them on your GPU, and runs a server that agents query over MCP. It offers three kinds of search: exact keyword matching, semantic search, and hybrid retrieval with reranking for RAG. Everything runs locally. No cloud services, no API keys.

Install

Requires Python 3.11 or newer. With uv:

uv tool install --torch-backend auto sift-rag   # installs the `sift` command

Or run it without installing: uvx --torch-backend auto sift-rag serve. With pip, in a virtual environment: pip install sift-rag.

On first use, sift downloads its two models from Hugging Face (about 1.5 GB).

GPU support

sift uses an NVIDIA GPU (CUDA) if there is one, else an Apple GPU, else the CPU, which works but embeds slowly.

  • Linux, macOS: nothing to do. PyTorch from PyPI includes CUDA on Linux and uses the Apple GPU on macOS.
  • Windows: PyTorch from PyPI has no CUDA support. uv's --torch-backend auto, used above, picks the CUDA build that matches your driver. With pip, install it afterwards: pip install --force-reinstall --no-deps torch --index-url https://download.pytorch.org/whl/cu128.

If an NVIDIA GPU sits unused, sift says so on start-up and prints the command that fixes it.

Usage

sift add ~/papers --name papers        # register a folder as a collection
sift index                             # scan files, chunk them, build the keyword index
sift embed                             # embed every chunk that has no vector yet
sift search '"reward shaping"'         # exact keyword search
sift vsearch "how do robots plan brush strokes"
sift query "mixing pigments to match a target colour"
sift get papers/2401.02225.md          # full document
sift get papers/2401.02225.md --lines 14-23   # only some lines, e.g. those of a search hit
sift status                            # collections and counts
sift rm papers                         # remove a collection from the index; its files stay on disk
sift serve                             # MCP server on http://127.0.0.1:8765/mcp

sift index and sift embed are incremental: run them again after files change, and only new or changed files are processed. Deleted files are removed. An interrupted sift embed continues where it stopped. A running server picks up new vectors on its own.

Search commands accept -k (number of results), -c (collection), --path (glob within the collection, e.g. "2024/*"), -f KEY=VALUE (front-matter filter, repeatable), --fields (front-matter fields to show with each hit, e.g. url,created, or * for all), --compact (no text) and --json.

search requires every term. If no chunk has them all and the query has no operators (AND, OR, NOT, NEAR), it returns the chunks that have any of them, those with more terms first.

Front matter

YAML front matter with flat key: value lines becomes filterable metadata; lists can be inline or one - item per line. A list field matches when it contains the value:

---
title: "Brush stroke planning"
categories: ["cs.RO", "cs.GR"]
year: 2024
tags:
  - painting
  - robots
---
sift query "stroke order" -f categories=cs.RO -f year=2024

Filters can also be ranges, with >, >=, < and <=. Dates compare at the precision given, so created<=2024 includes all of 2024 and created>2024 starts in 2025; a number compares with the number a date starts with:

sift search pigment -f "created>=2024-06" -f "created<2025"

The title field, or else the first heading outside code blocks, or else the file name, becomes the document title.

MCP

Tool Purpose
search Exact keyword search, ranked by BM25. Supports "phrases", prefix*, AND, OR, NOT.
vsearch Semantic search.
query Hybrid search for RAG: keyword and semantic candidates, reranked by a cross-encoder.
get Text of an indexed document by its id: all of it, or only lines such as a hit's "17-26". An id may leave out folders if the file name is unique.
status Collections, counts and front-matter fields.

The search tools take query, k, collection, path, filters, fields and compact. Every result carries id (collection/path), title, lines, score and the chunk text, so agents can cite their sources. fields adds front-matter fields to each result, e.g. ["url", "created"], and compact: true leaves out the text, so an agent can survey many results without filling its context and then read the ones that matter. Filters take values or ranges, e.g. {"created": {">=": "2024-06", "<": "2025"}}. The server tells agents when they connect which collections there are and which front-matter fields each has.

Claude Code

With the server running (sift serve), register it once for all your projects:

claude mcp add --scope user --transport http sift http://127.0.0.1:8765/mcp

Keep --scope user. Without it, claude mcp add registers sift for the current folder only, and sessions started anywhere else don't see it, including those in the Claude desktop app's Code tab. Start a new session afterwards: running sessions don't pick up new servers. One server serves any number of agents, with the models loaded once.

After upgrading sift, restart sift serve and start a new Claude Code session: a running session can keep an outdated list of sift's tools and their parameters, even after reconnecting.

Or let every Claude Code session start a server of its own over stdio. Then each session loads the models into memory itself:

claude mcp add --scope user sift -- sift serve --stdio

A registration made without --scope user can be removed in the folder where it was made, with claude mcp remove sift --scope local.

Connectors in claude.ai and in the Chat tab of the Claude apps can't use sift: claude.ai reaches connectors from Anthropic's servers, which can't reach a server on your computer.

Configuration

None needed: sift picks the device, the GPU memory budget, the batch size and the number of worker processes itself. Three optional settings exist for special cases:

Variable Default Purpose
SIFT_HOME ~/.sift Where the index lives
SIFT_EMBED_MODEL Qwen/Qwen3-Embedding-0.6B Any Sentence Transformers embedding model
SIFT_RERANK_MODEL Alibaba-NLP/gte-reranker-modernbert-base Any Sentence Transformers cross-encoder

After changing the embedding model, run sift embed --reset. Models are downloaded from Hugging Face on first use.

How it works

  • Indexing: worker processes read and parse files in parallel while the previous batch is written; small updates skip the process start-up. Files are compared by modification time and size, then by content hash, so unchanged files cost nothing. Files are read as UTF-8, or as UTF-16 when they start with its byte order mark (Windows PowerShell 5.1 writes those). Markdown is split into chunks of about 3,000 characters (about 750 tokens) on line boundaries, preferring headings, with a small overlap.
  • Storage: one SQLite database in WAL mode holds documents, chunks, metadata, an FTS5 keyword index and the vectors (fp16).
  • Embedding: PyTorch in fp16 on the GPU (NVIDIA, else Apple), in batches sorted by length to keep padding low. Each slab of 20,000 chunks is committed, so progress is never lost.
  • GPU memory: sift shares the GPU with other programs. On NVIDIA GPUs it caps itself at the memory that is free when it starts, minus headroom (10% of the GPU, at least 1 GB), asking NVML as well as CUDA, since on Windows CUDA counts memory held by other programs as free. It then measures how much memory its longest text needs at growing batch sizes and uses the largest batch that fills 90% of that budget; if a batch still doesn't fit, it is halved. With less than 2 GB to spare, sift uses the CPU instead.
  • Idle GPU: models and vectors wait in RAM and move to the GPU when a search needs them. After 5 minutes without GPU use, sift serve moves them back to RAM and hands the memory back; only CUDA's own context (about 0.3 GB) stays. The first search afterwards takes about a second longer; if other programs have taken the memory meanwhile, sift stays on the CPU rather than squeeze them. Keyword search never uses the GPU.
  • search: SQLite FTS5 with BM25, titles weighted double. Input that isn't valid FTS5 syntax is treated as exact phrases.
  • vsearch: exact nearest-neighbour search as one matrix multiply over all vectors on the GPU. No approximate index, so nothing to tune and no recall loss; a million 1024-dimensional vectors take about 2 GB of VRAM.
  • query: the top 40 (or k, if larger) keyword and semantic candidates are merged by reciprocal rank fusion and reranked in one GPU batch.
  • Server: sift serve loads models and vectors once and keeps them in memory.

Scope

In scope: plain text and Markdown files; Linux, macOS and Windows; NVIDIA GPUs (CUDA) and Apple GPUs (MPS), otherwise CPU; one user, any number of local agents.

Out of scope for now: PDF, Word and HTML parsing (convert to Markdown first); answer generation (sift retrieves, the agent writes); approximate nearest-neighbour indexes; live file watching; remote access and authentication.

Development

git clone https://github.com/tobiaswuerth/sift
cd sift
uv venv && uv pip install --torch-backend auto -e ".[dev]"   # or with pip: pip install -r requirements.txt -e ".[dev]"
pre-commit install      # lint, format and config checks on every commit
pytest --cov            # 100% line and branch coverage is required

The tests replace the embedding and reranking models with small deterministic fakes, so they need no GPU and no model downloads; everything else, including the MCP server, runs for real. See CONTRIBUTING.md for how changes and releases work.

License

MIT

Metadata

Release files for sift-rag 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sift-rag 0.2.0
File Size Uploaded Provenance
sift_rag-0.2.0.tar.gz 55.5 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for sift-rag 0.2.0
File Interpreter ABI Platform
sift_rag-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 85.3 kB

Release files / sift_rag-0.2.0.tar.gz

Download URL sift_rag-0.2.0.tar.gz
Size 55.5 kB
Tags Source
SHA-256 checksum
How to use checksums
b5d26ed45f94834d180a508ac8cd2ea1700cae6cd74d8277a3eed0f96ff5c9a9
BLAKE2b-256 checksum
How to use checksums
7d438008906e902a75ea1bf76f06f264f54aef585db8cecc98b81e4535b87411
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / sift_rag-0.2.0-py3-none-any.whl

Download URL sift_rag-0.2.0-py3-none-any.whl
Size 29.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c3490633a4961eb3aafa11aaee0b6b1593e062c3a3164f033a827711ec1fdcb8
BLAKE2b-256 checksum
How to use checksums
4a67ab3c9700f9b531f6702711291ed61e6d5c61c2582d0aa16f60df39dc18c9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Security for sift-rag 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for sift_rag-0.2.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page