Table of Contents

Thirdparty Modules

Contrib Modules

The modules (aka plugins) in this section are developed/maintained outside the mill git tree.

Besides the documentation provided here, we urge you to consult the respective linked plugin documentation pages. The usage examples given here are most probably incomplete and sometimes outdated.

If you develop or maintain a mill plugin, please create a pull request to get your plugin listed here.


AspectJ compiler support for mill.

Project home:


import mill._
import mill.scalalib._
import mill.define._

// Load the plugin from Maven Central via ivy/coursier
import $ivy.`de.tototec::de.tobiasroeser.mill.aspectj:0.1.0`, de.tobiasroeser.mill.aspectj._

object main extends AspectjModule {

  // Select the AspectJ version
  def aspectjVersion = T{ "{aspectjVersion}" }

  // Set AspectJ options, e.g. the language level and annotation processor
  // Run `mill main.ajcHelp` to get a list of supported options
  def ajcOptions = Seq("-8", "-proc:none")



Your module needs to extend de.tobiasroeser.mill.aspectj.AspectjModule which itself extends mill.scalalib.JavaModule.

The module trait de.tobiasroeser.mill.aspectj.AspectjModule has various configuration options (over those from mill.scalalib.JavaModule).

The most essential targets are:

For a complete list of configuration options and more documentation, please refer to the project home page.

Bash Completion

Limited bash completion support.

Project home:


Show transitive dependencies of your build in your browser.

Project home:


import $ivy.`com.github.ajrnz::mill-dgraph:0.2.0`
sh> mill plugin.dgraph.browseDeps(proj)()


Create an .ensime file for your build.

Project home:


import $ivy.`fun.valycorp::mill-ensime:0.0.1`
sh> mill fun.valycorp.mill.GenEnsime/ensimeConfig

Integration Testing Mill Plugins

Integration testing for mill plugins.


We assume, you have a mill plugin named mill-demo

import mill._, mill.scalalib._
object demo extends ScalaModule with PublishModule {
  // ...

Add an new test sub-project, e.g. it.

import $ivy.`de.tototec::de.tobiasroeser.mill.integrationtest:0.1.0`
import de.tobiasroeser.mill.integrationtest._

object it extends MillIntegrationTest {

  def millTestVersion = "{exampleMillVersion}"

  def pluginsUnderTest = Seq(demo)


Your project should now look similar to this:

+-- demo/
|   +-- src/
+-- it/
    +-- src/
        +-- 01-first-test/
        |   +--
        |   +-- src/
        +-- 02-second-test/

As the buildfiles in your test cases typically want to access the locally built plugin(s), the plugins publishes all plugins referenced under pluginsUnderTest to a temporary ivy repository, just before the test is executed. The mill version used in the integration test then used that temporary ivy repository.

Instead of referring to your plugin with import $ivy.'your::plugin:version', you can use the following line instead, which ensures you will use the correct locally build plugins.

import $exec.plugins

Effectively, at execution time, this line gets replaced by the content of, a file which was generated just before the test started to execute.

Configuration and Targets

The mill-integrationtest plugin provides the following targets.

Mandatory configuration

Optional configuration



Create static sites/blogs with JBake.

Plugin home:

JBake home:


import mill._
import $ivy.`de.tototec::de.tobiasroeser.mill.jbake:0.1.0`
import de.tobiasroeser.mill.jbake._

object site extends JBakeModule {

  def jbakeVersion = "2.6.4"


Generate the site:

bash> mill site.jbake

Start a local Web-Server on Port 8820 with the generated site:

bash> mill site.jbakeServe

Mill Wrapper Scripts

Small script to automatically fetch and execute mill build tool.

Project home:

How it works

millw is a small wrapper script around mill and works almost identical to mill. It automatically downloads a mill release into $HOME/.mill/download.

The mill version to be used will be determined by the following steps. The search ends, after the first step that results in a version.

sh $ mill --mill-version 0.3.6 --disable-ticker version 0.3.6

sh $ echo -n "0.3.6" > .mill-version sh $ mill --disable-ticker version 0.3.6

The values of the DEFAULT_MILL_VERSION variable inside the script will be used.

Use cases

As mill executable

Istead of installing mill, you can just place the script into you local $HOME/bin directory and rename it to mill.

If you need a special mill version in a project directory, just place a .mill-version file with the best mill version. Example: setting mill 0.3.6 as best local mill version

sh $ echo -n "0.3.6" > .mill-version

As a wrapper script in your project

To make the start for others easier or to always have the correct mill version in your CI environment, you can just place a copy of the script as millw in your project root directory.

You should change the DEFAULT_MILL_VERSION variable in that script to the correct version you want to use and add the file under version control.


Produce OSGi Bundles with mill.

Project home:


import mill._, mill.scalalib._
import $ivy.`de.tototec::de.tobiasroeser.mill.osgi:0.0.5`
import de.tobiasroeser.mill.osgi._

object project extends ScalaModule with OsgiBundleModule {

  def bundleSymbolicName = "com.example.project"

  def osgiHeaders = T{ super.osgiHeaders().copy(
    `Export-Package`   = Seq("com.example.api"),
    `Bundle-Activator` = Some("com.example.internal.Activator")

  // other settings ...



Mill plugin to publish artifacts into a local Maven repository.

Project home:


Just mix-in the PublishM2Module into your project. PublishM2Module already extends mill's built-in PublishModule.


import mill._, scalalib._, publish._

import $ivy.`de.tototec::de.tobiasroeser.mill.publishM2:0.0.1`
import de.tobiasroeser.mill.publishM2._

object project extends PublishModule with PublishM2Module {
  // ...

Publishing to default local Maven repository

> mill project.publishM2Local
[40/40] project.publishM2Local
Publishing to /home/user/.m2/repository

Publishing to custom local Maven repository

> mill project.publishM2Local /tmp/m2repo
[40/40] project.publishM2Local
Publishing to /tmp/m2repo

About the Author: Haoyi is a software engineer, an early contributor to Scala.js, and the author of many open-source Scala tools such as Mill, the Ammonite REPL and FastParse.

If you've enjoy using Mill, or enjoyed using Haoyi's other open source libraries, please chip in (or get your Company to chip in!) via Patreon so he can continue his open-source work

Contrib Modules