Repository navigation
Conversation
Runcrate is an online provider: offers are queried live from GET https://www.runcrate.ai/api/v1/instances/types with RUNCRATE_API_KEY. Each offer is a fixed on-demand VM shape in one region; instance_name is the offer id the create instance API takes as instance_type_id.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds Runcrate as an online catalog provider.
GET https://www.runcrate.ai/api/v1/instances/types(docs), needs an API key, so this is an online provider likeseewebandhotaisle:RuncrateProvider.from_env()readsRUNCRATE_API_KEYthroughget_creds_env, anddefault_catalog()skips the provider when the variable is not set.{"data": [...], "meta": {"total": N}}). OneCatalogItemper offer:instance_nameis the offerid, which the create instance API takes asinstance_type_id, so a future dstack backend can launch straight from the offer. Ids change as capacity changes, so they are meant to be used shortly after the query, which is how online providers are used anyway.locationisregionas the API returns it (the same string the create API accepts),priceishourly_ratefor the whole VM,cpu,memoryanddisk_sizearecpu_cores,memory_gbandstorage_gb.spotis alwaysFalse.provider_datacarries the Runcrategpu_type, which the create API also accepts together withgpu_countandregion.gpu_typeis mapped toKNOWN_NVIDIA_GPUSnames and memory through an explicitGPU_MAP, asdaytonadoes:A100_80GtoA10080 GB,A100toA10040 GB,V100_32GtoV10032 GB,V100toV10016 GB,RTXPro6000toRTXPRO6000, and the other 15 types by the same name (B300 uses the registered 270 GB). All 20 GPU types Runcrate lists today (https://www.runcrate.ai/api/gpu-pricing) are covered. An unknown type is skipped with a warning, and the integrity tests warn about unknown types in the live response (liketest_real_world_lium_gpu_models).GH200offers getcpu_arch=armthroughis_nvidia_superchip, asvultrdoes.gpu_type: "CPU",gpu_count: 0) are published with no GPU fields.raise_for_status(), an unexpected response shape raisesValueError, and a malformed or incomplete offer is skipped with a warning.ONLINE_PROVIDERS,ONLINE_PROVIDER_MODULES, the CLI (python -m gpuhunt runcrate), the README and the catalogs workflow (atest-runcrateintegrity job using aRUNCRATE_API_KEYsecret, liketest-seeweb).The structure follows the two most recent provider PRs: #259 (Lium: online provider, unit tests against a recorded response, integrity tests that warn about unmapped GPU names, workflow job) and #263 (Daytona: explicit GPU map, API key read from the environment,
test_default.pyupdate), plus #246 (Seeweb) for the authenticatedfrom_env.Testing
All run on this branch on 2026-10-25, Python 3.14,
uv sync --all-extras:uv run pytest src/tests: 356 passed (47 new insrc/tests/providers/test_runcrate.py, run against a response recorded from the live API on 2026-10-25 and trimmed to nine offers, with offer ids replaced by placeholders; no network)uv run pytest --doctest-modules src/gpuhunt: 4 passeduv run pytest src/integrity_tests/test_runcrate.pywithRUNCRATE_API_KEYset: 11 passed against the live API, no unknown-GPU warningsuv run pyright: 0 errorspre-commit run --all-files(ruff, ruff-format): passedpython -m gpuhunt runcrate --output runcrate.csv: 155 offersgpuhunt.query(provider=["runcrate"])withRUNCRATE_API_KEYset: 155 offers (111 GPU, 44 CPU) across 41 regions and 19 GPU types;gpuhunt.query(provider=["runcrate"], gpu_name=["A100"], min_gpu_memory=80, max_gpu_count=1)returns only 80 GB A100 offersThe new integrity job needs a
RUNCRATE_API_KEYrepository secret. Reading offers does not need a balance on the account; I can provide a key for it.Gaps
These matter for a dstack backend more than for the catalog, but to be clear up front:
spot=True.AI assistance
This PR was prepared with AI assistance (Claude) and tested end to end against the live Runcrate API: the unit tests, the live integrity tests, the CLI dump and
gpuhunt.queryresults above all come from real runs. I work on Runcrate and will maintain the provider; happy to adjust anything to your conventions.