@aizigao/pi-proxy-fetch
Pi extension package that routes globalThis.fetch through direct, proxy, or fallback behavior based on hostname rules.
Package details
Install @aizigao/pi-proxy-fetch from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@aizigao/pi-proxy-fetch- Package
@aizigao/pi-proxy-fetch- Version
0.1.1- Published
- May 20, 2026
- Downloads
- not available
- Author
- aizigao
- License
- MIT
- Types
- extension
- Size
- 14 KB
- Dependencies
- 1 dependency · 1 peer
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
@aizigao/pi-proxy-fetch
中文文档:README-CN.md
A Pi extension package that routes globalThis.fetch through direct, proxy, or direct-with-proxy-fallback behavior based on hostname rules.
Forked from haokanjiang/pi-proxy and adapted to preserve this package's current local routing behavior and packaging structure.
This package keeps the current local routing model intact:
- config file lives at
~/.pi/agent/proxy.json - rules are re-read on every request
- wildcard hostname matching is supported
- proxy requests use
undiciwithProxyAgent - fallback mode retries failed direct requests through the proxy
/proxycommand provides ON/OFF, stats, reload, and rule display
What it does
@aizigao/pi-proxy-fetch monkey-patches globalThis.fetch inside a Pi session.
For each request it:
- reads
~/.pi/agent/proxy.json - matches the request hostname against your rules
- chooses one of three actions:
direct: use the original fetchproxy: send viaProxyAgentfallback: try direct first, then retry through proxy on network failure
This is intentionally a network-layer fetch router. It is not a search tool and it does not change non-fetch HTTP clients.
Features
- Pi extension package layout
- Rule-based host matching
direct,proxy,fallbackactions- per-session fetch patching with shutdown restore
/proxyinteractive command- request counters for direct, proxy, and fallback traffic
- config-driven enable/disable switch persisted to disk
Requirements
- Node.js 20+
- Pi coding agent installed
- A Pi agent config directory at
~/.pi/agent
Repository
- GitHub: https://github.com/aizigao/pi-proxy-fetch
- Issues: https://github.com/aizigao/pi-proxy-fetch/issues
- npm package:
@aizigao/pi-proxy-fetch
Installation
Install with Pi
pi install npm:@aizigao/pi-proxy-fetch
Publishing
Before publishing, verify:
npm run check
npm run lint
Then publish:
npm publish
This package is configured as a public scoped package.
Configuration
Create ~/.pi/agent/proxy.json:
{
"enabled": true,
"proxy": "http://127.0.0.1:7890",
"mode": "direct",
"rules": [
{
"match": "api.openai.com,api.anthropic.com",
"action": "direct",
"comment": "keep AI API traffic direct"
},
{
"match": "*.google.com,*.github.com",
"action": "proxy",
"comment": "always proxy selected domains"
},
{
"match": "*",
"action": "fallback",
"comment": "default: direct first, proxy on network failure"
}
]
}
Config fields
| Field | Type | Description |
|---|---|---|
enabled |
boolean |
Global ON/OFF switch. /proxy can toggle and persist it. |
proxy |
string |
Proxy URL passed to undici ProxyAgent. |
mode |
direct | proxy | fallback |
Default action when no rule matches. |
rules |
ProxyRule[] |
Top-down rule list. First match wins. |
Rule format
{
"match": "*.example.com,api.example.com",
"action": "proxy",
"comment": "optional note"
}
matchsupports comma-separated patterns*matches everything- patterns without
*require exact hostname match - patterns with
*are treated as wildcards
Examples:
api.openai.com*.google.comgithub.**
Command
Inside Pi, run:
/proxy
Menu actions:
Turn ON/Turn OFFShow statsReload configShow rules
Behavior notes
Direct vs proxy vs fallback
direct: uses the original unpatched fetchproxy: usesundiciFetch(..., { dispatcher: new ProxyAgent(...) })fallback: tries direct first, then retries through proxy unless the failure is an abort/timeout-style error
What this package does not intercept
The patch only affects code that calls the patched globalThis.fetch after the extension has loaded.
It does not automatically intercept:
- code that cached the old
fetchbefore patching - code that imports
undici.fetchdirectly - other HTTP clients
Development
npm install
npm run check
npm run lint
Scripts
| Command | Description |
|---|---|
npm run check |
Run TypeScript type checking |
npm run lint |
Run ESLint |
npm run lint:fix |
Run ESLint with auto-fixes |
Project structure
.
├── index.ts # Pi extension entrypoint
├── eslint.config.js # ESLint flat config
├── tsconfig.json # TypeScript config
└── package.json # npm + Pi package metadata
Design choices
This package intentionally preserves the existing local behavior instead of fully copying upstream pi-proxy:
- config path stays
~/.pi/agent/proxy.json - config is re-read per request instead of cached in memory
- wildcard matching uses regex conversion
- fallback retries a broader set of non-abort failures
- proxy requests explicitly use
undici.fetch
License
MIT