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..."
}
]npm (recommended):
npm install -g @justestif/qrymise:
mise cache clear
mise use -g go:github.com/justestif/qry@latest
mise reshimAdapters are separate binaries that do the actual searching. Install the ones you want:
| Adapter | Source | Key required |
|---|---|---|
qry-adapter-brave-api |
Brave Search API | ✓ |
qry-adapter-brave-scrape |
Brave Search (scraping) | ✗ |
qry-adapter-ddg-scrape |
DuckDuckGo Lite (scraping) | ✗ |
qry-adapter-exa |
Exa AI (via MCP) | ✗ |
qry-adapter-github |
GitHub Search API | ✗ (optional) |
qry-adapter-searx |
SearXNG (self-hostable) | ✗ |
qry-adapter-stackoverflow |
Stack Exchange API | ✗ (optional) |
qry-adapter-wikipedia |
Wikipedia / MediaWiki API | ✗ |
npm:
npm install -g @justestif/qry-adapter-ddg-scrapemise:
mise use -g go:github.com/justestif/qry/adapters/qry-adapter-ddg-scrape@latest
mise reshimCreate ~/.config/qry/config.toml:
Use ${VAR} syntax in adapter config values — qry expands them from the environment
at runtime so secrets never live in the file:
[adapters.brave-api.config]
api_key = "${BRAVE_API_KEY}"[defaults]
num = 10
timeout = "5s"
[routing]
mode = "first"
pool = ["ddg-scrape"]
fallback = ["brave-scrape"]
[adapters.ddg-scrape]
bin = "~/.local/share/mise/shims/qry-adapter-ddg-scrape"
[adapters.brave-scrape]
bin = "~/.local/share/mise/shims/qry-adapter-brave-scrape"An agent skill is available for one-line install into any supported agent:
npx skills add justestif/qry -g -yBrowse 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-infoThe output includes the tool description, available flags, routing mode explanations,
and each configured adapter with its binary path and availability status. Adapter config
maps show ${VAR} template strings rather than resolved values, so secrets are never exposed.
first— tries adapters in order, returns on first success. Fast, good for most use cases.merge— queries all adapters concurrently, deduplicates by URL, returns combined results.
See docs/ for full documentation:
docs/architecture.md— how qry works internallydocs/schema.md— config and JSON schemasdocs/adapters.md— how to build your own adapter