Tracking Five Upstreams, Fuzzing the Parsers, and a Front Door: What Changed in llm-cli-gateway The llm-cli-gateway project released v1.16.0 through v1.16.2 and landed upstream-tracking and parser-hardening work on main, now tagged as v1.17.0 and v1.17.1. The gateway now tracks each of five provider CLIs' upstream contracts as checked-in artifacts, validated by CI tests and an offline re-validation gate, while a fuzzing pass hammers the three parsers that handle untrusted bytes from provider JSON/JSONL, Linux /proc, and the CLI argument sanitizer. A new website at llm-cli-gateway.dev serves as the project's front door, built agent-first so an MCP client can read one URL and configure itself. The last two posts were about features you can call: cache-aware spawning https://dev.to/wernerk au/cache-aware-spawning-what-changed-in-llm-cli-gateway-a-week-on-1dle across five providers, and the round before that. This one is mostly about the parts that do not show up as a tool. When you wrap five vendor CLIs that each ship on their own cadence, the interesting failure mode is not a bug in your code, it is one of those five CLIs quietly changing a flag underneath you. So the work that landed this week is about keeping pace with upstreams that move, hardening the bits that parse untrusted output, and finally, giving the project a front door. v1.16.0 through v1.16.2 are tagged and out; the upstream-tracking and Socket-hardening work changelogged as v1.17.0 and v1.17.1 , plus a fast-check fuzzing pass and a dependency-floor bump, have landed on main and go out in the next cut; and the website is now live at llm-cli-gateway.dev https://llm-cli-gateway.dev/ , the project's new front door. Short version: the gateway now tracks each provider CLI's upstream contract as a checked-in artefact. The contract table is pinned by tests that run in CI, an offline npm run upstream:contracts gate re-validates it on demand, and an advisory npm run upstream:scan -- --live reaches out to the upstream changelogs to flag where reality may have moved, so drift surfaces in a check I run rather than as a failed request on a user's machine. A fast-check fuzzing pass now hammers the three parsers that touch untrusted bytes, provider JSON/JSONL, Linux /proc , and the CLI argument sanitizer. Release tags can be Sigstore-signed through a dedicated workflow, the optional Redis layer is gone, and on main the dependency floor has moved to Zod 4 / TypeScript 6 / ESLint 10. And there is now a real website at llm-cli-gateway.dev , built agent-first: an MCP client can read one URL and configure itself. Long version is below, same shape as last time, problem, what changed, what it now does, caveats named up front rather than buried. The motivating incident is worth naming because it is the whole argument. Mistral's Vibe CLI dropped --output-format in favour of --output text|json|streaming . Nothing in the gateway's own code was wrong; the flag it had been emitting for weeks simply stopped existing on the other side of the spawn . v1.16.1 fixed the call and kept the legacy MCP aliases mapping plain → text and stream-json → streaming so nobody's saved config broke , but a one-line flag rename that only surfaces as a runtime failure on a user's machine is exactly the class of problem I would rather catch in CI. So the upstream-tracking work changelogged as v1.17.0, landed on main makes the contract a first-class, checked-in thing: claude , codex , gemini , grok , mistral gets a src/upstream-contracts.ts , exercised by the argument and env validators. Alongside it, docs/upstream/provider-sources.dag.toml is the scanner's upstream-sources.test.ts pins that separation. The source map stays byte-for-byte in sync with the contract table's metadata, scripts/upstream-scan.mjs backs two npm scripts. npm run upstream:contracts is an npm run upstream:scan is network-free by default too; pass --live npm run upstream:scan -- --live and it fetches the tracked upstream changelogs and flags, advisorily, where reality may have moved ahead of us. Neither is wired into the CI gate today, they're tools I run; the TS-contract-vs-source-map sync, however, The honest caveat: the live scan is advisory, not authoritative. It tells me where to look; it does not auto-patch a renamed flag, and it never will, because a CLI changing its surface is a thing a human should read and reason about, not a thing a script should silently adapt to. What changed is that the looking is now systematic instead of "wait for a user to file an issue." A gateway that spawns five CLIs and reads back their output has a clear trust boundary: everything coming back over stdout/stderr is, from the gateway's point of view, untrusted. Most of it is well-formed. The interesting question is what happens when it is not. So fast-check is now wired into the suite src/ tests /fuzz.test.ts , and it targets the three places where malformed input would actually hurt: /proc parsers /proc/