Model or dataset
silasxbt/anti-api avatar
silasxbt/anti-api

anti-api: a local proxy that speaks OpenAI and Anthropic to six provider CLIs

Turn Antigravity / codex / github copilot into Anthropic & Openai API compatible server. Usable with Claude Code / Xcode etc.

518 stars49 forksTypeScriptMIT

At a glance

What is it?
anti-api is a TypeScript and Rust proxy that exposes OpenAI-style and Anthropic-style endpoints backed by provider command line tools, so tools such as Claude Code or Xcode can talk to an Antigravity, Codex, Copilot, Zed, Kiro or Grok account the operator already has. It is fast moving, MIT licensed, and unusually explicit about the fact that it is an unofficial interoperability layer whose compatibility with upstream providers is not guaranteed.
Who is it for?
anti-api fits a developer who already pays for one or more provider CLI accounts and wants a single OpenAI or Anthropic compatible endpoint so that editors and agents can use them, with routing, quota visibility and failover handled in one place. It does not fit anyone without their own authorised provider accounts, and it should not be treated as a stable product contract, since the upstream endpoints it depends on can change without notice.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 38 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A compatibility shim in front of provider command line tools

anti-api describes itself as an independent local protocol-compatibility and routing proxy for OpenAI-style and Anthropic-style clients. The repository description is blunter about what it is for: turn Antigravity, Codex and GitHub Copilot into an Anthropic and OpenAI API compatible server, usable with Claude Code, Xcode and similar tools.

So the shape of it is a server you run locally that speaks the request formats those tools expect, and forwards each request to whichever provider account you have connected. The audience is a developer with existing subscriptions to developer-oriented assistants who wants to point one tool at one base URL instead of juggling accounts.

The project is built in TypeScript on Bun with a Rust component underneath. The package.json shows the runtime stack: hono for the HTTP layer, better-sqlite3 for the quota store, undici for outbound calls, citty for the command line, consola for output, localtunnel for a tunnel, connectrpc and its node and web variants, and the AWS CodeWhisperer streaming client. The repository layout confirms the split, with rust-proxy/ holding the Rust side and src/ the TypeScript server, alongside a Dockerfile, packaging/ and scripts/ directories, and documentation files including MULTI-ACCOUNT.md, SECURITY.md and CLAUDE.md.

The provider list in the release notes is the concrete feature set. Six providers can be imported, listed, quota-checked and routed from the dashboard: Antigravity, ChatGPT Codex, GitHub Copilot, Zed hosted models, Amazon Kiro and xAI Grok.

The homepage for the project is its own quota page, at http://localhost:8964/quota, which tells you the dashboard is the centre of the product.

The README leads with a warning, and that is the right place to start

The first substantive paragraph of the README is titled Scope and authorization, and it is the most important text in the project for anyone evaluating it.

It says Anti-API is an independent, unofficial interoperability project. Some integrations use provider CLI, web or internal endpoints and may break without notice. Compatibility does not imply provider affiliation or endorsement. And the instruction to the user is to use only accounts and services you own or are explicitly authorized to administer, subject to each provider's current terms, and not to disable security updates or provider controls to preserve compatibility.

That is a candid statement of the risk model, and it changes how you should read everything else. This is not an API vendor with a stability promise. It is a translation layer over endpoints that another company controls and can change. When a provider changes the shape of its CLI protocol, this project breaks, and the release notes even record a case where the compatibility shim had to add a client-version refresh with pin and disable overrides to keep up with Antigravity.

The last clause is the one to hold on to. The project asks users not to defeat provider protections to preserve compatibility. A tool that did the opposite would be a different product with a different risk profile, and the maintainers have explicitly not built that.

So the evaluation question is not only technical. Before you run it, you need to know whether your account and your usage pattern are permitted under the provider's terms, and whether the accounts involved are ones you are entitled to administer. Everything else in this article assumes that question has been answered yes.

Two listeners, one open to inference and one locked to loopback

The security architecture is described in the v3.2.0 notes and it is the part to understand before pointing anything at the server.

There is a public listener for remote inference, on port 8966 by default, and it is inference-only and token-gated with ANTI_API_PUBLIC_TOKEN. The dashboard and the management API remain loopback and token protected, including in container mode. So the design is that the inference endpoint may be reachable from elsewhere if you deliberately expose it and set a token, while the parts that can import accounts, read configuration and show quotas stay bound to the local machine.

The Docker Compose file shipped in the repository shows how that is expressed in configuration. The default port mapping binds to the loopback address only:

yaml
    image: ghcr.io/silasxbt/anti-api:latest
    ports:
      - "127.0.0.1:8964:8964"
      - "127.0.0.1:1455-1465:1455-1465"
      - "127.0.0.1:51121-51131:51121-51131"

