npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

model-catalog

v0.0.1

Published

A tiny JS/TS library and CLI for building AI model catalogs and listing BYOK-available models.

Readme

model-catalog

A tiny JS/TS library and CLI for building AI model catalogs and listing/filtering models.

Fetch models.dev once. Add custom generators. Store the snapshot anywhere. Render the model list your app wants.

Demo

Note: the UI is not part of the lib. But you can reference it on examples/*

https://github.com/user-attachments/assets/5a18dfa0-2acb-48b8-a496-40ad1ee7fd26

Why

  • Powered by models.dev.
  • Supports custom providers/generators for models that models.dev does not cover.
  • Lists and filters models from catalog data with one core API: catalog.listModels().
  • Storage-agnostic: database, file, localStorage, API route, static JSON, generated TypeScript.
  • Frameworkless core with copyable examples instead of framework adapters.

Install

npm install model-catalog

Quick start

import { createCatalog, refreshSnapshot } from "model-catalog";

const snapshot = await refreshSnapshot();

const catalog = createCatalog(snapshot);
const models = catalog.listModels({
  includeProviders: ["anthropic"],
  query: "claude tools",
  groupBy: "providerId",
});

console.log(models.groups[0]?.models[0]?.providerLogoUrl);

refreshSnapshot is never a fast operation so make sure to persist snapshot somewhere (i.e. database, redis, a json file on a non-ephemeral deployment, indexedDB, localStorage) before using it with createCatalog.

App-owned provider filtering

The package does not model provider credentials or provider configuration. If your app only wants to show providers that the current user configured, derive those provider IDs in your app and pass them to includeProviders.

const enabledProviders = providerConfigs
  .filter((provider) => provider.isEnabled && provider.hasApiKey)
  .map((provider) => provider.provider);

const catalog = createCatalog(snapshot);
const models = catalog.listModels({
  includeProviders: enabledProviders,
  require: ["tool_call"],
  minContext: 128_000,
  excludeDeprecated: true,
});

Custom generators

Generators run during refreshSnapshot() and receive a tiny context with ctx.addProvider(), ctx.addModel(), ctx.updateProvider(), and ctx.updateModel().

There are three useful patterns:

  1. Static JSON / static objects for small catalog extensions.
  2. API-backed generators that fetch from a remote endpoint and add plain provider/model records.
  3. Runtime generators that inspect the current machine, such as a local CLI. Runtime generators are Node/machine-only and should not be used in browser bundles.

Add models to an existing provider

If models.dev already has the provider and you only want to add or patch models, call ctx.addProvider() with the same provider id and only the models you care about. Existing provider data is preserved; model ids you define are added, and matching model ids are overwritten by your generator.

This is the same shape as the built-in catalog_extensions.json entry for xAI Composer 2.5.

import { defineGenerator, refreshSnapshot } from "model-catalog";

const xaiComposer = defineGenerator({
  id: "xai-composer-extension",
  kind: "static",
  generate(ctx) {
    ctx.addProvider({
      id: "xai",
      name: "xAI",
      models: [
        {
          id: "grok-composer-2.5-fast",
          name: "Composer 2.5",
          family: "grok-build",
          attachment: false,
          reasoning: false,
          reasoning_options: [],
          tool_call: true,
          structured_output: true,
          temperature: true,
          open_weights: false,
          modalities: { input: ["text", "pdf"], output: ["text"] },
          limit: { context: 256_000, output: 256_000 },
          cost: { input: 0.5, output: 2.5, cache_read: 0.2 },
        },
      ],
    });
  },
});

const snapshot = await refreshSnapshot({ generators: [xaiComposer] });

Add a completely new provider

For a provider that is not in models.dev, add the provider record and its models directly.

import { defineGenerator, refreshSnapshot } from "model-catalog";

const companyGateway = defineGenerator({
  id: "company-gateway",
  kind: "static",
  generate(ctx) {
    ctx.addProvider({
      id: "company",
      name: "Company Gateway",
      logoUrl: "https://example.com/company.svg",
      models: [
        {
          id: "fast",
          name: "Fast",
          attachment: false,
          reasoning: true,
          reasoning_options: [
            { type: "effort", values: ["low", "medium", "high"] },
          ],
          tool_call: true,
          structured_output: true,
          temperature: true,
          open_weights: false,
          modalities: { input: ["text"], output: ["text"] },
          limit: { context: 128_000 },
        },
      ],
    });
  },
});

const snapshot = await refreshSnapshot({ generators: [companyGateway] });

API-backed generator

For providers with a remote model endpoint, put the fetch/parsing logic in your generator. model-catalog does not need to know the provider's API URL shape; your generator just converts the response into provider/model records.

import { defineGenerator } from "model-catalog";

const remoteModels = defineGenerator({
  id: "remote-company-models",
  kind: "api",
  async generate(ctx) {
    const response = await ctx.fetch("https://api.company.test/v1/models");
    const payload = await response.json();

    ctx.addProvider({
      id: "company",
      name: "Company",
      api: "https://api.company.test/v1",
      npm: "@ai-sdk/openai-compatible",
      models: payload.data.map((model: { id: string; name?: string }) => ({
        id: model.id,
        name: model.name ?? model.id,
        tool_call: true,
        temperature: true,
        modalities: { input: ["text"], output: ["text"] },
      })),
    });
  },
});

Built-in generators

refreshSnapshot() already has the baseline catalog by default:

  • models.dev
  • catalog_extensions.json, package-maintained patches for things models.dev does not cover yet

There are also a few opt-in built-in generators:

import {
  commandCodeGenerator,
  ollamaCliGenerator,
  refreshSnapshot,
} from "model-catalog";

const snapshot = await refreshSnapshot({
  generators: [
    commandCodeGenerator(), // remote API-backed generator; opt-in latency
    ollamaCliGenerator(), // local CLI generator; opt-in machine state
  ],
});
  • [x] commandCodeGenerator - for commandcode.ai since they're pretty much ignoring this models.dev request and opencode request.
  • [x] ollamaCliGenerator() - runs ollama ls to get a personalized model list based on the user's config. It only works in Node.js on machines where the Ollama CLI is installed. Never run it in the browser; browser code cannot execute local CLIs.

CLI

model-catalog refresh --out ./model-catalog.json
model-catalog generate --out ./src/model-catalog.generated.ts
model-catalog inspect ./model-catalog.json
model-catalog list ./model-catalog.json --provider anthropic --query claude --tools

Examples

The core package does not export UI components. A self-contained, compile-ready Solid example lives at:

examples/solid/chat-model-selector.tsx

It shows how to achieve a great model-selector UX by consuming catalog.listModels()

What this library is not

  • A chat/completions SDK.
  • A replacement for Vercel AI SDK or provider SDKs.
  • Provider credential flows or secret storage.
  • A database/storage adapter layer.
  • A required model-selector UI abstraction.
  • A replacement for models.dev. It is powered by it.

License

MIT