Design Overview
How dependency locking and Nix composition fit together
Design Overview
When you run sbtix genNix / genComposition, the plugin orchestrates three steps:
Collect dependencies: Sbtix walks your sbt build, resolves everything with Coursier (using your resolvers + credentials), and emits a locked
repo.nix. Private repositories keep their own namespace (e.g.nix-private-demo) so you can see where each artifact originates. For Scala 2.13 and Scala 3 builds, sbtix also locks sbt tooling such asorg.scala-lang:scala2-sbt-bridge/org.scala-lang:scala3-sbt-bridgeso sbt can compile offline in the Nix sandbox.Generate the composition: The plugin now renders
sbtix-generated.nix, the machine-written derivation that wires togetherrepo.nix, the plugin bootstrap, and the staging/install logic. If there is nodefault.nixin your project yet, sbtix drops in a tiny example that simply imports./sbtix-generated.nix. Your owndefault.nixis never overwritten again.Consume from Nix: Import the generated file (
import ./sbtix-generated.nix { inherit pkgs; }) from your project’sdefault.nix, or call the helpers inplugin/nix-exprs/sbtix.nix(buildSbtProgram,buildSbtLibrary, etc.) if you need a different layout. Either way, the derivation reads the lockedrepo.nixfiles and the staged application copied in step 2, so builds are reproducible and network-free. The Nix build environment also setsSBTIX_NIX_BUILD=1and-Dsbtix.nixBuild=trueso your build can disable tasks that would otherwise try to download tooling (e.g. scalafmt).
This pipeline keeps your sbt workflow fast (dependency metadata is cached) while ensuring the Nix derivation is always in sync with what the sbt plugin produces.