Skip to content

Mise Integration

Note: This is a user guide (informative). For normative requirements, see the Configuration Specification.

Structyl uses mise as its primary build platform. All command execution is delegated to mise tasks, making mise.toml the central configuration for toolchain management and task execution.

Overview

When you run structyl build go, structyl:

  1. Ensures mise is installed
  2. Generates/updates mise.toml from your config.json
  3. Executes mise run build:go

This approach provides:

  • Consistent toolchain versions across all environments
  • Native mise task execution
  • Full compatibility with mise ecosystem tools

Installation

Mise must be installed to use structyl commands. If mise isn't found, structyl offers to install it:

bash
# Manual installation
curl https://mise.run | sh

# macOS via Homebrew
brew install mise

After installation, activate mise in your shell:

bash
# Add to ~/.bashrc or ~/.zshrc
eval "$(mise activate bash)"  # or zsh/fish

Configuration

Basic Setup

Mise integration is enabled by default. The mise.toml file is autogenerated and gitignored.

json
{
  "project": {
    "name": "my-project"
  },
  "targets": {
    "go": {
      "type": "language",
      "title": "Go",
      "toolchain": "go"
    }
  }
}

Mise-Specific Options

Configure mise behavior in your config.json:

json
{
  "mise": {
    "enabled": true,
    "auto_generate": true,
    "extra_tools": {
      "jq": "latest",
      "yq": "4"
    }
  }
}
FieldDefaultDescription
enabledtrueEnable mise integration
auto_generatetrueRegenerate mise.toml before each run
extra_tools{}Additional mise tools to install

Toolchain Versions

Override default toolchain versions per-target:

json
{
  "targets": {
    "go": {
      "type": "language",
      "title": "Go",
      "toolchain": "go",
      "toolchain_version": "1.23"
    }
  }
}

Or define version in a custom toolchain:

json
{
  "toolchains": {
    "go-legacy": {
      "extends": "go",
      "version": "1.21"
    }
  }
}

Version priority:

  1. Target's toolchain_version
  2. Custom toolchain's version
  3. Built-in default for the toolchain

CLI Commands

Running Commands

All standard commands delegate to mise:

bash
structyl build go        # → mise run build:go
structyl test            # → mise run test
structyl ci rs           # → mise run ci:rs

Mise Sync

Manually regenerate mise.toml:

bash
structyl mise sync  # Regenerate mise.toml (always regenerates)

Generation Commands

Generate Docker and CI configurations:

bash
structyl dockerfile      # Generate Dockerfiles with mise
structyl github          # Generate GitHub Actions workflow

Generated mise.toml

Given this config.json:

json
{
  "targets": {
    "go": {
      "type": "language",
      "title": "Go",
      "toolchain": "go",
      "toolchain_version": "1.23",
      "directory": "go"
    },
    "rs": {
      "type": "language",
      "title": "Rust",
      "toolchain": "cargo",
      "directory": "rs"
    }
  }
}

Structyl generates:

toml
[tools]
go = "1.23"
golangci-lint = "latest"
rust = "stable"

[tasks."clean:go"]
description = "Clean for go target"
dir = "go"
run = "go clean"

[tasks."restore:go"]
description = "Restore for go target"
dir = "go"
run = "go mod download"

[tasks."build:go"]
description = "Build for go target"
dir = "go"
run = "go build ./..."

[tasks."test:go"]
description = "Test for go target"
dir = "go"
run = "go test ./..."

[tasks."lint:go"]
description = "Lint for go target"
dir = "go"
run = "golangci-lint run"

[tasks."vet:go"]
description = "Vet for go target"
dir = "go"
run = "go vet ./..."

[tasks."check:go"]
description = "Check for go target"
depends = ["lint:go", "vet:go"]

[tasks."ci:go"]
description = "Run CI for go target"
depends = ["clean:go", "restore:go", "check:go", "build:go", "test:go"]

[tasks."clean:rs"]
description = "Clean for rs target"
dir = "rs"
run = "cargo clean"

[tasks."build:rs"]
description = "Build for rs target"
dir = "rs"
run = "cargo build"

[tasks."test:rs"]
description = "Test for rs target"
dir = "rs"
run = "cargo test"

[tasks."ci:rs"]
description = "Run CI for rs target"
depends = ["clean:rs", "build:rs", "test:rs"]

[tasks."build"]
description = "Build all targets"
depends = ["build:go", "build:rs"]

[tasks."test"]
description = "Test all targets"
depends = ["test:go", "test:rs"]

[tasks."ci"]
description = "Run CI for all targets"
depends = ["ci:go", "ci:rs"]

Task Naming Convention

Tasks follow the pattern <command>:<target>:

CommandDescription
build:goBuild Go target
test:rsTest Rust target
lint:pyLint Python target
ci:tsFull CI for TypeScript target

Aggregate tasks run across all targets:

  • build - Build all targets
  • test - Test all targets
  • ci - Full CI for all targets

Toolchain Mapping

Structyl automatically maps toolchains to mise tools:

ToolchainMise Tools
cargorust = "stable"
dotnetdotnet = "10.0"
gogo = "1.24", golangci-lint = "latest"
npmnode = "22"
pnpmnode = "22", pnpm = "10"
yarnnode = "22"
bunbun = "latest"
pythonpython = "3.13"
uvpython = "3.13", uv = "0.6", ruff = "latest"
poetrypython = "3.13"
gradlejava = "temurin-23"
mavenjava = "temurin-23"
denodeno = "latest"
swiftswift = "latest"

Docker Integration

Generated Dockerfiles install mise and run tasks:

dockerfile
FROM ubuntu:22.04

# Install mise
RUN curl -fsSL https://mise.run | sh
ENV PATH="/root/.local/bin:$PATH"

# Copy mise configuration
WORKDIR /workspace
COPY mise.toml mise.toml
RUN mise trust && mise install

# Set working directory to target
WORKDIR /workspace/go

GitHub Actions

Generated workflow uses jdx/mise-action:

yaml
name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  go:
    name: Go
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: jdx/mise-action@v2
      - run: mise run ci:go

  rs:
    name: Rust
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: jdx/mise-action@v2
      - run: mise run ci:rs

Disabling Mise

To use direct command execution instead of mise:

json
{
  "mise": {
    "enabled": false
  }
}

Or use the --docker flag, which falls back to direct execution in containers.

Best Practices

  1. Keep mise.toml gitignored: It's autogenerated from config.json
  2. Pin versions for production: Use specific versions instead of latest
  3. Use mise directly for development: Run mise run build:go locally
  4. Regenerate after config changes: Run structyl mise sync or let auto-generate handle it

© 2026 Andrey Akinshin MIT