This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Two overlapping things live here:
- A content repo for vLLM recipes — structured YAML at
models/<hf_org>/<hf_repo>.yaml, one per model. The path mirrors HuggingFace so the site URL/<hf_org>/<hf_repo>matcheshuggingface.co/<hf_org>/<hf_repo>. - A Next.js 15 site (App Router, React 19, Tailwind v4) that renders those YAMLs as an interactive command builder + static JSON API under
public/. The older top-level Markdown directories (DeepSeek/,Qwen/, etc.) andmkdocs.ymlare the legacy MkDocs site, kept for reference during migration.
The site is the canonical surface. New work goes into YAMLs + the Next.js app; the .md files are historical sources for the migrated YAMLs.
pnpm dev # Next dev server (do not kill or rebuild as part of a task)
pnpm build # Regenerates JSON API + fetches logos/HF dates, then next build
pnpm lint # next lint (ESLint)
node scripts/build-recipes-api.mjs # Rebuild the JSON API only — fastest validation that all YAMLs parse
node scripts/fetch-provider-logos.mjs # Re-download HF org avatars to public/providers/
node scripts/fetch-hf-dates.mjs # Refresh public/hf-dates.json (HF createdAt per model)
bash scripts/hf-info.sh <org>/<repo> # Pull config.json / params.json for a model (used when authoring recipes)There is no unit-test suite. The build-recipes-api script is the de-facto validator: if it prints ✓ JSON API: N models, <strategy-count> strategies the YAML set is internally consistent.
Dev-server convention: don't kill or restart the dev server as part of a task, and don't run pnpm build for each change. Use node scripts/build-recipes-api.mjs for fast feedback on YAML edits; rely on Next's HMR for src/ edits.
Commit convention: always use git commit -s (sign-off). The upstream vllm-project/recipes repo enforces DCO via the probot/dco GitHub App — commits without a Signed-off-by: trailer fail CI and block the PR. There's no GitHub-side auto-fix; the trailer has to be in the commit itself.
models/<org>/<repo>.yaml ──┐
strategies/*.yaml ─┼──► src/lib/*.js ─► Next.js pages + JSON API in public/
kv_store/*.yaml ─┤ (SSG, no runtime DB)
taxonomy.yaml ─┘
taxonomy.yaml— the controlled vocabulary: hardware profiles (GPUs/node + VRAM), tasks, serving strategy ids, plus thekv_offloadblock — the composing KV-offload options (Simple, LMCache), each{ display_name, label?, description, args[], strategies?, install?, companion? }, read data-driven by command synthesis.strategiesis a per-option serving-strategy allowlist (LMCache = single-node only);companionrenders as an extra command tab (e.g.lmcache server) while the option is active.strategies/*.yaml— the 9 serving strategies:single_node_{tp,tep,dep},multi_node_{tp,tep,dep,tp_pp,tp_dp},pd_cluster. Each defines the vLLM flags and env for that parallelism pattern.multi_node_tp_dpis the hybrid TP-per-node + DP-across-nodes layout (parallelism: tp_dpin the YAML → synthesis emits--tensor-parallel-size <gpus/node> --data-parallel-size <nodes> --data-parallel-size-local 1, worker node N = DP rank N).kv_store/*.yaml— the Mooncake KV-store deploymentskv_store_{distributed,centralized}_mooncake(deploy_type: kv_store_lb— router + master + optional store + N vLLM instances, each spanning the Nodes-row node count). They power the KV Offload row, not the Strategy row;loadStrategies()merges them into the same map (looked up by id everywhere) but the JSON API publishes them underpublic/kv_store/so/strategies.jsonstays the serving vocabulary.src/lib/recipes.js,strategies.js,taxonomy.js— filesystem readers that parse YAML once per process.src/lib/command-synthesis.js— the core of the site. Pure functions that take(recipe, variantKey, strategyName, hwProfileId, features, strategies, taxonomy, advancedArgs, nodeCount)and return either a singlevllm servecommand, a pair of head+worker commands (multi-node), or a prefill/decode pair (pd_cluster). All parallel flag decisions, per-generation hardware overrides, and multi-node mp args (--nnodes/--node-rank/--master-addrfor TP,--data-parallel-*for DEP) live here.scripts/build-recipes-api.mjs— writespublic/taxonomy.json,public/strategies/*.json,public/kv_store/*.json, andpublic/<hf_org>/<hf_repo>.jsonat build time so agents can consume recipes without the website.
src/app/page.js— homepage (provider grid, alphabetical).src/app/[org]/page.js— org overview, task-grouped sections.src/app/[org]/[repo]/page.js— the recipe detail page. SSG viagenerateStaticParamsover all YAMLs. Renders header +<CommandBuilder>+ guide markdown (viareact-markdown, not MDX — MDX chokes on<think>and<64Kliterals in guide text).src/app/[org]/layout.js— wraps every recipe/org page with the left<ModelSidebar>, sorted by HF release date desc.src/components/recipes/CommandBuilder.jsx— the interactive piece. Client component. Holds state forvariant,hwId,strategyOverride,nodeCount,features,advanced; syncs all of them to URL query params; renders Hardware / Variant / Strategy / KV Offload / Nodes / Features / Advanced rows + the sticky command block. CallsresolveCommandon every change. The KV Offload row: Off (default) / Simple (taxonomy-driven--kv-transfer-configappended to the current strategy; disabled under pd_cluster) / one merged Mooncake pill. Every option COMPOSES with the serving strategy — the KV layer is orthogonal to parallelism, the Strategy row is always in effect. Mooncake wraps the selected strategy in akv_store_lbdeployment shell (router + master + optional store around N instances, each instance running the serving strategy's exact command — TP/TEP/DEP, single- or multi-node — with the MooncakeStoreConnector args/env appended last-wins; synthesis exposes the pairing asservingStrategy, the JSON API asserving_strategy). Offered on every non-omni recipe by default, needs scalable NVIDIA/AMD hardware (isKvStoreBrandSupported— the transfer engine has no CPU/TPU build; the brand-keyedvllm.installresolves CUDA vs non-CUDA wheel and the kv YAML'smin_vllm_versionbumps the Install header while active); a recipe opts a GPU out viakv_cache_strategy_hardware: { <kv_store_id>: { <gpu_id>: unsupported } }; URL paramkv_offloadholds the topology's strategy id. A Mooncake pick reveals a Store Topology row (Distributed embedded vs Centralized standalone store — shortlabelfrom the kv_store YAML; distributed is the first-click default) and an Instances input (URLkv_instances; default = the topology'sdefault_instances: distributed 1 — a single embedded instance is a complete CPU-offload tier — centralized 2). The router only exists at ≥2 instances; at 1 the client target falls back to VLLM_HOST:8000 and cURL/Bench move to the vLLM tab. The Nodes row keeps meaning nodes PER INSTANCE — relabeled "Nodes / Instance" while Mooncake is active, tooltips multiply totals by the instance count; at >1 each instance shards like multi_node_tp (tabs named Head / Node 1, same as MultiNodeBlock;--master-addris $HEAD_IP at 1 instance, $VLLM_INSTANCE_N when routed). Under pd_cluster Mooncake COMPOSES instead of replacing: PD keeps Prefill/Decode/Router, each role's Nixl config swaps (last-wins) for the kv_store YAML'spd.<role>.argsMultiConnector (Nixl + MooncakeStoreConnector), both roles gain the Mooncake env + config heredoc, and Mooncake Master/(Store) tabs lead the PD block; the Instances row hides (PD pools size themselves). Interaction-expression conventions: the Strategy row description gains an "Each Mooncake instance runs this strategy." suffix while Mooncake is active (composition made explicit, no dimming — the strategy is genuinely in effect); the active KV option's description + Docs link render under the row (Strategy-row style); Store Topology / Instances / the spec-method row useConfigRow nested(blue left rail = child of the pick above); command-block tabs go through the sharedCommandTabs(ARIA tablist, arrow-key roving focus, dimmedstepnumbers whenever the tabs form a launch sequence — always for Mooncake/kv_store, PD only when composing, companions); cURL/Bench render disabled-with-tooltip (never hidden) on tabs clients don't connect to; disabledPills wrap in a span so Radix tooltips still explain WHY (nativedisabledswallows pointer events); the "Verified on " badge yields to the config summary whenever any KV Offload option is active (verification covered the plain serving path); setting KV Offload back to Off resets kv_instances/kv_instance to topology defaults.
Top-level keys, in this order:
meta— title, slug, provider, description, date_added, date_updated, difficulty, tasks[], performance_headline, related_recipes[], optionaldefault_hardware, optionalhardware: { gpu_id: verified | unsupported }.date_addedis the immutable day the recipe first entered the catalog and drives the homepage's "Latest recipes" ranking;date_updatedrecords the latest material recipe change. Hardware is tri-state:verified= tested end-to-end (green ✓ badge);unsupported= not yet runnable on this hardware today — compat gap / missing kernel / upstream blocker that could lift later (pill rendered but disabled + struck through, tooltip says "Not yet supported"); absent = silent default, assumed to work. Don't useunsupportedfor "untested" — only when you've confirmed it currently fails.default_hardwareis a single GPU profile id (b300,dgx_spark_gb10, …) — the hardware the page and the JSON API open on. Precedence: URL?hardware=> the user's stored global preference (set only by an explicit pill click) >default_hardware> thepickDefaultHardwareheuristic (B200 for Blackwell-constrained variants, else H200). A returning visitor's own GPUs therefore still win — this key only replaces the model-blind heuristic. It's validated and fail-open: an id that's unknown to the taxonomy, precision-incompatible with the resolved variant, markedunsupported, or arestrictedprofile the recipe doesn't declare inmeta.hardwarefalls through silently to the heuristic. Authoring rule: set it to the hardware the guide's numbers, theperformance_headlineand theverifiedbadge were taken on — not to the biggest GPU. Landing on averifiedprofile is what makes the command block's green "Verified on " badge the built-in explanation for the choice, so no extra banner is needed; pointing it at an unverified GPU loses that badge and is worse than leaving the key absent. Most important for the JSON API, which has no URL or localStorage —default_hardwareis the only way an author steersrecommended_command(everything else stays addressable underby_hardware).model—model_id,min_vllm_version,architecture(denseormoe),parameter_count,active_parameters,context_length,base_args[],base_env{}, optionaldefault_frontend: python | rust(defaults to Python). Setdefault_frontend: rustfor recipes that recommend it. The selector is saved per recipe and in?frontend=python|rust; command synthesis emitsVLLM_USE_RUST_FRONTEND=1for Rust and omits the variable for Python. Keep this variable in the frontend synthesis path; usedefault_frontendto express recipe defaults. The JSON API uses the same recipe default.dependencies(optional) — list of{ command, note?, optional?, brand?, install_modes? }. Rendered as the "extra install" block abovevllm serve. Use this for DeepGEMM pins,vllm[audio], pinned transformers commits, vllm-omni source installs, etc.optional: truedims the entry and excludes it from the block's "Copy all" button (the user must copy it explicitly).brand: NVIDIA | AMD | Intel(or array) hides the entry when the current hardware pill is a different brand — use for CUDA-only kernels (xformers, DeepGEMM) or ROCm-only wheels. Omitbrandfor platform-agnostic deps (diffusers from source, transformers commits, etc.).install_modesgates the entry by Install tab, and absent means[pip]— the block is pip-scoped by default because the Docker image already bundles the pip installs, so repeating them besidedocker runis noise.install_modes: [pip, docker]opts an entry into both tabs; reserve it for host-side prerequisites Docker cannot satisfy, i.e. a gated checkpointhf downloadmust place on disk beforebuildDockerRuncan bind-mount it (MiniMax-H3). A pip install never wants this. Keep the runnable fetch step here rather than as a#comment on the command — the block's "Copy all" yields executable lines, a comment does not.features— map of{feature_key: { description, args[], env?, label? }}. Naming convention:tool_calling,reasoning,spec_decoding(the unified key for MTP / Eagle3 / ERNIE-MTP — don't usemtp, it was renamed across all recipes),long_context(RoPE/YaRN context extension — see below). Each feature is a boolean toggle by default. Optionallabeloverrides the pill text (default: title-cased key).env{}— env vars set only while the feature is on. Emitted frombuildEnvas the mirror of the featureargsblock inbuildArgs(step 7): applied after every override layer so an enabled feature wins, and gated identically (strategy allowlist, Mooncake-companion skip, active mode) so a feature's env and args can never disagree about whether it's on. Amodesentry may carryenvtoo, andhardware_overrides.<key>.envREPLACES it the same wayargsdoes. Use it for features whose documented launch line is env + flags rather than flags alone —long_contextneedsVLLM_ALLOW_LONG_MAX_MODEL_LEN: "1"wherever the target window exceeds the checkpoint'smax_position_embeddings. Propagates to every rendering: single-node, head + each worker on multi-node (one env map per deployment), both PD roles, and the Docker-eflags.long_context— the context-extension toggle, ALWAYS inopt_in_features: static YaRN holds its scaling factor constant regardless of input length, so leaving it on costs short-prompt quality, and the longer window inflates the KV budget. Args are--hf-overrides '<rope json>'+--max-model-len <extended>; because features emit last anddedupeArgsis last-wins, both cleanly shadow a--max-model-lenalready inbase_args. Use--hf-overrides, never--rope-scaling— the latter is what most model cards still print, but it was removed from vLLM'sModelConfigby 0.26, and transformers v5 renamed the config fieldrope_scaling→rope_parameters(vLLM 0.29 readshf_config.rope_parameters). So a card's--rope-scaling '{...}'translates to--hf-overrides '{"rope_parameters":{...}}', and on a VL/omni checkpoint the block nests undertext_config(a top-level override silently misses the decoder's config). Only add this feature where the model card documents a specific extension config — don't invent a factor.- Single-select sub-modes — when one feature has several mutually exclusive methods (e.g. a model offering more than one speculative method: MTP / DSpark / DFlash), replace the feature's flat
args[]with amodesmap and it renders as a "pick one" segmented row under the feature toggle instead of a boolean. A mode contributes onlyargs(the--speculative-config) — the method, never the served checkpoint. Shape:{ description, default_mode?, modes: { <mode_key>: { label?, description?, args[], variants?, hardware_overrides?, hardware? } } }. Only the selected mode'sargsare emitted, so exactly one--speculative-configis ever produced — no dedupe conflict between sibling methods, and nodisables_featuresgymnastics.default_modepicks the initial mode (else the first key). A mode may restrict itself to specific checkpoints withvariants: [<variant_key>, …]— e.g. the dspark method only exists on the fused DSpark checkpoint, so FP8/NVFP4 offer MTP only (a mode with novariantsis available everywhere). The row renders only when ≥2 modes are available for the current variant — a single available method is left to the boolean feature toggle (no redundant one-pill row, no disabled cross-axis buttons). The effective mode is resolved byresolveModeKey(variant + hardware availability, then user pick →variant.default_modes→feature.default_mode→ first available). Keep the booleanargs[]form for recipes that ship a single method — the two forms coexist and single-method recipes need no change. Selected mode syncs to the URL as?fmode=spec_decoding:dflash(default omitted). Synthesis + UI helpers:defaultModeFor/isModeSupportedincommand-synthesis.js.- Method vs. checkpoint — the two axes stay separate. The served checkpoint (
vllm serve <X>) is always owned by the Variant row (variant.model_id); a mode only picks the--speculative-configmethod. So: a method that adds an externally-trained draft (a separate speculator repo named inside the configmodel, e.g. GLM'sRedHatAI/GLM-5.2-speculator.dspark-preview) is a pure mode —<X>is unchanged. A method that ships as a fused checkpoint you serve instead (the draft is baked in,--speculative-configcarries nomodel, e.g. officialdeepseek-ai/DeepSeek-V4-Pro-DSpark) is a variant (itsmodel_id) plus a mode for the config. Couple them withvariant.default_modes: { <feature>: <mode> }(seevariantsbelow): selecting the DSpark variant flipsspec_decodingto the dspark method by default, while the checkpoint still runs MTP if the user switches the mode back. Don't put--speculative-configin a variant'sextra_args(last-wins dedupe would let the boolean/mode feature shadow it) — keep it in the mode. - Per-mode hardware gating — a mode may carry
hardware_overrides.<gen>.args(per-generation arg swap, same semantics as feature-level) and a tri-statehardware: { <gen_or_gpu_id>: unsupported }to gate a mode to specific GPUs (e.g. a DFlash draft that only ships for Blackwell →hardware: { hopper: unsupported }); the pill is struck-through on incompatible hardware and the selection auto-falls-back to the first supported mode.
- Method vs. checkpoint — the two axes stay separate. The served checkpoint (
- Per-strategy gating — a feature may declare
strategies: [<strategy_id>, …](allowlist; absent = every strategy). Gate a feature when its args collide with a strategy's own flags or its setup doesn't generalize (e.g. a--kv-transfer-configthat would clobber pd_cluster's NixlConnector — features emit last, so last-wins dedupe would win). On excluded strategies the pill renders disabled ("Not available with this strategy"); the toggle state is preserved and synthesis independently skips the feature's args and companion. Helper:isFeatureAllowedForStrategyincommand-synthesis.js. NB: KV offloading itself is NOT a per-recipe feature in this repo — it lives on the universal KV Offload row (taxonomykv_offload+kv_store/), which reuses the same gating idea viaisKvOffloadAllowedForStrategy. - Companion process — a feature may declare
companion: { label, description?, command }for a helper that must run alongsidevllm serveon the same node. While the feature is on, the single-node command block renders PD-style tabs (vLLM Serve · <label>); the companion tab shows the raw command (no docker wrap, no env prelude) with the description as a#comment line. Carried in the JSON API ascompanions[]on single-node renderings. The taxonomy'skv_offload.<key>.companion(LMCache'slmcache server) flows through the same machinery.
opt_in_features[]— subset of feature keys that default OFF; others default ON. Typicallyspec_decodingis opt-in. (For a modes-feature, opt-in still governs the on/off toggle; the mode row only appears once the feature is on.)variants— must include adefaultvariant. Each hasprecision,vram_minimum_gb, optionaldescription, optionalmodel_idoverride (for quantized checkpoints shipped under a different HF repo, e.g.nvidia/*-NVFP4), optionalextra_args/extra_env, optionallabel(overrides the pill text, which otherwise showsprecision.toUpperCase()— use it to disambiguate two variants of the same precision, e.g. a fused-spec checkpoint →label: "DSpark"), optionaldefault_modes: { <feature>: <mode> }(steers a modes-feature's default mode when this variant is selected and auto-enables that feature even if it's inopt_in_features— e.g. the DSpark checkpoint variant turnsspec_decodingon and defaults to the dspark method; see spec_decoding modes above), optionalmin_vllm_version/nightly_required(bump the recipe baseline for a variant that needs a newer vLLM — the Install block shows the higher version and, ifnightly_required, switches to the nightly wheel index + tag; e.g. the DSpark checkpoint requires 0.25.0, currently nightly), optionaltp(per-variant single-node TP override; either a bare number or a hardware-aware map keyed by exact GPU id, generation, brand, ordefault, e.g.{ b300: 1, h200: 2 }. Use it when a variant has documented per-GPU layouts or stricter sharding constraints — typically FP8-block-quantized siblings whosemoe_intermediate_size / TPmust stay divisible byblock_n=128. Do not put--tensor-parallel-sizeinsideextra_args; it gets silently overridden by the strategy emitter), optionalhardware_overrideswith two disjoint keyspaces: a generation key (hopper/blackwell/amd/nvidia) layers ADDITIVELY on top of the recipe-levelhardware_overrides.<gen>baseline — applies to every variant includingdefault(unlike the top-level variantextra_args, which is a non-default checkpoint delta; the generation HO is hardware-conditional config, sodefaultuses it too). Use it for a per-variant hw delta that only some precisions want: e.g. the FP8 checkpoints of DeepSeek-V4 add--moe-backend deep_gemm_mega_moe(an FP8-only MoE kernel) on Blackwell while the NVFP4 variant adds nothing — the recipe-levelblackwellblock holds only the shared--attention_config.use_fp4_indexer_cache=True. Precedence: a per-strategystrategy_overrides.<s>.hardware_overrides.<gen>still REPLACES both the recipe baseline and the variant delta (e.g.single_node_tpdropping the mega-kernel), so strategy HO > (recipe HO + variant HO). The other keyspace, an exact-GPU-id key (b200,mi355x, …), is additive too (non-default variants only) and can also carryvram_minimum_gb(GPU-resident fit budget after CPU weight offload — replaces the variant's fullvram_minimum_gbforfitsSingleNodeon that GPU only; never bump taxonomyvram_gbwith host RAM),docker_image(per-variant-per-GPU image pin) andinstall: { pip: false }— the per-GPU form ofmodel.install.pip: false, declaring that no wheel can run this recipe on that GPU so the Install block hides the pip tab there (and the command block rendersdocker run) while leaving pip intact on every other hardware. Use it when the pinned image carries kernels that aren't in vLLM main, so the generated args would abort on an official wheel — DeepSeek-V4-Flash's B12X flags on DGX Spark. Not for "docker is easier here": a pip path that merely isn't the recommended one stays offered.precision_hardware(optional, variant-level) — overrides the default hardware constraint implied byprecision, using{ brand?, generation? }. Use only for exceptional checkpoints whose runtime fallback expands compatibility beyond the stored format, such as NVFP4 weights that vLLM dequantizes to BF16 on Hopper. Pair it withsupported_hardwarewhen only specific GPU profiles are documented.
compatible_strategies[]— subset of the serving strategy ids. Dense models typically only getsingle_node_tp+multi_node_tp; MoE models can have every serving strategy. Membership doubles as the default support state per GPU: listed = supported on every hardware, unlisted = supported nowhere —strategy_hardwareoverrides either default per hardware, and a strategy grantedsupportedthere joins the offered set without being listed here (appended after the listed ones; helpereffectiveCompatibleStrategiesincommand-synthesis.js). Do NOT listkv_store_*_mooncakeids here — KV-offload options (Simple + both Mooncake modes) are implicit on every non-omni recipe and feed the "KV Offload" row, not the Strategy row.strategy_min_gpus(optional) — minimum GPUs a strategy needs for this model. Either a bare number (one bar for every strategy) or a map keyed by strategy id ({ multi_node_dep: 16, multi_node_tp: 8 }) so one parallelism can demand more than another — e.g. Kimi-K3 runs TP/TEP from 8 GPUs but needs 16 for DEP. The map takes a second, disjoint keyspace: an exact GPU id (h100: 32, or nested per-strategyh100: { multi_node_dep: 32 }) layering a hardware-conditional floor on top of the strategy bars, highest wins. Use it when one GPU needs a bigger cluster than the recipe baseline — K3's ~1.68 TB of weights fits 2 H200 nodes but needs 4 on H100, soh100: 32, which also dropssingle_node_tpfrom the H100 pill row for free (8 GPUs can't clear a 32-GPU bar). Only exact GPU ids are read, never generations: GPUs of one generation differ in VRAM, which is exactly what moves the floor. Opt-in and fail-open: absent = no floor, so existing recipes are unaffected. A multi-node strategy stays offered and grows the node count to meet its bar when picked (the Nodes row gains the count that first clears it, e.g. 4 on a 4-GPU NVL tray); a single-node strategy can't scale, so it drops out when the floor exceeds one node's GPUs. Applies to PD pools too, keyed by pool parallelism (tp/tep/dep→ the matchingmulti_node_*entry) — each pool is sized to its own floor. Helpers:minGpusForStrategy/nodesForStrategy/isStrategyReachableincommand-synthesis.js, shared by the builder and the JSON API. Distinct from the (currently unread)hardware_match.min_gpusinstrategies/*.yaml, which is a per-strategy structural minimum rather than a per-recipe one.kv_cache_strategy_hardware(optional) — per-strategy/per-GPU opt-OUT for the Mooncake pills:{ <kv_store_id>: { <gpu_id>: unsupported } }. Follows the repo's fail-open hardware convention: absent = assumed to work (pill enabled on any scalable GPU);unsupporteddisables the pill and makes the JSON API skip that strategy on that hardware. "Off" and "Simple" need no gating (Simple is defined once intaxonomy.yaml → kv_offload).strategy_hardware(optional) — per-serving-strategy hardware overrides,{ <strategy_id>: { <hw_key>: unsupported | supported } }, layered on the membership default fromcompatible_strategies(listed = supported everywhere, unlisted = nowhere). Each per-strategy map takes the variant-tpkeyspace — exact GPU id > generation > brand (lowercase) >default, first key present wins, an explicitdefault:beating the membership baseline — so both directions are one line per hardware key:unsupportedopts a listed strategy out of a GPU/generation/brand;supportedopts an unlisted strategy in, which also adds it to the offered set (nocompatible_strategiesentry needed — e.g. Kimi-K3 offersmulti_node_tp_dponly via{ h200: supported, gb200: supported, gb300: supported }).unsupportedrenders the Strategy pill disabled with a tooltip, keeps it out of the recommended/active fallback, and makes the JSON API skip that strategy on that GPU. Useunsupportedwhen a listed strategy is genuinely unusable on specific hardware (e.g. multi-node pure-TP on Hopper, which has no cross-node NVLink) — not for "untested". Helpers:isStrategySupportedOnHardware+effectiveCompatibleStrategiesincommand-synthesis.js(shared by the builder and the JSON API).hardware_overrides— optional per-generation tweaks keyed byhopper,blackwell,amd, or the brand-widenvidia. Generation-specific blocks take precedence over the NVIDIA fallback. Each supplies{ extra_args[], extra_env{} }.strategy_overrides— optional per-strategy tweaks (rare). Forpd_clusterspecifically:prefill/decodesub-objects set each pool'snodes,parallelism(tp|tep|dep), andtp;router.intra_node_data_parallel_sizepins the router flag that otherwise derives from the pools'max(dp_local); plus optionalpool_modes: [<mode>, …]— narrows the PD-pool parallelism pills INDEPENDENTLY of the Strategy row. PD-pool modes are otherwise derived fromcompatible_strategies[]suffixes (viapdPoolModes), sopool_modesis how you offer TP/TEP as standalone serving strategies while locking disaggregated PD to a subset (e.g.pool_modes: [dep]→ both pools DEP-only, single mode hides the pills; synthesis snaps any resolved mode not in the set to the first allowed one, so the JSON API stays consistent too).omni(optional) — vllm-omni online-serving config. Required whenmeta.tasksincludesomni. Shape:{ serve_binary?, port?, task_label?, task_hint?, tasks: [...] }.tasksaccepts bare ids from the catalog (t2i,i2i,t2v,i2v,ti2v,t2a) or{ id, key?, model_id?, vram_minimum_gb?, description?, extra_args?, curl?, benchmark? }overrides — Wan2.2 uses overrides to swap the served checkpoint per task.benchmarkis a static command override for diffusion or other non-LLM endpoints that cannot use the defaultvllm bench servecommand.serve_binary: "vllm-omni serve"swaps the binary; currently unused, and needed only for recipes pinned below vLLM 0.20.0, where thevllmconsole-script does not yet delegate to vllm-omni on--omni. Catalog lives atsrc/lib/omni-tasks.js.keyis the unique selector and URL identity when multiple request presets share one catalogid; absentkeyfalls back toid.task_labelandtask_hintcustomize that selector row.guide— markdown string (|-block), rendered withreact-markdown+remark-gfm+rehype-slug.
VRAM formula: vram_minimum_gb = ceil(params × bytes × 1.2). Bytes per param: bf16/fp16=2, fp8/int8/awq/gptq=1, int4/nvfp4/fp4/mxfp4=0.5. For MoE, use total params (inactive experts still live in VRAM). Exception — mixed-precision quants (NVFP4/ModelOpt, hf_quant_config.json → quant_algo: MIXED_PRECISION): only MLP linears are 4-bit while attention/KV/embeddings stay FP8+, so the table underestimates. Size from the real checkpoint instead: ceil(safetensors total_size_GB × 1.2).
- Hardware is never blocked by VRAM. Multi-node scales VRAM, so
command-synthesis.jsonly uses VRAM as a display hint. Precision constraints (NVFP4/FP4 require Blackwell by default) are the only things that disable a hardware pill; exceptional runtime fallbacks can broaden them with variant-levelprecision_hardware. - Default hardware is always H200 (or B200 for Blackwell-constrained variants).
pickDefaultHardwareprefers NVIDIA over AMD;loadPreferencesdeliberately ignores AMD entries from localStorage so first-page-load is always H200. - Omni recipes render
vllm serve --omnivia a dedicatedresolveOmniCommandpath (no strategy / multi-node / pd). The command builder adds a Task pill row (T2I / I2I / T2V / I2V / TI2V / T2A) above Hardware, with task-specific cURL examples in the popover. Detection:meta.tasksincludesomni. The--omniflag is auto-injected, so don't add it tomodel.base_args. - Multi-node uses vLLM mp (multiprocessing) backend, not Ray. For TP/TEP every node runs the same command varying
--node-rank; rank>0 adds--headless. For DEP, Node N adds--data-parallel-start-rank = N × gpus_per_node. One command per node, never a repeated one: synthesis renders the head (rank 0) plus one command per follower rank viabuildArgs(role, "worker", rank)—followerRanks(nodeCount)=[1 … nodeCount-1]— so the command block shows a tab per node (Head · Node 1 · … · Node N-1) and a 4-node cluster gets three distinct worker commands. Same in the Mooncake block (nodes per instance). The JSON API carries the full list asworker_commands[]/worker_argvs[](+worker_docker_*s[], andvllm_worker_*s[]underkv_store_lb); the older singularworker_command/worker_argvstay as rank 1 for compatibility — agents should loop the plural arrays, since replaying rank 1 on every node hangs the rendezvous. - Taxonomy hardware specs follow inferencex.semianalysis.com/gpu-specs: B200 SXM is 180 GB/GPU (not the nameplate 192, which is pre-ECC), GB200/GB300 are 4-GPU compute trays (NVL4, the NVL72 rack unit), B300 is 268 GB/GPU.
- Legacy Markdown under
DeepSeek/,Qwen/etc. is read-only reference. When migrating or updating a recipe, read those to extract flags and env, but write the YAML; don't edit the Markdown. public/is generated — don't commit it..gitignoreshould cover it; if something slips through, leave it untracked.
A dedicated skill lives at .claude/skills/add-recipe/SKILL.md and is auto-loaded when the user asks to add/create/contribute a recipe. It covers HF metadata extraction, the full schema, VRAM formula, provider-registry updates, and the validation/commit loop.