Skip to main content


Instead of passing paths to your sources, you can also pass the code itself with the appropriate option.

scala-cli run --scala-snippet '@main def hello() = println("Hello")'

You can also divide your code into multiple snippets when passing it this way. Each snippet is then treated as a separate input by Scala CLI.

scala-cli run --scala-snippet '@main def main() = println(Messages.hello)' --scala-snippet 'object Messages { def hello = "Hello" }'


  • scripts
scala-cli run -e 'println("Hello")'
  • Scala code
scala-cli run --scala-snippet '@main def hello() = println("Hello")'
  • Java code
scala-cli run --java-snippet 'class Hello { public static void main(String args[]) { System.out.println("Hello"); } }'
  • Markdown code (experimental)
scala-cli run --markdown-snippet '# Markdown snippet
with a code block
  • a mix of Scala, Java and scripts
scala-cli run --scala-snippet '@main def hello() = println(s"${JavaSnippet.hello} ${}")' --java-snippet 'public class JavaSnippet { public static String hello = "Hello"; }' --script-snippet 'def world = "world"'
Hello world

Snippets and other kinds of inputs

It is also possible to mix snippets with on-disk sources.

object Main extends App {
val snippetData = SnippetData()
scala-cli Main.scala --scala-snippet 'case class SnippetData(value: String = "Hello")'

Or even with piped ones, why not.

echo 'println(SnippetData().value)' ||  scala-cli --scala-snippet 'case class SnippetData(value: String = "Hello")'

Nothing stops you from mixing everything all at once, really.

object Main extends App {
val scalaSnippetString = ScalaSnippet().value
val javaSnippetString =
val scriptSnippetString = snippet.script
val pipedInputString = stdin.piped
val ondiskScriptString = ondisk.script
println(s"Output: $scalaSnippetString $javaSnippetString $scriptSnippetString $pipedInputString")
def script = "on-disk-script"
echo 'def piped = "piped-script"'|scala-cli . --scala-snippet 'case class ScalaSnippet(value: String = "scala-snippet")' --java-snippet 'public class JavaSnippet { public static String data = "java-snippet"; }' --script-snippet 'def script = "script-snippet"'
Output: scala-snippet java-snippet script-snippet piped-script

Referring to code from a snippet

When referring to code coming from a script snippet passed with --script-snippet (or -e), you use its wrapper name: snippet

scala-cli run --scala-snippet '@main def main() = println(snippet.hello)' --script-snippet 'def hello: String = "Hello"'

When referring to code coming from multiple script snippets, you use their wrapper names according to the order they were passed (starting from 0 for the first script snippet): snippet${snippetNumber}. The snippetNumber is omitted for the first script snippet (0). In other words, the first passed snippet is just snippet, the second is snippet1, then snippet2 and so on, as in the example:

scala-cli run --scala-snippet '@main def main() = println(s"${snippet.hello} ${}${snippet2.exclamation}")' --script-snippet 'def hello: String = "Hello"' --script-snippet 'def world: String = "world"' --script-snippet 'def exclamation: String = "!"'
Hello world!

This is similar to how you refer to code from piped scripts through their wrapper name (stdin), more on which can be found in the scripts guide.

In fact, you can refer to both kinds of scripts at one time, just keep in mind that you need to pick which script is to actually be run with the --main-class option when multiple scripts are present on the classpath (and no non-script main class was passed).
println(s"${stdin.hello} ${}${snippet1.exclamation}")
echo 'def hello = "Hello"' | scala-cli -e 'def world = "world"' -e 'def exclamation = "!"' --main-class ondisk_sc
Hello world!

When in doubt on what main classes are available on the classpath, you can always refer to the output of --list-main-classes

echo 'def hello = "Hello"' | scala-cli -e 'def world = "world"' -e 'def exclamation = "!"' --list-main-classes
ondisk_sc snippet_sc stdin_sc