Search CLI
One binary, 11 providers, 14 modes. The web search tool your AI agent is missing.
A single Rust binary that aggregates Brave, Serper, Exa, Jina, Firecrawl, Tavily, SerpApi, Perplexity, xAI, and more into one unified search interface. Designed from day one for AI agents -- structured JSON output, semantic exit codes, auto-JSON when piped, and parallel fan-out across providers in under 2 seconds.
Install | How It Works | Features | Providers | Contributing
Why This Exists
Every search API is good at something different. Brave has its own 35-billion page index. Serper gives you raw Google results plus Scholar, Patents, and Places. Exa does neural/semantic search. Perplexity gives AI-synthesized answers with citations. Jina reads any URL into clean markdown. Firecrawl renders JavaScript-heavy pages. xAI searches X/Twitter.
You shouldn't have to wire up each one separately, handle their different response formats, manage rate limits, or figure out which provider to use for which query type. search does all of that for you -- routes your query to the right combination automatically, fans out in parallel, deduplicates results, and gives you a single clean response.
That's it — a plain search "query" runs a general multi-provider web search and merges the results in under 2 seconds. You stay in control of routing: pick a mode with -m or specific providers with -p (run search agent-info for the full map). The CLI never guesses intent from your query.
Install
Cargo (recommended):
Homebrew:
One-liner (macOS / Linux):
|
From source:
Binary size is ~6 MB. Startup is ~2 ms. Memory is ~5 MB. No Python, no Node, no Docker.
Quick Start
# Set your API keys (any combination works -- even just one)
# Or use environment variables
# Search
How It Works
┌─────────────┐
│ Your Query │
└──────┬──────┘
│
┌──────▼──────┐
│ Classify │ regex-based intent detection
└──────┬──────┘
│
┌────────────┼────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Brave │ │ Serper │ │ Exa │ parallel fan-out
└────┬─────┘ └────┬─────┘ └────┬─────┘ via tokio::JoinSet
│ │ │
└────────────┼────────────┘
│
┌──────▼──────┐
│ Dedup & │ URL normalization
│ Merge │ across providers
└──────┬──────┘
│
┌───────────┴───────────┐
▼ ▼
┌────────────┐ ┌────────────┐
│ JSON │ │ Table │
│ (piped) │ │ (terminal) │
└────────────┘ └────────────┘
- Parse -- Clap parses your query, mode, provider filter, and output preferences
- Classify -- If mode is
auto, regex-based intent classifier picks the right mode - Route -- Mode determines which providers to query (or you override with
-p) - Fan out --
tokio::JoinSetfires all providers in parallel with per-provider timeouts - Collect -- Results stream in as providers respond (no waiting for the slowest)
- Dedup -- URL normalization removes duplicates across providers
- Render -- JSON envelope when piped, colored terminal table when interactive
Features
14 Search Modes
Pick a mode explicitly with -m (default is general):
| Mode | What it does | Providers used |
|---|---|---|
general |
Broad web search (default) | Brave + Serper + Exa + Jina + Tavily + Perplexity |
news |
Breaking news, current events | Brave News + Serper News + Tavily + Perplexity |
academic |
Research papers, studies | Exa + Serper + Tavily + Perplexity |
people |
LinkedIn profiles, bios | Exa |
deep |
Maximum coverage | Brave (LLM Context) + Exa + Serper + Tavily + Perplexity + xAI |
scholar |
Google Scholar | Serper + SerpApi |
patents |
Patent search | Serper |
images |
Image search | Serper |
places |
Local businesses, maps | Serper |
extract |
Full text from a URL | Stealth -> Jina -> Firecrawl -> Browserless |
scrape |
Page scraping | Stealth -> Jina -> Firecrawl -> Browserless |
similar |
Find similar pages to a URL | Exa |
social |
X/Twitter social search | xAI (Grok) |
Agent-First Design
Built for Claude Code, Codex CLI, Gemini CLI, OpenClaw, and any AI agent that can shell out to a command.
# Discover capabilities programmatically
# Structured JSON with metadata
# {
# "status": "success",
# "query": "...",
# "mode": "general",
# "results": [...],
# "metadata": {
# "elapsed_ms": 1542,
# "result_count": 10,
# "providers_queried": ["brave", "serper", "exa"]
# }
# }
Auto-JSON: Output is automatically JSON when piped to another program. Human-readable tables when you're in a terminal.
Semantic exit codes:
| Code | Meaning | Agent action |
|---|---|---|
| 0 | Success | Process results |
| 1 | Runtime error | Retry might help |
| 2 | Config error | Fix configuration |
| 3 | Auth missing | Set API key |
| 4 | Rate limited | Back off and retry |
Usage Examples
# Default general web search (no mode = general; no intent guessing)
# Force a specific mode
# Search X (Twitter) only
# Pick specific providers
# Control output
|
Providers
| Provider | What it does | Best for |
|---|---|---|
| Brave | Independent 35B-page index + LLM Context API | Web search, news, RAG-ready content |
| Serper | Raw Google SERP + specialist endpoints | Scholar, patents, images, places |
| Exa | Neural/semantic search, category filters | Research papers, people search, similar sites |
| Jina | Fast URL-to-markdown, 500 RPM free tier | Reading article content, quick extraction |
| Firecrawl | JavaScript rendering, structured extraction | Dynamic pages, SPAs, data extraction |
| Tavily | General + deep search, research-focused | Broad coverage, research queries |
| SerpApi | 80+ engines: Google, Bing, YouTube, Baidu | Scholar, multi-engine coverage |
| Perplexity | AI-powered answers with citations (Sonar Pro) | Complex queries, synthesized answers |
| Browserless | Cloud browser for Cloudflare/JS-heavy pages | Anti-bot bypass, dynamic rendering |
| Stealth | Built-in anti-bot scraper | Protected pages, no API key needed |
| xAI | X/Twitter search via Grok AI | Tweets, trending topics, social sentiment |
Configuration
Config file lives at ~/.config/search/config.toml (Linux) or ~/Library/Application Support/search/config.toml (macOS).
Environment variables override the config file, so a freshly-exported or CI-injected key always wins over stale local config. Two accepted forms:
# Standard per-provider variables (recommended):
# ...also PERPLEXITY_API_KEY, JINA_API_KEY, FIRECRAWL_API_KEY, TAVILY_API_KEY,
# SERPAPI_API_KEY, BROWSERLESS_API_KEY, XAI_API_KEY, PARALLEL_API_KEY
# Or the SEARCH_KEYS_ prefixed form:
Precedence (highest first): <PROVIDER>_API_KEY env → SEARCH_KEYS_* env → config file.
Updating
Building from Source
# Binary at target/release/search
Contributing
Contributions are welcome. See CONTRIBUTING.md for guidelines.
License
Built by Boris Djordjevic at 199 Biotechnologies | Paperfoot AI
If this is useful to you: