Custom Mix Tasks

Creating custom Mix tasks for your Elixir projects.

Table of Contents


It’s not uncommon to want to extend your Elixir applications functionality by adding custom Mix tasks. Before we learn about how to create specific Mix tasks for our projects, let’s look at one that already exists:

$ mix my_phoenix_app

* creating my_phoenix_app/config/config.exs
* creating my_phoenix_app/config/dev.exs
* creating my_phoenix_app/config/prod.exs
* creating my_phoenix_app/config/prod.secret.exs
* creating my_phoenix_app/config/test.exs
* creating my_phoenix_app/lib/my_phoenix_app.ex
* creating my_phoenix_app/lib/my_phoenix_app/endpoint.ex
* creating my_phoenix_app/test/views/error_view_test.exs

As we can see from the shell command above, The Phoenix Framework has a custom Mix task to generate a new project. What if we could create something similar for our project? Well the great news is we can, and Elixir makes this easy for us to do.


Let’s set up a basic Mix application.

$ mix new hello

* creating
* creating .gitignore
* creating mix.exs
* creating config
* creating config/config.exs
* creating lib
* creating lib/hello.ex
* creating test
* creating test/test_helper.exs
* creating test/hello_test.exs

Your Mix project was created successfully.
You can use "mix" to compile it, test it, and more:

cd hello
mix test

Run "mix help" for more commands.

Now, in our lib/hello.ex file that Mix generated for us, let’s create a simple function that will output “Hello, World!”

defmodule Hello do
  @doc """
  Outputs `Hello, World!` every time.
  def say do
    IO.puts("Hello, World!")

Custom Mix Task

Let’s create our custom Mix task. Create a new directory and file hello/lib/mix/tasks/hello.ex. Within this file, let’s insert these 7 lines of Elixir.

defmodule Mix.Tasks.Hello do
  use Mix.Task

  @shortdoc "Simply calls the Hello.say/0 function."
  def run(_) do
    # calling our Hello.say() function from earlier

Notice how we start the defmodule statement with Mix.Tasks and the name we want to call from the command line. On the second line we introduce the use Mix.Task which brings the Mix.Task behaviour into the namespace. We then declare a run function which ignores any arguments for now. Within this function, we call our Hello module and the say function.

Mix Tasks in Action

Let’s checkout our mix task. As long as we are in the directory it should work. From the command line, run mix hello, and we should see the following:

$ mix hello
Hello, World!

Mix is quite friendly by default. It knows that everyone can make a spelling error now and then, so it uses a technique called fuzzy string matching to make recommendations:

$ mix hell
** (Mix) The task "hell" could not be found. Did you mean "hello"?

Did you also notice that we introduced an new module attribute, @shortdoc? This comes in handy when shipping our application, such as when a user runs the mix help command from the terminal.

$ mix help

mix app.start         # Starts all registered apps
mix hello             # Simply calls the Hello.say/0 function.

Note: Our code must be compiled before new tasks will appear in the mix help output. We can do this either by running mix compile directly or by running our task like we did with mix hello, which will trigger the compilation for us.

Caught a mistake or want to contribute to the lesson? Edit this page on GitHub!