Mill Command-Line Flags

When running Mill, keep in mind there are often four things that can take command-line flags or options:

  1. The task you are running, e.g. foo.run --text hello. These are passed directly from the command line

  2. The JVM running the task e.g. foo.run, which may take flags e.g. java -Xss10m -Xmx10G. These are configured using Compilation and Execution Flags

  3. The Mill build tool process, e.g. ./mill --jobs 10. These can be passed directly after the ./mill executable name, or set in your Build Header Config or .mill-opts file as shown in Repo-Level Mill Options

  4. The JVM running the Mill build tool process, which may take flags. e.g. java -Xss10m -Xmx10G. These are passed via JAVA_OPTs, your Build Header Config or via a .mill-jvm-opts file as shown in Mill with custom JVM options

This can get confusing, so when you want to pass some flags to a Mill task, to Mill, or to the JVM (which one?) be clear who you want to pass the flags to so you can ensure they go to the right place.

Mill Flags Listing

To see a cheat sheet of all the command line flags that Mill supports, you can use ./mill --help:

> mill --help
Mill Build Tool, version 1.1.0-SNAPSHOT
Usage: mill [options] task [task-options] [+ task ...]

Task cheat sheet:
  mill resolve _                 # see all top-level tasks and modules
  mill resolve __.compile        # see all `compile` tasks in any module (recursively)

  mill foo.bar.compile           # compile the module `foo.bar`

  mill foo.run --arg 1           # run the main method of the module `foo` and pass in `--arg 1`
  mill -i foo.console            # run the Scala console for the module `foo` (if it is a ScalaModule)

  mill foo.__.test               # run tests in modules nested within `foo` (recursively)
  mill foo.test arg1 arg2        # run tests in the `foo` module passing in test arguments `arg1 arg2`
  mill foo.test + bar.test       # run tests in the `foo` module and `bar` module
  mill '{foo,bar,qux}.test'      # run tests in the `foo` module, `bar` module, and `qux` module

  mill foo.assembly              # generate an executable assembly of the module `foo`
  mill show foo.assembly         # print the output path of the assembly of module `foo`
  mill inspect foo.assembly      # show docs and metadata for the `assembly` task on module `foo`

  mill clean foo.assembly        # delete the output of `foo.assembly` to force re-evaluation
  mill clean                     # delete the output of the entire build to force re-evaluation

  mill path foo.run foo.sources  # print the task chain showing how `foo.run` depends on `foo.sources`
  mill visualize __.compile      # show how the `compile` tasks in each module depend on one another

Options:
  -D --define <k=v>        Define (or overwrite) a system property.
  --allow-positional       Allows command args to be passed positionally without `--arg` by default
  -b --bell                Ring the bell once if the run completes successfully, twice if it fails.
  --color <bool>           Toggle colored output; by default enabled only if the console is
                           interactive and NO_COLOR environment variable is not set
  -d --debug               Show debug output on STDOUT
  --help                   Print this help message and exit.
  --help-advanced          Print a internal or advanced command flags not intended for common usage
  -i --interactive         Run Mill in interactive mode, suitable for opening REPLs and taking user
                           input. Identical to --no-daemon. Must be the first argument.
  --import <str>           Additional ivy dependencies to load into mill, e.g. plugins.
  -j --jobs <str>          The number of parallel threads. It can be an integer e.g. `5` meaning 5
                           threads, an expression e.g. `0.5C` meaning half as many threads as
                           available cores, or `C-2` meaning 2 threads less than the number of
                           cores. `1` disables parallelism and `0` (the default) uses 1 thread per
                           core.
  --jshell                 Open a JShell REPL with the classpath of the meta-level 1 build module
                           (mill-build/). This is useful for interactively testing and debugging
                           your build logic. Implies options `--meta-level 1` and `--no-server`.
  -k --keep-going          Continue build, even after build failures.
  --meta-level <int>       Select a meta-level to run the given tasks. Level 0 is the main project
                           in `build.mill`, level 1 the first meta-build in `mill-build/build.mill`,
                           etc.
  --no-daemon              Run without a long-lived background daemon. Must be the first argument.
  --no-filesystem-checker  Globally disables the checks that prevent you from reading and writing to
                           disallowed files or folders during evaluation. Useful as an escape hatch
                           in case you desperately need to do something unusual and you are willing
                           to take the risk
  --notify-watch <bool>    Use filesystem based file watching instead of polling based one (defaults
                           to true).
  --offline                Try to work offline. This tells modules that support it to work offline
                           and avoid any access to the internet. This is on a best effort basis.
                           There are currently no guarantees that modules don't attempt to fetch
                           remote sources.
  --repl                   Open a Scala REPL with the classpath of the meta-level 1 build module
                           (mill-build/). Implies options `--meta-level 1` and `--no-server`.
  --tab-complete           Runs Mill in tab-completion mode
  --ticker <bool>          Enable or disable the ticker log, which provides information on running
                           tasks and where each log line came from
  -v --version             Show mill version information and exit.
  -w --watch               Watch and re-run the given tasks when when their inputs change.
  task <str>...            The name or a query of the tasks(s) you want to build.

Please see the documentation at https://mill-build.org for more details,
or `./mill --help-advanced` for a list of advanced flags

Notable Flags

This section covers some of the flags that are worth discussing in more detail

--interactive/-i/--no-server

This flag is necessary to run any interactive terminal programs using Mill: things like ScalaModule#console, ScalaModule#repl, and so on.

By default, Mill runs tasks in a long-lived background daemon. While this is good for performance (as it avoids paying the server startup time each command), it is incompatible with tasks like .repl which require a direct stdin/stdout forwarding connection to the user’s terminal. --interactive/-i instead runs tasks in a short-lived background server with proper port pipe forwarding configured, which enables tasks like .repl to run while paying what higher startup overhead.

--watch/-w

You can use the --watch flag to make Mill watch a task’s inputs, re-evaluating the task as necessary when the inputs change:

> mill --watch foo.compile
> mill --watch foo.run
> mill -w foo.compile
> mill -w foo.run

Mill’s --watch flag watches both the files you are building using Mill, as well as Mill’s own build.mill file and anything it imports, so any changes to your build.mill will automatically get picked up.

For long-running processes like web servers, you can use runBackground to make sure they recompile and restart when code changes, forcefully terminating the previous process even though it may be still alive:

> mill -w foo.runBackground

Note that even if you interrupt mill watch via CTRL+C, the server spawned by runBackground still runs in the background. To actually stop the background server use:

> mill clean foo.runBackground

--jobs/-j

Configures how much Parallelism Mill should run with. Defaults to the number of cores available on your system.

Example: Use up to 4 parallel threads to compile all modules:

> mill -j4 __.compile

You can also set Mill’s parallelism to some multiple of the number of cores, e.g. -j0.5C to use half as many threads as cores, or -j2C to use twice as many threads as cores. These can be useful as cli/build-header.adoc#_mill_opts to configure an appropriate level of parallelism that scales based on the number of cores available (which might differ between e.g. developer laptops and CI machines)