ai-model-watch
by markksantos
README.md
# ai-model-watch
List the models each AI provider's API serves, and see what's new since the last time you looked. One command, no dependencies, Node 18+. It also runs as an MCP server, so Claude or Cursor can check for you.
New models often show up in a provider's `/models` list before any announcement. `ai-model-watch` saves each provider's list, and on the next run prints only the model IDs that weren't there before. Run it by hand, from cron, or in CI with `--exit-code`.

```
$ ai-model-watch -p openrouter
2026-10-17T09:26:01.231Z
OpenRouter: 2 new
+ deepseek/deepseek-v4.1-flash-1017 DeepSeek: DeepSeek V4.1 Flash 1017 (listed as created 2026-10-17)
+ reflection/beam-1.0-501b-a23b Reflection: Beam 1.0 501B A23B (listed as created 2026-10-16)
```
The first run records a baseline (`OpenRouter: 470 models recorded as the baseline`), so you only hear about changes after that.
## Providers
| Provider | Endpoint | Key |
|---|---|---|
| OpenRouter | `GET https://openrouter.ai/api/v1/models` | none, works out of the box |
| OpenAI | `GET https://api.openai.com/v1/models` | `OPENAI_API_KEY` |
| Anthropic | `GET https://api.anthropic.com/v1/models` (paginated) | `ANTHROPIC_API_KEY` |
| Google Gemini | `GET https://generativelanguage.googleapis.com/v1beta/models` (paginated) | `GEMINI_API_KEY` or `GOOGLE_API_KEY` |
| Mistral | `GET https://api.mistral.ai/v1/models` | `MISTRAL_API_KEY` |
| xAI | `GET https://api.x.ai/v1/models` | `XAI_API_KEY` |
| DeepSeek | `GET https://api.deepseek.com/models` | `DEEPSEEK_API_KEY` |
Listing models is free on every one of these APIs. Nothing is generated and no tokens are spent. A provider whose key isn't set is skipped. Keys are sent only to that provider and never printed.
## Install and run
```
brew install markksantos/tap/ai-model-watch # macOS / Linux (Homebrew)
# or, with Node 18+
npx github:markksantos/ai-model-watch
# or
git clone https://github.com/markksantos/ai-model-watch && node ai-model-watch/bin/ai-model-watch.js
```
```
ai-model-watch [options]
-p, --providers <list> openrouter,openai,anthropic,gemini,mistral,xai,deepseek (default: all with a key)
-s, --state <file> where the last-seen lists live (default: ~/.cache/ai-model-watch/state.json)
-w, --watch <seconds> keep running and check every N seconds (minimum 60)
--removed also print models that disappeared
--json JSON output
--exit-code exit 1 when anything new appears (for cron and CI)
-q, --quiet print only new models
--mcp run as an MCP server on stdio
```
### MCP server (Claude, Cursor, VS Code)
`--mcp` runs it as a [Model Context Protocol](https://modelcontextprotocol.io) server on stdio, so an assistant can ask what's new itself. Two tools:
- `check_new_models`: the model IDs each provider started listing since the last check (same state file as the CLI).
- `list_models`: what one provider lists right now, with an optional substring filter.
Claude Code:
```
claude mcp add ai-model-watch -- npx -y github:markksantos/ai-model-watch --mcp
```
Claude Desktop, Cursor and other clients (`mcpServers` in their JSON config):
```json
{
"mcpServers": {
"ai-model-watch": {
"command": "npx",
"args": ["-y", "github:markksantos/ai-model-watch", "--mcp"]
}
}
}
```
OpenRouter works without a key. To include another provider, add its key from the [Providers](#providers) table to an `env` object in the same entry.
### Cron
```
*/15 * * * * OPENAI_API_KEY=... ANTHROPIC_API_KEY=... ai-model-watch -q >> ~/model-drops.log
```
### GitHub Actions
[`examples/github-action.yml`](examples/github-action.yml) runs the check on a schedule, caches the state file between runs, and fails the job (so GitHub emails you) when a new model appears.
## Library
`npm install github:markksantos/ai-model-watch`, then:
```js
const { check, fetchProvider } = require('ai-model-watch');
const report = await check({ providers: ['openrouter', 'anthropic'] });
for (const p of report.providers) {
for (const m of p.added || []) console.log(p.label, m.id);
}
```
`fetchProvider(id, { env, fetch })` returns `{ status: 'ok' | 'skipped' | 'error', models: [{ id, name, created }] }`. `check()` diffs against the state file and saves the new lists. A provider that errors keeps its last good list, so a failed request never makes the next run report the whole catalog as new.
## What a list can't tell you
A model ID in a `/models` list means the provider lists it. It doesn't prove the model answers requests yet, and some providers list models days before they are generally available. `created` is whatever date the provider reports, not when the model appeared.
The hosted version, **[ArtificialWatch](https://artificialwatch.com)**, polls these APIs plus the public catalogs every 60 seconds and confirms a detection on a second sweep before anything fires. Then it alerts you by email and Chrome push (free), or by text or phone call. Use it if you'd rather not keep a cron job running.
## License
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues