qry
A terminal-native, agent-first web search CLI.
Routes queries through swappable adapter binaries and always outputs JSON.
$ qry "what is the latest version of numpy" [ { "title": "NumPy 2.0 Release Notes", "url": "https://numpy.org/doc/stable/release/2.0.0-notes.html", "snippet": "NumPy 2.0.0 is the first major release since 2006..." } ]
Install
Pick your preferred package manager.
$ npm install -g @justestif/qry
$ mise use -g go:github.com/justestif/qry@latest $ mise reshim
Adapters
Adapters are separate binaries that do the actual searching. Install the ones you want.
| Adapter | Source | API Key |
|---|---|---|
qry-adapter-brave-api |
Brave Search API | Required |
qry-adapter-brave-scrape |
Brave Search (scraping) | None |
qry-adapter-ddg-scrape |
DuckDuckGo Lite (scraping) | None |
qry-adapter-exa |
Exa AI (via MCP) | None |
qry-adapter-github |
GitHub Search API | Optional |
qry-adapter-searx |
SearXNG (self-hostable) | None |
qry-adapter-stackoverflow |
Stack Exchange API | Optional |
qry-adapter-wikipedia |
Wikipedia / MediaWiki API | None |
Install an adapter the same way:
$ npm install -g @justestif/qry-adapter-ddg-scrape
$ mise use -g go:github.com/justestif/qry/adapters/ddg-scrape@latest $ mise reshim
qry — they can be written in any language
and swapped without changing core. See
adapters.md ↗
to build your own.
Configure
Create ~/.config/qry/config.toml. Config is read fresh on every invocation — no restart needed.
[defaults]
num = 10 # results to return
timeout = "5s" # per-adapter timeout
[routing]
# "first" — try adapters in order, stop at first success
# "merge" — query all concurrently, deduplicate by URL
mode = "first"
pool = ["brave-api", "ddg-scrape"]
fallback = ["brave-scrape"] # used only in "first" mode
[adapters.brave-api]
bin = "~/.local/share/mise/shims/qry-adapter-brave-api"
timeout = "5s"
[adapters.brave-api.config]
api_key = "${BRAVE_API_KEY}" # expanded from env at runtime
[adapters.ddg-scrape]
bin = "~/.local/share/mise/shims/qry-adapter-ddg-scrape"
${VAR} syntax in adapter config values — qry expands them
from the environment at runtime so secrets never live in the file.
Agent Usage
qry is designed to be composed. Output is always JSON — pipe it directly to agents or jq.
An agent skill is available for one-line install into any supported agent:
$ npx skills add justestif/qry -g -y
Browse and discover skills at skills.sh ↗.
Run qry --agent-info (or -A) to get a JSON description of the tool and your current configuration — useful for agents to orient themselves before making search calls:
$ qry --agent-info
The output includes the tool description, available flags, routing mode explanations, and each configured adapter with its binary path and availability status.
${VAR} template strings rather than resolved values,
so secrets are never exposed to agents.
Routing modes
Tries adapters in order, returns on first success. Fast — typically only one adapter is invoked per query. Good for most use cases.
Queries all adapters concurrently, deduplicates results by URL. Broader coverage. Partial failure is not an error — results from successful adapters are returned with warnings.
Reference
Full documentation lives on GitHub.