Skip to content

Toolchains

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

Toolchains provide default command implementations for different build ecosystems. They map Structyl's standard commands to language-specific tools.

Using Toolchains

Specify a toolchain in your target configuration:

json
{
  "targets": {
    "rs": {
      "type": "language",
      "title": "Rust",
      "toolchain": "cargo"
    }
  }
}

Auto-Detection

If you don't specify a toolchain, Structyl detects it from marker files:

Marker FileDetected Toolchain
Cargo.tomlcargo
go.modgo
deno.jsonc, deno.jsondeno
pnpm-lock.yamlpnpm
yarn.lockyarn
bun.lockbbun
package.jsonnpm
uv.lockuv
poetry.lockpoetry
pyproject.toml, setup.pypython
build.gradle.kts, build.gradlegradle
pom.xmlmaven
build.sbtsbt
Package.swiftswift
CMakeLists.txtcmake
Makefilemake
*.sln, Directory.Build.props, global.jsondotnet
*.csproj, *.fsprojdotnet
Gemfilebundler
composer.jsoncomposer
mix.exsmix
stack.yamlstack
*.cabalcabal
dune-projectdune
project.cljlein
build.zigzig
rebar.configrebar3
DESCRIPTIONr

Detection order matters: When multiple marker files exist in a directory, the first match in the table above wins. For example, a directory with both pnpm-lock.yaml and package.json detects as pnpm, not npm. Similarly, uv.lock takes precedence over pyproject.toml.

Built-in Toolchains

Rust: cargo

json
{ "toolchain": "cargo" }
CommandRuns
buildcargo build
build:releasecargo build --release
testcargo test
checkcargo clippy -- -D warnings + cargo fmt --check
check:fixcargo fmt
benchcargo bench
packcargo package
doccargo doc --no-deps
democargo run --example demo

Go: go

json
{ "toolchain": "go" }
CommandRuns
buildgo build ./...
testgo test ./...
checkgolangci-lint run + go vet ./... + test -z "$(gofmt -l .)"
check:fixgo fmt ./...
restorego mod download
benchgo test -bench=. ./...
docgo doc ./...
demogo run ./cmd/demo

.NET: dotnet

json
{ "toolchain": "dotnet" }
CommandRuns
builddotnet build
build:releasedotnet build -c Release
testdotnet test
checkdotnet format --verify-no-changes
check:fixdotnet format
restoredotnet restore
packdotnet pack
demodotnet run --project Demo

Python: uv

json
{ "toolchain": "uv" }
CommandRuns
builduv build
testuv run pytest
checkuv run ruff check . + uv run mypy . + uv run ruff format --check .
check:fixuv run ruff check --fix . + uv run ruff format .
restoreuv sync --all-extras
packuv build
demouv run python demo.py

Python: poetry

json
{ "toolchain": "poetry" }
CommandRuns
buildpoetry build
testpoetry run pytest
checkpoetry run ruff check . + poetry run mypy . + poetry run ruff format --check .
check:fixpoetry run ruff check --fix . + poetry run ruff format .
restorepoetry install
packpoetry build
demopoetry run python demo.py

Python: python

json
{ "toolchain": "python" }
CommandRuns
buildpython -m build
testpytest
checkruff check . + mypy . + ruff format --check .
check:fixruff check --fix . + ruff format .
restorepip install -e .
packpython -m build
demopython demo.py

Node.js: npm

json
{ "toolchain": "npm" }
CommandRuns
buildnpm run build
testnpm test
checknpm run lint + npm run typecheck + npm run format:check
check:fixnpm run lint -- --fix + npm run format
restorenpm ci
packnpm pack
demonpm run demo

Node.js: pnpm

json
{ "toolchain": "pnpm" }
CommandRuns
buildpnpm build
testpnpm test
checkpnpm lint + pnpm typecheck + pnpm format:check
check:fixpnpm lint --fix + pnpm format
restorepnpm install --frozen-lockfile
packpnpm pack
demopnpm run demo

Node.js: yarn

json
{ "toolchain": "yarn" }
CommandRuns
buildyarn build
testyarn test
checkyarn lint + yarn typecheck + yarn format:check
check:fixyarn lint --fix + yarn format
restoreyarn install --frozen-lockfile
packyarn pack
demoyarn run demo

Node.js: bun

json
{ "toolchain": "bun" }
CommandRuns
buildbun run build
testbun test
checkbun run lint + bun run typecheck + bun run format:check
check:fixbun run lint --fix + bun run format
restorebun install --frozen-lockfile
packbun pm pack
demobun run demo

Deno: deno

