Documents
Mise Tool Management
Mise Tool Management
Type
Topic
Status
Published
Created
Feb 28, 2026
Updated
Apr 19, 2026
Created by
Dosu Bot
Updated by
Dosu Bot

Mise Tool Management#

Mise (formerly rtx) is a polyglot runtime and tool version manager used in the opnDossier project to manage development tool dependencies and ensure reproducible builds across local development environments and CI/CD pipelines. The project migrated to mise in January 2026 to replace multiple individual tool setup actions with a unified configuration-driven approach.

The mise.toml configuration file defines 18 development tools including Go (1.26.0), GoReleaser, golangci-lint, security scanners, documentation generators, and pre-commit hooks. All tools are automatically installed via mise install and made available through mise's PATH management and optional shim system. The configuration enables aggressive activation mode to ensure tools activate in all shell contexts.

While mise manages most development tools, the project makes a deliberate exception for cyclonedx-gomod, which is installed via go install due to trust issues with mise shims in GoReleaser subprocesses. This limitation highlights a key architectural constraint when integrating mise with tools that spawn subprocesses expecting direct binary execution.

Mise Architecture and Purpose#

What is Mise?#

Mise is an open-source tool version manager that handles multiple programming language runtimes and CLI tools through a single configuration file. It provides:

  • Unified tool management: Single configuration for all development dependencies
  • Automatic environment setup: Tools are automatically available when entering project directories
  • Version pinning: Ensures consistent tool versions across team members and environments
  • Polyglot support: Manages tools from multiple ecosystems (Go, Python, Node.js, system packages)
  • Shim system: Creates wrapper executables that automatically route to the correct tool version

Why opnDossier Uses Mise#

