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:
{
"targets": {
"rs": {
"type": "language",
"title": "Rust",
"toolchain": "cargo"
}
}
}Auto-Detection
If you don't specify a toolchain, Structyl detects it from marker files:
| Marker File | Detected Toolchain |
|---|---|
Cargo.toml | cargo |
go.mod | go |
deno.jsonc, deno.json | deno |
pnpm-lock.yaml | pnpm |
yarn.lock | yarn |
bun.lockb | bun |
package.json | npm |
uv.lock | uv |
poetry.lock | poetry |
pyproject.toml, setup.py | python |
build.gradle.kts, build.gradle | gradle |
pom.xml | maven |
build.sbt | sbt |
Package.swift | swift |
CMakeLists.txt | cmake |
Makefile | make |
*.sln, Directory.Build.props, global.json | dotnet |
*.csproj, *.fsproj | dotnet |
Gemfile | bundler |
composer.json | composer |
mix.exs | mix |
stack.yaml | stack |
*.cabal | cabal |
dune-project | dune |
project.clj | lein |
build.zig | zig |
rebar.config | rebar3 |
DESCRIPTION | r |
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.yamlandpackage.jsondetects aspnpm, notnpm. Similarly,uv.locktakes precedence overpyproject.toml.
Built-in Toolchains
Rust: cargo
{ "toolchain": "cargo" }| Command | Runs |
|---|---|
build | cargo build |
build:release | cargo build --release |
test | cargo test |
check | cargo clippy -- -D warnings + cargo fmt --check |
check:fix | cargo fmt |
bench | cargo bench |
pack | cargo package |
doc | cargo doc --no-deps |
demo | cargo run --example demo |
Go: go
{ "toolchain": "go" }| Command | Runs |
|---|---|
build | go build ./... |
test | go test ./... |
check | golangci-lint run + go vet ./... + test -z "$(gofmt -l .)" |
check:fix | go fmt ./... |
restore | go mod download |
bench | go test -bench=. ./... |
doc | go doc ./... |
demo | go run ./cmd/demo |
.NET: dotnet
{ "toolchain": "dotnet" }| Command | Runs |
|---|---|
build | dotnet build |
build:release | dotnet build -c Release |
test | dotnet test |
check | dotnet format --verify-no-changes |
check:fix | dotnet format |
restore | dotnet restore |
pack | dotnet pack |
demo | dotnet run --project Demo |
Python: uv
{ "toolchain": "uv" }| Command | Runs |
|---|---|
build | uv build |
test | uv run pytest |
check | uv run ruff check . + uv run mypy . + uv run ruff format --check . |
check:fix | uv run ruff check --fix . + uv run ruff format . |
restore | uv sync --all-extras |
pack | uv build |
demo | uv run python demo.py |
Python: poetry
{ "toolchain": "poetry" }| Command | Runs |
|---|---|
build | poetry build |
test | poetry run pytest |
check | poetry run ruff check . + poetry run mypy . + poetry run ruff format --check . |
check:fix | poetry run ruff check --fix . + poetry run ruff format . |
restore | poetry install |
pack | poetry build |
demo | poetry run python demo.py |
Python: python
{ "toolchain": "python" }| Command | Runs |
|---|---|
build | python -m build |
test | pytest |
check | ruff check . + mypy . + ruff format --check . |
check:fix | ruff check --fix . + ruff format . |
restore | pip install -e . |
pack | python -m build |
demo | python demo.py |
Node.js: npm
{ "toolchain": "npm" }| Command | Runs |
|---|---|
build | npm run build |
test | npm test |
check | npm run lint + npm run typecheck + npm run format:check |
check:fix | npm run lint -- --fix + npm run format |
restore | npm ci |
pack | npm pack |
demo | npm run demo |
Node.js: pnpm
{ "toolchain": "pnpm" }| Command | Runs |
|---|---|
build | pnpm build |
test | pnpm test |
check | pnpm lint + pnpm typecheck + pnpm format:check |
check:fix | pnpm lint --fix + pnpm format |
restore | pnpm install --frozen-lockfile |
pack | pnpm pack |
demo | pnpm run demo |
Node.js: yarn
{ "toolchain": "yarn" }| Command | Runs |
|---|---|
build | yarn build |
test | yarn test |
check | yarn lint + yarn typecheck + yarn format:check |
check:fix | yarn lint --fix + yarn format |
restore | yarn install --frozen-lockfile |
pack | yarn pack |
demo | yarn run demo |
Node.js: bun
{ "toolchain": "bun" }| Command | Runs |
|---|---|
build | bun run build |
test | bun test |
check | bun run lint + bun run typecheck + bun run format:check |
check:fix | bun run lint --fix + bun run format |
restore | bun install --frozen-lockfile |
pack | bun pm pack |
demo | bun run demo |
Deno: deno
{ "toolchain": "deno" }| Command | Runs |
|---|---|
test | deno test |
check | deno lint + deno check **/*.ts + deno fmt --check |
check:fix | deno fmt |
restore | deno install |
bench | deno bench |
doc | deno doc |
demo | deno run demo.ts |
JVM: gradle
{ "toolchain": "gradle" }| Command | Runs |
|---|---|
build | gradle build -x test |
test | gradle test |
check | gradle check -x test + gradle spotlessCheck |
check:fix | gradle spotlessApply |
pack | gradle jar |
doc | gradle javadoc |
demo | gradle run |
JVM: maven
{ "toolchain": "maven" }| Command | Runs |
|---|---|
build | mvn compile |
test | mvn test |
check | mvn checkstyle:check + mvn spotless:check |
check:fix | mvn spotless:apply |
restore | mvn dependency:resolve |
pack | mvn package -DskipTests |
doc | mvn javadoc:javadoc |
demo | mvn exec:java |
Scala: sbt
{ "toolchain": "sbt" }| Command | Runs |
|---|---|
build | sbt compile |
test | sbt test |
check | sbt scalafmtCheck |
check:fix | sbt scalafmt |
restore | sbt update |
pack | sbt package |
doc | sbt doc |
demo | sbt run |
Swift: swift
{ "toolchain": "swift" }| Command | Runs |
|---|---|
build | swift build |
build:release | swift build -c release |
test | swift test |
check | swiftlint + swiftformat --lint . |
check:fix | swiftlint --fix + swiftformat . |
restore | swift package resolve |
demo | swift run Demo |
C/C++: cmake
{ "toolchain": "cmake" }| Command | Runs |
|---|---|
build | cmake --build build |
test | ctest --test-dir build |
check | cmake --build build --target lint + cmake --build build --target format-check |
check:fix | cmake --build build --target format |
restore | cmake -B build -S . |
pack | cmake --build build --target package |
doc | cmake --build build --target doc |
demo | cmake --build build --target demo && ./build/demo |
Generic: make
{ "toolchain": "make" }| Command | Runs |
|---|---|
build | make |
build:release | make release |
test | make test |
check | make check |
check:fix | make fix |
bench | make bench |
pack | make dist |
doc | make doc |
demo | make demo |
Ruby: bundler
{ "toolchain": "bundler" }| Command | Runs |
|---|---|
build | bundle exec rake build |
test | bundle exec rake test |
check | bundle exec rubocop |
check:fix | bundle exec rubocop -a |
restore | bundle install |
pack | gem build *.gemspec |
doc | bundle exec yard doc |
demo | bundle exec ruby demo.rb |
PHP: composer
{ "toolchain": "composer" }| Command | Runs |
|---|---|
test | composer test |
check | composer run-script lint + composer run-script format:check |
check:fix | composer run-script format |
restore | composer install |
demo | php demo.php |
Elixir: mix
{ "toolchain": "mix" }| Command | Runs |
|---|---|
build | mix compile |
test | mix test |
check | mix credo + mix dialyzer + mix format --check-formatted |
check:fix | mix format |
restore | mix deps.get |
doc | mix docs |
demo | mix run demo.exs |
Haskell: cabal
{ "toolchain": "cabal" }| Command | Runs |
|---|---|
build | cabal build |
test | cabal test |
check | cabal check + hlint . + ormolu --mode check $(find . -name '*.hs') |
check:fix | ormolu --mode inplace $(find . -name '*.hs') |
restore | cabal update |
bench | cabal bench |
doc | cabal haddock |
demo | cabal run |
Haskell: stack
{ "toolchain": "stack" }| Command | Runs |
|---|---|
build | stack build |
test | stack test |
check | stack exec -- hlint . + stack exec -- ormolu --mode check $(find . -name '*.hs') |
check:fix | stack exec -- ormolu --mode inplace $(find . -name '*.hs') |
restore | stack setup |
bench | stack bench |
doc | stack haddock |
demo | stack run |
OCaml: dune
{ "toolchain": "dune" }| Command | Runs |
|---|---|
build | dune build |
test | dune runtest |
check | dune fmt --preview |
check:fix | dune fmt |
restore | opam install . --deps-only |
doc | dune build @doc |
demo | dune exec demo |
Clojure: lein
{ "toolchain": "lein" }| Command | Runs |
|---|---|
build | lein compile |
test | lein test |
check | lein check + lein eastwood + lein cljfmt check |
check:fix | lein cljfmt fix |
restore | lein deps |
pack | lein jar |
doc | lein codox |
demo | lein run |
Zig: zig
{ "toolchain": "zig" }| Command | Runs |
|---|---|
build | zig build |
build:release | zig build -Doptimize=ReleaseFast |
test | zig build test |
check | zig fmt --check . |
check:fix | zig fmt . |
demo | zig build run |
Erlang: rebar3
{ "toolchain": "rebar3" }| Command | Runs |
|---|---|
build | rebar3 compile |
test | rebar3 eunit |
check | rebar3 dialyzer + rebar3 lint |
check:fix | rebar3 format |
restore | rebar3 get-deps |
pack | rebar3 tar |
doc | rebar3 edoc |
demo | rebar3 shell |
R: r
{ "toolchain": "r" }| Command | Runs |
|---|---|
build | R CMD build . |
test | Rscript -e "devtools::test()" |
check | Rscript -e "lintr::lint_package()" + Rscript -e "styler::style_pkg(dry='on')" |
check:fix | Rscript -e "styler::style_pkg()" |
pack | R CMD build . |
doc | Rscript -e "roxygen2::roxygenise()" |
demo | Rscript 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:
{
"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:
{
"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:
{
"targets": {
"rs": {
"toolchain": "cargo",
"commands": {
"test": "cargo test --release"
}
}
}
}Next Steps
- Commands - Understand the command system
- Configuration - Full configuration reference