Check CX: a status board that proves an AI relay is actually working
实时跟踪 OpenAI、Gemini、Anthropic 等 AI 模型 API 的可用性、延迟与错误信息
At a glance
- What is it?
- Check CX probes OpenAI, Gemini, Anthropic and relay endpoints with real streaming model calls, then validates the answers against randomly generated language challenges so a proxy returning canned text gets caught. The whole stack, including a self-hosted Supabase, runs from one compose file.
- Who is it for?
- Check CX fits a team that depends on paid model endpoints and relay providers, and that needs to tell its own users when an outage is happening rather than when a TCP port answers. It does not fit a deployment that cannot hand over API keys, since the probes need working credentials for every endpoint you monitor, and it is heavier than a simple uptime check.
- 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 37 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 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why a ping is not enough when the endpoint is a paid model
Check CX positions itself with a single line: when your AI API goes down, you should be the first to know. The README's why section names the problem better than the tool does. Relay providers are flaky and you never know which hop is the problem, because Check CX sends real model requests and measures end-to-end availability rather than whether the port answers. Some relays return fake responses to fool health checkers, and every Check CX probe is a randomly generated language challenge where a wrong answer marks the endpoint as down, so canned-text fake proxies cannot hide. The third reason is evidentiary. When users report issues you need proof, and 7, 15 and 30-day uptime statistics with a history timeline turn occasional timeouts into a quantifiable curve. The fourth is that you need a status page you can put on your own site, with grouped views, website links and a public read-only status API.
Random challenges are the core idea, and they are graded
Each check generates a fresh language challenge on the fly, with category selection across reading comprehension, state tracking, logical implication and instruction following, spread over five difficulty tiers, and requires the model to produce the one correct answer. Random guessing almost never passes, which is what makes the check meaningful against a fake proxy. The challenges do double duty. Health checks also sample the high difficulty tiers, three to five, and show the result as an intelligence score on each card, with per-tier pass rates on hover. The README is careful about the split between the two signals: failing a hard challenge affects the capability score, not the health status, so a weak model does not flap between healthy and unhealthy, while the capability difference between models remains visible at a glance. That separation is what lets the tool be both a monitoring system and a comparison chart without the two confusing each other.
Real streaming calls, and what is measured from them
The health check section is explicit that there are no fake probes. Every check is a real streaming model call, and the tool captures the true time-to-first-token, which the README notes is immune to endpoints that stream empty chunks to fake latency, plus a separate endpoint ping latency. Both Chat Completions and Responses endpoints are supported, and Gemini is auto-detected between the native Google API and the OpenAI-compatible format, which matters because the two behave differently in latency and in error reporting. Reasoning models get attention too: o1, GPT-5, DeepSeek-R1 and QwQ automatically get reasoning-effort configuration, so a request that would be rejected for a missing effort parameter is not counted as an outage. The dependency list shows the mechanism, with the Vercel AI SDK packages for Anthropic, Google, OpenAI and OpenAI-compatible providers, plus the ai package itself at version 7.
The deployment is one compose file with a whole Supabase inside it
The getting started section recommends the one-command stack, where docker-compose.yml bundles the full self-hosted Supabase stack, covering Postgres, PostgREST, GoTrue, Storage, Realtime, Studio and the API gateway, plus the Check CX panel and admin panel. Tables are created on first start, so there is no cloud Supabase project and no manual SQL to run.
git clone https://github.com/BingZi-233/check-cx.git
cd check-cx
cp .env.example .env
docker compose up -dThree addresses come up afterwards. The panel is at localhost:3000 and works with zero configuration. The admin panel is at localhost:3001 and its sign-in requires GitHub OAuth. The Supabase API is at localhost:8000. The compose file includes the upstream self-hosted Supabase stack from the supabase repository through a path include, and adds a check-cx-init service that runs the schema file on first start with a check for whether the table already exists, so the initialization is idempotent. The panel image is published as bingzi233/check-cx, and the project is private in the package manifest, which is consistent with it being a deployment rather than a library.
Which ports are published, and why the admin one is loopback
The port exposure table is the security-relevant part of the setup, and the defaults are deliberate. The default stack publishes only the panel and the Supabase API and auth to the network, the admin panel is loopback-only, and Postgres and the transaction pooler stay inside the Docker network entirely, with opt-in compose overrides for temporary host-side SQL access. The binding variables are named per service, with CHECK_CX_BIND_ADDRESS and CHECK_CX_PORT for the panel, ADMIN_BIND_ADDRESS and ADMIN_PORT for the admin, and API_GW_BIND_ADDRESS with API_GW_HTTP_PORT for the Supabase API. Directly exposing the admin panel requires setting ADMIN_BIND_ADDRESS to 0.0.0.0 explicitly, and the README says to use a host reverse proxy for remote admin access. A local profile that avoids port conflicts looks like this.
CHECK_CX_PORT=13000
ADMIN_PORT=13001
API_GW_HTTP_PORT=18000
SUPABASE_PUBLIC_URL=http://localhost:18000
API_EXTERNAL_URL=http://localhost:18000/auth/v1
SITE_URL=http://localhost:13001
ADDITIONAL_REDIRECT_URLS=http://localhost:13001/auth/callback
APP_URL=http://localhost:13001Container ports stay unchanged, and every browser-visible URL has to use the matching host port, which is the kind of detail that silently breaks a deployment if it is missed.
Multi-node deployments elect a leader instead of polling twice
The production design section lists four properties worth examining. Multi-node deployments auto-elect a leader through database leases, so you can run as many replicas as you like without duplicate polling, which is the difference between a monitoring system and a load generator pointed at your own provider. Automatic retries on network hiccups mean transient aborts do not cause false alarms, which matters for a system whose entire value is not crying wolf. API keys live only in the database and are read only server-side, never in the frontend or config files, which is a direct consequence of the keys being usable to spend money. History data is pruned automatically by retention days, so the database does not grow without bound. The status API is a single endpoint, GET /api/v1/status, returning structured status data that you can hook up to uptime robots, alerting bots or your own systems.
A Next.js app with live config reload and official status pages
The application is Next.js 16 on React 19 with Tailwind 4, shadcn components, Radix UI primitives and Recharts for the graphs, and the package manifest requires Node 22 or newer with pnpm as the package manager. The Dockerfile is a four-stage build on node:22-alpine: pnpm is enabled through corepack, dependencies install in their own layer, the Next.js standalone build is produced in the builder stage, and the runtime stage copies the standalone output, the static assets and the public directory, then creates a non-root user with uid 1001 and switches to it before starting the server. The frontend features are not just cosmetic. Live config reload means the frontend watches for config changes over SSE and refreshes automatically, so editing a model config in the admin panel does not need an F5. There are grouped views for organising models by provider or relay, each with its own tags and website link, a dedicated group detail page, a maintenance mode that stops polling without the card turning red, rotating Markdown notification banners, and official status sync that polls the OpenAI and Anthropic status pages so that a provider-side incident is obvious even when your own probes are green.
Editorial conclusion
Check CX fits a team that depends on paid model endpoints and relay providers, and that needs to tell its own users when an outage is happening rather than when a TCP port answers. It does not fit a deployment that cannot hand over API keys, since the probes need working credentials for every endpoint you monitor, and it is heavier than a simple uptime check. Verify first that your endpoints can actually run the challenge, that your latency measurements match what your users experience through the same relay, and that the admin panel stays behind a reverse proxy before you expose it.
Frequently asked questions
How does Check CX detect a relay that returns fake responses?
Every probe generates a random language challenge on the fly across five difficulty tiers and requires the one correct answer, so a proxy returning canned text fails the check and is marked as down. The same high-difficulty challenges are also used to produce a capability score shown on each card, separately from the health status.
How do I run Check CX locally?
Clone the repository, copy the .env.example to .env, and run docker compose up -d. That brings up the panel on port 3000, the admin panel on 3001 with GitHub OAuth sign-in, and the Supabase API on 8000, with the database tables created automatically on first start.
Can I run multiple Check CX instances without duplicate polling?
Yes. Multi-node deployments auto-elect a leader using database leases, so you can run as many replicas as you like without the same endpoint being polled by several of them. Automatic retries on network hiccups are also built in to avoid false alarms.
Where are my API keys stored in Check CX?
The README states that API keys live only in the database and are read only server-side, never in the frontend or config files. The admin panel is bound to loopback by default, and exposing it to a network requires setting ADMIN_BIND_ADDRESS explicitly or putting a reverse proxy in front of it.
Official sources
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.
[](https://hysenlabs.com/projects/bingzi-233-check-cx)Was this useful?