Skip to content

Feat: custom mise backend for consuming multiple backing CLIs from one origin monorepo #23

@so0k

Description

@so0k

Summary

A skillrig origin can co-locate multiple backing CLIs in one repo (e.g. cmd/<tool>, cli/<tool>), each released on its own version stream so consumers pin/track them independently. The documented consumption path uses mise's github backend, one [tools] entry per CLI, disambiguated by a per-stream tag_regex:

"github:<org>/<origin-repo>[tag_regex=^jira-v]" = "latest"
"github:<org>/<origin-repo>[tag_regex=^tfc-v]"  = "latest"
# ...one per backing CLI

This does not work for more than one binary. mise keys a github-backend tool by owner/repo and tracks one active version per tool; tag_regex only filters version resolution and is not part of the tool's identity. So every entry collapses into a single tool: mise ls shows one row, all entries' mise where resolve to the same install dir, and only one binary installs.

Reproduction / evidence

Validated on mise 2026.3.0 against a private origin shipping 5 CLIs, each released as <bin>_<ver>_<os>_<arch>.tar.gz + <bin>_checksums.txt:

  • Per-stream resolution works in isolation — a config with only tag_regex=jira$ resolves the latest jira tag, downloads jira_<ver>_<os>_<arch>.tar.gz, checksum-verifies, and runs the binary. ✅
  • Co-installing 2+ streams from the same repo collapsesmise ls shows one github:<org>/<origin-repo> tool at a single version; mise where for every stream points at that one install dir; only one binary is present. ❌
  • mise also caches the resolved version per repo, so the first stream resolved "wins" for the repo tool until the cache is cleared.

Format-independent. The collision is keyed by repo, not tag shape — prefixed tags (jira-v1.7.0) and semver build-metadata tags (1.7.0+jira) collide identically. It is not a tag-convention problem.

Impact. Any origin that ships >1 binary, or any consumer that vendors two skills whose binaries live in the same origin, is affected. It undercuts the "co-located backing CLIs, consumed via mise" story.

Proposed feature: a skillrig mise backend plugin

mise backend plugins (vfox-style, Lua 5.1) let one plugin provide many tools, addressed plugin:tool@version, where ctx.tool distinguishes them. Because identity is plugin:tool (not owner/repo), N binaries from one repo become N distinct tools — collision gone:

"skillrig:<org>/<origin-repo>/jira"   = "latest"
"skillrig:<org>/<origin-repo>/tfc"    = "0.0.6"
"skillrig:<org>/<origin-repo>/awsinv" = "latest"

Hooks:

  • BackendListVersions(ctx) — list the binary's release stream. Learn each binary's tag scheme + asset-name template from the origin's own metadata (.skillrig-origin.toml / index.json) rather than a hardcoded regex, so it works for both prefix (<bin>-v<ver>) and build-metadata (<ver>+<bin>) streams without per-consumer config.
  • BackendInstall(ctx) — resolve the version, download the matching <bin>_<ver>_<os>_<arch> asset, verify the per-tool checksum (and optionally GitHub artifact attestation / SLSA), extract.
  • BackendExecEnv(ctx) — put the binary on PATH.

Value-adds that make this a skillrig offering rather than a generic github backend:

  1. Multi-binary co-install from one origin monorepo (the core fix).
  2. Tamper-evidence parity with skills — checksum + optionally tie the binary's release tag/commit to the treeSha/commit skillrig already records in .skillrig/skills-lock.json for the skill that required it.
  3. Central auth — resolve a token once (MISE_GITHUB_TOKENGITHUB_TOKEN → a configurable credential_command for secret managers → gh auth token). See gotcha below.
  4. Auto-wiringskillrig add writes the skillrig:<origin>/<bin> entry when a vendored skill's x-skillrig.requires declares a binary.
  5. No registry/index service — just a small published plugin (keeps skillrig's "no extra architecture" promise).

Auth gotcha worth documenting regardless

mise's github backend returns 404 on a private origin's /releases when unauthenticated. gh stores its token in the OS keyring, not hosts.yml, so mise can't read it and falls back to anonymous. Today you must export MISE_GITHUB_TOKEN=$(gh auth token). A skillrig backend should handle this centrally.

Scope

  • Prototype (hours): three Lua hooks; build-metadata stream convention; checksum verify; token from MISE_GITHUB_TOKEN/gh. Enough to co-install all of an origin's CLIs.
  • Productized (days): origin-metadata-driven stream/asset resolution (both schemes), pluggable auth incl. credential_command, attestation/treeSha verification, skillrig add auto-wiring, tests, docs.

Open questions

  1. Plugin home/name & its own release cadence.
  2. Origin metadata contract — does .skillrig-origin.toml/index.json already carry per-binary stream + asset conventions, or add a [[binaries]] section?
  3. Verification depth for v1 (checksum-only vs full provenance/treeSha).
  4. Spike whether a current mise (asset_pattern + aliases, ≥2026.5) covers multi-binary-from-one-repo natively before committing to a plugin.

Filed from an origin-validation exercise; a full design doc lives alongside the validated origin (docs/BINARY-DISTRIBUTION.md).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions