Sixteen language toolchains, each a small declarative Flox environment — plus a
polyglot environment that composes all sixteen into one. Clone and activate locally, or pull the
same environments from FloxHub.
C/C++ · Rust · Go · Zig · Node/TypeScript · Python · Ruby · PHP · Perl · Lua · Erlang/Elixir · Haskell · Kotlin · Clojure · Scala · R/Julia
# the whole 16-language stack, from this repo
git clone <repo-url> && cd polyglot-playground/polyglot
flox activate
# just one toolchain
cd ../rust-dev && flox activate
# …or straight from FloxHub, no clone needed
flox activate -r flox-labs/polyglot-playground
flox activate -r flox-labs/rust-devEvery tool lands on PATH the moment you activate.
| Directory | Toolchain | FloxHub |
|---|---|---|
cxx |
C/C++ — gcc/clang, cmake, ninja, gdb/lldb, valgrind | flox-labs/cxx |
rust-dev |
Rust — rustc, cargo, clippy, rustfmt, rust-analyzer | flox-labs/rust-dev |
go |
Go — go, gopls, delve, golangci-lint | flox-labs/go |
zig |
Zig — zig, zls | flox-labs/zig |
node |
Node.js + TypeScript | flox-labs/node |
python3 |
Python — python, uv | flox-labs/python3 |
ruby |
Ruby — ruby, bundler | flox-labs/ruby |
php |
PHP — php, composer | flox-labs/php |
perl |
Perl — perl, cpanm, perltidy, perlcritic | flox-labs/perl |
lua |
Lua — lua, luarocks | flox-labs/lua |
erlang |
Erlang + Elixir (BEAM) — rebar3, mix, LSPs | flox-labs/erlang |
haskell |
Haskell — ghc, cabal, stack | flox-labs/haskell |
kotlin |
Kotlin (JVM) — kotlin, gradle | flox-labs/kotlin |
clojure |
Clojure (JVM) — clojure, leiningen | flox-labs/clojure |
scala |
Scala (JVM) — scala, sbt, metals | flox-labs/scala |
datascience |
R + Julia — gfortran | flox-labs/datascience |
Each <lang>/ is a self-contained Flox environment. polyglot/ declares no packages of its own —
it [include]s all sixteen by path.
polyglot-playground/
├── polyglot/ # composer: includes the 16 leaves by path
├── cxx/ rust-dev/ go/ zig/ # compiled / systems
├── node/ python3/ ruby/ php/ perl/ lua/ # scripting / dynamic
├── kotlin/ clojure/ scala/ # JVM
├── erlang/ haskell/ datascience/ # BEAM · functional · data
├── README.md
└── polyglot/README.md # composed-environment reference
Don't need all sixteen? A composed environment is just a manifest with an [include] block and
nothing else. Point it at the leaves you want — by FloxHub handle (works anywhere) or, inside this
repo, by path (what polyglot/ does):
# jvm-stack/.flox/env/manifest.toml
[include]
environments = [
{ remote = "flox-labs/kotlin" }, # or { dir = "../kotlin" } within this repo
{ remote = "flox-labs/clojure" },
{ remote = "flox-labs/scala" },
]flox activate yields Kotlin + Gradle, Clojure + Leiningen, and Scala + sbt + Metals on a shared
JDK. Swap the list for a systems stack (cxx + rust-dev), a data stack (python3 +
datascience), or whatever a project needs. Includes merge at build time: on an install-ID
conflict the last include wins, and the composer's own [install] beats every include.
Every flox command acts on one environment — the one in the current directory, or whichever you
name with -d <dir>. In this repo that's either a leaf (rust-dev/, cxx/, …) or the
composer (polyglot/), and which you target matters:
- A leaf is the toolchain's definition. Change it and you change that toolchain for everyone who
uses it — anyone activating the leaf, and every composed stack that includes it (after a
flox include upgrade). Put things here that genuinely belong to the language. - The composer (
polyglot/) affects only the composed stack, and its own[install]wins over the includes — so it's where you add a stack-wide tool, or pin/override a single package, without touching any leaf.
Activate — one toolchain or the whole stack:
flox activate -d rust-dev # just the Rust toolchain
flox activate -d polyglot # all sixteen (or: cd into the dir and `flox activate`)Add or override a tool — pick the target deliberately:
flox install -d polyglot ripgrep # a tool for the whole composed stack; leaves untouched
flox install -d rust-dev cargo-watch # part of the Rust toolchain itself — every rust-dev user gets it
flox install -d polyglot nodejs@20 # composer override beats the node leaf's version, for this stack onlyUpgrade one axis — packages are grouped, so you bump them independently (again, per environment):
flox upgrade -d rust-dev rust # just the Rust toolchain
flox upgrade -d cxx shared # just the shared plumbing (git, openssl, …)Edit a leaf, then refresh the composer:
flox edit -d cxx -f cxx/.flox/env/manifest.toml # change the leaf
flox include upgrade -d polyglot cxx # pull the change into the composed stackVersioning & rollback — in this repo it's plain git (every leaf and the composer are text
manifests); on FloxHub every push is a generation you can inspect or pin to
(flox generations list -r flox-labs/<name>, flox pull --copy flox-labs/<name>). Either way,
updates are targeted, reviewable diffs — no image rebuilds.
This repo is self-contained: polyglot/ composes its siblings by path, with no dependency on
FloxHub — git clone and go. The identical environments are also published on FloxHub under
flox-labs/*, so any flox activate -r flox-labs/<name> runs the same thing without cloning.
A leaf is just a manifest.toml. Packages are sorted into groups so each can be upgraded on its
own:
[install]
python3.pkg-path = "python313Full"
python3.pkg-group = "python" # the language's own runtime + tooling
gcc.pkg-path = "gcc"
gcc.systems = ["x86_64-linux", "aarch64-linux"]
gcc.pkg-group = "compilers-linux" # gcc on Linux, clang on Darwin
git.pkg-path = "git"
git.pkg-group = "shared" # git/gh/openssl/pkg-config/zlib/… — common plumbing- Package groups are the independent upgrade axes:
<language>,shared,compilers-linux(gcc) /compilers-darwin(clang), anddarwin(Apple frameworks). - Cross-platform — one manifest resolves the right pieces per host: Clang/LLDB on macOS, GCC/GDB/Valgrind on Linux; ARM and x86, no virtualization.
- No
LD_LIBRARY_PATHshims — Flox'sld-floxlib.soexposes$FLOX_ENV/libas a non-shadowing fallback, so composed leaves never clobber each other's libraries. - Compose vs. layer —
[include]merges at build time (deterministic, shareable); you can also layer ad hoc at runtime (flox activateinsideflox activate) for a tool you need right now.
See polyglot/README.md for the composed environment specifically.
The model above ships each toolchain as an environment. A natural evolution ships each as a
package: one built artifact per language that links its tools into a single output and carries its
own etc/profile.d script to set the language's env vars and PATH — published to a catalog and
kept current by automation. Then flox install your-org/erlang drops a complete, self-configuring
toolchain into any environment — no composition, and none of the generic plumbing that really
belongs to the base environment or to Flox itself.