The two ranges are OAuth callback ports, which is why they are mapped at all. The environment block sets the data directory, the host, the container control plane flag, and requires a control token with an explicit error message if it is missing:

yaml
    environment:
      ANTI_API_DATA_DIR: /app/data
      ANTI_API_HOST: "0.0.0.0"
      ANTI_API_CONTAINER_CONTROL_PLANE: "1"
      ANTI_API_CONTROL_TOKEN: "${ANTI_API_CONTROL_TOKEN:?set ANTI_API_CONTROL_TOKEN to protect the container control plane}"

Public inference is opt-in. The compose file ships the mapping for it commented out, with a note to set ANTI_API_PUBLIC_TOKEN before exposing it. A project that fails closed when the token variable is unset is a project whose defaults were chosen by someone who has thought about the failure mode.

Routing that keeps a cursor, a quota store and a cooldown list

The interesting engineering is in the routing layer, and the v3.2.0 notes describe it in enough detail to be useful.

Provider compatibility work in that release covers Antigravity Gemini 3.1 request encoding, dynamic Copilot and model normalization, Codex reasoning-effort handling, and Responses API multimodal conversion for Zed, Codex and Grok. The routing itself preserves a sticky cursor and wraps through every eligible fallback entry, which means a conversation stays on the account it started on, and a failure moves the request along the fallback chain rather than restarting it.

Models are discovered per account rather than hard-coded. Routing fetches live models from each available Codex and Copilot account, and includes Zed account-level model sync. Zed accounts can be imported one by one and kept in the project, but cannot be bulk auto-discovered the way Codex and Copilot accounts can. That asymmetry is a provider limitation rather than a design choice in the proxy, and it is the kind of detail that only shows up in the notes of a project that is actually used against live accounts.

Failure handling is described as cooldown-aware 404 and 429 failover. Request bodies and streams are bounded, request aborts are propagated through routed providers, and upstream response bodies and credential data were removed from the logs. The quota store, backed by better-sqlite3, is what lets the dashboard show remaining quota per account, and the quota page at http://localhost:8964/quota is where you see it.

For images, the inputs are validated, size-bounded, SSRF-protected, and converted to provider-native inputs without dropping supported image parts, so an OpenAI image_url block and an Anthropic base64 block both survive the trip.

OAuth flows with PKCE validation and sanitised errors

Account import is where a project like this usually leaks secrets or goes wrong, and the release notes treat it as a first-class concern.

The v3.2.0 notes list hardened PKCE and state validation, loopback callback handling, Antigravity client-version refresh with pin and disable overrides, explicit Zed credential import, and sanitized login and diagnostic errors. The Grok work in v3.1.0 added account import through an explicit user action that imports an existing local CLI session, with no standalone login flow added, and the notes are explicit that provider policy, quota and account enforcement decisions still apply.

Two patterns are worth naming. First, the import is explicit and user-initiated, so nothing is harvested silently from a session the user did not open. Second, the diagnostics panel is localhost-only, and it checks for missing account files, CLI tools, callback ports and provider setup, which is the difference between a helpful error and a support ticket.

Credential storage is described in the feature set: passwords and private keys are stored in the iOS Keychain, which is specific to the Remux-style mobile client and not part of this project, so ignore that detail here. What applies to anti-api is the container layout, where HOME and ANTI_API_DATA_DIR are both set to /app/data, and where the compose file shows optional read-only mounts for existing host credentials:

yaml
      # - ${HOME}/.codex:/app/data/.codex:ro
      # - ${HOME}/.cli-proxy-api:/app/data/.cli-proxy-api:ro

Read-only mounts for credential directories are the right pattern, since the container reads the provider's existing session files and never needs to write them.

The Dockerfile also carries a health check that verifies the control token is present and queries an auth status endpoint:

dockerfile
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
    CMD test -n "$ANTI_API_CONTROL_TOKEN" && curl -fsS -H "x-api-key: $ANTI_API_CONTROL_TOKEN" http://127.0.0.1:8964/auth/status > /dev/null || exit 1

Note that the health check fails closed when the token is unset, which is the same philosophy as the compose file's required variable.

Three ways to install and one warning about self-updates

anti-api distributes through the package managers you would expect, and the release notes are unusually candid about how each behaves.

Homebrew is the cleanest route. The v2.9.0 notes record a stable Homebrew package that installs a prebuilt macOS Apple Silicon bundle, so brew install anti-api no longer depends on local Rust, LLVM or Bun downloads. WinGet support added Windows portable packaging, WinGet manifest generation and a release workflow for winget install anti-api, with portable bundles and checksums. Docker is the third route, using a prebuilt multi-arch image from GHCR with docker compose pull, or docker compose up --build to build locally, and the v3.2.2 release was precisely a fix to the Dockerfile health-check instruction so that multi-architecture images build with Docker Buildx.

