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 theversion
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 youra.scala
file
- and so,
- 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
- if a snippet was passed with
- 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
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.
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
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 _.mdHello
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.
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