Skip to main content

Under the hood


This page is for people who are already familiar with the Scala/JVM ecosystem.

If you just want to learn Scala CLI, head out to the Commands section.

Under the hood

Scala CLI consists of a native executable, generated by GraalVM Native Image. It runs fine on Linux and macOS with no prior requirements, and only requires the Visual C++ Redistributable Runtime on Windows. Native Image lets us build Scala CLI as a native image for each platform, and lets Scala CLI be responsive, as a command line application should be.

Caching and incrementality

Since most of the tasks require compilation or dependency resolution under the hood, Scala CLI heavily uses caches and incrementality under the hood to provide output as quickly as possible.

But note that incremental compilation and caching are not perfect. In some cases, when there's a compilation problem and you don't think it's a problem with the code, it may be the stale state of the project - cleaning the project state might help. For this reason Scala CLI has the clean command, which invalidates local caches and forces the next compilation to be a total rebuild from a clean slate.

We provide a more in-depth overview about how caching works in the Scala CLI internals guide.

Bloop and Coursier

To ensure the quickest compilation, Scala CLI uses and manages the Bloop compilation server. We have a detailed guide that describes how Scala CLI interacts with the local Bloop server. The main point to know is that Scala CLI takes care of fetching and starting Bloop if needed, so you don't have to worry about it.

Scala CLI uses Coursier to manage dependencies. It automatically downloads and unpacks a JVM if none is installed on your system, so that all its commands work fine even if a JVM isn't already installed. Scala CLI shares Coursier caches with other tools like sbt, Mill, or Metals.

scala-cli's JVM

Scala CLI is a JVM application. Although by default it is distributed as a GraalVM native image, it is still possible to set Java properties. In order set them, the -D command-line flags must be placed as the first options to scala-cli, for example:

scala-cli -Dfoo1=bar1 -Dfoo2=bar2 run ...
  • scala-cli run . -Dfoo=bar would pass the java property into your Scala app
  • scala-cli -Dfoo=bar run . would pass the java property into scala-cli.