Fan out research queries to multiple search and deep-research APIs in parallel.
Inspired by Aaron Francis' counselors, librarium applies the same fan-out pattern to search APIs. Where counselors fans out prompts to multiple LLM CLIs, librarium fans out research queries to search engines, AI-grounded search, and deep-research APIs -- collecting, normalizing, and deduplicating results into structured output.
npm install -g librariumpnpm install -g librariumyarn global add librariumbrew install jkudish/tap/librariumcurl -fsSL https://raw.githubusercontent.com/jkudish/librarium/main/scripts/install.sh | shnpx librarium run "your query"librarium upgradeAuto-detects your install method (npm, pnpm, yarn, Homebrew, standalone) and runs the correct upgrade command.
# Auto-configure (discovers API keys from environment)
librarium init --auto
# Run a research query
librarium run "PostgreSQL connection pooling best practices"
# Use a specific group
librarium run "React Server Components" --group quick
# Check async deep research status
librarium status --waitLibrarium ships with 13 built-in provider adapters organized into three tiers:
| Provider | ID | Tier | API Key Env Var |
|---|---|---|---|
| Perplexity Sonar Deep Research | perplexity-sonar-deep |
deep-research | PERPLEXITY_API_KEY |
| Perplexity Deep Research | perplexity-deep-research |
deep-research | PERPLEXITY_API_KEY |
| Perplexity Advanced Deep Research | perplexity-advanced-deep |
deep-research | PERPLEXITY_API_KEY |
| OpenAI Deep Research | openai-deep |
deep-research | OPENAI_API_KEY |
| Gemini Deep Research | gemini-deep |
deep-research | GEMINI_API_KEY |
| Perplexity Sonar Pro | perplexity-sonar-pro |
ai-grounded | PERPLEXITY_API_KEY |
| Brave AI Answers | brave-answers |
ai-grounded | BRAVE_API_KEY |
| Exa Search | exa |
ai-grounded | EXA_API_KEY |
| Perplexity Search | perplexity-search |
raw-search | PERPLEXITY_API_KEY |
| Brave Web Search | brave-search |
raw-search | BRAVE_API_KEY |
| SearchAPI | searchapi |
raw-search | SEARCHAPI_API_KEY |
| SerpAPI | serpapi |
raw-search | SERPAPI_API_KEY |
| Tavily Search | tavily |
raw-search | TAVILY_API_KEY |
Perplexity provider IDs were renamed to match current product names:
perplexity-sonar->perplexity-sonar-properplexity-deep->perplexity-sonar-deep
For backward compatibility, librarium still accepts legacy IDs in:
run --providers- provider config keys in
~/.config/librarium/config.json - custom group members
fallbacktargets
Legacy IDs are normalized to canonical IDs and emit a warning. Output files and run.json always use canonical IDs.
You can also add custom providers (npm modules or local scripts) via config. See Custom Providers.
Providers are categorized into three tiers based on their capabilities, latency, and depth:
-
deep-research -- Async deep research providers that take minutes to complete but produce comprehensive, multi-source reports. These providers may use a submit/poll/retrieve pattern. Best for thorough research on important topics.
-
ai-grounded -- AI-powered search with inline citations. Returns results in seconds with good quality and source attribution. A solid middle ground between speed and depth.
-
raw-search -- Traditional search engine results. Fast responses with many links and snippets, but no AI synthesis. Useful for broad link discovery and verifying specific facts.
Run a research query across multiple providers.
librarium run <query> [options]| Flag | Description |
|---|---|
-p, --providers <ids> |
Comma-separated provider IDs |
-g, --group <name> |
Use a predefined provider group |
-m, --mode <mode> |
Execution mode: sync, async, or mixed |
-o, --output <dir> |
Output base directory |
--parallel <n> |
Max parallel requests |
--timeout <n> |
Timeout per provider in seconds |
--json |
Output run.json to stdout |
# Run with specific providers
librarium run "database indexing" --providers perplexity-sonar-pro,exa
# Deep research, wait for completion
librarium run "AI agent architectures" --group deep --mode sync
# Fast results only
librarium run "Node.js 22 features" --group fastCheck or wait for async deep-research tasks.
librarium status [options]| Flag | Description |
|---|---|
--wait |
Block and poll until all async tasks complete |
--retrieve |
Fetch completed results and write output files |
--json |
Output JSON |
# Check pending tasks
librarium status
# Wait for completion then retrieve results
librarium status --wait --retrieveList all available providers with their status.
librarium ls [--json]Shows each provider's ID, display name, tier, source (builtin, npm, script), enabled state, and whether an API key is configured.
List and manage provider groups.
# List all groups
librarium groups
# Add a custom group
librarium groups add my-stack perplexity-sonar-pro exa tavily
# Remove a custom group
librarium groups remove my-stack
# Output as JSON
librarium groups --jsonSet up librarium configuration. Auto mode discovers API keys from your environment and enables matching providers.
# Auto-discover (non-interactive)
librarium init --auto
# Interactive setup
librarium initHealth check: tests API connectivity for all enabled providers.
librarium doctor [--json]Print the resolved configuration (global merged with project).
# Show resolved config
librarium config
# Show only global config
librarium config --global
# Output raw JSON
librarium config --jsonRemove old output directories.
# Delete directories older than 30 days (default)
librarium cleanup
# Custom age threshold
librarium cleanup --days 7
# Preview what would be deleted
librarium cleanup --dry-runGroups are named collections of provider IDs. Librarium ships with six default groups:
| Group | Providers | Use Case |
|---|---|---|
deep |
perplexity-sonar-deep, perplexity-deep-research, perplexity-advanced-deep, openai-deep, gemini-deep | Thorough async research |
quick |
perplexity-sonar-pro, brave-answers, exa | Fast AI-grounded answers |
raw |
perplexity-search, brave-search, searchapi, serpapi, tavily | Traditional search results |
fast |
perplexity-sonar-pro, perplexity-search, brave-answers, exa, brave-search, tavily | Quick results from multiple tiers |
comprehensive |
All deep-research + all ai-grounded | Deep + AI-grounded combined |
all |
All 13 providers | Maximum coverage |
Add custom groups via CLI or config file:
# Via CLI
librarium groups add my-research perplexity-sonar-pro exa brave-search
# Via config.json
{
"groups": {
"my-research": ["perplexity-sonar-pro", "exa", "brave-search"]
}
}Librarium supports three execution modes, configurable via --mode or the defaults.mode config key:
-
sync-- Wait for all providers to complete, including deep-research providers. Deep research runs synchronously (can take several minutes). -
async-- Submit deep-research tasks and return immediately. Uselibrarium status --wait --retrieveto poll and fetch results later. -
mixed(default) -- Run ai-grounded and raw-search providers synchronously. Submit deep-research providers asynchronously. You get fast results right away and can retrieve deep research later.
When a provider fails for any reason (exception, error response, timeout), librarium can automatically try a lighter alternative. Add an optional fallback field to any provider's config:
{
"providers": {
"gemini-deep": {
"apiKey": "$GEMINI_API_KEY",
"enabled": true,
"fallback": "openai-deep"
},
"openai-deep": {
"apiKey": "$OPENAI_API_KEY",
"enabled": false
}
}
}Behavior:
- Fallback triggers after the primary provider's execution fails (error or timeout)
- Only single-level fallback is supported (a fallback's own fallback is ignored)
- The fallback provider must be configured with a valid API key but can be
enabled: false(it will only activate as a backup) - If the fallback provider is already running in the same dispatch (e.g., explicitly listed in
--providers), it won't be triggered again - Output files use the fallback provider's ID (e.g.,
openai-deep.md)
In run.json, both the original error report and the fallback result appear in the providers array. The fallback report includes a fallbackFor field indicating which provider it replaced:
{
"id": "openai-deep",
"tier": "deep-research",
"status": "success",
"fallbackFor": "gemini-deep"
}Librarium uses a layered configuration system:
- Global config:
~/.config/librarium/config.json - Project config:
.librarium.json(in current directory) - CLI flags: Passed directly to commands
Each layer overrides the previous:
defaults: project overrides globalproviders: deep-merged by provider ID (project overrides keys on conflict)customProviders: merged by provider ID (project overrides global on same ID)trustedProviderIds: union + dedupe across global and projectgroups: project overrides global group names on conflict
{
"version": 1,
"defaults": {
"outputDir": "./agents/librarium",
"maxParallel": 6,
"timeout": 30,
"asyncTimeout": 1800,
"asyncPollInterval": 10,
"mode": "mixed"
},
"providers": {
"perplexity-sonar-pro": {
"apiKey": "$PERPLEXITY_API_KEY",
"enabled": true
},
"brave-answers": {
"apiKey": "$BRAVE_API_KEY",
"enabled": true
},
"exa": {
"apiKey": "$EXA_API_KEY",
"enabled": true
},
"tavily": {
"apiKey": "$TAVILY_API_KEY",
"enabled": true
}
},
"customProviders": {},
"trustedProviderIds": [],
"groups": {
"my-custom-group": ["perplexity-sonar-pro", "exa"]
}
}API keys use the $ENV_VAR pattern -- the value "$PERPLEXITY_API_KEY" resolves to process.env.PERPLEXITY_API_KEY at runtime. Keys are never stored in plaintext.
Some providers support optional model overrides. For example, to override Gemini Deep Research:
{
"providers": {
"gemini-deep": {
"apiKey": "$GEMINI_API_KEY",
"enabled": true,
"model": "gemini-2.5-flash"
}
}
}{
"defaults": {
"outputDir": "./research",
"timeout": 60
},
"providers": {
"perplexity-sonar-pro": {
"enabled": false
},
"my-script-provider": {
"enabled": true
}
},
"customProviders": {
"my-script-provider": {
"type": "script",
"command": "node",
"args": ["./scripts/librarium-provider.mjs"]
}
},
"trustedProviderIds": ["my-script-provider"],
"groups": {
"project-research": ["my-script-provider", "exa"]
}
}Librarium supports external providers without changing core code. Add definitions to config and trust them explicitly.
For provider-author implementation details (module contract, script runtime semantics, timeouts, and troubleshooting), see docs/provider-development.md.
- Custom providers load only when their ID appears in
trustedProviderIds - Trust lists from global and project config are unioned and deduped
- Built-in IDs are reserved; custom providers cannot override built-ins
{
"customProviders": {
"my-npm-provider": {
"type": "npm",
"module": "librarium-provider-myteam",
"export": "createProvider",
"options": { "preset": "fast" }
}
},
"trustedProviderIds": ["my-npm-provider"],
"providers": {
"my-npm-provider": {
"enabled": true,
"apiKey": "$MY_PROVIDER_API_KEY"
}
}
}module resolution order is:
- Current project (
process.cwd()) - Librarium runtime install context
In standalone/Homebrew binary installs, npm custom providers are skipped with a warning.
{
"customProviders": {
"my-script-provider": {
"type": "script",
"command": "node",
"args": ["./scripts/librarium-provider.mjs"],
"cwd": ".",
"env": { "LOG_LEVEL": "warn" },
"options": { "flavor": "deep" }
}
},
"trustedProviderIds": ["my-script-provider"],
"providers": {
"my-script-provider": {
"enabled": true
}
}
}Script providers are invoked as one process per operation (describe, execute, submit, poll, retrieve, test) with JSON over stdin/stdout.
Request envelope:
{
"protocolVersion": 1,
"operation": "execute",
"providerId": "my-script-provider",
"query": "research topic",
"options": { "timeout": 30 },
"providerConfig": { "enabled": true },
"sourceOptions": { "flavor": "deep" }
}Response envelope:
{
"ok": true,
"data": {
"provider": "my-script-provider",
"tier": "ai-grounded",
"content": "# Result",
"citations": [],
"durationMs": 1200
}
}Error response:
{
"ok": false,
"error": "upstream timeout"
}describe must return provider metadata and capabilities:
{
"ok": true,
"data": {
"displayName": "My Script Provider",
"tier": "deep-research",
"envVar": "MY_PROVIDER_API_KEY",
"requiresApiKey": true,
"capabilities": {
"submit": true,
"poll": true,
"retrieve": true,
"test": true
}
}
}Each research run creates a timestamped output directory:
./agents/librarium/1771500000-postgresql-pooling/
prompt.md # The research query
run.json # Run manifest (machine-readable)
summary.md # Synthesized summary with statistics
sources.json # Deduplicated citations across all providers
perplexity-sonar-pro.md # Per-provider markdown results
perplexity-sonar-pro.meta.json # Per-provider metadata (model, timing, citations)
brave-answers.md
brave-answers.meta.json
async-tasks.json # Present if any async tasks were submitted
{
"version": 1,
"timestamp": 1771500000,
"slug": "postgresql-pooling",
"query": "PostgreSQL connection pooling best practices",
"mode": "mixed",
"outputDir": "/absolute/path/to/output",
"providers": [
{
"id": "perplexity-sonar-pro",
"tier": "ai-grounded",
"status": "success",
"durationMs": 2340,
"wordCount": 850,
"citationCount": 12,
"outputFile": "perplexity-sonar-pro.md",
"metaFile": "perplexity-sonar-pro.meta.json"
}
],
"sources": {
"total": 45,
"unique": 28,
"file": "sources.json"
},
"asyncTasks": [],
"exitCode": 0
}| Code | Meaning |
|---|---|
0 |
All providers succeeded |
1 |
Partial success (some providers failed) |
2 |
Total failure (all providers failed, or configuration error) |
Librarium is designed to be used by AI coding agents. There are three ways to set it up:
The built-in skill teaches Claude Code how to use librarium through a 7-phase research workflow.
# Install via CLI
librarium install-skill
# Or manually
mkdir -p ~/.claude/skills/librarium
curl -o ~/.claude/skills/librarium/SKILL.md https://raw.githubusercontent.com/jkudish/librarium/main/SKILL.mdOnce installed, Claude Code will automatically use librarium when you ask it to research a topic. Triggers: /librarium, /research, /deep-research.
Drop this into any AI agent's system prompt to give it librarium capabilities:
You have access to the `librarium` CLI for deep multi-provider research.
To research a topic, run:
librarium run "<query>" --group <group>
Groups:
quick — Fast AI-grounded answers (seconds)
deep — Thorough async research (minutes)
fast — Quick results from multiple tiers
comprehensive — Deep + AI-grounded combined
all — All 13 providers
Output lands in ./agents/librarium/<timestamp>-<slug>/:
summary.md — Synthesized overview with stats
sources.json — Deduplicated citations ranked by frequency
{provider}.md — Per-provider detailed results
run.json — Machine-readable manifest
For async deep research, check status with:
librarium status --wait
Cross-reference sources appearing in multiple providers for higher confidence.
Add to your project's CLAUDE.md for project-scoped research:
## Research
Use `librarium` for research queries. It's installed globally.
- Quick lookups: `librarium run "query" --group quick`
- Deep research: `librarium run "query" --group deep --mode sync`
- Results land in `./agents/librarium/` — read `summary.md` first, then `sources.json` for citationsThe skill guides agents through:
- Query Analysis -- Classify the research question and pick the right provider group
- Provider Selection -- Match query type to tier (
quickfor facts,deepfor thorough research,allfor max coverage) - Dispatch -- Run the query with appropriate flags
- Monitor -- Track async deep-research tasks
- Retrieve -- Fetch completed async results
- Analyze -- Read
summary.md,sources.json, and per-provider output files - Synthesize -- Cross-reference multi-provider findings, weight by citation frequency
The release workflow at .github/workflows/release.yml handles npm publishing. It requires a NPM_TOKEN repository secret configured in GitHub Settings > Secrets.
If librarium saves you time, consider sponsoring development. ❤️
MIT
