pi-cliproxyapi-autoconnect1.2.8
Independent CLIProxyAPI provider for pi: sign in with your CLIProxyAPI domain and API key, auto-discover OpenAI-, Gemini-, or Anthropic-compatible endpoints, and register models in /model.
Untested on omp
This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.
Reports 0
No reports yet.
Readme
pi-cliproxyapi-autoconnect
An independent CLIProxyAPI provider for pi.
The extension adds CLIProxy to pi's /login flow. Enter the CLIProxyAPI bound domain and client API key once; the plugin derives the compatible endpoints, tests them automatically, downloads the model catalog, and registers every model in /model.
- Provider ID:
cliproxy - Models are listed as
cliproxy/<model-id> - Endpoint discovery order: OpenAI → Gemini → Anthropic (OpenAI first)
- No runtime dependencies beyond the packages pi already provides
This is a community extension. It is not an official CLIProxyAPI or pi package.
Links: npm package · pi package gallery · CLIProxyAPI
Requirements
- pi 1.2.0 or newer (tested with pi 1.2.x and 1.3.x)
- Node.js 22.19 or newer (required by pi)
- A running CLIProxyAPI instance whose OpenAI-, Gemini-, or Anthropic-compatible API you can reach
- A CLIProxyAPI client API key (configured in
access.api-keys)
The key you enter here is CLIProxyAPI's own client key — not an OpenAI, Anthropic, or Google upstream key.
Install
Install the extension through pi:
pi install npm:pi-cliproxyapi-autoconnect
Restart pi. On a running session, /reload also reloads extensions.
Confirm that pi has recorded the package:
pi list
Do not install this package with
npm install. It is a pi extension, not a standalone CLI; pi must install it so the extension is loaded and managed.
After installation, the provider appears in /login. The cliproxy/* models appear after the first successful login and model discovery. To verify the registered models at that point:
pi --list-models
Update
Update only this extension:
pi update npm:pi-cliproxyapi-autoconnect
Update every installed pi package:
pi update --extensions
Restart pi after updating.
pi update without a target updates pi itself. pi update --models refreshes pi's built-in or models.json catalog and does not refresh this extension's provider catalog; use /cliproxy refresh, open /model, or restart pi for that.
Uninstall
Before removing the extension, run /logout and select CLIProxy if you want to delete the saved API key from pi's auth.json. You can also remove the saved connection metadata with /cliproxy clear.
Then remove the package:
pi remove npm:pi-cliproxyapi-autoconnect
Restart pi. Removing the package does not automatically delete credentials from auth.json; remove them with /logout before uninstalling, or edit auth.json manually.
Migrating from pi-cliproxy
The package was renamed from pi-cliproxy to pi-cliproxyapi-autoconnect. The provider ID, model prefix, cliproxy.json format, and existing credentials are unchanged.
pi remove npm:pi-cliproxy
pi install npm:pi-cliproxyapi-autoconnect
Restart pi afterward. Models remain cliproxy/<model-id>, and no config or cache rebuild is required.
Quick start
- Start pi and run
/login. - Choose Sign in with an API key (not an account/subscription login).
- Select CLIProxy.
- Enter the bound domain, for example
proxy.example.comorhttps://proxy.example.com. - Enter the CLIProxyAPI client key.
- Wait for automatic endpoint discovery to finish.
- Run
/modeland select acliproxy/<model-id>entry.
Domain input
The value is normalized to a root URL before compatible endpoints are derived. You can paste a bare host, a full URL, or a complete compatible endpoint.
| You enter | Normalized root |
|---|---|
proxy.example.com |
https://proxy.example.com |
https://proxy.example.com/ |
https://proxy.example.com |
http://192.168.1.10:8317 |
http://192.168.1.10:8317 |
https://proxy.example.com/v1 |
https://proxy.example.com |
https://proxy.example.com/v1/models |
https://proxy.example.com |
https://proxy.example.com/cliproxy/v1 |
https://proxy.example.com/cliproxy |
Trailing slashes and common suffixes such as /v1, /v1beta, /v1/models, and /v1beta/models are removed. A reverse-proxy path prefix is preserved.
Without an explicit scheme, local and private hosts (localhost, 127.*, ::1, 10.*, 192.168.*, 172.16–31.*, .local, .lan) default to http://; public hosts default to https://. A bare host is also retried with the alternate scheme.
How discovery works
The plugin probes the compatible endpoints in this order and uses the first one that returns a non-empty model list:
| Priority | Protocol | Derived base URL | Model discovery |
|---|---|---|---|
| 1 | OpenAI compatible | <root>/v1 |
GET /v1/models |
| 2 | Gemini compatible | <root>/v1beta |
GET /v1beta/models |
| 3 | Anthropic compatible | <root> |
GET /v1/models?limit=1000 (best effort) |
The scheme (http or https) and any path prefix come from the normalized root. For example, with https://proxy.example.com, the OpenAI base URL is https://proxy.example.com/v1.
If you entered a bare host without a scheme, all three protocols are also tried with the alternate scheme, for at most six probes. OpenAI candidates run first, then Gemini, then Anthropic.
When discovery succeeds, the selected base URL, protocol, and model metadata are saved. The models are immediately available in /model.
If discovery fails
- No endpoint returned models, and at least one returned 401/403: the key is the likely problem. The plugin asks for the key again, retries every endpoint, and aborts without saving anything if authentication still fails.
- No endpoint returned models, and all probes failed with other errors (404, timeout, format error, etc.): the plugin reports each failure, probes
/healthzto check whether the service is CLIProxyAPI, and shows an endpoint picker:- Retry OpenAI compatible:
<root>/v1 - Anthropic compatible:
<root> - Gemini compatible:
<root>/v1beta - Custom compatible endpoint: enter a full base URL and choose a protocol
- Retry OpenAI compatible:
- An endpoint responded successfully with an empty model list: the picker is skipped and you are asked for model IDs manually. This usually means the upstream account has no available credentials.
- The selected endpoint still returns no model list: enter model IDs manually, separated by commas or spaces. You can leave this empty and add models later.
An Anthropic-compatible endpoint does not always expose a model list. If its list request returns 404/405/501, automatic discovery continues; after selecting that endpoint, enter model IDs manually.
/cliproxy command
/cliproxy Show the current endpoint, protocol, model count, and last error
/cliproxy refresh Refresh the model list immediately
/cliproxy clear Delete the saved config and its backup
The extension registers one top-level command, /cliproxy; refresh and clear are arguments, not separate slash commands. In the TUI, type /cliproxy (with a trailing space) to see argument completions.
The model catalog is cached for 5 minutes. Opening /model normally reuses the recent snapshot; /cliproxy refresh forces an upstream refresh.
Signing out and reconfiguring
/logout removes the API key from pi's auth.json but keeps cliproxy.json, so a later /login can reuse the saved domain and endpoint. While signed out, /cliproxy reports that CLIProxy is not signed in instead of showing the old endpoint as active.
Use /cliproxy clear to delete the saved domain, endpoint, and model cache. It does not sign you out; use /logout if you also want to delete the API key from auth.json. To change the domain or key, run /login → CLIProxy again. If you switched to a different domain and the previous models are still visible, run /reload or restart pi so the provider is rebuilt from the new config.
Files and security
Paths below use pi's default agent directory, ~/.pi/agent (on Windows, %USERPROFILE%\.pi\agent). If PI_CODING_AGENT_DIR is set, pi uses that directory instead.
| Content | Location |
|---|---|
| API key | <agent-dir>/auth.json (written and managed by pi) |
| Domain, endpoint, protocol, model cache | <agent-dir>/cliproxy.json |
| pi model catalog cache | <agent-dir>/models-store.json (maintained by pi) |
The API key is stored by pi's login flow in auth.json. This extension does not write the key to cliproxy.json.
Example cliproxy.json:
{
"version": 2,
"domain": "proxy.example.com",
"rootUrl": "https://proxy.example.com",
"baseUrl": "https://proxy.example.com/v1",
"api": "openai-completions",
"models": [
{
"id": "gemini-2.5-pro",
"name": "gemini-2.5-pro",
"ownedBy": "google",
"reasoning": false,
"input": ["text"],
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
"contextWindow": 1000000,
"maxTokens": 65536
}
],
"source": "auto",
"updatedAt": 0
}
Notes:
- The previous config is saved as
cliproxy.json.bakbefore each write, for manual recovery. /logoutremoves the credential fromauth.jsonbut keepscliproxy.json; use/cliproxy clearto delete the saved config as well.- Removing the extension does not by itself remove credentials from
auth.json. Run/logoutbefore uninstalling, or editauth.jsonmanually. - Treat
auth.jsonas sensitive. Do not commit it, share it, or include it in bug reports.
Model capabilities
Model list endpoints usually return only model IDs and, sometimes, an owner. The extension also reads the extended fields that richer OpenAI-compatible endpoints expose:
- context:
context_length,context_window,context_window_tokens,inputTokenLimit, ortop_provider.context_length - output:
max_output_tokens,max_completion_tokens,max_tokens,outputTokenLimit, ortop_provider.max_completion_tokens - display name:
display_name,displayName, orname(whenidis also present) - images:
supports_imageorinput - reasoning:
thinking(enabled/disabled),supports_reasoning,reasoning, orreasoning_effort_config.support_thinking
capability: "reasoning_model" is intentionally not treated as a thinking toggle: it is too broad and would advertise thinking controls that the model does not expose. Likewise, reasoning_effort_config.support_thinking: false only means the endpoint has no effort knob; it is not treated as proof that the model cannot reason.
The extension resolves capability fields (name, reasoning, input, cost, contextWindow, maxTokens) in this order:
- The same model ID in
<agent-dir>/models.json(explicit user config, highest priority) - Metadata returned by the model list endpoint, or already stored in
cliproxy.json - The same model ID cached by pi in
<agent-dir>/models-store.json - pi's built-in model catalog (after removing prefixes such as
cn:,global:, andmodels/) - Conservative guesses based on the model name and protocol
For models.json, entries from the cliproxy provider or from a provider whose baseUrl points at the same endpoint win over unrelated providers with coincidentally identical model IDs.
This means an existing hand-written provider for the same CLIProxyAPI instance can supply more accurate metadata, and upgrading from an older version does not lose it.
When no metadata is available, the guesses are:
claude*or Anthropic protocol: 200K context, 64K max outputgemini*or Gemini protocol: 1M context, 65,536 max outputgpt-5*,gpt-6*,gpt-7*: 272K context, 128K max outputo1–o9: 200K context, 100K max output- GLM / Kimi / Qwen / Doubao / DeepSeek / MiniMax / MiMo: family-specific windows between 200K and 512K
- everything else: 128K context, 32K max output
- text input only, reasoning disabled, cost set to 0
Guesses and values inherited from models-store.json are not frozen into cliproxy.json; only explicit models.json metadata and fields returned by the model-list endpoint are persisted there. When the endpoint starts declaring a field, its value wins over cached guesses.
If a model's real capabilities differ, add its metadata to <agent-dir>/models.json; the extension will inherit it. The fallback guesses are only a last resort, and guessLimits() / modelMetadataFromRecord() in parsing.ts control them. For a development copy, edit those functions and run /reload; do not edit the installed package in place.
Refresh and failure behavior
- Model-list responses are capped at 8 MiB and 10,000 entries.
- Discovery probes compatible endpoints in parallel; the first non-empty list in protocol order wins.
- A transient empty upstream list no longer wipes the cached catalog; the previous models are kept and an error is recorded.
- Failed refresh attempts are negatively cached for 60 seconds so opening
/modeldoes not hammer a dead proxy. - If
cliproxy.jsonis unreadable, the previous generation (cliproxy.json.bak) is loaded instead. - The API key is sent to Gemini-compatible endpoints as an
x-goog-api-keyheader first; the?key=query form is only retried for endpoints that reject the header.
Troubleshooting
The extension does not appear after installation
- Run
pi listand confirm thatnpm:pi-cliproxyapi-autoconnectis present. - Restart pi, or run
/reload. - Check that pi is version 1.2.0 or newer.
- Check the startup diagnostics for extension load errors.
401 / invalid API key
The client key lives in access.api-keys in the CLIProxyAPI v8 config (the top-level api-keys in older versions):
access:
api-keys:
- sk-your-real-key
/v1/models requires authentication unless the server has no keys configured.
Login tries every compatible endpoint first. If no endpoint returns models and at least one returns 401/403, the plugin prompts for the key again and retries. If authentication still fails, login aborts and does not save the config.
403 unsafe_example_api_key
CLIProxyAPI detected that an example key (your-api-key-1, etc.) is still in use. Replace access.api-keys with a real key and restart CLIProxyAPI.
/v1/models returns an empty list
This is a valid response: there may be no available upstream credentials, or all of them may be cooling down. Configure or sign in to the upstream accounts in CLIProxyAPI, then run /cliproxy refresh.
/healthz works but /v1/models returns 404
CLIProxyAPI itself expects to be served at the root path. If nginx or Caddy adds a path prefix, configure the reverse proxy to strip it before forwarding. For example:
location /cliproxy/ {
proxy_pass http://127.0.0.1:8317/; # trailing slash removes the /cliproxy prefix
}
Alternatively, choose Custom compatible endpoint in the plugin and enter the exact base URL exposed by the reverse proxy.
Streaming disconnects mid-response
CLIProxyAPI recommends increasing nginx's proxy_read_timeout. Cloudflare's free-plan 100-second timeout can also truncate long streaming responses.
No models visible in /model
/modellists models only from providers with configured authentication. Complete/loginfirst.- Run
/cliproxyto check the endpoint, protocol, model count, and last error. - Run
/cliproxy refreshto retry discovery. - Run
pi --list-modelsand confirm thatcliproxy/*entries exist.
The same models appear twice
If /model shows both cliproxy/* and cliproxyapi/* entries, both this extension and the separate @router-for-me/pi-cliproxyapi-provider package are installed. They are independent providers. Remove the one you do not need:
pi remove npm:@router-for-me/pi-cliproxyapi-provider
or
pi remove npm:pi-cliproxyapi-autoconnect
Restart pi afterward.
Models look stale after changing the domain
Run /reload, or restart pi. The model list is also refreshed whenever /model is opened and the cached snapshot is older than five minutes.
Development
The published npm tarball contains the full extension source (index.ts), README.md, LICENSE, and package.json. There is no build step and no compiled output.
To try the published source without adding it to pi's settings:
npm pack pi-cliproxyapi-autoconnect
tar -xzf pi-cliproxyapi-autoconnect-*.tgz
pi --extension ./package/index.ts
The extension depends only on packages supplied by pi at runtime:
@earendil-works/pi-ai@earendil-works/pi-coding-agent
Core implementation points in index.ts:
runLogin()— domain, key, endpoint discovery, and fallbackrefreshProviderModels()— startup,/model, and/cliproxy refreshrefreshesbuildProvider()— registers the native pi-ai provider;apiKey.loginmakes it appear in/login
CLIProxyAPI reference: https://github.com/router-for-me/CLIProxyAPI
Changelog
1.2.8
- Read the extended model-list fields: context/output aliases (
context_window,max_tokens,max_completion_tokens,inputTokenLimit,outputTokenLimit,top_provider.*), display names,supports_image, and the reasoning signals (thinking,supports_reasoning,reasoning_effort_config.support_thinking). - Never freeze guesses or models-store values into
cliproxy.json; only explicitmodels.jsonmetadata and fields returned by the endpoint are persisted, so a one-time wrong 128K guess can no longer survive future refreshes. - Keep the cached catalog when the upstream transiently returns an empty model list.
- Recover from an unreadable
cliproxy.jsonby loadingcliproxy.json.bak. - Negatively cache failed refreshes for 60 seconds and stop
unsupportedendpoints from being probed on every/modelopen. - Cap model-list responses at 8 MiB / 10,000 entries and stream-read them instead of buffering without limit.
- Send the Gemini-compatible API key as
x-goog-api-keyinstead of putting it in the query string. - Follow Anthropic model-list pagination (
has_more/last_id). - Probe compatible endpoints in parallel during login.
- Scope
models.jsonmetadata to providers pointing at the same endpoint. - Strip terminal control sequences from upstream-provided IDs, names, and error text.
- Validate custom endpoints as http(s) URLs and keep
rootUrlin sync with them. - Redact URL credentials before storing the domain.
- Fix the stale hard-coded
User-Agentversion; it now comes frompackage.json. - Extract pure parsing/URL helpers into
parsing.tsand add unit tests (npm test).
1.2.7
- Read
context_lengthandmax_output_tokensfrom OpenAI-compatible model lists when the endpoint provides them, instead of discarding the fields and falling back to the conservative 128K / 32K guesses. - Models exposed as separate large-context variants (for example
*-max) now inherit their declared context window.
1.2.6
- Clarified that
/cliproxy clearremoves saved connection metadata but does not sign out. - Clarified model capability overrides and warned against editing an installed package in place.
- Tightened the discovery-failure and private-host wording.
1.2.5
- Documentation and metadata release.
- Made
pi install npm:pi-cliproxyapi-autoconnectthe documented installation path and removed local-directory and script instructions. - Standardized command examples for a public audience.
- Clarified update/uninstall behavior, endpoint normalization, discovery fallback, model capability overrides, and troubleshooting.
1.2.4
- Added argument completions for
/cliproxy: typing/cliproxynow suggestsrefreshandclearin the TUI. - The extension still registers a single top-level command; subcommands remain arguments rather than separate slash commands.
1.2.3
/cliproxynow checks whether CLIProxy is actually signed in. After/logoutit reports “not signed in” instead of displaying the previous endpoint and model count as if they were active.- Added
/cliproxy clearto deletecliproxy.jsonand its backup when the saved config should not be reused. /cliproxy refreshrefuses to run while signed out.
1.2.2
- Rewrote the README in English for the npm package page and the pi package gallery.
- Translated the npm package description to English.
- The pi TUI remains fully English.
1.2.1
- All pi TUI strings are now English: login prompts, endpoint picker, errors, and
/cliproxyoutput. - The provider display name remains
CLIProxy; the/loginentry,/cliproxycommand, andcliproxy/model prefix are unchanged.
1.2.0
- Renamed the package from
pi-cliproxytopi-cliproxyapi-autoconnect; the provider ID,cliproxy.json,/cliproxycommand, andcliproxy/model prefix are unchanged. - Login now tries every compatible endpoint automatically: OpenAI → Gemini → Anthropic, OpenAI first; the first non-empty model list wins.
- A bare domain also tries both https and http for every protocol, for up to six candidates.
- Added best-effort discovery of Anthropic's
/v1/models; if the endpoint is missing (404/405/501), fall back to manual model IDs instead of skipping Anthropic entirely. - When every endpoint fails and at least one returned 401/403, the plugin asks for the key again. When an endpoint returns an empty list, it skips the endpoint picker and goes straight to manual input.
/cliproxy refreshkeeps the cache when the Anthropic endpoint has no model list; it does not persist a refresh error in that case.
1.1.0
- On 401/403 during login, prompt for the key again instead of incorrectly entering the endpoint picker; if the second attempt fails, abort without saving the config.
cliproxy.jsonnow stores complete model metadata (reasoning / input / cost / contextWindow / maxTokens) and keeps a.bakbackup.- Model refresh now has a five-minute TTL;
/cliproxy refreshstill forces a refresh. - Capability metadata now also comes from
models-store.jsonand pi's built-in catalog, so upgrading from an older config does not lose information. - Refresh failures persist
lastErrorto the config, so/cliproxycan show the last error after a restart.