ripgrep in a compact and cross-platform npm package. Works with Node.js, Bun, and Deno without native binaries. Bundler-friendly, with the WASM embedded as z85+brotli.
npx ripgrep TODO src/
# or install globally
npm i -g ripgrep
rg TODO src/import { ripgrep, rgPath } from "ripgrep";
// Run ripgrep programmatically
const { code } = await ripgrep(["--json", "TODO", "src"]);
// 0 = matches found, 1 = no matches, 2 = error
// Buffer output as strings
const { code, stdout, stderr } = await ripgrep(["TODO", "src"], { buffer: true });
// Or spawn as a child process (drop-in for vscode-ripgrep)
import { spawn } from "node:child_process";
spawn(rgPath, ["TODO", "src"], { stdio: "inherit" });Runs ripgrep with the given CLI arguments and returns a { code } result object. By default, output is written to the host's process.stdout / process.stderr.
Options:
stdout— writable stream to use instead ofprocess.stdout. When provided, TTY auto-detection for--color=ansiis skipped. WithnodeWasi, only streams with a numericfdproperty are supported.stderr— writable stream to use instead ofprocess.stderr. WithnodeWasi, only streams with a numericfdproperty are supported.buffer— whentrue, capture stdout and stderr and return them as strings in the result ({ code, stdout, stderr }). Customstdout/stderrstreams take precedence over buffering for the corresponding channel (default:false).env— environment variables passed to the WASI instance (default:process.env).preopens— WASI preopened directories mapping guest paths to host paths (default:{ ".": process.cwd() }). Absolute paths passed as args are auto-added as preopens.returnOnExit— whentrue,proc_exitreturns the exit code instead of terminating the process (default:true).nodeWasi— use Node's built-innode:wasiinstead of the bundled WASI shim. Enabled by default on Node.js for best performance; automatically disabled on Bun and Deno wherenode:wasiis not available, falling back to the bundled shim. Can also be forced on viaRIPGREP_NODE_WASI=1.
Absolute filesystem path to a JS shim that runs ripgrep via ripgrep. Drop-in replacement for rgPath from vscode-ripgrep / @vscode/ripgrep-style consumers that spawn the binary directly.
- ripgrep is cross-compiled to
wasm32-wasip1with SIMD (simd128) enabled viacargo zigbuild, using Zig as the C compiler/linker. This unlocksmemchr's vectorized search routines for faster byte scanning. - The resulting
.wasmis brotli-compressed and z85-encoded intolib/_rg.wasm.mjs, so it ships as a plain ESM module — no.wasmasset resolution or postinstall needed. - On first use, the z85 blob is decoded and decompressed, then cached to the OS temp directory (
$TMPDIR/ripgrep-wasm-<hash>.wasm). Subsequent calls (even across processes) skip decoding entirely. The z85 string itself is wrapped in a function so V8 lazy-parses it only when needed. - The compiled
WebAssembly.Moduleis memoized in-process — repeatedripgrep()calls only pay the compilation cost once. Fresh instances are still created per-call since WASI state (memory, file descriptors) is per-instance. - A minimal WASI preview1 shim (
lib/_wasi.mjs, ~20 syscalls, backed bynode:fs) instantiates the module. Works uniformly on Node, Bun, and Deno. - ripgrep's TTY color detection doesn't survive the WASI boundary, so
ripgrep()auto-injects--color=ansiwhen the host stdout is a TTY and the caller hasn't picked a color mode.
Requirements:
zig(tested with 0.15.2)rustc+cargo(tested with 1.94.1)cargo-zigbuild:cargo install cargo-zigbuildrustup target add wasm32-wasip1
Then:
git submodule update --init --recursive
zig build # → dist/rg-wasm32-wasip1.wasm
node build.ts # inline wasm into lib/_rg.wasm.mjsNative cross-compiled binaries (macOS / Linux / Windows) are also available via zig build native, but they are not part of the published npm package — WASI is the only shipped flavor.
MIT. ripgrep itself is licensed under MIT / Unlicense by its authors — see vendor/ripgrep.