Are you the author? Sign in to claim
Locally hosted semantic search for AI agents. 20+ document formats, hybrid search, agent memory, zero cloud dependencies
Local semantic search for AI agents and humans.
Quarry indexes documents in 20+ formats, embeds them with a local ONNX model (snowflake-arctic-embed-m-v1.5, 768-dim), stores vectors in LanceDB, and serves semantic search to Claude Code, Claude Desktop, and the CLI. Everything runs locally — no API keys, no cloud accounts. The embedding model (~120 MB int8) downloads once on first use. CUDA GPUs are auto-detected for faster inference.
Platforms: macOS, Linux
curl -fsSL https://raw.githubusercontent.com/punt-labs/quarry/a3c10f9/install.sh | sh
Restart Claude Code, then:
> /ingest report.pdf # index a document (runs in background)
> /quarry status # after a moment, confirm it's there
> /find "what does the report say about margins" # search by meaning
Once installed, a plugin hook auto-indexes your current project directory on every session start — you don't need to /ingest your codebase manually.
uv tool install punt-quarry
quarry install
quarry doctor
For non-Claude harnesses (Codex, Cursor, a plain terminal) or Claude Code users whose org policy blocks marketplace/plugin installs, add --no-plugin to install the CLI, daemon, and MCP server while skipping only the marketplace-register and plugin-install steps:
curl -fsSL https://raw.githubusercontent.com/punt-labs/quarry/a3c10f9/install.sh | sh -s -- --no-plugin
In contexts that cannot pass a flag (CI templating a bare curl … | sh, config systems that set only env), set QUARRY_NO_PLUGIN=1 — honored only when exactly 1:
curl -fsSL https://raw.githubusercontent.com/punt-labs/quarry/a3c10f9/install.sh | QUARRY_NO_PLUGIN=1 sh
Everything else runs unchanged — binary, PATH, embedding model, TLS, and the health check. Use the CLI (quarry find, quarry ingest, quarry remember) and the stdio MCP server (quarry mcp) directly; both talk to the resident quarryd daemon that quarry install starts. To add the plugin later, re-run the installer without --no-plugin.
curl -fsSL https://raw.githubusercontent.com/punt-labs/quarry/a3c10f9/install.sh -o install.sh
shasum -a 256 install.sh
cat install.sh
sh install.sh
Run quarry on a GPU server and connect from any Mac or Linux client over TLS.
Server (GPU host, serves remote clients):
export QUARRY_API_KEY=$(openssl rand -hex 32)
curl -fsSL https://raw.githubusercontent.com/punt-labs/quarry/a3c10f9/install.sh | sh -s -- --network
Generates TLS certificates, binds daemon to 0.0.0.0, registers a systemd service, and prints a CA fingerprint. NVIDIA GPUs are auto-detected for CUDA inference.
Client (connects to remote server):
curl -fsSL https://raw.githubusercontent.com/punt-labs/quarry/a3c10f9/install.sh | sh
quarry login <server-hostname> --api-key <token>
No special flag needed --- the default install runs a local daemon on localhost. quarry login redirects queries to the remote server over wss:// with TOFU certificate pinning.
The .mcpb bundle is an on-top way to reach the same local quarry index from Claude Desktop and CoWork agents. It embeds no engine: it registers the thin quarry mcp stdio client, which talks to the same resident quarryd daemon that backs the CLI and Claude Code. Desktop searches exactly the data you have already indexed --- not a separate store --- precisely because every surface shares one daemon. The dependency is the same one a menu-bar surface would have: a thin client over the running quarryd, not a self-contained app.
It is not a standalone install. Quarry must already be present: install it first, which puts the quarry binary on your PATH and starts the daemon:
curl -fsSL https://raw.githubusercontent.com/punt-labs/quarry/a3c10f9/install.sh | sh
With quarry installed, add it to Claude Desktop by either route:
quarry install also configures Claude Desktop --- nothing else to do.A fresh-machine double-click of the .mcpb alone will not work --- it needs the quarry binary and a running daemon behind it.
Note: Uploaded files in Claude Desktop live in a sandbox that quarry cannot access. Use remember for uploaded content, or provide local file paths to ingest.
quarryd process loads the embedding model once and serves the CLI and hooks over a versioned REST API (/v1); Claude Code connects through the stdio quarry mcp serverquarry enable sets up three scoped collections per project: file sync, passive captures (web fetches + session transcripts), and per-agent memory. Captures are separated from the code index so research doesn't pollute code searchuse for work/personal separationresearcher subagent combines quarry local search with web research, auto-ingests valuable findings> /ingest report.pdf
▶ Ingesting report.pdf (background)
> /quarry
▶ Database: default
Documents: 47
Chunks: 1,203
Size: 12.4 MB
Model: snowflake-arctic-embed-m-v1.5 (768-dim)
> /find "what were the Q3 revenue figures"
▶ [report.pdf p.12 | text/.pdf] (similarity: 0.4521)
Third quarter revenue reached $142M, up 18% year-over-year,
driven primarily by expansion in the enterprise segment.
Gross margins improved to 71% from 68% in Q2.
| Command | What it does |
|---|---|
/ingest <source> | Ingest a URL, directory, or file |
/remember <name> | Ingest inline text under a document name |
/find <query> | Semantic search. Questions get synthesized answers; keywords get raw results |
/explain <topic> | Search and synthesize an explanation |
/source <claim> | Find which document a claim comes from |
/quarry [sub] | Manage: status, sync, collections, databases, registrations |
| Tool | Purpose | Execution |
|---|---|---|
ingest | Index a file or URL | Background |
remember | Index inline text | Background |
register_directory | Register directory for sync | Background |
sync_all_registrations | Re-index all registered directories | Background |
find | Semantic search with filters | Sync |
show | Document metadata or page text | Sync |
list | Documents, collections, databases, registrations | Sync |
status | Database statistics | Sync |
delete | Remove document or collection | Background |
deregister_directory | Remove registration (validates; errors if unknown) | Sync |
use | Switch active database | Sync |
quarry ingest report.pdf # index a file
quarry ingest https://example.com # index a webpage
echo "notes" | quarry remember --name notes.md # index inline text
quarry find "revenue trends" # hybrid search (vector + FTS)
quarry list documents # list indexed documents
quarry register ~/Documents/notes # watch a directory
quarry sync # re-index registered dirs
quarry use work # switch database
quarry enable # set up project collections + captures
quarry disable # remove project registration + data
quarry captures init # bootstrap the private capture shadow repo
quarry captures push # re-scrub + push captures to the shadow
quarry status # database dashboard
quarry doctor # health check
quarry install # set up daemon service, TLS certs, mcp-proxy
quarryd # run the engine in the foreground (normally the service runs it)
# Remote connections
quarry login okinos.local --api-key <token> # TOFU login to remote server
quarry logout # disconnect, revert to local daemon
quarry remote list --ping # show remote config and health
# Agent memory tagging
quarry ingest notes.md --agent-handle claude --memory-type fact
quarry find "deployment steps" --agent-handle claude
echo "key insight" | quarry remember --name insight.md --agent-handle claude \
--memory-type observation --summary "Key insight from review"
Quarry works with zero configuration. These environment variables are available for customization:
| Variable | Default | Description |
|---|---|---|
QUARRY_PROVIDER | (auto) | ONNX execution provider: cpu, cuda, or unset (auto-detect) |
QUARRY_API_KEY | (none) | Bearer token for quarryd (required for a non-loopback bind) |
QUARRY_ROOT | ~/.punt-labs/quarry/data | Base directory for all databases |
CHUNK_MAX_CHARS | 1800 | Max characters per chunk (~450 tokens) |
CHUNK_OVERLAP_CHARS | 200 | Overlap between consecutive chunks |
For the full configuration reference, see Architecture section 7.
Beyond explicit /ingest and /find commands, quarry runs as a Claude Code plugin with hooks that capture knowledge automatically during your sessions:
| Hook | When it fires | What it does |
|---|---|---|
| Session start | On every session start | Auto-registers your project directory and syncs it in the background. Your codebase is searchable without manual ingestion. |
| Web fetch | After any WebFetch tool call | URLs Claude fetches during research are auto-ingested into the project's <name>-captures collection (or global web-captures if no project is enabled). |
| Pre-compact | Before context compaction | Captures the conversation transcript into the project's <name>-captures collection (or global session-notes if no project is enabled). |
All hooks are fail-open — failures are ignored and never block Claude Code. Each hook is individually toggleable via .punt-labs/quarry/config.md YAML frontmatter. See AGENTS.md for the full integration model.
Captures (session transcripts and auto-ingested web fetches) are redacted at write time, before anything touches disk or the <name>-captures/web-captures collection. A single write choke point scrubs, in order, secrets → filesystem paths (/Users//home/<user>/ → ~/) → emails (→ [REDACTED:email]) → the local hostname (→ [REDACTED:hostname]) → profanity. Web-fetch captures also redact the source URL's userinfo, query, and fragment so a URL like …/reset?email=…&token=… cannot leak. Redaction is idempotent and fail-closed (on any scrub error, no capture is written). Deliberately-ingested content (quarry ingest, remember) is not scrubbed — only the automatic capture paths are, since those feed the shared/pushable collections. See DES-036.
<repo> → <repo>-quarry)Redacted capture .md files live in the gitignored .punt-labs/quarry/captures/ dir with no durable home. Enable the optional shadow sync to push them to a per-project private repo <repo>-quarry instead. Opt in by uncommenting the shadow: block in .punt-labs/quarry/config.md:
shadow:
enabled: true # off by default — a network + security action
remote: "" # empty → derive <origin>-quarry from the public remote
acknowledge_unverified: false # required to push when gh cannot confirm the remote is private
Pre-create the private repo first. quarry does not create it by default (a wrong owner or an accidental public repo would leak). Create <repo>-quarry as private and let the remote derive, or run quarry captures init --create to create it via gh (which verifies visibility is private before any push).
Once enabled, the captures dir becomes a standalone nested git repo. quarry captures push — and the tail of every quarry sync — re-scrubs the staged captures with the same DES-036 scrubber, aborts the commit if any file is not clean, then commits and pushes. Auth reuses your existing git credentials; quarry stores no new secret. The push is fail-open: a network or auth failure never blocks a session.
Visibility is load-bearing. The re-scrub cannot catch every residual (IDN emails, non-/Users//home paths, a hostname from another machine), so those are backstopped only by the remote being private. quarry therefore refuses to push to a verifiably public remote, and requires acknowledge_unverified: true in .punt-labs/quarry/config.md when gh is absent and it cannot confirm the remote is private. quarry doctor reports the shadow state, and flags a required failure if the public repo already tracks capture files (which git rm --cached stops going forward, but an already-pushed capture needs a history purge — git filter-repo/BFG + force-push — coordinated with the repo owner). See DES-039.
Quarry runs as a daemon — one quarryd process per machine holds the engine (embedding model, LanceDB, pipeline, sync registry) and serves a versioned REST API under /v1. The CLI and Claude Code hooks reach it over HTTP; Claude Code's MCP tools run through the stdio quarry mcp server, which is itself a thin REST client of the daemon — it loads no engine.
HTTP /v1 (TLS, pinned CA)
CLI + hooks <---------------------------------------> quarryd
(one engine)
stdio, MCP JSON-RPC HTTP /v1
Claude Code <--------------------> quarry mcp <-----> quarryd
One resident engine means the CLI and hooks reuse the daemon's loaded model instead of a per-invocation ~200 MB reload. Remote and loopback REST connections use TLS with a self-signed, pinned CA — even on localhost.
The target is that every interface — CLI, library, and MCP — is a thin client of that one daemon over a versioned REST contract; this daemon-first model is specified in DES-031 v2 (ACCEPTED, in implementation). MCP is now a pure client: quarry mcp reaches the daemon through QuarryClient (loopback token, or a remote login's TLS + pinned CA), loading no engine of its own. The CLI and library still load the engine in-process on some local calls; those remaining local-engine paths are being removed.
Claude Code's plugin runs quarry mcp directly — no mcp-proxy in quarry's MCP path. quarry install still downloads mcp-proxy (SHA256-verified, correct platform) because it remains a supported tool for other consumers, and configures MCP clients to spawn quarry mcp.
quarry install registers quarryd as a per-user background service that starts at login and restarts on crash — launchd on macOS (label com.punt-labs.quarry) and systemd on Linux (unit quarry.service). You rarely need to touch it, but after upgrading the wheel you must restart the service so the new engine loads — a running daemon holds the old code in memory (quarry doctor reports the CLI version, not the daemon's).
macOS (launchd):
launchctl kickstart -k gui/$(id -u)/com.punt-labs.quarry # restart (use after an upgrade)
launchctl unload -w ~/Library/LaunchAgents/com.punt-labs.quarry.plist # stop
launchctl load -w ~/Library/LaunchAgents/com.punt-labs.quarry.plist # start
launchctl list com.punt-labs.quarry # status (shows PID, or "-" if stopped)
Linux (systemd, user scope):
systemctl --user restart quarry # restart (use after an upgrade)
systemctl --user disable --now quarry # stop
systemctl --user enable --now quarry # start
systemctl --user status quarry # status
quarry doctor confirms quarryd: running and ready. quarry uninstall removes the service and its unit file. To run the engine in the foreground for debugging, run quarryd directly — it blocks until you stop it.
Architecture | Z Specification | Design | Agents | Changelog
uv sync # install dependencies
make check # run all quality gates (lint, type, test)
make test # test suite only
make format # auto-format code
make docs # build LaTeX documents
make eval # retrieval-quality eval harness (MRR/success@k, dev/CI only)
Direction tracks the PR/FAQ. Current focus:
make eval harness (per-bucket MRR/success@k + a metadata-pollution diagnostic) now baselines search on quarry's own data; embedding levers (contextual embeddings, late chunking) are measured against it before adoption. See docs/eval-harness-design.md.<repo> → <repo>-quarry, above) now pushes the redacted captures off the public repo entirely.MIT
Run analytics queries on ClickHouse — explore schemas, execute SQL, fetch results
Run Claude Code as an MCP server so any agent can delegate coding tasks to it
Browser automation using accessibility snapshots instead of screenshots
Google's universal MCP server supporting PostgreSQL, MySQL, MongoDB, Redis, and 10+ databases