Scallop: a command line parser for Scala that handles trailing arguments
a simple Scala CLI parsing library
At a glance
- What is it?
- Scallop parses command line arguments for Scala with a configuration-object style API, supporting short and long options, property arguments, subcommands and a backtracking parser that can find boundaries in trailing argument lists. It is cross-built for Scala 3.7 through 2.10, Scala Native and Scala.js.
- Who is it for?
- Scallop fits a Scala team writing a command line tool that needs typed options, nested subcommands and a parser that can work out where one trailing argument list ends and the next begins, without pulling in a general-purpose framework. It does not fit a team that wants a runtime configuration system rather than a parser, since the author's own posts cover both and Scallop is the parsing half.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 18 days ago.
- What is it written in?
- Mainly Scala, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Configuration objects instead of a parse function
Scallop is described as a simple command-line arguments parsing library for Scala, and the shape of its API is the interesting part. Rather than calling a parse function and reading values out of a map, you subclass ScallopConf and declare each option as a val, so the options are typed, the defaults live next to the definitions, and the compiler enforces the types. The example in the README is the whole idea in fifteen lines. A Conf class extends ScallopConf, taking the argument sequence, and declares an Int option marked required, another Int option, and a trailing argument of String, then calls verify(). The object Main constructs the Conf and prints the value. The declared types are the result types, so a required Int option cannot be read as a String, and the required flag is checked when verify runs. The audience is Scala developers writing a CLI who want type safety without hand-rolling a parser, and the design leans on the language's type system rather than on a DSL.
Adding the dependency, and the %%% difference for Native and JS
Installation is a single line in build.sbt:
libraryDependencies += "org.rogach" %% "scallop" % "6.0.1"The organisation is org.rogach and the artefact is scallop. For Scala Native and Scala.js the operator changes, because those platforms use a triple-percent form that encodes the platform suffix:
libraryDependencies += "org.rogach" %%% "scallop" % "6.0.1"The README notes that if you were using the 5.x version or older, you should see the migration notes, which is worth doing before upgrading because the version 6 line is a coordinated release across the whole cross-build matrix. The cross-build list is unusually wide: Scala 3.7 and later, then 2.13, 2.12, 2.11 and 2.10, with support for Scala Native and Scala.js. The repository layout reflects the same split, with jvm, js, native and src directories at the top level, so the platform-specific parts of the library are separated rather than hidden behind conditionals.
The option vocabulary: short, long, numeric and property forms
The supported option forms are listed in the README and they are the surface most users touch. Flags, single-value and multiple-value options are all supported. Short option names follow the POSIX style, and they can be grouped, so -abc means three flags at once. Long option names follow the GNU style, accepting both --opt and --opt=value. There are unnamed integer options, in the manner of GNU tail, where -42 is a value rather than a flag. Property arguments are supported in the -Dkey=value form and also in the separated -D key1=value key2=value form. Values are not limited to strings, since converters for other types are extendable, which is what lets an option be declared as opt[Int] and be typed that way all the way through. The example parses argument lines like --apples 4 --bananas 10 strangeTree and the short form -a 4 appleTree, with the trailing argument collected separately from the options.
Backtracking to find where one argument list ends
The feature that separates Scallop from simpler parsers is its matching on trailing arguments, and the README calls it powerful matching on trailing args. The example builds a configuration whose argument list mixes property arguments and several positional groups, with firstListName followed by a list of Ints, then secondListName followed by a list of Doubles, and the parser is expected to work out the boundaries on its own. The README states plainly that Scallop's backtracking parser is clever enough to distinguish the boundaries of the argument lists. The consequence for a user is that you do not have to declare counts in advance, which is what makes it usable for a command like a compiler driver or a diff tool where the tail of the command line is variable-length and heterogeneous. The trade-off is that the work happens at parse time, so a pathological input costs more than a linear scan, and the library gives you no way to see the backtracking decisions it made.
Subcommands, and subcommands inside subcommands
Scallop supports parsing of subcommands, and the README highlights that not only subcommands but nested subcommands are supported. The example nests four levels, with sub1 containing sub2 containing sub3 containing sub4, each declared as an object extending Subcommand with a name, and each registered on its parent with addSubcommand. The trailing argument lives in the innermost object, and after verification the path of taken subcommands is available as a list, so you can walk Conf.sub1.sub2.sub3.sub4 to reach the options, and the assertion in the example checks that the list of subcommands equals the path that was declared. This is a tree-shaped configuration rather than a flat one, which is what makes a git-style or docker-style command with subcommand-specific flags expressible without a hand-rolled dispatch mechanism.
Documentation lives in the wiki, the API docs and the test suite
The README is deliberately a summary and it points elsewhere for the details. The project wiki holds the usage information, and there are API docs published for the org.rogach.scallop package. The README also says that for more examples you can look at the wiki and the test suite, and points at the jvm test directory, which is a useful and slightly unusual recommendation, since the tests are the only worked examples of the more complex cases. The author has also written two blog posts that give the reasoning behind the design, one on better command line option parsing in Scala and one on configuration objects in Scallop specifically. The repository carries a CHANGELOG.md and a release-checklist.txt at the top level, and the licence is MIT, with the notice in license.txt pointing at the MIT terms.
Version 6 released in late 2025, with the branch still on develop
The release history shows a project that has settled on a yearly major version rather than a fast cadence. v5.3.0 came on 2025-11-14, v6.0.0 on 2025-11-30, and v6.0.1 on 2026-10-05, with the last push to the repository on the same day as the 6.0.1 tag. The default branch is develop, not master, so the branch you clone is the integration branch rather than a release branch, and the tags are the stable points. That combination, a small library with a wide cross-build matrix and infrequent major releases, means the upgrade cost is concentrated in the 5.x to 6.x boundary and the migration notes rather than spread across many small changes. The stated compatibility range, down to Scala 2.10, is what makes the library usable in older codebases, and it also constrains the language features the implementation can use, which is a reasonable trade for a parsing library that many projects depend on indirectly.
Editorial conclusion
Scallop fits a Scala team writing a command line tool that needs typed options, nested subcommands and a parser that can work out where one trailing argument list ends and the next begins, without pulling in a general-purpose framework. It does not fit a team that wants a runtime configuration system rather than a parser, since the author's own posts cover both and Scallop is the parsing half. Before adopting it, check the Scala versions your project needs against the cross-build list, which runs from Scala 3.7 down to 2.10, and read the migration notes if you are moving from the 5.x line, since the coordinate and API both changed with version 6.
Frequently asked questions
How do I add Scallop to a Scala project?
Add libraryDependencies += "org.rogach" %% "scallop" % "6.0.1" to your build.sbt. For Scala Native and Scala.js use the %%% operator instead of %%, because those platforms need a different artifact suffix.
What kinds of command line arguments does Scallop support?
Flags, single-value and multiple-value options, POSIX-style short names with grouping, GNU-style long names in both --opt and --opt=value forms, unnamed integer options like GNU tail, property arguments in -Dkey=value and -D key1=value form, and non-string value types through extendable converters.
Does Scallop support nested subcommands?
Yes. The README shows four levels of subcommand objects extending Subcommand, each registered on its parent with addSubcommand, with the taken path available afterwards as a list that you can walk to reach the options of the innermost command.
Which Scala versions does Scallop build for?
The README states it is cross-built for Scala 3.7 and later, 2.13, 2.12, 2.11 and 2.10, and supports Scala Native and Scala.js. Users on the 5.x line or older are pointed to the migration notes before moving to version 6.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/scallop-scallop)Was this useful?