What is interesting is the update contract. The release notes describe package-manager safeguards: Homebrew and WinGet installs redirect updates to brew upgrade anti-api and winget upgrade anti-api instead of self-overwriting. A tool that installs itself over your own installation is a recurring source of breakage, and the maintainers chose to hand that job to the package manager.

For developers, the project runs directly on Bun, and the package.json scripts are short:

json
  "scripts": {
    "dev": "bun run --watch src/main.ts start",
    "start": "bun run src/main.ts start",
    "build": "bun build src/main.ts --outdir dist --target bun",
    "test": "bun test ./test --test-concurrency 1",

The Dockerfile installs python3, make, g++, curl and ca-certificates on top of the Bun image, fetches the ngrok binary for the tunnel, and runs the server with bun run src/main.ts start.

A fast release cadence and a strict separation between the loop and the release

The version history explains how fast this project moves and, more interestingly, how the author tests it.

The recent releases are v3.2.2 on 2026-09-15, v3.2.1 on the same day, and v3.2.0 on 2026-08-31. Two releases in a single day, a month after the previous minor line, is the rhythm of a project chasing upstream providers rather than shipping features on a schedule.

What is documented is the verification behind each release. The v3.2.1 notes say release validation covered 196 Bun tests, a Rust release compilation, both Bun entrypoint bundles, and a compiled-runtime smoke test covering both loopback listeners, sidecar authentication, graceful shutdown, one-shot behaviour and forced-startup cleanup. The v3.2.0 notes list the TypeScript check, 190 Bun tests, Rust tests and the release build, the production dashboard bundle, the archive layout, checksum generation and local HTTP smoke checks. The v3.2.1 entry also describes a fix to make the Bun test suite deterministic, because shared Codex and Copilot module mocks were exposing an incomplete runtime surface and letting test file order produce false missing-export failures.

That level of release discipline in a fast-moving project is worth something. It also makes clear what the release notes are for: they are a changelog of compatibility work, not of features.

The licence is MIT, declared in the package.json and present as a LICENSE file in the repository root. The package is marked private, meaning it is not published to a registry under that name. On activity, the last push was on 2026-09-15, matching the newest release.

Editorial conclusion

anti-api fits a developer who already pays for one or more provider CLI accounts and wants a single OpenAI or Anthropic compatible endpoint so that editors and agents can use them, with routing, quota visibility and failover handled in one place. It does not fit anyone without their own authorised provider accounts, and it should not be treated as a stable product contract, since the upstream endpoints it depends on can change without notice. Verify first that your provider accounts and terms permit this use, that the public inference listener stays token-gated, and that the credential and log handling in the version you install matches the behaviour the README describes.

Frequently asked questions

Which providers can anti-api route to?

Six: Antigravity, ChatGPT Codex, GitHub Copilot, Zed hosted models, Amazon Kiro and xAI Grok. They can be imported, listed, quota-checked and routed from the dashboard, subject to each provider's current access and terms.

How do I run anti-api with Docker?

The compose file uses the prebuilt multi-arch image ghcr.io/silasxbt/anti-api:latest, so docker compose pull and docker compose up --build both work. You must set ANTI_API_CONTROL_TOKEN, and the default port mappings bind 8964 and the OAuth callback ranges to 127.0.0.1 only.

How is the public inference endpoint of anti-api protected?

The public listener is inference-only, defaults to port 8966, and is token-gated with ANTI_API_PUBLIC_TOKEN. The dashboard and management API remain loopback and token protected, including in container mode, and the compose file ships the public mapping commented out.

Can I install anti-api with Homebrew or WinGet?

Yes. The README release notes describe brew install anti-api as installing a prebuilt macOS Apple Silicon bundle without local Rust, LLVM or Bun downloads, and winget install anti-api as the Windows portable route with checksums. Updates are directed to brew upgrade anti-api and winget upgrade anti-api rather than self-overwriting.

Is using anti-api allowed with my provider accounts?

The README states it is an independent, unofficial interoperability project, that some integrations use provider CLI, web or internal endpoints and may break without notice, and that you should use only accounts and services you own or are explicitly authorized to administer, subject to each provider's current terms.

What licence is anti-api released under and how often does it change?

MIT, declared in the package.json with a LICENSE file at the repository root, and the package is marked private. Releases come fast, with v3.2.2 and v3.2.1 both published on 2026-09-15 after v3.2.0 on 2026-08-31, and the last push was on 2026-09-15.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. silasxbt/anti-api on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/silasxbt-anti-api.svg)](https://hysenlabs.com/projects/silasxbt-anti-api)

Was this useful?