Define tasks in Python.
Run only what changed.
A task management & automation tool like make,
but in pure Python.
Tracks file dependencies, caches results, and skips tasks that are already up-to-date.
Often compared to make, just, invoke, and snakemake — but with DAG execution and incremental builds built in.
Quick Example¶
Create a dodo.py — tasks are plain Python dicts.
def task_hello():
"""create a greeting file"""
return {
'actions': ['echo "Hello from doit" > hello.txt'],
'targets': ['hello.txt'],
'clean': True,
}
def task_shout():
"""convert greeting to uppercase"""
return {
'actions': ['tr a-z A-Z < hello.txt > shout.txt'],
'file_dep': ['hello.txt'],
'targets': ['shout.txt'],
'clean': True,
}
$ pip install doit
$ doit
. hello
. shout
$ doit # nothing to do — already up-to-date
-- hello
-- shout
$ doit clean # remove generated files
$ doit # runs again
. hello
. shout
Python-Native Task Runner¶
No DSL, no YAML — tasks are plain Python dicts and functions.
- Pure Python
- Tasks are Python dicts. Use any library, generate tasks programmatically, debug with pdb.
- Shell or Python actions
- Run shell commands, call Python functions, or mix both in a single task.
- Self-documenting
doit listshows all tasks with docstrings.doit help <task>for details.
Incremental Builds & Pipelines¶
DAG execution with dependency tracking — run only what changed.
- Incremental builds
- Tracks file dependencies and targets (MD5 or timestamp). Skips tasks that are already up-to-date.
- Flexible up-to-date checks
- Not limited to file timestamps. Computed dependencies (
calc_dep), custom checkers, and result-based checks. - Pipelines
- Pass results between tasks without intermediate files. Dynamic task creation via
yieldfor complex workflows.
Advanced Features¶
- Extensible
- Plugin architecture — custom commands, storage backends, task loaders, and output reporters. Framework API — build your own tools on top of doit.
- Batteries included
- Parallel execution (threaded or multi-process) · Shell tab-completion (bash and zsh) · DAG visualisation (graphviz).
What people are saying
Congratulations! Your tool follows the KISS principle very closely. I always wondered why build tools had to be that complicated.
Let me start by saying I’m really lovin doit, at first the interface seemed verbose but quickly changed my mind when I started using it and realized the flexibility.
I love all the traditional unix power tools, like cron, make, perl… I also like new comprehensive configuration management tools like CFEngine and Puppet. But I find doit to be so versatile and so productive.
I needed a sort of make tool to glue things together and after trying out all kinds, doit … has actually turned out to be beautiful. Its easy to add and manage tasks, even complex ones.
I went back and forth on different Pythonic build tools for awhile… I’ve been using doit more and more, and I’m continually impressed. It works amazingly well for automating tricky/exotic build processes.
I grew frustrated with Make and Ant and started porting my build files to every build tool I found. Each time I ran into stumbling blocks. Then I discovered this little gem of simplicity: doit.
doit is a mature project actively maintained since
2008.
Python 3.10+. 99% unit-test code coverage.
Contributions welcome — development is driven by real-world use cases.
MIT License · PyPI · GitHub · Support · Documentation