@pi-vault/pi-tools
Pi extension for web search, content extraction, documentation lookup, and deep research tools
Package details
Install @pi-vault/pi-tools from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@pi-vault/pi-tools- Package
@pi-vault/pi-tools- Version
0.5.0- Published
- Jul 22, 2026
- Downloads
- 680/mo · 208/wk
- Author
- lanhhoang
- License
- MIT
- Types
- extension
- Size
- 390 KB
- Dependencies
- 5 dependencies · 3 peers
Pi manifest JSON
{
"extensions": [
"./src/index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@pi-vault/pi-tools
Web search, content extraction, documentation lookup, and deep research tools for Pi.
What's new in 0.5.0
Dashboard replaces typed
/toolssubcommands. Run/toolsto open the interactive dashboard with three tabs: Providers (toggle, key, default, run tests), Status (budgets, session outcomes, latency), and Activity (recent provider events). Typed subcommands such as/tools status,/tools enable,/tools key,/tools test,/tools default, and/tools monitor on|offare no longer supported.Provider budgets are enforceable. Hard, managed, unlimited, and shared-pool policies replace the old
monthlyQuotasettings. Budget status is reported per provider in the Status tab.
openai-codexrequires Pi OAuth. TheOPENAI_API_KEYfallback is gone. Run/loginand selectopenai-codexbefore using it. To search withOPENAI_API_KEYinstead, configureopenai-web-search.Usage persistence moved. Provider usage now lives at
$PI_CODING_AGENT_DIR/cache/pi-tools/usage.jsonusing a version 2 UTC-period ledger.
Install
pi install npm:@pi-vault/pi-tools
Reload Pi after installation:
/reload
The extension can use keyless providers such as Jina. DuckDuckGo also works without an API key after you install the ddgs CLI:
uv tool install ddgs
# or: pip install ddgs
Run /tools in Pi to open the dashboard and configure more providers. The dashboard detects available environment variables and can write the global config for you.
/tools
Use it
Ask Pi in plain language. The extension registers up to seven tools, depending on which providers you configure:
| Tool | Use it for |
|---|---|
web_search |
Current information, releases, and live web results |
web_fetch |
Web pages, PDFs, GitHub URLs, YouTube videos, and local video files |
web_read |
Full text from a large response using its contentId |
code_search |
Programming examples and technical documentation through Exa |
web_docs_search |
Finding a Context7 library ID |
web_docs_fetch |
Focused, version-aware Context7 documentation |
web_research |
Multi-source Exa research and saved findings reports |
Search the web
Search the web for the latest Vitest mocking documentation.
Search npm release notes after 2026-01-01, using only npmjs.com.
Search for current SQLite performance guidance and combine multiple providers.
web_search supports provider selection, domain filters, publication dates, compact results, and optional multi-provider fusion. If a provider fails, Pi Tools tries the next eligible provider unless the request was cancelled.
Fetch pages and files
Fetch https://example.com/spec and summarize the requirements.
Fetch these URLs and compare them: https://a.dev/docs, https://b.dev/docs
Fetch https://example.com/page in raw mode.
web_fetch accepts one URL or up to 20 URLs. It extracts readable HTML, PDFs, GitHub repositories and files, and some Next.js RSC pages. It can fall back to Jina, Gemini, or a configured fetch provider when direct extraction is not enough.
Large responses include a contentId. Ask Pi to pass that ID to web_read for the full text. Stored content lasts for the current session.
Work with YouTube, video, and PDFs
Fetch https://www.youtube.com/watch?v=VIDEO_ID and summarize the transcript.
Extract 4 frames from https://www.youtube.com/watch?v=VIDEO_ID between 02:00 and 03:00.
Analyze /absolute/path/to/demo.mp4 and list the main steps shown.
Fetch https://example.com/scanned-report.pdf and summarize it.
YouTube transcript extraction can use Gemini or Perplexity. Frame extraction uses yt-dlp and ffmpeg. Local video analysis uses Gemini. Scanned PDF OCR uses pdftoppm and either the active model's image support or Gemini as a fallback.
Look up code and library documentation
Find TypeScript examples for AbortSignal timeout handling.
Find the React library in Context7 for hooks documentation.
Fetch Context7 docs for /facebook/react about useState hooks.
Use web_docs_search before web_docs_fetch. Include a focused question, and pin a version in the library ID when reproducibility matters, such as /vercel/next.js@v15.1.8.
Run deep research
Research the trade-offs between PostgreSQL logical replication and CDC. Save a findings report to docs/replication.md.
web_research supports lite, standard, and full modes. It requires EXA_API_KEY. Pass outputPath to save a report and rawOutputPath to keep the source metadata.
Manage providers
Run /tools to open the interactive dashboard. The dashboard has three tabs:
- Providers — toggle a provider on or off, set a credential, change the default provider, and run a test in place.
- Status — per-provider budget state, session outcomes (success/failure), and average latency.
- Activity — recent provider events streamed live.
Switch between global and project scope inside the dashboard. Project scope requires the project to be trusted or to already have a .pi/tools.json.
Provider configuration refreshes automatically every 30 seconds. The dashboard's reload action triggers an immediate refresh.
Available providers
| Provider | Capabilities | Setup |
|---|---|---|
| Brave | Search | BRAVE_API_KEY |
| Brave LLM | Search | BRAVE_API_KEY |
| Context7 | Docs | CONTEXT7_API_KEY |
| DuckDuckGo | Search | ddgs CLI |
| Exa | Search, fetch, code, research | EXA_API_KEY |
| fastCRW | Search | FASTCRW_API_KEY |
| Firecrawl | Search, fetch | API key optional |
| Jina | Search, fetch | API key optional |
| LangSearch | Search | LANGSEARCH_API_KEY |
| Linkup | Search | LINKUP_API_KEY |
| Marginalia | Search | No API key |
| Ollama | Search, fetch | Local Ollama server |
| OpenAI Codex | Search | Pi /login OAuth |
| OpenAI web search | Search | OPENAI_API_KEY |
| Parallel | Search, fetch | PARALLEL_API_KEY |
| Perplexity | Search, YouTube fallback | PERPLEXITY_API_KEY |
| SearXNG | Search | SearXNG instance, API key optional |
| Serper | Search | SERPER_API_KEY |
| Sofya | Search, fetch | SOFYA_API_KEY |
| Tavily | Search, fetch | TAVILY_API_KEY |
| WebSearchAPI | Search | WEBSEARCHAPI_API_KEY |
| You.com | Search | YOUCOM_API_KEY |
Pi Tools ranks providers by tier and availability, and optionally by recent session performance. Automatic selection skips exhausted hard budgets. Provider-specific date and domain filters depend on the upstream API; unsupported filters are applied locally where possible.
openai-codex uses the active Pi OAuth session. Run /login and select openai-codex before using it; the provider no longer accepts OPENAI_API_KEY as a fallback. To search with OPENAI_API_KEY instead, configure openai-web-search.
Configure files and credentials
The global config is $PI_CODING_AGENT_DIR/extensions/tools.json; when the variable is unset, Pi supplies its agent directory. A project .pi/tools.json overrides it. Pi Tools deep-merges project settings, global settings, and built-in defaults in that order.
Minimal config
A starter configuration with one keyed search provider and a few keyless defaults:
{
"defaultProvider": "auto",
"providers": {
"exa": {
"enabled": true,
"apiKey": "EXA_API_KEY"
},
"duckduckgo": { "enabled": true },
"firecrawl": { "enabled": true },
"jina": { "enabled": true },
"marginalia": { "enabled": true },
"openai-codex": { "enabled": true }
}
}
A provider apiKey can be:
- an environment-variable name, such as
"EXA_API_KEY" - a literal key
- a shell command prefixed with
!, such as"!op read op://pi/exa/api-key"
Shell-command credentials are cached until the next config refresh. Sensitive fields in project config are ignored until Pi marks the project as trusted.
Full configuration reference
The complete shape of the merged configuration. Every field shown here is honored by the extension; omit any section to use the built-in default.
{
"defaultProvider": "auto",
"selectionStrategy": "auto",
"providers": {
"brave": {
"enabled": false,
"apiKey": "BRAVE_API_KEY"
},
"brave-llm": {
"enabled": false,
"apiKey": "BRAVE_API_KEY",
"tokenBudget": 4096
},
"context7": {
"enabled": false,
"apiKey": "CONTEXT7_API_KEY"
},
"duckduckgo": {
"enabled": true,
"ddgsBackend": "api",
"ddgsRegion": "us-en"
},
"exa": {
"enabled": false,
"apiKey": "EXA_API_KEY"
},
"fastcrw": {
"enabled": false,
"apiKey": "FASTCRW_API_KEY",
"baseUrl": "https://api.fastcrw.com"
},
"firecrawl": {
"enabled": true
},
"jina": {
"enabled": true
},
"langsearch": {
"enabled": false,
"apiKey": "LANGSEARCH_API_KEY"
},
"linkup": {
"enabled": false,
"apiKey": "LINKUP_API_KEY",
"depth": "standard"
},
"marginalia": {
"enabled": true
},
"ollama": {
"enabled": false,
"baseUrl": "http://localhost:11434"
},
"openai-codex": {
"enabled": true
},
"openai-web-search": {
"enabled": false,
"apiKey": "OPENAI_API_KEY",
"model": "gpt-4.1-mini"
},
"parallel": {
"enabled": false,
"apiKey": "PARALLEL_API_KEY"
},
"perplexity": {
"enabled": false,
"apiKey": "PERPLEXITY_API_KEY",
"model": "sonar"
},
"searxng": {
"enabled": false,
"instanceUrl": "http://localhost:8080"
},
"serper": {
"enabled": false,
"apiKey": "SERPER_API_KEY"
},
"sofya": {
"enabled": false,
"apiKey": "SOFYA_API_KEY",
"searchDepth": "basic",
"topic": "general"
},
"tavily": {
"enabled": false,
"apiKey": "TAVILY_API_KEY"
},
"websearchapi": {
"enabled": false,
"apiKey": "WEBSEARCHAPI_API_KEY"
},
"youcom": {
"enabled": false,
"apiKey": "YOUCOM_API_KEY"
}
},
"github": {
"enabled": true,
"maxRepoSizeMB": 350,
"cloneTimeoutSeconds": 30
},
"combine": {
"enabled": false,
"mode": "targeted",
"targetBackends": 3,
"k": 60
},
"gemini": {
"apiKey": "GEMINI_API_KEY",
"baseUrl": "https://generativelanguage.googleapis.com",
"cloudflareApiKey": "CLOUDFLARE_API_KEY",
"allowBrowserCookies": false,
"chromeProfile": "Default"
},
"youtube": {
"enabled": true,
"preferredModel": "gemini-3-flash-preview"
},
"video": {
"enabled": true,
"preferredModel": "gemini-3-flash-preview",
"maxSizeMB": 50
},
"pdf": {
"ocrEnabled": true,
"ocrMaxPages": 5,
"ocrDpi": 150
},
"deepResearch": {
"enabled": true,
"modeDefaults": {
"lite": {
"type": "deep-lite",
"numResults": 15,
"textMaxCharacters": 10000,
"timeoutSeconds": 300,
"highlightsMaxCharacters": 600,
"highlightNumSentences": 3,
"highlightsPerUrl": 1
},
"standard": {
"type": "deep-reasoning",
"numResults": 50,
"textMaxCharacters": 16000,
"timeoutSeconds": 600,
"highlightsMaxCharacters": 900,
"highlightNumSentences": 4,
"highlightsPerUrl": 2
},
"full": {
"type": "deep-reasoning",
"numResults": 100,
"textMaxCharacters": 24000,
"timeoutSeconds": 1800,
"highlightsMaxCharacters": 1200,
"highlightNumSentences": 5,
"highlightsPerUrl": 3
}
},
"outputSchema": null,
"guidance": {}
},
"guidance": {
"web_search": {},
"web_fetch": {},
"web_read": {},
"code_search": {},
"web_docs_search": {},
"web_docs_fetch": {}
},
"ssrf": {
"allowRanges": []
}
}
Provider budgets
Every built-in provider has a default budget. Omit it to keep that default, or replace the complete object for one provider:
{
"providers": {
"exa": {
"budget": {
"mode": "hard",
"limit": 10,
"period": "month",
"unit": "usd",
"pool": "exa"
}
},
"jina": { "budget": { "mode": "managed" } },
"duckduckgo": { "budget": { "mode": "unlimited" } }
}
}
Hard budgets accept day, month, or lifetime periods and request, credit, or usd units. Day and month boundaries use UTC calendar time. A pool shares one counter across providers; every provider in that pool must use the same limit, period, and unit. Invalid or conflicting overrides are ignored as a group.
managed delegates limits to the provider or plan. unlimited means Pi Tools does not meter the provider. Local reservations are saved before requests to $PI_CODING_AGENT_DIR/cache/pi-tools/usage.json. Version 2 keeps compatible current-month legacy request counts for non-shared monthly budgets; monthlyQuota settings are not migrated.
Enforcement is atomic within one Pi process. Separate concurrent Pi processes can briefly exceed the same local ceiling; interprocess locking is intentionally deferred until that becomes an observed need.
Useful advanced settings:
selectionStrategy:autoorbest-performingcombine: optional reciprocal-rank fusion across eligible providersgithub: GitHub repository size and clone timeout limitsgemini: API key, custom base URL, Cloudflare AI Gateway key, and browser-cookie accessyoutubeandvideo: enablement, preferred Gemini model, and local video size limitpdf: OCR enablement, page limit, and rasterization DPIdeepResearch: mode defaults, structured output schema, and report guidanceguidance: prompt overrides for individual toolsssrf.allowRanges: explicit CIDR exceptions for trusted private networks
To use Gemini browser cookies, set PI_ALLOW_BROWSER_COOKIES=1 or enable gemini.allowBrowserCookies in the global config. Project config cannot enable sensitive cookie or network access unless the project is trusted.
Optional command-line tools
| Tool | Enables |
|---|---|
ddgs |
Keyless DuckDuckGo search |
gh |
Richer GitHub repository access when Pi chooses the CLI |
yt-dlp |
YouTube stream lookup and frame extraction |
ffmpeg |
YouTube and local video frame extraction |
pdftoppm from Poppler |
Scanned PDF rasterization for OCR |
Development
pnpm install
pnpm check
pnpm release:check
Changelog
See CHANGELOG.md for release notes.
License
MIT. See LICENSE.