7 releases

0.2.0 Sep 20, 2023
0.1.3 Sep 10, 2023
0.1.2 Feb 10, 2023
0.1.1 Jan 28, 2023
0.1.0-alpha.1 Sep 18, 2022

#213 in Development tools


954 lines


A task runner with DAG-based parallelism


  • Use any interpreter (typically, a shell such as sh)
  • Tasks can depend on other tasks (within the same group)
  • Groups can depend on other groups
  • Get an overview of tasks and groups by viewing them as a graph
  • Run a subset of the tasks and groups
    • Run a single group (and its dependencies)
    • Run a single task from that group (and its dependencies)
  • List available groups and tasks
  • Shell completions


A simple Engage file might look like this:

interpreter = ["bash", "-euo", "pipefail", "-c"]

name = "cargo"
group = "versions"
script = "cargo --version"

# There's no side effect that the following tasks depend on caused by the
# previous task, but this is just an example, and you wouldn't do this for real.

name = "cargo fmt"
group = "versions"
script = "cargo fmt --version"
depends = ["cargo"]

name = "cargo clippy"
group = "versions"
script = "cargo clippy --version"
depends = ["cargo"]

This creates a group called "versions"[^1] with three tasks: "cargo fmt" and "cargo clippy", which depend on "cargo". This can be visualized by running engage dot and feeding the output to Graphviz:

Graph of the example Engage file

When it's time to run a task, its script will be appended as a single element to the interpreter list, which will then be executed.

When run with no arguments, Engage will execute the entire DAG, starting by entering the "versions" group, running the "cargo" task's script first, then the other two tasks' scripts in parallel, and finally exiting the group.

This implicit parallelism with explicit ordering when required allows Engage to run your tasks as fast as possible, speeding up your workflows.


  • All task scripts are executed with the working directory set to the location of the Engage file.

  • Operations that require the Engage file can be invoked from the directory it's in or any of that directory's children.

  • Group and task dependencies must form a directed acyclic graph. In other words, dependency cycles are not allowed.

  • If a task fails, any dependent tasks will not be executed and Engage will exit with a status of 1.

  • If some other error occurs (e.g. configuration error), Engage will exit with a status of 2.

  • If no subcommand is supplied, all groups and tasks will be scheduled and executed based on their dependencies.


  • Run engage help to see the available commands and their descriptions.


[^1]: Nouns are preferred for group names to make the single-group invocation syntax grammatically correct.


~142K SLoC