Skip to main content

Basics

Scala CLI is a command line tool that executes a given sub-command on the inputs it’s provided with, using a given configuration to produce a result.

The most important sub-commands are:

  • compile compiles your code (excluding tests)
  • run runs your code using the provided arguments (it’s also used when no other command is provided)
  • test compiles and runs the tests defined in your code
  • package packages your code into a jar or other format
  • repl / console runs the interactive Scala shell
  • fmt formats your code

Scala CLI can also be run without passing any explicit sub-command, in which case it defaults to one of the sub-commands based on context:

  • if the --version option is passed, it prints the version command output (unmodified by any other options)
  • if any inputs were passed, it defaults to the run sub-command
    • and so, scala-cli a.scala runs your a.scala file
  • additionally, when no inputs were passed, it defaults to the run sub-command in the following scenarios:
    • if a snippet was passed with -e, --execute-script, --execute-scala, --execute-java or --execute-markdown
    • if a main class was passed with the --main-class option alongside an extra --classpath
  • otherwise if no inputs were passed, it defaults to the repl sub-command

Input formats

The Scala CLI commands accept input in a number of ways, most notably:

  • as source files
  • as one or several directories that contain source files
  • as URLs pointing to sources
  • by processing source code via piping or process substitution

Note that all of these input formats can be used alongside each other.

Source files

Scala CLI accepts the following types of source code:

  • .scala files, containing Scala code
  • .sc files, containing Scala scripts (see more in the Scripts guide)
  • .java files, containing Java code
  • .md files, containing Markdown code (experimental, see more in the Markdown guide)
  • .c and .h files, containing C code (only as resources for Scala Native, see more in the Scala Native guide)
  • .jar files, (see more in the Run docs)

The following example shows the simplest input format. First, create a source file:

object Hello {
def main(args: Array[String]): Unit =
println("Hello from Scala")
}

Then run it by passing it to Scala CLI:

scala-cli Hello.scala
Hello from Scala

You can also split your code into multiple files:

object Messages {
def hello = "Hello from Scala"
}
object Hello {
def main(args: Array[String]): Unit =
println(Messages.hello)
}

and the run them with Scala CLI:

scala-cli Hello.scala Messages.scala
Hello from Scala
note

Scala CLI compiles only the provided inputs. For example, if we provide only one of the files above:

scala-cli Hello.scala

compilation will fail. Scala CLI compiles only the files it’s given.

While this is very convenient for projects with just a few files, passing many files this way can be cumbersome and error-prone. In the case of larger projects, passing whole directories can help.

Directories

Scala CLI accepts whole directories as input.

This is convenient when you have many .scala files, and passing them all one-by-one on the command line isn't practical:

object Messages {
def hello = "Hello from Scala"
}
object Hello {
def main(args: Array[String]): Unit =
println(Messages.hello)
}

In this case, you can run all the source code files in my-app by supplying the directory name:

scala-cli my-app
Hello from Scala

In our experience, scala-cli . is the most used command; it compiles and runs all sources in the current directory.

note

Scala CLI process all files within the specified directories and all of its subdirectories.

Scala CLI ignores all subdirectories that start with . like .scala-build or .vscode. Such directories needs to be explicitly provided as inputs.

URLs

warning

Running unverified code from the internet can be very handy for trusted sources, but it can also be really dangerous, since Scala CLI does not provide any sandboxing at this moment.

Make sure that you trust the code that you are about to run.

Scala CLI accepts input via URLs pointing at .scala files. It downloads their content, and runs them:

scala-cli https://gist.github.com/alexarchambault/f972d941bc4a502d70267cfbbc4d6343/raw/2691c01984c9249936a625a42e29a822a357b0f6/Test.scala
Hello from Scala GitHub Gist

GitHub Gist

Scala CLI accepts input via Github Gist’s urls. It downloads the gist zip archive and runs it:

scala-cli https://gist.github.com/alexarchambault/7b4ec20c4033690dd750ffd601e540ec
Hello

More details in the GitHub gists cookbook.

Zip archive

Scala CLI accepts inputs via a zip archive path. It unpacks the archive and runs it:

object Hello extends App {
println("Hello")
}
unzip -l hello.zip
Archive:  hello.zip
Length Date Time Name
--------- ---------- ----- ----
49 12-07-2021 00:06 Hello.scala
--------- -------
49 1 file
scala-cli hello.zip
Hello

Piping

You can also pipe code to Scala CLI for execution:

  • scripts

    echo 'println("Hello")' | scala-cli _.sc
    Hello
  • Scala code

    echo '@main def hello() = println("Hello")' | scala-cli _.scala
    Hello
  • Java code

    echo 'class Hello { public static void main(String args[]) { System.out.println("Hello"); } }' | scala-cli _.java
    Hello
  • Markdown code (experimental)

    echo '# Example Snippet
    ```scala
    println("Hello")
    ```' | scala-cli _.md
    Hello

More details in the Piping guide.

Scala CLI version

Scala CLI can also run another launcher version, which can be helpful to test unreleased Scala CLI functionalities.

warning

Running another Scala CLI version might be slower because it uses JVM-based Scala CLI launcher.

To run another Scala CLI version, specify it with --cli-version before any other argument:

scala-cli --cli-version 0.1.17-62-g21e1cf44-SNAPSHOT version
Scala CLI version: 0.1.17-62-g21e1cf44-SNAPSHOT
Scala version (default): 3.2.1

To use the latest Scala CLI nightly build, pass nightly to --cli-version parameter:

scala-cli --cli-version nightly version
Fetching Scala CLI 0.1.17-62-g21e1cf44-SNAPSHOT
Scala CLI version: 0.1.17-62-g21e1cf44-SNAPSHOT
Scala version (default): 3.2.1

Process substitution

Lastly, Scala CLI also accepts input via shell process substitution:

scala-cli <(echo 'println("Hello")')
Hello

Logging

To turn off logging in the application, pass the -q flag once. This will suppress all logging output except for errors:

object Hello extends App {
println("Hello"
}
scala-cli Hello.scala -q  
[error] ./Hello.scala:6:3: ')' expected, but '}' found
[error] }
[error] ^
Compilation failed

Note that this will also suppress any logging related to tasks such as downloading dependencies, logs about the start of compilation, and so on.

Warning suppression

Some particular warning logs can be suppressed, either for a particular command by passing an option or with a global config. More details can be found in the verbosity guide