sqry is a semantic code search tool. It parses source code into an AST and builds a graph of symbols and relationships, so you can search by what code means rather than just what it says.
Website: https://sqry.dev
# Index a codebase (creates .sqry/graph/snapshot.sqry)
sqry index
# Find all public async functions
sqry query "kind:function AND async:true AND visibility:public"
# Who calls this function?
sqry query "callers:authenticate"
# Trace a path between two symbols
sqry graph trace-path main handle_request
# Find circular dependencies
sqry cycles
# Ask in plain English (translates to sqry syntax, then searches)
sqry ask "find all error handling functions"If you just need text search, use ripgrep - it's faster and simpler for that job.
sqry is useful when you need to search by code structure: finding all callers of a function, tracing execution paths, detecting cycles, or querying by symbol kind, visibility, or return type. These are things text search can't do reliably.
- Relation queries:
callers:X,callees:X,imports:X,returns:Result- exact answers from the call graph - Graph analysis: trace paths between symbols, find cycles, detect unused code
- Structured queries: combine predicates with boolean logic (
kind:function AND lang:rust AND async:true) - Cross-language detection: FFI linking (Rust<>C/C++), HTTP route matching (JS/TS<>Python/Java/Go)
- AI assistant integration: MCP server with 36 tools, LSP server for editors
- Simple text search: Use ripgrep. It's faster for grep-style patterns.
- Pattern matching on syntax: Use ast-grep. It's better for "find this syntax pattern and replace it."
- Linting or rule enforcement: Use language-specific linters (clippy, eslint, semgrep).
- Full IDE features: Use your editor's built-in language server.
- Hosted code search: Use Sourcegraph if you need a web UI and team features.
sqry is focused on one thing: local semantic code search via AST analysis.
- Accurate unused-code analysis across binding boundaries:
sqry unused, LSP analysis, and MCPfind_unusednow gather a full candidate superset before CLI/MCP/LSP filters run, then apply the binding-plane post-filter at the boundary. This prevents visibility, kind, and scope filters from hiding symbols that should still be considered during reachability. - Binding-plane resolution is first-class: V9 snapshots derive scope, alias, shadow, import, and export tables from the graph, and
sqry graph resolve <symbol> --explain --jsonexposes witness-bearing resolution for debugging name lookup. - Derived Analysis DB is the shared query path: cycle, unused, reachability, entry-point, trace, dependency, subgraph, export, semantic-diff, CLI, and MCP analysis paths now share
sqry-dbquery implementations with sharded derived-result caches. - Incremental graph persistence moved to V10: snapshots now persist the file-segment table used for append-only node allocation and safe per-file reindexing. After upgrading from a pre-V10 release, run
sqry index --forceonce so the graph is rebuilt with V10 metadata. - Daemon-backed workflows are production surfaces:
sqrydkeeps graphs hot across CLI, MCP, and LSP sessions;sqry daemon load,sqry daemon rebuild,sqry daemon status, andsqry daemon logsare available, andsqry-mcp --daemon/sqry lsp --daemoncan auto-start the daemon. - Workspace-aware multi-repo indexing remains opt-in and explicit: define a
.sqry-workspaceregistry or a VS Code.code-workspacesqry.workspaceblock when you want multiple source roots queried as one logical workspace. - Public release artifacts are signed and complete: v13.0.3 publishes crates, Linux/macOS/Windows binaries for
sqry,sqry-mcp,sqry-lsp, andsqryd, checksums, attestations, and the VS Code.vsixrelease asset from the publicrelease-distribute.ymlworkflow.
Invoke-WebRequest https://raw.githubusercontent.com/verivus-oss/sqry/main/scripts/install.ps1 -OutFile install.ps1
Get-Content .\install.ps1
.\install.ps1 -Component all -VerifySignaturesThis installs sqry.exe, sqry-mcp.exe, sqry-lsp.exe, and sqryd.exe into %LOCALAPPDATA%\Programs\sqry\bin and adds that directory to the user PATH. -Component all (the default) installs all four binaries from the Windows release ZIP.
By default the installer resolves the latest GitHub release; use .\install.ps1 -Version vX.Y.Z to pin a specific release tag.
-VerifySignatures uses Cosign to verify that the downloaded release zip was produced by the official release-distribute.yml GitHub Actions workflow for this repository. Older releases signed by oss-distribute.yml remain accepted for legacy compatibility. Install cosign and ensure it is on PATH before using this mode. SHA256 verification remains enabled by default and protects against download corruption; use -NoChecksum only for diagnostics.
Note: Windows Defender and enterprise EDR products commonly flag the
irm ... | iexpattern heuristically, even when the installer script is benign. If you are on a managed machine, use the download-review-run path above or install from release assets/package-manager manifests instead of piping the script directly intoiex.If PowerShell execution policy blocks
.\install.ps1after download, prefer release assets or package-manager manifests rather than weakening machine-wide policy settings.
Convenience shortcut for personal or non-managed machines (installs all four binaries):
$script = irm https://raw.githubusercontent.com/verivus-oss/sqry/main/scripts/install.ps1
& ([scriptblock]::Create($script)) -Component allPinned-release example:
.\install.ps1 -Component all -Version v13.0.3 -VerifySignaturesManual fallback:
- download the Windows ZIP release asset (
sqry-<version>-windows-x86_64.zip) - extract all contents, including the bundled
.dllruntime files - place them in a directory on
PATH
curl -fsSL https://raw.githubusercontent.com/verivus-oss/sqry/main/scripts/install.sh | bash -s -- --component allInstalls sqry, sqry-mcp, sqry-lsp, and sqryd into ~/.local/bin (override with --install-dir).
Downloads individual binaries directly from GitHub releases with per-asset SHA256 checksum
verification against SHA256SUMS.txt. Add --verify-signatures to enforce Cosign bundle
verification (requires cosign). Published binaries are available for Linux x86_64/arm64,
Windows x86_64, and macOS Apple Silicon/Intel.
Options: --component sqry|sqry-mcp|sqry-lsp|sqryd|all, --version vX.Y.Z, --install-dir DIR,
--repo OWNER/REPO, --no-checksum.
git clone https://github.com/verivus-oss/sqry.git
cd sqry
cargo install --path sqry-cli
cargo install --path sqry-mcp
cargo install --path sqry-lsp
cargo install --path sqry-daemon # installs sqryd
sqry --version
sqryd --versionRequirements: Rust 1.90+ (Edition 2024). About 20 GB disk for a full build (37 tree-sitter grammars are compiled from source).
Release packaging configs are generated from signed release checksums for:
- Homebrew (published to the sqry tap and included as a release formula asset)
- Scoop
- Winget
- AUR
- Nix
- Snap
Look for these files in release assets (homebrew-sqry.rb, scoop-sqry.json, winget-*.yaml, aur-PKGBUILD, nix-*.nix, snap-snapcraft.yaml).
Primary install methods provide sqry, sqry-mcp, sqry-lsp, and sqryd. The shell installer and the Windows ZIP both support sqryd as a component. Raw binaries and .bundle files are advanced/manual verification assets.
# Default fast-path index
sqry index
# Include all high-cost plugins
sqry index --include-high-cost
# Force the fast path even if SQRY_INCLUDE_HIGH_COST=1 is set
sqry index --exclude-high-cost
# Include one high-cost plugin explicitly
sqry index --enable-plugin json
# Exclude a plugin explicitly
sqry index --disable-plugin jsonsqry persists the active plugin set in the unified graph manifest, so later
query, watch, diff, and graph-loader paths reuse the indexed semantics
instead of silently reinterpreting the workspace under current defaults.
Currently, the default fast path excludes these high-cost plugins:
jsonservicenow-xml
The same plugin-selection flags also apply to sqry update and sqry watch.
--enable-language and --disable-language remain accepted compatibility
aliases for --enable-plugin and --disable-plugin.
The CLI flags above also have environment-variable equivalents, useful for CI
pipelines and shell sessions where you want a stable default without retyping
flags on every sqry invocation. Per-invocation CLI flags always win over
environment defaults.
SQRY_INCLUDE_HIGH_COST=1— include everyHighWallClockplugin in the default fast path. Equivalent to passing--include-high-cost. Example:SQRY_INCLUDE_HIGH_COST=1 sqry index.SQRY_EXCLUDE_HIGH_COST=1— force the fast path even whenSQRY_INCLUDE_HIGH_COST=1is set elsewhere. Equivalent to--exclude-high-costand useful for overriding a CI-wide default in a single job. Example:SQRY_EXCLUDE_HIGH_COST=1 sqry index.SQRY_ENABLE_PLUGINS=json,servicenow-xml— comma-separated list of plugin IDs to opt back into the fast path one at a time. Equivalent to repeating--enable-plugin <id>. Example:SQRY_ENABLE_PLUGINS=json sqry index.SQRY_DISABLE_PLUGINS=json,servicenow-xml— comma-separated list of plugin IDs to drop from the active set even when they would otherwise be on. Equivalent to repeating--disable-plugin <id>. Example:SQRY_DISABLE_PLUGINS=servicenow-xml sqry index.
When sqry's in-format graph semantics change between releases (for example
the v10.0.x Cluster C field-edge source migration that re-sources Go
struct-field TypeOf{Field} edges from the new NodeKind::Property
nodes), an existing .sqry/graph/snapshot.sqry keeps loading but returns
the legacy graph shape until rebuilt. Run sqry index --force once after
upgrading across such releases. The release notes for any version that
needs the rebuild call this out explicitly.
# Index with macro boundary analysis
sqry index --enable-macro-expansion
# Include cfg-gated items
sqry index --enable-macro-expansion --cfg 'feature="serde"'
# Search with macro filters
sqry search "Handler" --cfg-filter 'feature="serde"' --include-generated
sqry search "process_" --macro-boundaries# Index with automatic wrapper/tool resolution (Gradle: gradlew -> gradle, Maven: mvnw -> mvn)
sqry index --classpath
# Shallow resolution (direct dependencies only)
sqry index --classpath --classpath-depth shallow
# Use a specific classpath file
sqry index --classpath-file classpath.txt
# Restrict discovery to a specific JVM build system in a larger monorepo
sqry index --classpath --build-system gradle- Missing JVM tooling with no cache is treated as an error, not a successful empty external graph.
- Nested JVM build roots are discovered from the repo root, and workspace import edges are scoped to the nearest containing module/root.
# On-the-fly search (no index needed, slower)
sqry search "kind:function" src/
# Indexed query (fast, requires sqry index first)
sqry query "kind:class OR kind:struct"
sqry query "kind:function AND visibility:public AND callers:helper"
# Fuzzy search (typo-tolerant)
sqry --fuzzy "patern" .
# Hierarchical search (results grouped by file, useful for RAG)
sqry hier "kind:function visibility:public"sqry query (and sqry plan-query) accepts a whitespace-separated chain
of steps. Each step narrows the result set; the chain must start with a
context-free step (kind: or name:) and may continue with any number of
filter / relation / traversal steps.
| Step | Example | Meaning |
|---|---|---|
kind:<NodeKind> |
kind:function |
Restrict to nodes of the given AST kind (function, method, class, struct, enum, interface, trait, module, variable, constant, type, property, …). |
name:<value> |
name:NeedTags |
Literal value is an exact byte-for-byte match against the interned simple or qualified name of the node (case-sensitive). Glob meta in the value (*, ?, [) promotes the pattern to a glob match (e.g. name:parse_* matches parse_expr, parse_stmt). Either way, synthetic placeholder nodes are excluded and there is no implicit substring or regex form. See "name: contract" below. |
visibility:<v> |
visibility:public |
public or private. |
has:caller / has:callee |
kind:function has:caller |
Existence checks over the call graph. |
unused |
kind:function unused |
Nodes with no inbound use edges. |
in:<glob> |
in:src/api/**/*.rs |
Filter by file-path glob. |
scope:<kind> |
scope:module |
Restrict to a binding-plane scope kind (module, function, class, namespace, trait, impl). |
returns:<TypeName> |
returns:Result |
Functions whose TypeOf{Return} edge targets a node whose interned name equals TypeName (exact, no glob). |
callers:<value> / callees:<value> |
callees:visit_* |
Relation predicates; value can be a bare word, a glob, a quoted string, or a sub-query in parentheses. |
imports:<value> / exports:<value> |
imports:serde |
Module-graph relation predicates. |
implements:<value> (alias impl:<value>) |
kind:class implements:Visitor |
OO interface/trait conformance. |
references:<value> / references ~= /regex/ |
references ~= /handle_.*/i |
Literal value or regex form (with i/m/s flags). |
traverse:<dir>(<edge>,<depth>) |
kind:function traverse:forward(calls,3) |
Walk <edge> for up to <depth> hops in forward / reverse / both direction. |
Name and qualified-name format. Node names follow per-language conventions:
- Simple name (
entry.name) — typically the local identifier (e.g.NeedTags,parseConfig). - Qualified name (
entry.qualified_name) — language-canonical fully-qualified form. For Go:<package>.<TypeName>.<FieldName>(e.g.main.SelectorSource.NeedTags); for Rust:<crate>::<module>::<symbol>; for Java/Kotlin/Scala:<package>.<Class>.<member>.name:<X>matches both fields in parallel — it returns a node whose simple name or qualified name equalsX.
name: contract (B1_ALIGN, locked). For literal values (no
*, ?, or [ in the pattern), the planner's name:<literal> step
and the top-level CLI shorthand sqry --exact <literal> are
contract-bound to return identical sets against any fixture:
sqry query 'name:NeedTags' . # planner exact-name lookup (literal)
sqry --exact NeedTags . # CLI exact-name shorthandBoth:
- Look up the literal in the snapshot string interner.
- Walk the by-name and by-qualified-name indices for that interned id.
- Drop synthetic placeholder nodes (Go-plugin
<field:operand.field>shadows;<ident>@<offset>per-binding-site Variables; any future nodes flaggedNodeMetadata::Synthetic). - Return the deduplicated
NodeIdset.
For values containing glob meta (*, ?, [), the planner's name:
step promotes to a glob match (still synthetic-filtered); the
top-level CLI --exact does not accept glob meta and treats every
character as a literal. Use sqry query 'name:parse_*' for glob
matching against names; the exact-set-equality contract above does
not apply when the value contains glob meta.
Surface precedence and synthetic visibility.
| Surface | Match mode | Synthetic placeholders |
|---|---|---|
sqry --exact <literal> (top-level) |
Exact byte-for-byte match (literal only; glob meta is treated as literal characters). | Filtered out. |
sqry search <pat> (no flag, default) |
Regex match against interned simple and qualified names. Invalid regex returns an error; there is no implicit substring fallback. | Not filtered — the regex surface is a literal scan over interned strings. |
sqry query 'name:<value>' (planner) |
Exact byte-for-byte match for literal values; glob match when the value contains */?/[. |
Filtered out (both literal and glob paths). |
sqry query 'name~/<regex>/' |
Reserved for a future regex variant (mirrors the existing references ~= /…/ split). Not yet implemented; users wanting regex name matching today should use sqry search <regex> or references ~= /…/ for incoming references. |
n/a |
Only the structured name:<literal> prefix and the top-level
--exact <literal> shorthand are bound to the exact-set-equality
contract — every other surface in the table has its own match mode and
synthetic-visibility policy as listed.
sqry query "callers:process_data" # Who calls this?
sqry query "callees:main" # What does this call?
sqry query "imports:utils" # Who imports this?
sqry query "returns:Result" # Functions returning Result
sqry graph direct-callers parse_config # Direct callers
sqry graph direct-callees main # Direct callees
sqry graph call-hierarchy parse_config --depth 3sqry graph trace-path main handle_error # Execution path between symbols
sqry graph dependency-tree module # Transitive dependencies
sqry graph cross-language # Cross-language relationships
sqry cycles # Circular dependencies
sqry duplicates # Duplicate code
sqry unused # Dead code detection
sqry impact parse_config # Dependency impact analysis
sqry graph complexity # Complexity metrics
sqry diff HEAD~1 HEAD # Semantic diff between git refsFor very large C++ codebases, pathological single-file graph builds are now bounded so one oversized translation unit does not pin the entire index run indefinitely.
sqry impact and sqry explain (and the MCP dependency_impact tool)
resolve a bare symbol name against the graph's by-name index. When a
bare name matches more than one indexable node — for example NeedTags
matches both the Go Property node main.SelectorSource.NeedTags and
a local variable of the same name — the command returns a typed
AmbiguousSymbol envelope under the stable error code
sqry::ambiguous_symbol:
{
"error": {
"code": "sqry::ambiguous_symbol",
"message": "Symbol 'NeedTags' is ambiguous; specify the qualified name",
"candidates": [
{
"qualified_name": "main.SelectorSource.NeedTags",
"kind": "property",
"file_path": "main.go",
"start_line": 12,
"start_column": 4
},
{
"qualified_name": "main.useSelector.NeedTags",
"kind": "variable",
"file_path": "main.go",
"start_line": 30,
"start_column": 6
}
],
"truncated": false
}
}Pass the qualified name (sqry impact main.SelectorSource.NeedTags) to
disambiguate. The candidate list is capped at 20 entries with
truncated: true set when the underlying set is larger.
MCP redaction policy (minimal preset, default). When the same
AmbiguousSymbol envelope is delivered through the MCP transport
(e.g. via dependency_impact), the sqry-mcp-redaction layer
rewrites every per-candidate file_path to a workspace-relative form
under the default minimal preset, so the absolute repository path
(home directory, machine layout, etc.) is never exposed. The redacted
MCP envelope still surfaces qualified_name, kind, start_line,
and start_column per candidate so AI-assistant consumers can
disambiguate. No source excerpt, snippet, or code-context field is
introduced into the envelope. The CLI envelope is unredacted (CLI
users have direct filesystem access already); only the MCP boundary
applies the redaction. For stricter envelopes (filename hashing, no
position info), set SQRY_REDACTION_PRESET=strict.
sqry ask "What functions handle error recovery?"
sqry ask "Find all public structs" --auto-executesqry export --format dot # Graphviz DOT
sqry export --format mermaid # Mermaid
sqry export --format d2 # D2 diagrams
sqry export --format json # JSON
sqry visualize "callers:main" --format mermaidSee docs/user-guide/visualization.md for examples.
sqry --preview main # Text with context (default 3 lines)
sqry --json --preview 5 "pattern" # JSON with context
sqry --csv --headers --columns name,file,line pattern > results.csvCSV/TSV output escapes per RFC 4180 and prefixes formula-leading characters unless --raw-csv is set.
sqry cache stats # View cache statistics
sqry cache prune --days 30 # Remove old entries
sqry cache prune --size 1GB # Cap cache size
sqry cache clear --confirm # Clear all cached ASTs
sqry cache expand # Generate/refresh macro expansion cache (Rust)
sqry cache expand --dry-run # Preview without writingsqry shell # Interactive REPL
sqry batch commands.txt # Batch processing
sqry watch --build # Watch mode (auto-update index)
sqry repair --dry-run # Check for index corruption
sqry --list-languages # List supported languages
sqry completions bash # Shell completions| Task | Command | Needs Index? |
|---|---|---|
| Quick exploration | sqry search |
No |
| Find callers/callees | sqry query |
Yes |
| Trace execution paths | sqry graph trace-path |
Yes |
| Compare semantic changes across refs | sqry diff |
Yes |
| Find cycles | sqry cycles |
Yes |
| Export diagrams | sqry export |
Yes |
sqry search parses files on demand - useful for one-off queries. sqry query and sqry graph use a prebuilt index and are much faster for repeated use.
For monorepos or saved VS Code workspaces that contain several source roots, sqry can treat the folders as one logical workspace while preserving per-root index status.
sqry workspace init /projects --name "My Workspace"
sqry workspace scan /projects --mode git-roots
sqry workspace add /projects /projects/backend --name backend
sqry workspace query /projects "kind:function AND repo:backend"
sqry workspace stats /projects
sqry workspace status /projects --json --no-cacheDiscovery modes:
index-files(default): find existing.sqry/graph/indexes under the root.git-roots: find repositories by.git/directories.
Use sqry workspace status to see each source root as ok, building,
missing, or error plus the aggregate workspace verdict. VS Code and the LSP
use the same aggregate status surface, so a healthy multi-root workspace should
show indexed roots in the sqry pane instead of a false "not indexed" state.
See docs/cli/workspace.md for .sqry-workspace and
.code-workspace configuration.
sqry supports 37 languages through tree-sitter-based plugins. 28 of these have full relation extraction (calls, imports, exports); the remaining 9 have symbol extraction with basic import tracking.
Full relation support (28): C, C++, C#, CSS, Dart, Elixir, Go, Groovy, Haskell, HTML, Java, JavaScript, Kotlin, Lua, Perl, PHP, Python, R, Ruby, Rust, Scala, Shell, SQL, Svelte, Swift, TypeScript, Vue, Zig
Symbol extraction + imports (9): JSON, Oracle PL/SQL, Pulumi, Puppet, Salesforce Apex, SAP ABAP, ServiceNow Xanadu, ServiceNow XML, Terraform
Each language plugin lives in its own crate (sqry-lang-*) and implements the GraphBuilder trait. See CONTRIBUTING.md for how to add a new language.
sqry includes an MCP server with 36 JSON-RPC tools for AI assistants (Claude, Codex, Gemini, Cursor, Windsurf):
# Start MCP server (stdio transport)
sqry-mcp
# Auto-configure for your AI assistant
sqry mcp setup
# Or add to ~/.claude.json manually:
# "mcpServers": { "sqry": { "command": "sqry-mcp", "args": [] } }The MCP server gives AI assistants structured access to the code graph - exact caller/callee lists, path tracing, cycle detection, etc. - rather than relying on text search or embedding similarity.
See sqry-mcp/README.md for setup details and tool documentation. For sensitive repositories, use sqry-mcp-redaction to sanitize MCP responses before sending data to external LLMs.
sqry lsp --stdio # Start LSP server (stdio mode)Supports hover, definition, references, call hierarchy, document/workspace symbols, code actions, and 29 custom sqry methods. Works with VS Code, Neovim, Helix, and any LSP 3.17 client. Socket mode available for shared instances.
See sqry-lsp/ for configuration details.
The VS Code extension provides in-editor semantic queries, a "Semantic Results" panel, and CodeLens caller count annotations. Multi-root workspaces are supported with per-folder index status and tree data, and cross-repo analysis is opt-in per workspace rather than enabled by default — add a sqry.workspace block inside a saved .code-workspace file (or commit a .sqry-workspace registry under any of your workspace folders) to define sourceRoots, memberFolders, exclusions, and projectRootMode. When a .code-workspace is open, the extension parses it and forwards a lightweight { folders, classification } hint plus the workspace-file path under initializationOptions.sqry to sqry lsp. sqry lsp then runs its canonical LogicalWorkspace resolver in this fixed order (see sqry-lsp::session::resolve_logical_workspace): (1) a hand-crafted LogicalWorkspace from initializationOptions.sqry.workspace (the extension's lightweight hint is detected and skipped), (2) --index-root <path>/.sqry-workspace, (3) <workspace_folder>/.sqry-workspace walked across every workspace folder, (4) the .code-workspace JSON loaded via from_code_workspace using initializationOptions.sqry.workspaceFile, and (5) anonymous multi-root from the workspace folders as a last resort. The extension also contributes four settings — sqry.indexRoot, sqry.projectRootMode, sqry.workspaceFolderExcludes, sqry.workspaceClassification — that govern extension-side runtime behaviour: excludes filter every enumeration loop, and sqry.workspaceClassification is the user-editable surface for the inline sqry.workspace block. See docs/cli/workspace.md for the full configuration surface, including the CLI parity flag (--workspace <PATH> / SQRY_WORKSPACE_FILE). Source is in sqry-vscode/.
cd sqry-vscode && npm install && npm run compile
# Launch via F5 in VS Codesqry stores configuration in .sqry/graph/config/config.json, created automatically with sensible defaults on first use.
# View configuration
sqry config show
# Common environment variable overrides
export SQRY_CACHE_ROOT=/mnt/ssd/.sqry-cache # Custom cache location
export SQRY_CACHE_MAX_BYTES=524288000 # 500 MB cache limit
export SQRY_CACHE_DISABLE_PERSIST=1 # Memory-only cachingSee docs/PERFORMANCE_TUNING.md for all tuning options and CONFIGURATION_TUNING_GUIDE.md for the full reference.
sqry index . --no-incremental # Force full rebuild
sqry index --validate=fail # Strict validation (exit 2 on corruption)
sqry update --validate=fail --auto-rebuild # Auto-rebuild on corruptionExclude files from indexing using gitignore syntax:
echo "node_modules/" >> .sqryignore
echo "target/" >> .sqryignore
sqry indexsqry also skips common dependency, generated, build-output, editor-cache, and
CI-runner roots by default: .git, .hg, .svn, .cache, .next, .nuxt,
.sqry, .turbo, .venv, __pycache__, _actions, _update, _work,
build, dist, node_modules, target, vendor, venv, and directories
whose names start with externals.. This keeps editor-triggered indexing from
walking third-party or generated trees when ignore files are absent. If a
repository intentionally stores first-party code in those directories, run with
SQRY_INCLUDE_DEFAULT_EXCLUDED_DIRS=1.
sqryd is a background daemon that keeps your code graph in memory across multiple CLI, LSP, and MCP invocations. Instead of parsing and indexing from scratch on every sqry query or AI assistant request, sqryd keeps the graph hot and rebuilds it incrementally when source files change.
# Start the daemon (background process, keeps graph in memory)
sqry daemon start
sqry daemon load /path/to/project
# Check status — shows version, uptime, memory, workspaces
sqry daemon status
# Rebuild a loaded workspace in place
sqry daemon rebuild /path/to/project --timeout 1800
# Stop the daemon
sqry daemon stop
# Tail the daemon log (requires log_file set via daemon.toml or SQRY_DAEMON_LOG_FILE)
sqry daemon logs --followExample sqry daemon status output:
sqryd v13.0.3 -- uptime 2h 14m
Memory: 391 MB / 2048 MB (peak: 418 MB)
Workspaces (2 loaded):
~/projects/sqry 304 MB (peak: 318 MB) [Loaded]
~/projects/myapp 87 MB (peak: 91 MB) [Loaded]
The peak value per workspace shows the high-water mark: the maximum resident memory since that workspace was loaded or last evicted. It persists across incremental rebuilds but resets when the workspace is unloaded or evicted. The aggregate Memory peak shows the highest total across all workspaces. A peak close to the memory limit signals you are near the LRU eviction threshold.
Pass --daemon to sqry-mcp or sqry lsp to route all tool calls through the running daemon instead of loading the graph in-process:
sqry-mcp --daemon # connect to default socket
sqry-mcp --daemon --daemon-socket /tmp/sqryd.sock # custom socket path
sqry lsp --daemon # LSP backed by daemonIf no daemon is running when --daemon is specified, sqry-mcp and sqry lsp will auto-start one. Binary resolution order: SQRYD_PATH env var, then a sqryd sibling next to the running binary, then sqryd on PATH.
The daemon reads ~/.config/sqry/daemon.toml at startup (XDG; on macOS: ~/Library/Application Support/sqry/daemon.toml). Key fields:
memory_limit_mb = 2048 # evict LRU workspaces above this threshold (MB)
idle_timeout_minutes = 30 # unload workspace after N minutes of inactivity
log_max_size_mb = 50 # rotate log file at this size (MB)
log_keep_rotations = 5 # number of rotated log files to retain
[socket]
path = "" # Unix socket path (default: $XDG_RUNTIME_DIR/sqry/sqryd.sock,
# fallback: $TMPDIR/sqry-<uid>/sqryd.sock, then /tmp/sqry-<uid>/sqryd.sock)
pipe_name = "" # Windows named pipe name (default: sqry → \\.\pipe\sqry)Selected environment-variable overrides:
SQRY_DAEMON_MEMORY_MB— overridememory_limit_mbSQRY_DAEMON_SOCKET— overridesocket.pathSQRY_DAEMON_LOG_LEVEL— override log level (info,debug,warn,error)
A daemon restart is required for any configuration change to take effect, whether editing daemon.toml or changing environment variables.
See docs/cli/daemon.md for the full CLI reference, all flags, exit codes, and tuning guidance.
sqry builds a code graph in 5 passes:
- AST parsing - tree-sitter parses source files into syntax trees
- Symbol extraction - nodes (functions, classes, etc.) and structural edges (defines, contains)
- Enrichment - visibility, types, async markers
- Intra-file edges - calls, references within each file
- Cross-file edges - import resolution, FFI linking, HTTP route matching
The resulting graph is persisted to .sqry/graph/snapshot.sqry and loaded for queries. Graph queries use precomputed analyses (SCCs, condensation DAGs, 2-hop labels) for fast cycle detection, path finding, and reachability.
sqry uses arena-based storage with CSR (Compressed Sparse Row) adjacency for cache-friendly O(1) traversal, generational indices for safety, MVCC for concurrent reads, and string interning to reduce memory. Parallelism uses rayon; locks use parking_lot.
The binding plane is a first-class derived layer (Phase 4e, V9 snapshot) that computes scope/alias/shadow tables from the structural edges emitted by language plugins, then exposes witness-bearing resolution via BindingPlane<'g>. The sqry graph resolve <symbol> [--explain] command is the CLI proof point for this layer.
These numbers are from sqry's own codebase (~384K nodes, ~1.3M edges). Your results will vary depending on codebase size, language mix, and hardware.
- Indexed queries: ~4ms with warm cache (vs ~452ms cold)
- Cycle check: <1s (precomputed SCC lookup)
- Path finding: <1s typical (condensation DAG pruning)
- Indexing throughput: varies by language (JavaScript ~760K LOC/s, C++ ~1.1M LOC/s, Python ~500K LOC/s on the test machine)
sqry/
├── sqry-core/ # Core library (graph, symbols, search, plugin system)
├── sqry-cli/ # CLI binary ('sqry')
├── sqry-lsp/ # LSP server
├── sqry-mcp/ # MCP server (36 tools for AI assistants)
├── sqry-daemon/ # Daemon binary + library (sqryd)
├── sqry-daemon-protocol/ # Wire types and framing (free functions, envelope types)
├── sqry-daemon-client/ # Client library (shim mode, management API)
├── sqry-db/ # Derived analysis DB + query planner (Phase 3)
├── sqry-classpath/ # JVM classpath analysis (bytecode, Gradle/Maven/Bazel/sbt)
├── sqry-nl/ # Natural language query translation
├── sqry-plugin-registry/ # Plugin registration
├── sqry-mcp-redaction/ # MCP response redaction
├── sqry-lang-*/ # 37 language plugins
├── sqry-lang-support/ # Plugin infrastructure
├── sqry-tree-sitter-support/ # Tree-sitter helpers
├── sqry-test-support/ # Test infrastructure
└── crates/tree-sitter-* # Vendored tree-sitter grammars
| Feature | sqry | ripgrep | ast-grep | Sourcegraph |
|---|---|---|---|---|
| Text search | Yes (with fallback) | Yes | No | Yes |
| AST awareness | Yes | No | Yes | Yes |
| Relation queries | Yes (28 langs) | No | No | Yes |
| Local/offline | Yes | Yes | Yes | No |
| MCP server | Yes (36 tools) | No | No | No |
| LSP server | Yes | No | No | Yes |
| Cost | Free (MIT) | Free | Free | Paid |
This is a rough comparison; each tool has different strengths. ripgrep is faster than sqry for plain text search. ast-grep is better for syntax pattern matching. Sourcegraph offers team features sqry doesn't. sqry's strength is local graph-based queries (callers, cycles, paths).
We welcome contributions of all sizes - from typo fixes to new language plugins. See CONTRIBUTING.md for guidelines.
cargo build --workspace # Build
cargo test --workspace # Tests
cargo fmt --all # Format
cargo clippy --all-targets --workspace -- -D warnings # Lint- Quick Start Guide - Get started in 5 minutes
- Usage Examples - Real-world examples
- Feature List - Complete feature reference
- Schema Reference - Query syntax and metadata keys
- Performance Tuning - Optimization guide
- CLI Documentation - Full CLI reference
- Daemon CLI Reference -
sqry daemonsubcommands, flags, exit codes, and memory tuning - MCP Server - AI assistant integration
- Troubleshooting - Common issues and solutions
sqry depends on excellent open-source projects:
- tree-sitter - Incremental parsing (and the many grammar maintainers)
- ripgrep - Text search engine (used as a library for fallback search)
- rayon - Data parallelism
- serde - Serialization
- clap - CLI argument parsing
- tokio - Async runtime (LSP/MCP servers)
MIT - see LICENSE
Developed by Verivus