{"_id":"@axlabs/venice-e2ee-proxy","_rev":"2-f174a42595e5313fe0bb609f4fa06425","name":"@axlabs/venice-e2ee-proxy","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"@axlabs/venice-e2ee-proxy","version":"1.0.0","keywords":["venice","venice-ai","e2ee","end-to-end-encryption","tee","intel-tdx","confidential-computing","attestation","openai","openai-compatible","proxy","llm","nestjs","privacy"],"author":{"url":"https://axlabs.com","name":"AxLabs","email":"info@axlabs.com"},"license":"Apache-2.0","_id":"@axlabs/venice-e2ee-proxy@1.0.0","maintainers":[{"name":"merl123","email":"mathias@axlabs.com"},{"name":"axlabs-bot","email":"tech@axlabs.com"},{"name":"mialbu","email":"bucher_michael@hotmail.com"},{"name":"gsperbmachado","email":"guil@axlabs.com"},{"name":"thedanielmark","email":"danielmark.uc@gmail.com"}],"homepage":"https://github.com/AxLabs/venice-e2ee-proxy#readme","bugs":{"url":"https://github.com/AxLabs/venice-e2ee-proxy/issues"},"bin":{"venice-e2ee-proxy":"dist/main.js"},"dist":{"shasum":"941c8c3fae5e76cc57cda27a507404e33e611f2c","tarball":"https://registry.npmjs.org/@axlabs/venice-e2ee-proxy/-/venice-e2ee-proxy-1.0.0.tgz","fileCount":77,"integrity":"sha512-slBJaiiYzmD9KzNsQaksUtPQOYi2NWC2+7b53vm/XfdQU7vsy7wBlOzMqiQUlauata1Wo4npXOMV4M3nHMIrDw==","signatures":[{"sig":"MEQCICi0tbD4yUIrEj9mixq7ZU6QdPfI3hH4PL9eH/787IbaAiB11qI0bazapl2GgJWivOWRQr/o8PwhDld+K9Xnkd2hiA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":168404},"main":"dist/main.js","types":"./dist/main.d.ts","engines":{"node":">=20"},"gitHead":"ce5099779759906aa3c9260e59753a2cc162798b","scripts":{"lint":"eslint \"{src,test}/**/*.ts\" --max-warnings 0","test":"vitest run","build":"nest build","start":"node dist/main.js","format":"prettier --write \"src/**/*.ts\" \"test/**/*.ts\"","release":"./scripts/release.sh","lint:fix":"eslint \"{src,test}/**/*.ts\" --fix","prebuild":"rimraf dist","start:dev":"nest start --watch","start:prod":"node dist/main.js","test:watch":"vitest","start:debug":"nest start --debug --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"gsperbmachado","email":"guil@axlabs.com"},"repository":{"url":"git+https://github.com/AxLabs/venice-e2ee-proxy.git","type":"git"},"_npmVersion":"11.6.0","description":"Lightweight OpenAI-compatible proxy that adds end-to-end encryption (E2EE) for Venice.ai TEE-backed models.","directories":{},"_nodeVersion":"24.8.0","dependencies":{"rxjs":"^7.8.1","@nestjs/core":"^11.0.0","@nestjs/common":"^11.0.0","@nestjs/config":"^4.0.0","@nestjs/swagger":"^11.0.0","@phala/dcap-qvl":"^0.3.9","class-validator":"^0.14.1","reflect-metadata":"^0.2.2","class-transformer":"^0.5.1","@axlabs/venice-e2ee":"^0.2.0","@nestjs/platform-express":"^11.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^9.17.0","rimraf":"^6.0.1","vitest":"^2.1.8","ts-node":"^10.9.2","prettier":"^3.4.2","@swc/core":"^1.10.1","supertest":"^7.0.0","@eslint/js":"^9.17.0","typescript":"^5.7.2","@nestjs/cli":"^11.0.0","@types/node":"^22.10.0","unplugin-swc":"^1.5.1","@types/express":"^5.0.0","tsconfig-paths":"^4.2.0","@nestjs/testing":"^11.0.0","@types/supertest":"^6.0.2","typescript-eslint":"^8.18.0","@nestjs/schematics":"^11.0.0","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.2.1"},"_npmOperationalInternal":{"tmp":"tmp/venice-e2ee-proxy_1.0.0_1781795306235_0.24352425947356982","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@axlabs/venice-e2ee-proxy","version":"1.0.1","description":"Lightweight OpenAI-compatible proxy that adds end-to-end encryption (E2EE) for Venice.ai TEE-backed models.","license":"Apache-2.0","author":{"name":"AxLabs","email":"info@axlabs.com","url":"https://axlabs.com"},"homepage":"https://github.com/AxLabs/venice-e2ee-proxy#readme","repository":{"type":"git","url":"git+https://github.com/AxLabs/venice-e2ee-proxy.git"},"bugs":{"url":"https://github.com/AxLabs/venice-e2ee-proxy/issues"},"keywords":["venice","venice-ai","e2ee","end-to-end-encryption","tee","intel-tdx","confidential-computing","attestation","openai","openai-compatible","proxy","llm","nestjs","privacy"],"bin":{"venice-e2ee-proxy":"bin/venice-e2ee-proxy.js"},"main":"dist/main.js","publishConfig":{"access":"public"},"scripts":{"prebuild":"rimraf dist","build":"nest build","start":"node dist/main.js","start:dev":"nest start --watch","start:debug":"nest start --debug --watch","start:prod":"node dist/main.js","lint":"eslint \"{src,test}/**/*.ts\" --max-warnings 0","lint:fix":"eslint \"{src,test}/**/*.ts\" --fix","format":"prettier --write \"src/**/*.ts\" \"test/**/*.ts\"","test":"vitest run","test:watch":"vitest","release":"./scripts/release.sh","prepublishOnly":"npm run build"},"dependencies":{"@axlabs/venice-e2ee":"^0.2.0","@nestjs/common":"^11.0.0","@nestjs/config":"^4.0.0","@nestjs/core":"^11.0.0","@nestjs/platform-express":"^11.0.0","@nestjs/swagger":"^11.0.0","@phala/dcap-qvl":"^0.3.9","class-transformer":"^0.5.1","class-validator":"^0.14.1","reflect-metadata":"^0.2.2","rxjs":"^7.8.1"},"devDependencies":{"@eslint/js":"^9.17.0","@nestjs/cli":"^11.0.0","@nestjs/schematics":"^11.0.0","@nestjs/testing":"^11.0.0","@swc/core":"^1.10.1","@types/express":"^5.0.0","@types/node":"^22.10.0","@types/supertest":"^6.0.2","eslint":"^9.17.0","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.2.1","prettier":"^3.4.2","rimraf":"^6.0.1","supertest":"^7.0.0","ts-node":"^10.9.2","tsconfig-paths":"^4.2.0","typescript":"^5.7.2","typescript-eslint":"^8.18.0","unplugin-swc":"^1.5.1","vitest":"^2.1.8"},"engines":{"node":">=20"},"_id":"@axlabs/venice-e2ee-proxy@1.0.1","gitHead":"8ae626776ae35a183145e20722593daffaef5cf8","types":"./dist/main.d.ts","_nodeVersion":"24.8.0","_npmVersion":"11.6.0","dist":{"integrity":"sha512-Lio8Gpb7mBq/mwVxB/lo7oIvh65EEDMH5XV0J3dNLA36rTiDMk5KAhQUFJ1aYpiDIWzKZ2FQZo7zTNCSW+n+Sw==","shasum":"3a6d51e7c0b69fbf3a1e0ee821453553de9b6252","tarball":"https://registry.npmjs.org/@axlabs/venice-e2ee-proxy/-/venice-e2ee-proxy-1.0.1.tgz","fileCount":78,"unpackedSize":172645,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCGZAe+LqjSqFrGgbAOd6gGELn/i2oUwHsn3nzTzcZEUgIgKdgNrTUHA32ySc6Z84JvAYREmLUkft//+ta+wZ5/mzI="}]},"_npmUser":{"name":"gsperbmachado","email":"guil@axlabs.com"},"directories":{},"maintainers":[{"name":"merl123","email":"mathias@axlabs.com"},{"name":"axlabs-bot","email":"tech@axlabs.com"},{"name":"mialbu","email":"bucher_michael@hotmail.com"},{"name":"gsperbmachado","email":"guil@axlabs.com"},{"name":"thedanielmark","email":"danielmark.uc@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/venice-e2ee-proxy_1.0.1_1781815447217_0.577214746459588"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-18T15:08:26.051Z","modified":"2026-06-18T20:44:07.577Z","1.0.0":"2026-06-18T15:08:26.444Z","1.0.1":"2026-06-18T20:44:07.364Z"},"bugs":{"url":"https://github.com/AxLabs/venice-e2ee-proxy/issues"},"author":{"name":"AxLabs","email":"info@axlabs.com","url":"https://axlabs.com"},"license":"Apache-2.0","homepage":"https://github.com/AxLabs/venice-e2ee-proxy#readme","keywords":["venice","venice-ai","e2ee","end-to-end-encryption","tee","intel-tdx","confidential-computing","attestation","openai","openai-compatible","proxy","llm","nestjs","privacy"],"repository":{"type":"git","url":"git+https://github.com/AxLabs/venice-e2ee-proxy.git"},"description":"Lightweight OpenAI-compatible proxy that adds end-to-end encryption (E2EE) for Venice.ai TEE-backed models.","maintainers":[{"name":"merl123","email":"mathias@axlabs.com"},{"name":"axlabs-bot","email":"tech@axlabs.com"},{"name":"mialbu","email":"bucher_michael@hotmail.com"},{"name":"gsperbmachado","email":"guil@axlabs.com"},{"name":"thedanielmark","email":"danielmark.uc@gmail.com"}],"readme":"# Venice E2EE Proxy\n\nA lightweight, **OpenAI-compatible proxy** that adds **end-to-end encryption (E2EE)** for [Venice.ai](https://venice.ai)'s TEE-backed models. Point any OpenAI-compatible tool — **Cline**, the OpenAI SDK, `curl`, … — at it and talk to Venice's confidential models without writing a single line of crypto.\n\nWhen you call a model whose id starts with `e2ee-`, the proxy encrypts your messages client-side; they are only decrypted inside Venice's Intel TDX **Trusted Execution Environment** — Venice never sees your plaintext. Every other model is proxied straight through, unchanged.\n\n---\n\n## Quick start\n\nThe fastest way to run the proxy — **no clone, no build**. All you need is **Node.js 20+** and a **Venice API key**.\n\n```bash\nnpx @axlabs/venice-e2ee-proxy --venice-api-key sk-your-venice-key\n```\n\nYou should see:\n\n```\nVenice E2EE Proxy listening on http://0.0.0.0:3000\nOpenAI-compatible base URL: http://0.0.0.0:3000/v1 (also accepts http://0.0.0.0:3000/api/v1)\nSwagger UI: http://0.0.0.0:3000/docs\n```\n\nThat's it. Now point any OpenAI-compatible client at `http://localhost:3000/v1` and use an `e2ee-` model:\n\n```bash\ncurl http://localhost:3000/v1/chat/completions \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"model\": \"e2ee-qwen3-5-122b-a10b\",\n    \"messages\": [{ \"role\": \"user\", \"content\": \"Hello from the encrypted side\" }]\n  }'\n```\n\n> **Requirements:** Node.js 20+. All dependencies (including the [`@axlabs/venice-e2ee`](https://github.com/AxLabs/venice-e2ee) encryption library) install straight from npm.\n\n### Other ways to run it\n\n```bash\n# Pin a specific version\nnpx @axlabs/venice-e2ee-proxy@1.0.0 --venice-api-key sk-...\n\n# Install globally, then run the command directly\nnpm install -g @axlabs/venice-e2ee-proxy\nvenice-e2ee-proxy --venice-api-key sk-...\n\n# See every available option\nnpx @axlabs/venice-e2ee-proxy --help\n```\n\nPrefer to run from a checkout for development? See [Run from source](#run-from-source).\n\n---\n\n## Configuration\n\nConfigure the proxy whichever way fits your workflow: **CLI flags**, **environment variables**, or a **`.env` file** in the current directory.\n\n**Precedence (highest wins):** CLI flags → environment variables → `.env` file → built-in defaults.\n\n```bash\n# Everything via CLI flags\nnpx @axlabs/venice-e2ee-proxy --venice-api-key sk-... --port 8080 --log-level debug\n\n# API key from the environment, port from a flag\nVENICE_API_KEY=sk-... npx @axlabs/venice-e2ee-proxy --port 8080\n\n# From a .env file in the current directory (CLI flags still win)\necho \"VENICE_API_KEY=sk-...\" > .env\nnpx @axlabs/venice-e2ee-proxy\n```\n\nThe only **required** setting is your Venice API key (`--venice-api-key` / `VENICE_API_KEY`). Everything else has a sensible default. Configuration is validated at startup, so mistakes fail fast with a clear message.\n\n| CLI flag | Env variable | Default | Description |\n| -------- | ------------ | ------- | ----------- |\n| `--venice-api-key <key>` | `VENICE_API_KEY` | — | Your Venice API key (**required**). |\n| `-p`, `--port <port>` | `PORT` | `3000` | Port to listen on. |\n| `--host <host>` | `HOST` | `0.0.0.0` | Interface to bind. |\n| `--session-ttl-ms <ms>` | `SESSION_TTL_MS` | `1800000` (30 min) | E2EE session cache TTL in milliseconds. |\n| `--verify-attestation <bool>` | `VERIFY_ATTESTATION` | `true` | Verify TEE attestation on session creation. |\n| `--no-verify-attestation` | `VERIFY_ATTESTATION` | — | Shorthand to disable attestation verification. |\n| `--verify-dcap <bool>` | `VERIFY_DCAP` | `true` | Run full TDX DCAP verification via `@phala/dcap-qvl`. Only effective when `VERIFY_ATTESTATION=true`. |\n| `--no-verify-dcap` | `VERIFY_DCAP` | — | Shorthand to disable DCAP verification. |\n| `--verify-gpu-attestation <bool>` | `VERIFY_GPU_ATTESTATION` | `true` | Enforce NVIDIA GPU attestation before each E2EE session. See [ARCHITECTURE.md §7](./ARCHITECTURE.md#7-confidential-computing-on-the-gpu). |\n| `--no-verify-gpu-attestation` | `VERIFY_GPU_ATTESTATION` | — | Shorthand to disable GPU attestation enforcement. |\n| `--dcap-pccs-url <url>` | `DCAP_PCCS_URL` | Phala PCCS | Optional PCCS server URL for DCAP collateral fetching. |\n| `--base-url <url>` | `BASE_URL` | `https://api.venice.ai` | Venice API base URL. |\n| `--max-body-size <size>` | `MAX_BODY_SIZE` | `25mb` | Max request body size (any `bytes`-compatible value). |\n| `--log-level <level>` | `LOG_LEVEL` | `info` | `error` \\| `warn` \\| `info` \\| `debug` \\| `verbose`. Secrets and prompt contents are never logged. |\n\nBoolean flags accept `true`/`false`, `1`/`0`, `yes`/`no`, or `on`/`off`. Every flag has an environment-variable equivalent (see the `Env variable` column above) — handy for Docker, systemd, or CI. A `.env` file in the working directory is loaded automatically; copy [`.env.example`](./.env.example) to get started.\n\n---\n\n## Connect your client\n\nThe proxy speaks the **OpenAI API**, so it works with **any client, IDE, or agent that supports an OpenAI-compatible endpoint** — chat UIs, coding assistants, autonomous agents, SDKs, and scripts alike. There's no special integration: just point the tool at the proxy.\n\nWherever the tool asks for an OpenAI-compatible provider, set:\n\n- **Base URL:** `http://localhost:3000/v1` (the Venice-style `http://localhost:3000/api/v1` also works)\n- **API key:** any non-empty value (the proxy uses your own `VENICE_API_KEY` upstream — clients don't need a real key)\n- **Model:** an `e2ee-` model (e.g. `e2ee-qwen3-5-122b-a10b`) for encrypted inference, or any regular Venice model id\n\nA few tools that work out of the box: [Jan](https://jan.ai), [Open WebUI](https://openwebui.com), [Cline](https://cline.bot), [Continue](https://continue.dev), [Roo Code](https://roocode.com), [Hermes](https://hermes-agent.nousresearch.com), [OpenClaw](https://openclaw.ai), [LibreChat](https://www.librechat.ai), and the official OpenAI SDKs — among many others. See [Compatible tools](#compatible-tools) below.\n\n> **Tip:** Some \"OpenAI Compatible\" providers (e.g. Cline) have no model picker — type the model id by hand. The proxy logs the available `e2ee-` model ids at startup for easy copy-paste.\n\n---\n\n## API\n\n### `GET /v1/models`\n\nReturns the available models in OpenAI list format.\n\n```bash\ncurl http://localhost:3000/v1/models\n```\n\n### `POST /v1/chat/completions`\n\nOpenAI-compatible chat completions (streaming and non-streaming).\n\n**Non-streaming, E2EE:**\n\n```bash\ncurl http://localhost:3000/v1/chat/completions \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"model\": \"e2ee-qwen3-5-122b-a10b\",\n    \"messages\": [{ \"role\": \"user\", \"content\": \"Hello from the encrypted side\" }]\n  }'\n```\n\n**Streaming, E2EE (SSE):**\n\n```bash\ncurl -N http://localhost:3000/v1/chat/completions \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"model\": \"e2ee-qwen3-5-122b-a10b\",\n    \"messages\": [{ \"role\": \"user\", \"content\": \"Stream me a haiku\" }],\n    \"stream\": true\n  }'\n```\n\n### Swagger UI\n\nInteractive API documentation is served at **[http://localhost:3000/docs](http://localhost:3000/docs)** (OpenAPI JSON at `/docs-json`).\n\n### Health check\n\n`GET /healthz` → `{ \"status\": \"ok\", \"uptime\": <seconds> }`\n\n---\n\n## How it works\n\n```\n┌─────────┐    OpenAI API     ┌──────────────────┐   encrypted (E2EE)   ┌──────────────┐\n│  Cline  │ ───────────────►  │ Venice E2EE Proxy │ ──────────────────► │  Venice TEE  │\n│ /OpenAI │ ◄───────────────  │   (this server)   │ ◄────────────────── │  (Intel TDX) │\n└─────────┘  plaintext SSE    └──────────────────┘   encrypted stream    └──────────────┘\n```\n\n- **`e2ee-*` models** → the proxy creates a verified TEE session, encrypts your messages, forwards them to Venice with `venice_parameters: { enable_e2ee: true }`, and decrypts the streamed response on the fly.\n- **All other models** → the request is proxied straight through to Venice unchanged.\n\n**Under the hood:** NestJS (TypeScript, strict mode); encryption via the [`@axlabs/venice-e2ee`](https://github.com/AxLabs/venice-e2ee) library (ECDH secp256k1 → HKDF-SHA256 → AES-256-GCM + TEE attestation); Swagger UI at `/docs`.\n\n> **Note:** Venice requires `stream: true` for E2EE models. If a client sends a non-streaming request to an `e2ee-` model, the proxy transparently streams upstream, buffers the decrypted output, and returns a single OpenAI `chat.completion` object — so non-streaming clients still work.\n\n> 📐 For the deeper \"why\" — the E2EE/TEE protocol dynamics, why DCAP collateral comes from Intel via **PCCS** (not Venice), how **NVIDIA GPU confidential computing** extends the trust boundary, and the project's design decisions — see **[ARCHITECTURE.md](./ARCHITECTURE.md)**.\n\n---\n\n## Run from source\n\nFor local development or contributing, run the proxy from a checkout:\n\n```bash\n# 1. Install dependencies (a .nvmrc pins Node 24; run `nvm use` first)\nnpm install\n\n# 2. Configure\ncp .env.example .env   # then edit .env and set VENICE_API_KEY\n\n# 3. Start with hot reload\nnpm run start:dev\n\n# …or build and run the compiled output\nnpm run build\nnpm start\n```\n\nYou can also run the local build through `npx` from the repo root: `VENICE_API_KEY=sk-... npx .`.\n\n---\n\n## Project structure\n\n```\nsrc/\n├── main.ts                  # Bootstrap + Swagger setup\n├── app.module.ts            # Root module\n├── app.setup.ts             # Shared global pipes/filters/versioning/CORS\n├── config/                  # Env configuration + validation\n│   ├── config.module.ts\n│   ├── app-config.service.ts\n│   └── env.validation.ts\n├── e2ee/                    # Wrapper around the @axlabs/venice-e2ee library\n│   ├── e2ee.module.ts\n│   └── e2ee.service.ts\n├── chat/                    # Chat completions controller + service\n│   ├── chat.controller.ts\n│   ├── chat.service.ts\n│   └── dto/\n├── models/                  # Models controller + service\n├── health/                  # Liveness probe\n└── common/                  # Shared interfaces, utils, filters, HTTP client\ntest/\n├── openai.util.spec.ts      # Unit tests for OpenAI helpers\n├── openai-compliance.spec.ts # API compliance + E2EE behavior tests\n└── helpers/test-app.ts      # Test harness with mocked upstream + E2EE\n```\n\n---\n\n## Testing\n\nThe suite uses **Vitest** and verifies:\n\n- The server returns proper OpenAI-shaped responses (`/v1/models`, `chat.completion`).\n- Streaming works correctly (SSE with `chat.completion.chunk` events and a `[DONE]` sentinel).\n- `e2ee-` models are handled via the encryption path (session creation + encryption) while regular models are proxied straight through.\n\n```bash\nnpm test          # run once\nnpm run test:watch\n```\n\nTests run fully offline — the `@axlabs/venice-e2ee` library and the upstream HTTP client are mocked, so no API key or network access is required.\n\n---\n\n## Security notes\n\n- Attestation verification is **on by default**. If the TEE attestation fails (nonce binding, signing-key binding, or debug-mode detection), session creation fails and the proxy returns a clear `503` error.\n- **Full TDX DCAP verification is also on by default** (PCK certificate chain, quote signature, QE identity, and TCB evaluation) via [`@phala/dcap-qvl`](https://github.com/Phala-Network/dcap-qvl). It runs as part of attestation and fetches collateral from a PCCS server (Phala's by default; override with `DCAP_PCCS_URL`). Disable it with `VERIFY_DCAP=false`. Note this requires outbound network access to the PCCS at runtime.\n- **GPU attestation enforcement is on by default** (`VERIFY_GPU_ATTESTATION`). Before each E2EE session the proxy fetches `/tee/attestation`, checks `verified` + nonce, and — for GPU-backed models — requires Venice's server-side NVIDIA verification to pass, failing closed otherwise. **Caveat:** this enforces Venice's GPU verdict; it is **not yet an independent client-side verification** of the NVIDIA quote (no audited JS verifier exists today — see [ARCHITECTURE.md §7](./ARCHITECTURE.md#7-confidential-computing-on-the-gpu)).\n- Treat your `VENICE_API_KEY` as a secret. The proxy adds the `Authorization` header upstream; clients connecting to the proxy do not need to provide a real key.\n\n---\n\n## Compatible tools\n\nBecause the proxy exposes a standard **OpenAI-compatible API**, it drops into virtually any OpenAI-compatible client, IDE, or agent — just set the base URL to the proxy. A few popular ones:\n\n<table>\n  <tr>\n    <td align=\"center\" width=\"110\"><a href=\"https://jan.ai\"><img src=\"https://github.com/janhq.png\" width=\"56\" height=\"56\" alt=\"Jan logo\"><br/>Jan</a></td>\n    <td align=\"center\" width=\"110\"><a href=\"https://openwebui.com\"><img src=\"https://github.com/open-webui.png\" width=\"56\" height=\"56\" alt=\"Open WebUI logo\"><br/>Open WebUI</a></td>\n    <td align=\"center\" width=\"110\"><a href=\"https://cline.bot\"><img src=\"https://github.com/cline.png\" width=\"56\" height=\"56\" alt=\"Cline logo\"><br/>Cline</a></td>\n    <td align=\"center\" width=\"110\"><a href=\"https://continue.dev\"><img src=\"https://github.com/continuedev.png\" width=\"56\" height=\"56\" alt=\"Continue logo\"><br/>Continue</a></td>\n  </tr>\n  <tr>\n    <td align=\"center\" width=\"110\"><a href=\"https://roocode.com\"><img src=\"https://github.com/RooCodeInc.png\" width=\"56\" height=\"56\" alt=\"Roo Code logo\"><br/>Roo Code</a></td>\n    <td align=\"center\" width=\"110\"><a href=\"https://hermes-agent.nousresearch.com\"><img src=\"https://github.com/NousResearch.png\" width=\"56\" height=\"56\" alt=\"Hermes / Nous Research logo\"><br/>Hermes</a></td>\n    <td align=\"center\" width=\"110\"><a href=\"https://openclaw.ai\"><img src=\"https://github.com/openclaw.png\" width=\"56\" height=\"56\" alt=\"OpenClaw logo\"><br/>OpenClaw</a></td>\n    <td align=\"center\" width=\"110\"><a href=\"https://www.librechat.ai\"><img src=\"https://github.com/danny-avila.png\" width=\"56\" height=\"56\" alt=\"LibreChat logo\"><br/>LibreChat</a></td>\n  </tr>\n</table>\n\n…plus the official **OpenAI SDKs** (Python, Node, …), [LangChain](https://www.langchain.com), [LlamaIndex](https://www.llamaindex.ai), the [Vercel AI SDK](https://sdk.vercel.ai), and any other tool or script that lets you point at an OpenAI-compatible base URL.\n\n> Logos belong to their respective projects and are shown only to indicate compatibility; this does not imply any affiliation or endorsement.\n\n---\n\n## Development & releases (maintainers)\n\n- **CI:** [`.github/workflows/ci.yml`](./.github/workflows/ci.yml) builds, lints, and tests on **every commit** and pull request, on **self-hosted runners**, using the Node version from `.nvmrc`. CI does not publish.\n- **Releases:** cut **locally** with a script that bumps the version, tags, pushes, and publishes to npm (so the proxy stays runnable via `npx`).\n\n```bash\nnpm login                 # one-time: must have access to the @axlabs scope\n\nnpm run release -- patch  # 1.0.0 -> 1.0.1   (bug fixes)\nnpm run release -- minor  # 1.0.0 -> 1.1.0   (new features)\nnpm run release -- major  # 1.0.0 -> 2.0.0   (breaking changes)\n# or an explicit version:\nnpm run release -- 1.2.3\n```\n\nThe release script ([`scripts/release.sh`](./scripts/release.sh)) runs pre-flight checks (clean `main`, in sync with origin, npm auth), then `npm ci` + lint + test + build, bumps the version with an annotated `vX.Y.Z` tag, pushes the commit and tag, publishes to npm, and (if `gh` is installed) creates a GitHub Release.\n\nSee **[DEVELOPMENT.md](./DEVELOPMENT.md)** for the full guide, the manual fallback, and release verification.\n\n---\n\n## License\n\nLicensed under the [Apache License, Version 2.0](./LICENSE).\n\n> ⚠️ **Heads-up:** this proxy depends on [`@axlabs/venice-e2ee`](https://github.com/AxLabs/venice-e2ee), which is **GPL-3.0**. Running the proxy (including as a hosted service) is unaffected, but **distributing** a build that bundles that library brings the combined work under GPL-3.0. See [NOTICE.md](./NOTICE.md) for details and the full third-party license list.\n","readmeFilename":"README.md"}