Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
ix
Sub-millisecond code search via sparse trigram indexing.
ix pre-computes a byte-level trigram index to narrow search candidates
to a fraction of the total file set, then verifies matches with a
memory-constant streaming architecture. This eliminates the linear-scan
bottleneck of traditional tools on large codebases.
Documentation
| For | Read |
|---|---|
| Getting started (tutorial) | docs/QUICKSTART.md |
| CLI flag reference | ix --help |
| Running the daemon | docs/DAEMON-RUNBOOK.md |
.ixd.toml config |
docs/.ixd.toml.md |
| Socket API (tool builders) | docs/SOCKET-API.md |
| Index delta format | docs/DELTA-FORMAT.md |
| Performance benchmarks | docs/BENCHMARKS.md |
| Contributing | docs/CONTRIBUTING.md |
| Release history | CHANGELOG.md |
| Upgrade from v0.7.x | docs/v0.8.0-UPGRADE-GUIDE.md |
Install
Installs two binaries:
ix— CLI search toolixd— background daemon (requiresnotifyfeature, enabled by default)
You only need ix for search. Install ixd if you want continuous indexing.
Quick Start
# Build the index
# Literal search
# Regex search
# Context lines around each match
# Show query statistics
# Only matching file paths
# Count matches only
# Filter by file extension
Daemon
ixd watches one or more directories for file changes and incrementally
updates the index:
# Single directory
# Multiple directories (v0.9+)
Each directory runs on its own thread with independent index, watcher, beacon, and Unix domain socket. Signal handling and memory monitoring are shared.
Service Management (Linux / systemd)
# Install as a user-level systemd service
# Start / stop / restart the service
The service auto-starts on login and survives reboots. See docs/DAEMON-RUNBOOK.md for full operation guide.
Daemon Socket
The daemon exposes a Unix domain socket for external consumers (editors, tooling):
$XDG_RUNTIME_DIR/ixd/{hash}.sock
Protocol is NDJSON — one JSON object per newline-terminated line. See
docs/SOCKET-API.md. The ix CLI reads the index
file directly, not through the socket.
Configuring the Daemon
Scope what the daemon watches and indexes with .ixd.toml:
# .ixd.toml
= ["src", "lib"]
= [".git", "node_modules", "target", "vendor"]
See docs/.ixd.toml.md for full schema and examples.
How It Works
- Index —
ix --buildwalks the directory, extracts byte-level trigrams from every file, and writes a compressed index to.ix/shard.ix. - Plan — On search, the query is decomposed into trigrams. The index is consulted to find candidate files.
- Verify — Candidates are streamed through a regex matcher with constant memory usage.
Index Format (v1.3)
All integers little-endian, offsets absolute from file start, 8-byte aligned.
| Section | Description |
|---|---|
| Header | 256 bytes: magic IX01, version, flags, section offsets |
| File table | Per-file metadata: path hash, content hash, size |
| Trigram table (CDX) | Delta-encoded + varint + ZSTD in 1024-entry blocks |
| Posting lists | Per-trigram file IDs, delta-encoded + varint + ZSTD |
| String pool | Interned file paths |
CDX compression is always-on since v1.3. Not backward compatible with v1.1/v1.2 — rebuild indexes after upgrading:
Performance
| Metric | Value |
|---|---|
| Index ratio | ~4× source size (ZSTD level 3) |
| Selective query (10% match) | 40ms — 10× fewer files than ripgrep |
| Small dataset (all match) | 305ms — ripgrep wins on all-match workloads |
| Cold start | <3s |
| Hot path p99 | <50ms |
ix wins when the trigram index eliminates most files from scanning.
On small repos or queries where every file matches, linear-scan tools
like ripgrep are faster.
Feature Flags
| Flag | Default | Description |
|---|---|---|
notify |
yes | File watcher + daemon (ixd) |
decompress |
no | gz/zst/bz2/xz decompression |
archive |
no | zip/tar archive support |
full |
no | All optional features |
Library
ix is also a library (moeix on crates.io, ix as the crate name):
[]
= "0.9"
use Reader;
use Executor;
use Planner;
let reader = open?;
let plan = plan;
let mut executor = new;
let = executor.execute?;
See docs.rs/moeix for the full API reference.
Building
Requires Rust 1.85+.
License
MIT