Model catalog data as JSON files, refreshed on a schedule.
https://raw.githubusercontent.com/cloudstack-llc/model-catalog/main/v1/prices.json
https://raw.githubusercontent.com/cloudstack-llc/model-catalog/main/v1/ollama-models.json
https://raw.githubusercontent.com/cloudstack-llc/model-catalog/main/v1/featured-models.json
https://raw.githubusercontent.com/cloudstack-llc/model-catalog/main/v1/smart-route-starters.json
| File | Contents | Source | Cadence |
|---|---|---|---|
v1/prices.json |
Token pricing for hosted models | models.dev | 6 hours |
v1/ollama-models.json |
The Ollama library: models, tags, sizes, context windows | ollama.com | 12 hours |
v1/featured-models.json |
Curated local models worth downloading, grouped into collections | Curated; resolved against Ollama and Hugging Face | Daily |
v1/smart-route-starters.json |
Model-neutral Smart Route starters, grouped by use | Curated | On change |
v2/runtime/{stable,dev}/runtime-release-feed.signed.json |
Signed Msty Nexus Runtime releases | Ollama, llama.cpp, and Msty MLX metadata | 4 hours |
Every model with a published input and output rate, in US dollars per one million tokens, grouped by provider.
"anthropic": {
"claude-opus-4-5": {"input":5,"output":25,"cache_read":0.5,"cache_write":6.25,"context":200000,"max_output":64000}
}| Field | Meaning |
|---|---|
input, output |
Required. USD per million tokens. |
cache_read, cache_write |
Prompt-cache rates, when published. |
reasoning, input_audio, output_audio |
Modality-specific rates, when published. |
context, max_output |
Token limits. |
tiers |
Long-context pricing, ascending by above_context. Rates replace the base rates once a request's context exceeds that size. |
An absent field means the rate is not published — never zero. Models with no price at all are omitted rather than published as free.
The envelope carries schema_version, generated_at, counts, and the upstream etag
and sha256.
v1/ is versioned on purpose. A breaking schema change ships as v2/ alongside it.
A scheduled job regenerates the file every six hours and commits it only when the prices
changed, so git log -p v1/prices.json shows actual price movement.
A run that finds no priced models, or fewer than 70% of the previous run's, fails without writing. Individual models that fail validation are dropped rather than repaired. CI re-serializes the committed file and range-checks every rate.
These are estimates. Providers change prices without notice and negotiated rates differ from list rates. Bill against your provider's invoice.
node --test scripts/*.test.mjs # transform rules
node scripts/verify.mjs # validate the committed file, no network
node scripts/generate.mjs # fetch upstream and rewrite v1/prices.jsonNo dependencies.
The runtime catalog lets Msty Nexus update managed runtimes independently from Nexus app releases. Every four hours, the publisher checks stable Ollama and llama.cpp releases plus the latest reviewed Msty MLX runtime. It writes only when a runtime version or immutable artifact identity changes.
The signed schema-2 feeds are served directly from this public repository:
https://raw.githubusercontent.com/cloudstack-llc/catalogs/main/v2/runtime/stable/runtime-release-feed.signed.json
https://raw.githubusercontent.com/cloudstack-llc/catalogs/main/v2/runtime/dev/runtime-release-feed.signed.json
They are not mirrored to R2. The signature is the trust boundary; the hosting origin supplies bytes but cannot authorize a runtime artifact.
Direct GitHub release assets are not downloaded by the publisher. GitHub's
SHA-256 digest and byte size enter the signed feed, and Nexus verifies the
download against that signed digest during installation. The Msty MLX archive
uses its published checksums.txt and an HTTP metadata request for size.
Upstream llama.cpp currently splits the Windows CUDA package into the server and CUDA runtime ZIPs. For that variant only, the publisher downloads both digest-pinned components, rejects unsafe or duplicate paths, merges them once, and publishes the result as an immutable GitHub Release asset. Later refreshes reuse that asset.
The feed uses the existing backend-aware Nexus schema and Ed25519 trust anchor.
The signing seed is stored only in the
MSTY_NEXUS_RUNTIME_RELEASE_FEED_PRIVATE_KEY repository secret. Pull requests
never receive it. REFRESH_TOKEN remains the repository-scoped token used by
the other scheduled catalogs; the default Actions token is a functional
fallback.
node --test scripts/runtime-feed.test.mjs
python3 -m unittest discover -s scripts -p '*_test.py'
node scripts/runtime-feed-verify-all.mjsv1/smart-route-starters.json gives Msty Nexus a model-neutral starting point
for common routing jobs. A starter contains the route name, classifier lanes,
target guidance, and the endpoint families it expects. It never contains a
model or pool ID. Nexus asks the person adding it to choose those targets.
Collections reference starters by ID, so one starter can appear in more than
one part of the catalog without being copied. revision changes when the
curated starter changes. Existing Smart Routes are independent copies and are
never changed by a catalog update.
Displayed copy describes each starter and lane directly. Lane descriptions are capped at 512 bytes because that is the classifier input limit.
Arch-Router matches the latest request against every lane as a natural-language route policy. Its training uses a domain-action taxonomy: the starter supplies the domain, while each lane should name a distinct action within that domain. See the model card and paper.
- Separate lanes by requested action, not by vague model qualities such as "easy" and "strong."
- Include concrete request signals, source material, and expected artifacts.
- State a boundary when two neighboring lanes could plausibly match the same opening request.
- Write each description for its actual job. Do not force every lane through one sentence template.
- Review the five lanes as a set and test short, ambiguous, and follow-up requests before publishing.
The fallback handles requests that do not clearly match a lane.
Validate a catalog edit before committing it:
node scripts/smart-route-starters-verify.mjsOptional REFRESH_TOKEN secret: a fine-grained PAT with contents: write on this
repository. GitHub disables scheduled workflows after 60 days without repository activity,
and pushes made with the default GITHUB_TOKEN do not reset that clock.
MIT (see LICENSE). Data derives from models.dev, also MIT — see NOTICE.
v1/ollama-models.json — every model in the Ollama library, with its tags,
download sizes, context windows, and per-tag parameter counts and quantization.
{
"name": "gpt-oss",
"description": "OpenAI's open-weight models ...",
"tags": [
{"tag":"20b","size":"14GB","digest":"17052f91a42e",
"model_info":{"contextWindow":"128K","parameters":"20.9b","quantization":"MXFP4","arch":"gptoss"}}
],
"params": ["tools","thinking","cloud","20b","120b"],
"pulls": "11.8M",
"pulls_approx": 11800000,
"updated": "1 month ago",
"updated_at": "2026-07-15T18:02:00Z"
}name, description, tags, params, pulls, and updated are present on every
model. digest, arch, pulls_approx, updated_at, cloud, cloud_tags, and
model_info.projector are additions.
pulls and updated are true only at generated_at. They are the strings the
site renders, so a file written at midnight still says "1 month ago" the next evening.
updated_at carries the absolute timestamp the relative string is derived from, and
pulls_approx decodes the display value so it can be sorted — it is a decoded
approximation, not a true count, because no absolute pull count is published anywhere.
Change detection ignores all four.
An unknown context window is "N/A", never an empty string.
Some tags carry an empty parameters and quantization. Ollama renders no metadata
block at all for certain variants (-mlx, -mxfp8, -nvfp4), so the values do not
exist to be scraped; those tags still carry a real size and contextWindow. The
count is declared in counts.missing_model_info and checked in CI, so a parser
regression cannot hide among them.
Cloud tags are excluded from tags[]. They host no weights, so they have no size,
parameters, or quantization. A model serving them carries "cloud": true and lists them
in cloud_tags.
Vision models keep their projector separate. The library renders two metadata blocks
for them — the model and its CLIP projector. model_info holds the model; the projector
is under model_info.projector.
Ollama publishes no API. Every API-shaped path returns 404, content negotiation is
ignored, and ollama.com/api/tags returns hosted cloud models rather than the library.
The catalog is therefore built from server-rendered HTML: one request for the library
index, one per model for its tags, and one per distinct layer digest for the fields that
appear nowhere else.
Parameter counts and quantization are immutable for a layer digest, so they are cached in
v1/ollama-model-info-cache.json. A cold run is ~6,500 requests; a warm one is a few
hundred. The crawl runs 8 concurrent with a truthful, contactable user agent.
Because this rests on presentation markup, the generator refuses to publish when a field drops below 95% coverage, when the catalog shrinks by more than 10%, or when tag names and scraped parameter counts start disagreeing. On refusal the job fails and the previous file stands.
v1/featured-models.json — the local models worth recommending to somebody who has
just installed a runtime and does not yet know what to download.
Unlike the scraped files this one is curated. Which models appear is a judgement, and it
lives in scripts/featured-curation.mjs; every value attached to them is not. Tags, sizes, context windows and parameter counts come from
ollama-models.json, and repositories, GGUF file names and byte counts come from the
Hugging Face API. A reference that cannot be confirmed fails the build rather than
shipping — a featured row with a dead download behind it is worse than one fewer row.
A featured entry is a model, not a repository. One entry carries every way to obtain that model, so a client can offer "Qwen3.5 9B" and let the engine and quantization be a detail behind it. Collections reference models by id rather than nesting them, so one model can appear in two collections without being described twice.
{
"schema_version": 1,
"generated_at": "2026-08-15T00:00:00Z",
"collections": [
{"id":"start-here","title":"Start here","description":"...","models":["qwen3.5-9b"]}
],
"models": [
{
"id": "qwen3.5-9b",
"name": "Qwen3.5 9B",
"publisher": "Qwen",
"summary": "Strong all-round chat with a very long context.",
"parameters": "9.7B",
"context": 262144,
"capabilities": ["chat","tools","reasoning","vision"],
"installs": [
{"runtime":"ollama","model":"qwen3.5:9b","quantization":"Q4_K_M","size_bytes":6600000000},
{"runtime":"llamacpp","repository":"unsloth/Qwen3.5-9B-GGUF","file":"Qwen3.5-9B-Q4_K_M.gguf",
"quantization":"Q4_K_M","size_bytes":7500000000,"projector":"mmproj-F32.gguf"},
{"runtime":"mlx","repository":"mlx-community/Qwen3.5-9B-MLX-4bit","size_bytes":6000000000}
]
}
]
}| Field | Meaning |
|---|---|
id, name |
Required. Everything else is optional. |
publisher, summary, parameters, context, capabilities, tags |
Description, for display and filtering. "coding" in tags marks a model that is good at writing code. |
tier |
Quality tier: frontier, excellent, strong, or good. |
installs[].runtime |
ollama, llamacpp, or mlx. |
installs[].model |
The Ollama tag. Ollama installs are addressed by it; Hugging Face installs are not. |
installs[].repository, file, revision |
The Hugging Face locator. revision defaults to main. |
installs[].quantization, size_bytes |
What the download is and how big. |
installs[].projector |
A file name in the same repository. |
size_bytes is what the download costs, so a llama.cpp entry with a projector counts
both files. The order of installs is the recommendation order: a consumer offers the
first entry it can actually run.
projector is llama.cpp only. A GGUF vision model needs its mmproj-* file loaded
beside the weights, and a model served without one answers questions about images it
cannot see. Ollama and MLX ship the projector inside the artifact they already download,
so they never name it. A publisher shipping a projector is also treated as stating the
model is multimodal, so those entries declare vision.
Only single-file GGUFs are featured. A featured row promises one click, and a sharded
download is a flow this format cannot describe. A repository publishing only shards gets
no llamacpp entry.
tier is a curated quality rating. Msty Nexus Cluster Advisor ranks by it. It rates
general chat and reasoning quality against the open models available at the time:
| Tier | Meaning |
|---|---|
frontier |
The best open models, close to hosted frontier models. |
excellent |
One step below: the previous generation's flagships and the top coding models. |
strong |
Capable mid-size models, roughly 20B to 130B. |
good |
Small models, and models with one narrow job (OCR, embeddings). |
Tiers are relative, so review them when a new generation of models is released. A client
that finds no tier estimates one from the model's size and says so. The field is
additive: older Nexus builds ignore it, so schema_version stays 1.
The cluster collection is a contract. Cluster Advisor reads it by id. It holds MLX
models too large for one Mac, from model families the cluster runtime can split across
Macs.
An Ollama size published as a range uses the upper end. Ollama shows a range, such as
6.6GB - 7.6GB, for a tag that resolves to different files per platform. size_bytes is
what the download may cost, so a fit check that overestimates is the safer error.
A daily job (refresh-featured.yml) rebuilds the file from the curation, the committed
ollama-models.json, and the Hugging Face API. It refreshes files, sizes, parameters,
context and popularity, and never adds or drops a model: only a reviewed edit of
scripts/featured-curation.mjs does that.
The job commits only when something other than generated_at or popularity changed;
Msty Nexus reads popularity live and treats the published numbers as a fallback. Any
reference it cannot confirm, or any Ollama size it cannot read, fails the run without
writing, so the published file stands until a maintainer fixes the curation.
After each run, featured-report.mjs lists mlx-community repositories that may be newer
versions of featured models (by each model's watch term) in the job summary. These are
leads for a maintainer, not changes.
To change the list, edit scripts/featured-curation.mjs, then rebuild and commit both:
node scripts/featured-generate.mjs # fetch and rewrite v1/featured-models.json
node scripts/featured-verify.mjs # offline: shape, sizes, and match with the curation
node --test scripts/featured.test.mjsCI runs the verifier, so a curation edit without a rebuild fails the pull request.