Scala CLI (Compiling and Running Code)

I initially created this Scala CLI content for my book, Learn Functional Programming Without Fear, but when I decided to shorten what I include in the book, I also decided to put the full version of this content here.

Scala CLI

Until some time in the year 2021 I would have written this book using only the Scala SDK and its scalac and scala commands to compile and run your code, respectively. (These are just like javac in Java, kotlinc in Kotlin, and java with both of those.)

But since that time the Scala CLI command project has come along, and it greatly simplifies the “getting started with Scala” experience, so I use it in this book. Scala CLI:

  • Is much simpler to use, especially when you’re first getting started with Scala
  • Lets you easily compile and run both (a) small applications and (b) Scala scripts
  • Lets you easily include third-party libraries in apps and scripts, such as using HTTP, JSON, and HTML libraries for working on the internet, along with testing libraries (so you can include tests in your code)
  • Lets you export your project configuration details to build tools like Sbt or Mill, once it feels too large for Scala CLI.

At the time of this writing there’s also an effort to make Scala CLI the official Scala command (scala). I don’t know if that will come to complete fruition, but if it does, you’ll be in great shape.

Because I use Scala CLI in this book, I want to share a little “cheat sheet” of how to use it.

NOTE: At the time of this writing, Scala CLI is at version 0.1.12, so be aware that some of the following features may change over time.

Starting the Scala REPL with Scala CLI

Use this Scala CLI command to start the Scala REPL:

$ scala-cli repl

If you prefer the Ammonite REPL, start it like this:

$ scala-cli repl --amm

Scala CLI: Compiling and running applications

If you have an application with an @main method named hello in a file named Hello.scala, and you want to run that application, this is how you run it:

$ scala-cli Hello.scala

That command both compiles and runs your application in one step. If instead you want to do those in separate steps, do this:

$ scala-cli compile Hello.scala
$ scala-cli run hello

You can also continuously compile your code with the --watch parameter:

$ scala-cli compile Hello.scala --watch

Scala CLI: Compiling and running scripts

Scala CLI currently makes a distinction between Scala applications, which are in .scala files, and Scala scripts, which are in files that end with the .sc extension. A main difference between the two is that a script doesn’t have to have an @main method; it can just consist of a series of statements and expressions.

To demonstrate how to run a script, here’s a script named MyScript.sc that consists of just one line:

args.foreach(println)

In a Scala CLI script, the args variable is implicitly made available to you, so you can access command-line arguments. This is how you run that script:

$ scala-cli MyScript.sc -- hello world
hello
world

Notice that the -- characters are required before your command-line arguments.

A self-enclosed Scala CLI script

If you’re working on a Unix-based system, such as macOS or Linux, you can also make a script self-enclosed by starting it with the first line shown here:

#!/usr/bin/env -S scala-cli shebang
println("Hello, world")

The first line of code is the “Unix + Scala CLI” way to say that you want this script to execute the scala-cli command with the shebang command-line option. After that, scala-cli is given the rest of the script to interpret.

If you haven’t seen anything like this before, most Unix shell scripts start with the #! characters, followed by specifying an interpreter for the script, typically something like /bin/sh or /usr/bin/env. This is the Unix way to say, “Run this script using the interpreter that follows the #! characters.”

Assuming that your code is in a file named HelloWorld.sc, and you have Scala CLI installed, just make the script executable:

$ chmod +x HelloWorld.sc

and then run it like this:

$ ./HelloWorld.sc

As shown before, if you want a script to handle command-line arguments, access those with the args variable:

#!/usr/bin/env -S scala-cli shebang
args.foreach(println)

If that script is named PrintAll.sc, you can make it executable and then run it like this:

# make it executable
$ chmod +x PrintAll.sc

# run it with command-line arguments
$ ./PrintAll.sc 1 2 3
1
2
3

Notice that when you use the “shebang” line to start your script, you don’t need to use the -- characters before your command-line arguments.

Scala CLI: ‘using’ directives

One of the great things about Scala CLI is its concept of “using directives.” These directives give you a way to control how your code will be run, including specifying what Scala version is used, and what third-party libraries your application uses.

You add these directives with this special syntax, which must be put in your script or application before any other Scala code:

//> using scala "3"

With this directive at the top of your file, when you run your application with scala-cli, it sees this line and then interprets the rest of your code using the latest version of Scala 3 (such as Scala 3.1.1, for example).

In addition to specifying which Scala version should be used, you can also specify the dependencies your application requires. For example, I use these two directives at the beginning of some HTTP GET and POST scripts I share in my book, Learn Scala 3 The Fast Way:

//> using scala "3"
//> using lib "com.softwaremill.sttp.client3::core::3.7.2"

// the rest of the Scala code follows ...

There are many more things you can do with using directives. See the Scala CLI website for more details.

More examples

If you want to see some complete examples of these features, check out the Github repositories for my two latest books:

You can also buy both of those books for just $10 each at these links:

Even more

On top of these basics there’s much more that Scala CLI can do for you. In addition to what I’ve shown, you can:

  • Include multiple dependencies
  • Declare specific Scala versions to use (such as 2.12.15 or 3.1.1)
  • Run tests
  • Create small projects
  • Integrate with your IDE
  • Package your applications
  • More!

For all those details, see the Scala CLI website.