Wiremux

Map Chat Completions, Messages, Responses, Gemini, and Converse through one in-process IR. Refresh tokens from the same pasteable vendor profiles. The host keeps the agent loop.
Crates
| Crate | Job |
|---|---|
wiremux (docs) |
Dialect maps (decode / encode / stream) plus optional CLI and loopback proxy |
wiremux-auth (docs) |
Profile catalog and TokenProvider (static, OAuth, GCP, Azure, AWS) |
Maps-only hosts depend on wiremux with default-features = false.
That path does not pull clap, tokio, reqwest, or aws-lc.
This repository may be ahead of crates.io. Host attach notes in
docs/CONSUME.md pin the published cut.
Install
MSRV is 1.95 (see rust-toolchain.toml).
CLI and proxy:
GitHub Release archives, provenance, and the other installers are
described in SUPPORT.md.
Maps-only hosts stop after the first command. TokenProvider hosts
also add wiremux-auth.
Maps
Decode a vendor JSON body into IrRequest, then encode another wire.
The profile supplies vendor quirks. Encode-side loss is typed
(preserve / degrade / drop / harderror).
wiremux map prints one stderr line per change:
degrade sampling.max_tokens: messages requires max_tokens
use ;
let src = br#"{"model":"gpt-4o","messages":[{"role":"user","content":"ping"}]}"#;
let = decode.unwrap;
let profile = load_profile_for_wire
.unwrap;
let = encode.unwrap;
Run the same program from this tree:
That example prints the encoded JSON. Loss, when there is any, is the Debug form of the report on stderr.
wiremux map prints the encoded body on stdout and the loss lines
above on stderr. It has no --dump-loss flag.
Wires: chat-completions (CLI also accepts chat), messages,
responses, gemini, converse. Profile TOML uses
wire = "chat-completions", not wire = "chat".
Auth and profiles
Shipped vendors are ordinary TOML. A gist uses the same schema, so a
rotated token URL, client id, or beta header does not need a crate
release. Profiles are data: no functions, no !command, no
URL-as-script. $VAR / ${VAR} / {env:VAR} are allowed.
wiremux auth login needs a profile id (--profile or the
positional argument). Omitting it exits 1.
The command follows the profile login engine. Shipped
openai-codex-oauth uses login = "none" until a public Wiremux
client id exists. wiremux auth login --profile openai-codex-oauth
exits 2 and prints why (set pkce or device, and a client id).
login = "setup-token" (shipped Anthropic) prints
setup_token_hint and also exits 2.
wiremux profile ingest writes user-dir profiles from
models.dev (default) or LiteLLM
(--source litellm). --dry-run prints the paths and does not
write. Catalog misses fail closed.
Proxy
Loopback only (127.0.0.1). Incoming harness dialect is --from.
Upstream comes from --profile.
The default listen address is 127.0.0.1:0. After bind, stdout prints
listening on 127.0.0.1:<port>. Point the harness at that address.
A bad --listen value and --read-timeout-secs 0 are reported
before the profile is loaded.
--dump-loss prints loss.encode: plus each loss event on stderr
per request. wiremux map does not take this flag.
Host attach
How a host application should pin, wrap TokenProvider, and map at
the adapter boundary: docs/CONSUME.md.
Architecture (IR, loss, what stays in the host):
docs/ARCHITECTURE.md.
Copy-paste examples: examples/.
Status
0.x. Public IR and error enums are #[non_exhaustive]. Dual license
MIT OR Apache-2.0.
This crate is not a LiteLLM clone, not a desktop switcher, and not a subscription pool. It does not ship a public Claude-Pro-in-Codex, Cline, or OpenCode preset.
Contributing
See CONTRIBUTING.md. make check is the local
gate. Commits need git commit -s (DCO). Questions:
SUPPORT.md. Maintainer rules:
GOVERNANCE.md.
Security reports go to SECURITY.md, not a public
issue.