@bitcraft-apps/pi-web-tools
Shell-only web search and fetch tools for pi.dev. No API keys.
Package details
Install @bitcraft-apps/pi-web-tools from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@bitcraft-apps/pi-web-tools- Package
@bitcraft-apps/pi-web-tools- Version
0.2.0- Published
- May 7, 2026
- Downloads
- not available
- Author
- sgraczyk
- License
- MIT
- Types
- extension
- Size
- 20.3 KB
- Dependencies
- 0 dependencies · 3 peers
Pi manifest JSON
{
"extensions": [
"./index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@bitcraft-apps/pi-web-tools
Shell-only web search and fetch tools for pi.dev. Zero API keys, zero accounts — just ddgr + pandoc/w3m running locally.
Tools
websearch— DuckDuckGo search viaddgr. Returns up to 25 results with title, URL, snippet.webfetch—fetch+ HTML→markdown viapandoc(preferred) orw3m(fallback). Auto-handles Cloudflare challenges via UA hack. Blocks SSRF (localhost/RFC1918).
Install
# 1. System deps (one-time)
brew install ddgr pandoc # macOS
# or: pip install ddgr; apt install pandoc w3m
# 2. Extension (from git for now; npm coming in v0.2)
pi install git:https://github.com/bitcraft-apps/pi-web-tools
# Or for local dev / hacking on the source:
pi install -e /path/to/pi-web-tools
After install, restart pi and the websearch and webfetch tools become available.
Usage examples
In a pi session:
> Find me docs for Bun's native Sqlite API
[agent uses websearch → gets bun.sh URL → uses webfetch → reads docs]
You don't call them directly — pi's agent calls them when it needs.
Limits and behavior
websearch: default 8 results, hard cap 25. DuckDuckGo rate-limits ~10 req/min/IP. If you hit it, wait or usewebfetchdirectly.webfetch: default 50k chars output, hard cap 200k. 5 MB response cap. 30s timeout. Cannot fetch: PDFs, images, video, audio, localhost, 127/8, 169.254/16. Cannot render: JS-heavy SPAs (you'll get an empty markdown).- Honors the
charset=parameter onContent-Typefor response decoding (e.g.windows-1250,iso-8859-2,shift_jis,gb2312). Unknown labels fall back to UTF-8. - All operations are read-only and synchronous. No persistent state, no cache.
Troubleshooting
ddgr not installed→brew install ddgrorpip install ddgrNeed pandoc or w3m installed→brew install pandocDuckDuckGo timed out (likely rate-limited)→ wait 1–2 minSite requires JS, cannot fetch in shell-only mode→ site uses Cloudflare/JS-only; not solvable without headless browser, out of scope for this tool
Development
# one-time, if you don't have bun:
# macOS: brew install bun
# Linux / WSL: curl -fsSL https://bun.sh/install | bash
# (or see https://bun.sh for other options)
git clone https://github.com/bitcraft-apps/pi-web-tools
cd pi-web-tools
bun install
bun run test # unit tests, no network
bun run test:network # integration tests (requires net)
We use bun as the dev package manager. The committed lockfile is bun.lock; package-lock.json is gitignored.
Caveat for end-user installs:
pi install git:...runsnpm installunder the hood, which ignoresbun.lockand re-resolves transitive deps against the registry. End-user installs are therefore not byte-reproducible until we publish to npm in v0.2 (#5). Acceptable for now: peer deps are wildcard-pinned and we have no runtime deps that drift in breaking ways.
Note on npm scope: the GitHub org is
bitcraft-appsbecausebitcraftwas taken on GitHub. The npm scope@bitcraftis also taken, so the npm package is published as@bitcraft-apps/pi-web-toolsto mirror the GH org (#5).
Hot-reload during dev:
ln -s "$(pwd)" ~/.pi/agent/extensions/pi-web-tools
# in pi session: /reload
License
MIT