How mise models and chooses backends#
Retrieved 2026-10-18. Source tree: jdx/mise at commit 2866bb93824ff4d76ada6d453a42d4409074a1fc (HEAD of main, 2026-10-18; latest tag v2026.10.14, Cargo.toml version 2026.10.14). Local mise used for CLI output: 2026.10.13.
Citation convention: repo:path means a file in the jdx/mise clone at the commit above (browsable at https://github.com/jdx/mise/blob/2866bb9/<path>). Docs pages are cited by their published URL on mise.jdx.dev. The text was read from the docs/ source in the same clone, not fetched live from the site. The URL-to-file mapping follows the page links inside the docs themselves, and I did not diff the live site against the clone.
Summary#
mise has about 20 backend types. A backend is a “source to install from”, written as
backend:tool[options]. The registry maps a short name to an ordered list of such identifiers.Short-name resolution is a fixed precedence chain:
MISE_BACKENDS_<TOOL>, then[tool_alias], then[plugins]URL, then the lockfile, then an installed plugin, then the first eligible registry backend. Eligible means it runs on this platform, is not indisable_backends, is not experimental-gated, and covers the requested version.The docs recommend this order: packslip, then aqua, then github/gitlab/forgejo, then http/s3, then language-package backends, then plugins.
ubiis deprecated (removal in 2027.1.0).asdfis legacy and never used on Windows.vfoxis a plugin backend, and newasdf,vfoxandubiregistry entries are rejected.Machine-readable sources:
registry/*.toml(with a JSON Schema),mise registry --json(lossy),mise tool <name> --json(resolved backend plus security), the hostedhttps://mise.jdx.dev/registry/latest.tar.zstarchive, and mise-versionsdata/<tool>.tomlanddata/index.v1.json. None of the hosted ones has a documented stability guarantee, except that mise-versions index.v1 carries aformatfield.Gaps and ambiguities are listed in section 5. The main ones are that the JSON output drops per-backend platforms, version ranges and options, and that the registry order is “preference”, not “quality”.
1. Backends mise supports#
Enumeration in source. The BackendType enum is: aqua, asdf, cargo, conda, core, dotnet, forgejo, gem, github, gitlab, go, npm, packslip, pipx (displayed and serialized as pypi, with pipx accepted as an input alias), spinel, spm, http, s3, ubi, vfox, plus VfoxBackend(plugin_name) and Unknown. (repo:src/backend/backend_type.rs)
mise backends ls printed, on the 2026.10.13 binary: aqua, asdf, cargo, conda, core, dotnet, forgejo, gem, github, gitlab, go, npm, packslip, pypi, spinel, spm, http, s3, ubi, vfox. (local run; verified)
Syntax. <backend>:<tool-name-within-backend>[@version], with optional tool options in brackets, for example 'pypi:black[extras=jupyter]'. Any identifier works in mise.toml without a registry entry. The registry only adds short names. Core tools use core: (for example core:node). Source: https://mise.jdx.dev/dev-tools/backends/#identifierss>s>s>s>s>
Prefix parsing. BackendType::guess takes the text before the first : and maps it as above. Anything else is Unknown. (repo:src/backend/backend_type.rs)
Experimental gate. dotnet, packslip, s3, spinel and spm consult an EXPERIMENTAL constant (BackendType::is_experimental). Registry-driven selection skips a backend whose constant is true unless experimental = true. (repo:src/backend/backend_type.rs, repo:src/registry.rs eligible_entries.) The values of those constants are not shown above. The docs list only spinel as “(experimental)”. Which of the five are currently gated is unverified.
Table, from https://mise.jdx.dev/dev-tools/backends/#which-backend-to-usee>e>e>e>e> (docs status wording quoted):
Backend |
Installs |
Example |
Docs status |
|---|---|---|---|
packslip |
releases with signed manifests |
|
first preference |
aqua |
release assets described by the aqua registry |
|
preferred |
github / gitlab / forgejo |
release assets from a forge |
|
preferred (same tier as aqua) |
http / s3 |
archives at URLs you provide |
|
S3 also needs AWS credentials |
cargo, go, npm, pypi (alias |
language packages |
|
needs the language runtime or toolchain |
conda |
conda packages and their dependencies |
|
needs nothing else |
spinel |
Ruby compiled to native executables |
|
experimental |
vfox |
Lua plugin |
|
works on Windows; use when custom logic is needed |
asdf |
shell-script plugin |
|
legacy; not available on Windows |
ubi |
GitHub and GitLab release assets |
|
deprecated; removed in 2027.1.0 |
core |
tools built into mise |
|
see https://mise.jdx.dev/core-tools.htmll>l>l>l>l> |
Deprecation and legacy facts:
ubi:has warned since 2026.4.0 and is removed in 2027.1.0. Migration isubi:togithub:,gitlab:, or anhttp:tool. https://mise.jdx.dev/dev-tools/backends/ubi.htmll>l>l>l>l> (repo:docs/dev-tools/backends/ubi.md)asdf plugins are “shell scripts that run with your permissions”. The docs say to prefer backends that install a publisher’s release directly. https://mise.jdx.dev/dev-tools/backends/asdf.htmll>l>l>l>l> (
repo:docs/dev-tools/backends/asdf.md)pipx:is another name forpypi:, which uses uv, or pipx when uv is unavailable. https://mise.jdx.dev/dev-tools/backends/pypi.htmll>l>l>l>l> (repo:docs/dev-tools/backends/pypi.md)
Plugin-provided backends. A vfox backend plugin supplies its own prefix (VfoxBackend(name)), and disable_backends can name it. (repo:src/backend/backend_type.rs disable_key; repo:settings.toml [disable_backends] docs.) Backend plugin authoring: https://mise.jdx.dev/backend-plugin-development.htmll>l>l>l>l>. I did not read that page, so the details of how third-party prefixes interact with the registry are unverified.
2. Registry mapping, ordering and user overrides#
Registry shape. One file per tool, registry/<name>.toml, where the file name is the short name. backends is an ordered list of strings or tables, “in order of preference”. version_order is required (semver or source). Source: https://mise.jdx.dev/contributing/registry.html#registry-formatt>t>t>t>t> (repo:docs/contributing/registry.md) and repo:schema/mise-registry-tool.json (required: ["backends", "version_order"]).
Examples at the commit above (repo:registry/):
jq.toml:["aqua:jqlang/jq", "asdf:mise-plugins/asdf-jq"]ripgrep.toml:aliases = ["rg"], backends["aqua:BurntSushi/ripgrep", "asdf:https://gitlab.com/wt0f/asdf-ripgrep", "cargo:ripgrep"]node.toml:["core:node"], withbins,detectandidiomatic_files
Size and distribution (computed from mise registry --json on 2026.10.13). 1067 rows, which include aliases as their own rows, and 1015 registry/*.toml files in the repo. 756 rows have more than one backend. Backend frequency across all lists: aqua 716, asdf 622, github 254, cargo 89, vfox 58, npm 55, pypi 32, go 25, conda 22, http 18, packslip 14, core 14, gem 3, spm 2, gitlab 1. Backend in first position: aqua 699, github 188, vfox 42, npm 41, pypi 23, conda 20, http 16, packslip 14, core 14, go 4, gem 3, spm 1, gitlab 1, cargo 1. These counts are a point-in-time computation and the registry changes with every release.
Per-backend entry fields (RegistryBackend, repo:src/registry.rs; repo:schema/mise-registry-tool.json): full, platforms (linux/macos/windows, x64/arm64, or os-arch; Windows arm64 also matches x64 selectors), min_version (inclusive), max_version (exclusive), attestations_since, options. Bounds require version_order = "semver". Source: https://mise.jdx.dev/contributing/registry.html#backend-entriess>s>s>s>s> and #minimum-backend-versions. In the clone, 35 files use platforms, 17 use min_version or max_version, and 7 use deprecated. These come from grep -l over registry/*.toml.
Tool-level fields: aliases, bins, description, detect, idiomatic_files, os, overrides, test, url, deprecated, version_order.
Selection order for a short name (https://mise.jdx.dev/dev-tools/backends/#how-backend-selection-workss>s>s>s>s>). An identifier with a prefix always uses that backend. Otherwise the first of these applies:
MISE_BACKENDS_<TOOL>environment variable (tool name uppercased,-to_;repo:src/registry.rsenv_backend_override).[tool_alias]entry naming a backend, such asnode = "core:node"(https://mise.jdx.dev/dev-tools/aliases.htmll>l>l>l>l>).A plugin URL for the tool under
[plugins].The backend recorded in
mise.lock, when it can serve the requested version.An installed plugin with the same name, unless its backend is disabled.
The first registry backend that runs on this platform, is not in
disable_backends, supports the requested version, and, if experimental, only withexperimental = true.
Code check of step 6. eligible_entries in repo:src/registry.rs filters in registry order by: keep, then backend_matches_platform, then membership in the set of all BackendType names minus Settings.disable_backends (and minus asdf on Windows, hard-coded, “whatever this setting says”), then the experimental gate. Duplicates are collapsed to the first position.
Version-specific selection. Entries with min_version or max_version are checked against the request. Exact versions are compared, and numeric prefixes are excluded only when wholly outside the range. latest and prefixes that span a boundary “keep the normal order”. These boundaries apply only to short names. An explicit identifier ignores them. A failed download or signature check does not fall back to the next backend. Source: https://mise.jdx.dev/dev-tools/backends/#version-specific-backendss>s>shttps://mise.jdx.dev/contributing/registry.html#minimum-backend-versionsons>ons>ons>ons>ons>. Code: RegistryBackend::supports_version in repo:src/registry.rs.
Settings that alter resolution:
disable_backends(envMISE_DISABLE_BACKENDS, comma list; default[]). Disabled backends are skipped for short names, and installing an explicit identifier on one fails. Already-installed versions stay on disk. A vfox plugin can be disabled by plugin name.repo:settings.toml[disable_backends]; https://mise.jdx.dev/dev-tools/backends/#disable-backendss>s>s>s>s>disable_default_registry(MISE_DISABLE_DEFAULT_REGISTRY): “Stop mapping short names such asphpto the asdf and vfox plugins listed in the registry.” The wording is narrow. I did not trace what it does to the other backends in the registry, so the exact semantics are unverified.repo:settings.tomlexperimental(gates experimental backends).registry_floating(default off),registry_cache_ttl,aqua.baked_registry,aqua.registries,aqua.registry_cache_ttl. See section 4.MISE_BACKENDS_<TOOL>and[tool_alias], as above.mise usewrites the identifier to[tools]as given, for example"aqua:BurntSushi/ripgrep" = "latest", so using the short name stores the short name and re-resolves through the chain above.mise backends switchrewrites lock entries to the registry’s current backend. https://mise.jdx.dev/dev-tools/backends//>/>/https://mise.jdx.dev/cli/backends/switch.htmltml>tml>tml>tml>tml>. I did not read themise usesource to confirm that it never rewrites a short name into an identifier. That is unverified beyond the docs example.
Options attached to a short name. A shorthand can set backend options. The docs’ example is aws-cli, which uses aqua:aws/aws-cli with symlink_bins = true. Writing the identifier yourself does not apply those options, so short name and identifier are not equivalent. https://mise.jdx.dev/registry.html#options-a-shorthand-setss>s>s>s>s>
Debug commands: mise tool <name> --backend, mise registry <name>, mise plugins ls, mise config ls, mise ls --current. https://mise.jdx.dev/dev-tools/backends/#troubleshootingg>g>g>g>g>. Local check: mise tool ripgrep --backend printed aqua:BurntSushi/ripgrep.
3. Documented guidance for choosing among backends#
Preference ladder. “Start with the tool’s registry short name. When you choose a backend yourself, prefer one that installs the publisher’s own prebuilt release”, ordered: (1) packslip, (2) aqua, or github, gitlab, forgejo, (3) http, s3, (4) language package backend, when the tool ships only as a package or you need package options, (5) a plugin only when custom logic is needed. https://mise.jdx.dev/dev-tools/backends/#which-backend-to-usee>e>e>e>e>
Registry acceptance tiers (for new entries only, “you can use any backend in your own config”): tier 1 packslip. Tier 2 aqua, github, gitlab. Tier 3 conda (“high bar”). Tier 4 npm, pypi, gem, cargo, go, dotnet (“very high bar”, needs maintainer agreement beforehand). Not accepted for new entries: asdf, vfox, ubi, “for supply-chain security reasons”. http is untiered and accepted only with a
version_list_url. forgejo, s3, spm and spinel are not covered by the tiers. https://mise.jdx.dev/contributing/registry.html#backend-acceptance-tierss>s>s>s>s>aqua over github when the tool is in the aqua registry. “its recipes carry per-version logic and SLSA and other verification metadata”. Use github for tools not in aqua but with GitHub releases. Same page.
Go and Rust tools “usually ship single binaries, so prefer a tier 1 or 2 backend for them”. Same page.
Windows. aqua “works on Windows”. asdf is never selected on Windows, and
asdf:tools are skipped. vfox runs on Windows. https://mise.jdx.dev/dev-tools/backends/aqua.htmll>https://mise.jdx.dev/dev-tools/backends/asdf.htmltmhttps://mise.jdx.dev/dev-tools/backends/vfox.html.html>.html>.html>.html>.html>. No explicit Windows statement was found for github, gitlab, http, npm, cargo, pypi or conda, so their status is unverified.Security and verification. “Verification differs by backend and by tool”, and a backend can check a signature or provenance only when the publisher provides one. Checks per backend (https://mise.jdx.dev/security.html#download-verificationn>n>n>n>n>): aqua gives checksums, Cosign, Minisign, SLSA and GitHub attestations as declared by the aqua recipe. github gives GitHub attestations when published, and SLSA when a signer is named. packslip gives a signed manifest, digests and a pinned signer. Node, Swift, Zig and precompiled Ruby and Python have their own checks. The page lists no checks for http, s3, cargo, npm, pypi, go, gem, conda or dotnet, which most naturally reads as “none documented”, but that is an inference and unverified. Per-tool results are visible via
mise tool <name>(Security line) andmise registry --json --security.Provenance can be required. A registry entry can set
attestations_since, from which version a missing GitHub attestation is treated as a downgrade (github backends only).repo:schema/mise-registry-tool.json,repo:src/registry.rs.Speed. I found no documented per-backend speed ranking. The docs only note that language backends need their toolchain, that cargo uses cargo-binstall for prebuilt binaries, and that
mise registry --json --securityis slow for a full listing. The speed question is unverified or undocumented. mise-versions exists to avoid GitHub’s anonymous rate limit (repo:settings.toml[use_versions_host]), which affects version listing, not install speed.aqua vs ubi vs asdf. The docs steer away from ubi (deprecated) and asdf (legacy, shell code, not Windows). The registry’s own data still has many asdf entries (622 backend occurrences, always as non-first fallbacks per
mise registryorder in the sampled tools). I did not check that asdf is never first. In the counted data, asdf is not among the first-position counts.
4. Machine-readable sources#
registry/*.tomlin jdx/mise. The authoritative source, bundled into each release. The schema isschema/mise-registry-tool.json(JSON Schema,unevaluatedProperties: false;required: backends, version_order; backend table keysfull,platforms,min_version,max_version,attestations_since,options).mise run lintvalidates files against it, and the build fails on unreadable entries. https://mise.jdx.dev/registry.htmll>https://mise.jdx.dev/contributing/registry.html#registry-formatmat>mat>mat>mat>mat>. Stability: the schema is versionless, in-repo and changes with mise. No compatibility promise is documented (unverified beyond that).mise registry --json. Rows haveshort,backends(strings only, in preference order),bins,description,url,aliases, andsecurity(only with--security, which requires--json). Optional fields are omitted when empty.mise registry <name> --jsongives one object, andmise registry --backend <b>filters. Source:repo:src/cli/registry.rs(RegistryToolOutput) and https://mise.jdx.dev/cli/registry.htmll>l>l>l>l>. Observed on 2026.10.13: aliases appear as separate rows, with the full alias list repeated on each. A resolver should dedupe byshortagainstaliasesor use--hide-aliased(a flag, though I did not test it with--json). The output is lossy: it does not include per-backendplatforms,min_version,max_version,options,os,deprecated,version_order,overridesordetect. Note also thatrt.backends()is the already-filtered view, so the CLI list reflects the local platform and settings. The code atsrc/registry.rs:816suggests this, but I did not read the function body, so this is unverified. If so,mise registry --jsondepends on the machine that runs it (OS,disable_backends,experimental).mise tool <name> --json. Gives the resolvedbackendfor this machine and config, plusdescription,url, installed and requested versions,tool_options, andsecurityentries (for example{"type":"checksum","algorithm":"sha256"}and{"type":"github_attestations","signer_workflow":"..."}). Local run, jq, 2026.10.13. This is the ground truth for “what would mise pick here”, but it needs a mise binary.Hosted registry archive.
https://mise.jdx.dev/registry/latest.tar.zst(HTTP 200, 94,279 bytes on 2026-10-18). It containsregistry/<name>.tomlfiles. mise downloads it only whenregistry_floating = true. mise caps entries at 4096, 1 MiB per entry and 16 MiB total, and requires version-order metadata.repo:src/registry.rs(MISE_REGISTRY_ARCHIVE_URL,parse_registry_archive), https://mise.jdx.dev/registry.html#floating-registriess>s>s>s>s>. This is the best hosted, no-binary source. The URL is hard-coded in the client but not documented as a public API, so its stability is unverified.https://mise.jdx.dev/registry.jsonreturned 404, so no hosted registry JSON exists at that path.Bundled aqua registry.
vendor/aqua-registry/registry.yml(about 2,147- type:lines) plusmetadata.jsonpinningaquaproj/aqua-registryat tag56d6f7647505550d2f47dbed308b676085302db5. mise reads recipes foraqua:and does verification and platform checks fromsupported_envs. https://mise.jdx.dev/dev-tools/backends/aqua.htmll>l>l>l>l>. The upstream ishttps://github.com/aquaproj/aqua-registry. I did not read the upstream aqua docs for its schema and stability, so those are unverified. Users can add registries viaaqua.registries, andregistry_floatingalso fetches the current official one.repo:settings.toml[aqua.registries].mise-versions (
https://mise-versions.jdx.dev). Used by mise for version lists, public GitHub release data and attestations.repo:src/versions_host.rsshows/data/<tool>.toml(a[versions]table of version to{created_at, prerelease?}) and/t?tool=...(an install tracking beacon, not a data API).repo:src/versions_index.rsshows/data/index.v1.jsonwith aformatheader (client accepts only 1), about 140 KB compressed per its comments, and a contract indocs/versions-index.mdof jdx/mise-versions (not read).data/node.tomlreturned 200 on 2026-10-18./api/returned 404. This is version data, not backend-resolution data. It is useful for “does this backend list versions”, but mise-versions is keyed by tool short name, and I did not verify per-backend coverage. Theuse_versions_hostsetting controls it.repo:settings.toml. Docs also say it carries security information per tool. https://mise.jdx.dev/registry.html#toolss>s>s>s>s>. How to query that is unverified.Docs registry page data.
docs/registry.data.tsand theRegistryVue component build https://mise.jdx.dev/registry.htmll>l>l>l>l>. I did not inspect whether they expose a JSON file, so that is unverified.
5. Open questions for the design interview#
What does “resolve” return? Options are: (a) mise’s own pick (
mise tool --backendsemantics, reproduce the six-step chain), (b) the registry’s preference list, or (c) a recommendation with reasons (security, platform). The docs’ ladder (packslip, aqua, forge, …) differs from the raw registry order in some entries, because older entries put vfox or asdf first (42 first-position vfox entries exist) and 1 puts cargo first.Should mibare follow mise’s order or re-rank? The registry order is a curated “preference”, but it carries legacy entries. Should the resolver apply the documented tiers on top and warn on asdf, vfox and ubi?
Inputs beyond short names. Handle user-supplied
owner/repo, URLs, package names (npm:,pypi:), aliases such asrg, and tools missing from the registry (fall back to aqua registry lookup, then github)? The registry is explicitly “not a list of every tool mise can install”, while the aqua registry has far more recipes.Platform and config context. Selection depends on OS and arch,
disable_backends,experimental, version request, lockfile, aliases and env overrides. Should mibare take a target platform and settings as input, or ignore them? Hard-coded rule: asdf is excluded on Windows.Data source choice and freshness. Bundle a registry snapshot, fetch
latest.tar.zst(undocumented URL, but used by mise itself), shell out tomise registry --json(lossy and machine-dependent), or read the git repo? Pinning to a mise version matters because the schema evolves (for examplemin_version,max_versionandattestations_sinceare recent).Version-range-dependent backends. The JSON CLI hides
min_versionandmax_version. If the resolver must answer “forhk@1.57which backend?”, it needs the TOML, not the JSON.Short name vs identifier equivalence. Registry options (
symlink_bins,allow_builds, per-platform URLs) are only applied via the short name. Should the output include the options and the short name, or only the identifier?Security data.
mise tool --jsonandregistry --json --securityexpose checks per backend, but only through a binary, and “badges come from registry metadata, so a check may apply only to some versions or platforms”. How much of this should mibare surface, and should it rank by it?Deprecation timeline. ubi removal in mise 2027.1.0. The registry still contains
ubi:entries? I did not count them: theubiprefix does not appear in the counted backend list, so possibly none remain. That is consistent with the data, but it is an inference from absence in one run.Unverified items worth confirming: which backends are currently experimental-gated; exact semantics of
disable_default_registry; third-party backend plugin prefixes in the registry; speed guidance (none found);mise usewriting a short name vs identifier; stability promises forlatest.tar.zst,mise registry --jsonand mise-versions endpoints; Windows status for non-aqua/asdf/vfox backends.