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