omp packages

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.

zorik181 Published 7 days ago MIT ~185 downloads/mo

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.

Did it work for you?

Result

One report per person. A new report replaces your old one.

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

  1. Start pi and run /login.
  2. Choose Sign in with an API key (not an account/subscription login).
  3. Select CLIProxy.
  4. Enter the bound domain, for example proxy.example.com or https://proxy.example.com.
  5. Enter the CLIProxyAPI client key.
  6. Wait for automatic endpoint discovery to finish.
  7. Run /model and select a cliproxy/<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

  1. 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.
  2. No endpoint returned models, and all probes failed with other errors (404, timeout, format error, etc.): the plugin reports each failure, probes /healthz to 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
  3. 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.
  4. 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.bak before each write, for manual recovery.
  • /logout removes the credential from auth.json but keeps cliproxy.json; use /cliproxy clear to delete the saved config as well.
  • Removing the extension does not by itself remove credentials from auth.json. Run /logout before uninstalling, or edit auth.json manually.
  • Treat auth.json as 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, or top_provider.context_length
  • output: max_output_tokens, max_completion_tokens, max_tokens, outputTokenLimit, or top_provider.max_completion_tokens
  • display name: display_name, displayName, or name (when id is also present)
  • images: supports_image or input
  • reasoning: thinking (enabled/disabled), supports_reasoning, reasoning, or reasoning_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:

  1. The same model ID in <agent-dir>/models.json (explicit user config, highest priority)
  2. Metadata returned by the model list endpoint, or already stored in cliproxy.json
  3. The same model ID cached by pi in <agent-dir>/models-store.json
  4. pi's built-in model catalog (after removing prefixes such as cn:, global:, and models/)
  5. 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 output
  • gemini* or Gemini protocol: 1M context, 65,536 max output
  • gpt-5*, gpt-6*, gpt-7*: 272K context, 128K max output
  • o1–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 /model does not hammer a dead proxy.
  • If cliproxy.json is unreadable, the previous generation (cliproxy.json.bak) is loaded instead.
  • The API key is sent to Gemini-compatible endpoints as an x-goog-api-key header first; the ?key= query form is only retried for endpoints that reject the header.

Troubleshooting

The extension does not appear after installation

  • Run pi list and confirm that npm:pi-cliproxyapi-autoconnect is 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

  • /model lists models only from providers with configured authentication. Complete /login first.
  • Run /cliproxy to check the endpoint, protocol, model count, and last error.
  • Run /cliproxy refresh to retry discovery.
  • Run pi --list-models and confirm that cliproxy/* 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 fallback
  • refreshProviderModels() — startup, /model, and /cliproxy refresh refreshes
  • buildProvider() — registers the native pi-ai provider; apiKey.login makes 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 explicit models.json metadata 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.json by loading cliproxy.json.bak.
  • Negatively cache failed refreshes for 60 seconds and stop unsupported endpoints from being probed on every /model open.
  • 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-key instead 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.json metadata 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 rootUrl in sync with them.
  • Redact URL credentials before storing the domain.
  • Fix the stale hard-coded User-Agent version; it now comes from package.json.
  • Extract pure parsing/URL helpers into parsing.ts and add unit tests (npm test).

1.2.7

  • Read context_length and max_output_tokens from 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 clear removes 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-autoconnect the 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 /cliproxy now suggests refresh and clear in the TUI.
  • The extension still registers a single top-level command; subcommands remain arguments rather than separate slash commands.

1.2.3

  • /cliproxy now checks whether CLIProxy is actually signed in. After /logout it reports “not signed in” instead of displaying the previous endpoint and model count as if they were active.
  • Added /cliproxy clear to delete cliproxy.json and its backup when the saved config should not be reused.
  • /cliproxy refresh refuses 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 /cliproxy output.
  • The provider display name remains CLIProxy; the /login entry, /cliproxy command, and cliproxy/ model prefix are unchanged.

1.2.0

  • Renamed the package from pi-cliproxy to pi-cliproxyapi-autoconnect; the provider ID, cliproxy.json, /cliproxy command, and cliproxy/ 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 refresh keeps 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.json now stores complete model metadata (reasoning / input / cost / contextWindow / maxTokens) and keeps a .bak backup.
  • Model refresh now has a five-minute TTL; /cliproxy refresh still forces a refresh.
  • Capability metadata now also comes from models-store.json and pi's built-in catalog, so upgrading from an older config does not lose information.
  • Refresh failures persist lastError to the config, so /cliproxy can show the last error after a restart.

License

MIT