/switch, /provider and the command palette, and cost tracking, failover chains, model routing, compaction and memory all run on top of it.
Preview. The protocol, the Go SDK and the
chatcli provider test conformance kit are available, so plugins can be built and verified today. Loading provider plugins into a running ChatCLI — process supervision, /switch, login and the encrypted credential store — is the next step of this feature and is not available yet.How it fits
ChatCLI keeps everything above the wire: the coder loop, tool execution, history, memory, compaction, prompt-cache planning, cost and failover. The plugin owns only how to reach the backend.Two modes
dialect
The plugin implements authentication (login, token, refresh) and the model list. ChatCLI talks to the backend with its built-in client for the wire format —
openai-chat, openai-responses, anthropic-messages or gemini — sending the plugin’s headers.Native tools, streaming, prompt caching and exact usage come for free. Prefer this mode whenever the backend speaks one of those formats.full
The plugin also implements chat over a normalized message schema: messages, tool calls, images, thinking blocks, streamed deltas and usage.Use it when the backend — or the SDK you are required to use — has a request format of its own.
Credentials stay with ChatCLI
The plugin never stores secrets. Its login ends with a credential — a flat key/value object — that ChatCLI encrypts, stores and hands back on every call that needs it. The login itself is a sequence of steps the plugin describes and ChatCLI renders:prompt fields, open_url and device_code. The plugin never touches the terminal, so the same flow works in the CLI, the web UI, IDE clients and messaging channels.
Gateway models keep their real limits and prices
Each listed model can name the built-in model it fronts with anupstream entry, for example {"provider": "CLAUDEAI", "model": "claude-sonnet-4-6"}. ChatCLI then reuses what it already knows about that model — context window, output limit, pricing and capabilities — unless the plugin sets them explicitly. A per-call cost reported by the gateway (costUSD) is treated as authoritative.
Build a plugin
- Go (SDK)
- Any language
The Go SDK, The repository ships a complete reference plugin in
github.com/diillson/chatcli/pkg/providersdk, implements the protocol. Implement Provider plus the interfaces that match your backend; the capabilities announced to ChatCLI are derived from them, so a plugin can never advertise something it does not serve.A minimal
dialect plugin for an OpenAI-compatible gateway:full mode — login, model list, streaming with cancellation, token counting and logout — at pkg/providersdk/examples/echo. It passes every conformance check and is the best starting point.Rules every plugin must follow
stdout carries protocol messages only
stdout carries protocol messages only
Anything else on stdout corrupts the stream. Log to stderr — ChatCLI keeps a tail of it — or send
$/log notifications.Provider names are unique and never shadow a built-in
Provider names are unique and never shadow a built-in
The name must match
^[A-Z][A-Z0-9_]{1,31}$ and can never be the name of a built-in provider (OPENAI, CLAUDEAI, BEDROCK, …). It is the value users pass to LLM_PROVIDER and /switch.Shutdown is ordered by arrival
Shutdown is ordered by arrival
Requests that arrived before
shutdown are still served; later ones fail with -32600. After exit, the process terminates with status 0.Error codes drive ChatCLI's reaction
Error codes drive ChatCLI's reaction
Verify a plugin with chatcli provider test
chatcli provider test runs the conformance kit against a plugin binary, talking to it over stdin and stdout exactly as ChatCLI does — the verdict is the same for a Go, Python or Java plugin.
upstream, non-negative limits and prices), chat results, streaming (the deltas must spell the final text), liveness after a cancelled request, token counting, a clean exit and stdout hygiene.
A check that needs something the run cannot provide is skipped with a hint, never failed:
auth.login asks for --input when a prompt field has no value, and a browser or device-code login asks for --credential-file.0 when nothing failed, 1 when a check failed and 2 on a usage error, so a plugin repository can gate its CI on it:
Security model
Signed binaries
Sign provider plugins with the same trusted-key tooling as tool plugins —
chatcli plugin keygen | sign | verify | trust — and ChatCLI verifies them with that mechanism when it loads them. See Signature Verification.Least environment
A plugin declares the env vars it reads (
authEnv). Those are the only credentials it should receive, and the secret redactor always treats them as secrets.No secrets in the plugin
Credentials live in ChatCLI’s encrypted store and are passed per call. A plugin that writes a secret to stdout or stderr is broken.
Conversations reach the plugin
A provider plugin sees every prompt sent through it, exactly like the vendor it fronts. Install only plugins you trust.
See also
Plugin System
Tool plugins (
@command) the model can call.Supported Models
The built-in providers and their models.
Provider Fallback
Failover chains across providers.
Cost Tracking
How usage and prices become
/cost.