The migration to mise (PR #172) addressed several pain points in the original development workflow:

  1. CI/CD Complexity: Replaced multiple individual GitHub Actions (setup-go, setup-python, setup-node) with a single jdx/mise-action
  2. Version Drift: Eliminated inconsistencies between local development and CI environments
  3. Setup Fragmentation: Consolidated tool installation logic from scattered scripts into one declarative configuration
  4. Reproducibility: Ensured that mise install produces identical environments across machines

Follow-up refinements (PR #173) established the pattern of using mise exec for tool invocations to guarantee tools run within the mise-managed environment.

mise.toml Configuration Reference#

Complete Configuration File#

The mise.toml file defines all managed tools and settings:

# cyclonedx-gomod: installed via go install in CI (mise shim causes trust issues in goreleaser subprocesses)

[tools]
act = "latest"
cosign = "3.0.5"
git-cliff = "2.12.0"
"github:anchore/quill" = "latest"
go = "1.26.0"
"go:github.com/google/go-licenses" = "1.6.0"
"go:github.com/securego/gosec/v2/cmd/gosec" = "latest"
"go:golang.org/x/perf/cmd/benchstat" = "0.0.0-20260409210113-8e83ce0f7b1c"
golangci-lint = "2.11.4"
goreleaser = "latest"
just = "1.46.0"
markdownlint-cli2 = "0.21.0"
"pipx:mdformat" = { version = "0.7.21", uvx_args = "--with mdformat-gfm --with mdformat-front-matters --with mdformat-footnote --with mdformat-simple-breaks --with mdformat-gfm-alerts --with mdformat-toc --with mdformat-wikilink --with mdformat-tables" }
"pipx:mkdocs" = { version = "1.6.1", uvx_args = "--with mkdocs-material --with pymdown-extensions" }
pre-commit = "latest"
python = "latest"
uv = "latest"

# Many of these settings are defaults, but we are explicit in case they change in the future and to make it clear to users what is enabled.
[settings]
activate_aggressive = true
idiomatic_version_file_enable_tools = [ "python", "go", "bun" ]
env_cache = true
exec_auto_install = true
github_attestations = true
lockfile = true
pin = true
slsa = true

[settings.npm]
package_manager = "bun"

[settings.pipx]
uvx = true

Tool Categories#

Core Development Tools#

Release and Build Tools#

Code Quality Tools#

Documentation Tools#

Testing and CI Tools#

Version Pinning Strategy#

The configuration uses a hybrid pinning strategy:

  • Exact versions for critical tools (Go, cosign, golangci-lint, git-cliff, go-licenses)
  • "latest" for evolving tools (goreleaser, gosec, act, quill, pre-commit, python, uv)
  • Idiomatic version files for language runtimes (Go, Python, Bun) via .go-version, .python-version, and .bun-version

This approach balances reproducibility (pinned versions prevent unexpected breakage) with security updates (latest versions ensure vulnerability patches).

Settings Configuration#

The mise configuration includes several settings to optimize tool management and security:

activate_aggressive#

activate_aggressive = true ensures mise tools activate in all shell contexts, including:

  • Non-interactive shells
  • Subshells spawned by scripts
  • CI/CD environments
  • Editor-integrated terminals

idiomatic_version_file_enable_tools#

idiomatic_version_file_enable_tools = ["python", "go", "bun"] enables mise to read language versions from standard version files:

  • .go-version: Contains 1.26.0, ensuring mise uses this Go version
  • .python-version: Contains 3.14.3, pinning Python despite python = "latest" in mise.toml
  • .bun-version: Contains 1.3.10 for Bun JavaScript runtime

This pattern allows dual-source version management: mise.toml declares "latest" for automatic updates, while idiomatic files pin specific versions for reproducibility. The idiomatic version files take precedence when present.

Other Settings#

As noted in the configuration, many of these are mise defaults but are explicitly declared to ensure stability if defaults change and to clearly document enabled features.

Security Settings and Build Hardening#

While mise itself doesn't provide security features like SLSA verification or attestations, the opnDossier project implements comprehensive security through mise-managed tools:

SLSA Provenance#

SLSA Level 3 provenance is generated using GitHub Actions' native attestation framework during the release workflow. The actions/attest-build-provenance action creates cryptographic attestations linking artifacts to their source code, build environment, and build process.

Artifact Signing with Cosign#

Cosign v3 (managed by mise) provides keyless signing via Sigstore's OIDC authentication. The GoReleaser configuration invokes cosign to sign all release artifacts with .sigstore.json bundles.

Security Scanning#

All security tools are version-controlled through mise.toml, ensuring consistent vulnerability detection across environments.

Tool Activation and Environment Management#

Automatic Activation#

Mise automatically activates tools when entering the project directory through:

  1. Shell Integration: Mise hooks into bash/zsh/fish to detect directory changes
  2. PATH Manipulation: Prepends mise-managed tool directories to PATH
  3. Shim System: Creates wrapper executables that route to the correct version
  4. Aggressive Mode: activate_aggressive = true ensures activation in all contexts

mise exec Pattern#

The project standardizes on using mise exec for explicit tool invocations, particularly in the justfile:

# Example from justfile
mise_exec := "mise exec --"

install-security-tools:
    @{{ mise_exec }} go install github.com/securego/gosec/v2/cmd/gosec@latest

This pattern ensures:

  • Tools run with mise-managed versions
  • Consistent behavior in different shell environments
  • Explicit dependency on mise for clarity

CI/CD Integration#

GitHub Actions workflows use jdx/mise-action@v4.0.0 to set up the mise environment:

- uses: jdx/mise-action@v4.0.0
  with:
    install: true
    cache: true
    github_token: ${{ secrets.GITHUB_TOKEN }}

This action:

  • Installs mise itself
  • Runs mise install to set up all tools
  • Caches mise installations for faster CI runs
  • Authenticates with GitHub for rate limit increases

Note: As of v4.0.0, mise-action requires Node.js 24 (updated from Node.js 20 in v3.x). Teams managing their own GitHub Actions runner environments must ensure Node.js 24 is available.

Environment Caching and Performance#

The project leverages multiple caching mechanisms for faster builds and installations:

  1. mise env_cache: env_cache = true caches environment variables to reduce shell activation overhead
  2. GitHub Actions Cache: The jdx/mise-action@v4.0.0 with cache: true caches mise tool installations across CI runs
  3. mise.lock: lockfile = true generates mise.lock to lock exact tool versions and checksums
  4. Go Module Cache: go.mod and go.sum ensure reproducible dependency resolution
  5. Pre-built Binaries: Mise downloads pre-compiled binaries when available, avoiding build overhead

Idiomatic Version Files#

The project uses idiomatic version files to pin specific language runtime versions, enabled by idiomatic_version_file_enable_tools = ["python", "go", "bun"]:

This dual-source versioning strategy balances flexibility and reproducibility:

  • mise.toml declares "latest" for tools to receive automatic updates
  • Idiomatic version files pin specific versions that have been tested and verified
  • Version files take precedence, allowing controlled updates by modifying a single file

This approach contrasts with the earlier strategy of explicitly declaring all versions in mise.toml, providing easier version updates while maintaining the benefits of pinned versions.

Package Manager Integrations#

pipx with uvx#

The configuration uses pipx-based tool installation with uvx arguments for Python tools, enabled by [settings.pipx] uvx = true:

[tools."pipx:mdformat"]
version = "0.7.21"
uvx_args = "--with mdformat-gfm --with mdformat-front-matters ..."

Key features:

  • uvx (uv-based pipx): Uses the uv tool as a faster alternative to traditional pipx
  • --with: Installs additional packages alongside the main tool
  • Python version comes from .python-version (3.14.3)

This pattern allows complex Python tooling with multiple extensions to be declaratively managed in mise.toml.

npm and bun#

The project configures Bun as the npm package manager via [settings.npm] package_manager = "bun", with version pinned in .bun-version (1.3.10).

While the project is primarily Go-based, Bun provides fast JavaScript execution for tools like markdownlint-cli2, which is installed directly through mise without requiring npm configuration.

Known Limitations and Workarounds#

cyclonedx-gomod: Mise Shim Trust Issues#

The most significant limitation is documented in the mise.toml comment:

# cyclonedx-gomod: installed via go install in CI (mise shim causes trust issues in goreleaser subprocesses)

Problem: GoReleaser invokes cyclonedx-gomod as a subprocess for SBOM generation. Mise's shim wrappers create execution or permission issues in this subprocess context.

Root Cause: Mise uses shim executables that wrap managed tools. When GoReleaser spawns subprocesses expecting direct binary execution, these shims cause:

  • Path resolution failures
  • Environment isolation issues
  • Trust/permission errors

Solution: Install cyclonedx-gomod via go install into the standard Go bin directory:

# From justfile
install-security-tools:
    @{{ mise_exec }} go install github.com/CycloneDX/cyclonedx-gomod/cmd/cyclonedx-gomod@latest

This uses mise-managed Go to install cyclonedx-gomod, but places it in ~/go/bin (standard PATH) rather than under mise's shim system.

Alternative in CI: CI workflows use the CycloneDX GitHub Action instead:

- name: Generate SBOM from binary (CycloneDX)
  uses: CycloneDX/gh-gomod-generate-sbom@efc74245d6802c8cefd925620515442756c70d8f # v2

This completely bypasses both mise and local installation, using a containerized action instead.

Tools Not Suitable for Mise#

Based on the cyclonedx-gomod experience, tools that should not be managed by mise include:

  1. Subprocess-invoked tools: Any tool called as a subprocess by build systems (GoReleaser, Make, etc.)
  2. Trust-sensitive executables: Tools that perform signing or security-critical operations may fail with shim wrappers
  3. Path-dependent binaries: Tools that expect to be in specific system locations

For these cases, use go install, cargo install, or system package managers instead.

gosec Installation Pattern#

Similarly, gosec is installed via go install despite being defined in mise.toml. The mise.toml entry go:github.com/securego/gosec/v2/cmd/gosec declares the tool for discoverability, but installation uses go install to avoid shim issues when gosec is invoked by golangci-lint subprocesses.

Usage Examples#

Initial Setup#

# Install mise (if not already installed)
curl https://mise.run | sh

# Clone repository
git clone https://github.com/EvilBit-Labs/opnDossier.git
cd opnDossier

# Install all tools from mise.toml
mise install

# Install additional security tools (cyclonedx-gomod, gosec)
just install-security-tools

# Set up pre-commit hooks
just install

Verifying Tool Versions#

# Check all installed tools
mise list

# Check specific tool version
mise current go
# Output: 1.26.0

# Show all available tools and versions
mise ls-remote go

Running Tools#

# Direct invocation (uses mise-managed versions via PATH/shims)
go version
golangci-lint run
just build

# Explicit mise exec (ensures mise environment)
mise exec -- go build
mise exec -- goreleaser check

Updating Tools#

# Update a specific tool
mise use go@1.27.0

# Update all "latest" tools
mise upgrade

# Pin current "latest" versions to specific versions
mise use goreleaser@$(mise current goreleaser)

CI/CD Workflow Example#

name: CI
on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: jdx/mise-action@v4.0.0
        with:
          install: true
          cache: true
          github_token: ${{ secrets.GITHUB_TOKEN }}

      - name: Build
        run: just build

      - name: Test
        run: just test

Relevant Code Files#

File PathDescriptionLinesLink
mise.tomlMain mise configuration defining 18 tools and settings~50View
mise.lockLockfile with pinned tool versions and checksums~70View
.go-versionIdiomatic version file pinning Go to 1.26.01View
.python-versionIdiomatic version file pinning Python to 3.14.31View
.bun-versionIdiomatic version file pinning Bun to 1.3.101View
justfileDevelopment task automation using mise-managed tools456View
.github/workflows/ci.ymlCI pipeline using jdx/mise-action~200View
.github/workflows/release.ymlRelease workflow with mise-managed GoReleaser~150View
.goreleaser.yamlGoReleaser configuration invoking cyclonedx-gomod subprocess and go-licenses342View
go.modGo module file with toolchain directive (go1.26.0)~50View
RELEASING.mdRelease documentation including tool installation128View
THIRD_PARTY_NOTICESGenerated third-party license notices from go-licenses2449View

References#

Mise Tool Management | Dosu