json
{ "toolchain": "deno" }
CommandRuns
testdeno test
checkdeno lint + deno check **/*.ts + deno fmt --check
check:fixdeno fmt
restoredeno install
benchdeno bench
docdeno doc
demodeno run demo.ts

JVM: gradle

json
{ "toolchain": "gradle" }
CommandRuns
buildgradle build -x test
testgradle test
checkgradle check -x test + gradle spotlessCheck
check:fixgradle spotlessApply
packgradle jar
docgradle javadoc
demogradle run

JVM: maven

json
{ "toolchain": "maven" }
CommandRuns
buildmvn compile
testmvn test
checkmvn checkstyle:check + mvn spotless:check
check:fixmvn spotless:apply
restoremvn dependency:resolve
packmvn package -DskipTests
docmvn javadoc:javadoc
demomvn exec:java

Scala: sbt

json
{ "toolchain": "sbt" }
CommandRuns
buildsbt compile
testsbt test
checksbt scalafmtCheck
check:fixsbt scalafmt
restoresbt update
packsbt package
docsbt doc
demosbt run

Swift: swift

json
{ "toolchain": "swift" }
CommandRuns
buildswift build
build:releaseswift build -c release
testswift test
checkswiftlint + swiftformat --lint .
check:fixswiftlint --fix + swiftformat .
restoreswift package resolve
demoswift run Demo

C/C++: cmake

json
{ "toolchain": "cmake" }
CommandRuns
buildcmake --build build
testctest --test-dir build
checkcmake --build build --target lint + cmake --build build --target format-check
check:fixcmake --build build --target format
restorecmake -B build -S .
packcmake --build build --target package
doccmake --build build --target doc
democmake --build build --target demo && ./build/demo

Generic: make

json
{ "toolchain": "make" }
CommandRuns
buildmake
build:releasemake release
testmake test
checkmake check
check:fixmake fix
benchmake bench
packmake dist
docmake doc
demomake demo

Ruby: bundler

json
{ "toolchain": "bundler" }
CommandRuns
buildbundle exec rake build
testbundle exec rake test
checkbundle exec rubocop
check:fixbundle exec rubocop -a
restorebundle install
packgem build *.gemspec
docbundle exec yard doc
demobundle exec ruby demo.rb

PHP: composer

json
{ "toolchain": "composer" }
CommandRuns
testcomposer test
checkcomposer run-script lint + composer run-script format:check
check:fixcomposer run-script format
restorecomposer install
demophp demo.php

Elixir: mix

json
{ "toolchain": "mix" }
CommandRuns
buildmix compile
testmix test
checkmix credo + mix dialyzer + mix format --check-formatted
check:fixmix format
restoremix deps.get
docmix docs
demomix run demo.exs

Haskell: cabal

json
{ "toolchain": "cabal" }
CommandRuns
buildcabal build
testcabal test
checkcabal check + hlint . + ormolu --mode check $(find . -name '*.hs')
check:fixormolu --mode inplace $(find . -name '*.hs')
restorecabal update
benchcabal bench
doccabal haddock
democabal run

Haskell: stack

json
{ "toolchain": "stack" }
CommandRuns
buildstack build
teststack test
checkstack exec -- hlint . + stack exec -- ormolu --mode check $(find . -name '*.hs')
check:fixstack exec -- ormolu --mode inplace $(find . -name '*.hs')
restorestack setup
benchstack bench
docstack haddock
demostack run

OCaml: dune

json
{ "toolchain": "dune" }
CommandRuns
builddune build
testdune runtest
checkdune fmt --preview
check:fixdune fmt
restoreopam install . --deps-only
docdune build @doc
demodune exec demo

Clojure: lein

json
{ "toolchain": "lein" }
CommandRuns
buildlein compile
testlein test
checklein check + lein eastwood + lein cljfmt check
check:fixlein cljfmt fix
restorelein deps
packlein jar
doclein codox
demolein run

Zig: zig

json
{ "toolchain": "zig" }
CommandRuns
buildzig build
build:releasezig build -Doptimize=ReleaseFast
testzig build test
checkzig fmt --check .
check:fixzig fmt .
demozig build run

Erlang: rebar3

json
{ "toolchain": "rebar3" }
CommandRuns
buildrebar3 compile
testrebar3 eunit
checkrebar3 dialyzer + rebar3 lint
check:fixrebar3 format
restorerebar3 get-deps
packrebar3 tar
docrebar3 edoc
demorebar3 shell

R: r

json
{ "toolchain": "r" }
CommandRuns
buildR CMD build .
testRscript -e "devtools::test()"
checkRscript -e "lintr::lint_package()" + Rscript -e "styler::style_pkg(dry='on')"
check:fixRscript -e "styler::style_pkg()"
packR CMD build .
docRscript -e "roxygen2::roxygenise()"
demoRscript demo.R

Custom Toolchains

Structyl follows a declarative approach to extensibility: all custom toolchains must be defined in the configuration file (see Toolchains Specification for normative requirements). There is no plugin system or external toolchain discovery. This design ensures that toolchain definitions are explicit, version-controlled, and portable across environments.

Create your own toolchain:

json
{
  "toolchains": {
    "my-toolchain": {
      "commands": {
        "build": "my-build-tool compile",
        "test": "my-build-tool test",
        "clean": "rm -rf out/"
      }
    }
  },
  "targets": {
    "custom": {
      "toolchain": "my-toolchain"
    }
  }
}

Extending Toolchains

Extend a built-in toolchain to customize specific commands:

json
{
  "toolchains": {
    "cargo-workspace": {
      "extends": "cargo",
      "commands": {
        "build": "cargo build --workspace",
        "test": "cargo test --workspace"
      }
    }
  }
}

Overriding Commands

Override specific commands in a target without creating a new toolchain:

json
{
  "targets": {
    "rs": {
      "toolchain": "cargo",
      "commands": {
        "test": "cargo test --release"
      }
    }
  }
}

Next Steps

© 2026 Andrey Akinshin MIT