doit logo

Table Of Contents


Your logo here


Gratipay weekly funding goal is $?.?? USD.

Why Donate? Help keep the project alive! Donations will be used for project maintanance tasks (bug fixes, merge patches, reply users).

For corporate donations the logo of your company will be placed on this website side-bar (see above). For more information please contact

Hire me

Looking for a python developer with a proven record of designing and developing robust and well tested applications? The creator and maintainer of doit is available for hire. Full-time, part-time or one-off job.

Other Commands


Not all options/arguments are documented below. Always check doit help <cmd> to see a complete list of options.

Let’s use a more complex example to demonstrate the command line features. The example below is used to manage a very simple C project.

DOIT_CONFIG = {'default_tasks': ['link']}

# map source file to dependencies
    'main': ["defs.h"],
    'kbd': ["defs.h", "command.h"],
    'command': ["defs.h", "command.h"],

def task_link():
    "create binary program"
    OBJECTS = ["%s.o" % module for module in SOURCE.iterkeys()]
    return {'actions': ['cc -o %(targets)s %(dependencies)s'],
            'file_dep': OBJECTS,
            'targets': ['edit'],
            'clean': True

def task_compile():
    "compile C files"
    for module, dep in SOURCE.iteritems():
        dependencies = dep + ['%s.c' % module]
        yield {'name': module,
               'actions': ["cc -c %s.c" % module],
               'targets': ["%s.o" % module],
               'file_dep': dependencies,
               'clean': True

def task_install():
    return {'actions': ['echo install comes here...'],
            'task_dep': ['link'],
            'doc': 'install executable (TODO)'


doit comes with several commands. doit help will list all available commands.

You can also get help from each available command. e.g. doit help run.

doit help task will display information on all fields/attributes a task dictionary from a dodo file accepts.


list is used to show all tasks available in a dodo file.

$ doit list
link : create binary program
compile : compile C files
install : install executable (TODO)

By default task name and description are listed. The task description is taken from the first line of task function doc-string. You can also set it using the doc attribute on the task dictionary. It is possible to omit the description using the option -q/–quiet.

By default sub-tasks are not listed. It can list sub-tasks using the option –all.

By default task names that start with an underscore(_) are not listed. They are listed if the option -p/–private is used.

Task status can be printed using the option -s/–status.

Task’s file-dependencies can be printed using the option –deps.


You can check a task meta-data using the info command. This might be useful when have some complex code generating the task meta-data.

$ doit info link

file_dep:set(['command.o', 'kbd.o', 'main.o'])



Suppose you change the compilation parameters in the compile action. Or you changed the code from a python-action. doit will think your task is up-to-date based on the dependencies but actually it is not! In this case you can use the forget command to make sure the given task will be executed again even with no changes in the dependencies.

If you do not specify any task, the default tasks are “forget”.

$ doit forget


doit keeps track of which tasks are successful in the file .doit.db.


A common scenario is a task that needs to “revert” its actions. A task may include a clean attribute. This attribute can be True to remove all of its target files. If there is a folder as a target it will be removed if the folder is empty, otherwise it will display a warning message.

The clean attribute can be a list of actions, again, an action could be a string with a shell command or a tuple with a python callable.

If you want to clean the targets and add some custom clean actions, you can include the doit.task.clean_targets instead of passing True:

from doit.task import clean_targets

def simple():
    print "ok"

def task_poo():
    return {
        'actions': ['touch poo'],
        'targets': ['poo'],
        'clean': [clean_targets, simple],

You can specify which task to clean. If no task is specified the clean operation of default tasks are executed.

$ doit clean

By default if a task contains task-dependencies those are not automatically cleaned too. You can enable this using the option -c/–clean-dep. If you are executing the default tasks this flag is automatically set.


By default only the default tasks’ clean are executed, not from all tasks. You can clean all tasks using the -a/–all argument.

If you want check which tasks the clean operation would affect you can use the option -n/–dry-run.


It is possible to set a task to be ignored/skipped (that is, not executed). This is useful, for example, when you are performing checks in several files and you want to skip the check in some of them temporarily.

def task_create_file():
    for i in range(3):
        filename = "file%d.txt" % i
        yield {'name': filename,
               'actions': ["touch %s" % filename]}
$ doit
.  create_file:file0.txt
.  create_file:file1.txt
.  create_file:file2.txt
$ doit ignore create_file:file1.txt
ignoring create_file:file1.txt
$ doit
.  create_file:file0.txt
!! create_file:file1.txt
.  create_file:file2.txt

Note the !!, it means that task was ignored. To reverse the ignore use forget sub-command.

auto (watch)


Supported on Linux and Mac only.

auto sub-command is an alternative way of executing your tasks. It is a long running process that only terminates when it is interrupted (Ctrl-C). When started it will execute the given tasks. After that it will watch the file system for modifications in the file-dependencies. When a file is modified the tasks are re-executed.

$ doit auto


The dodo file is actually re-loaded/executed in a separate process every time tasks need to be re-executed.

watch parameter

Apart from file_dep you can use the parameter watch to pass extra paths to be watched for (including folders). The watch parameter can also be specified for a group of “sub-tasks”.

import glob

def task_xxx():
    """my doc"""
    LIST = glob.glob('*.xyz') # might be empty
    yield {
        'basename': 'do_x',
        'name': None,
        'doc': 'docs for X',
        'watch': ['.'],
    for item in LIST:
        yield {
            'basename': 'do_x',
            'name': item,
            'actions': ['echo %s' % item]


This command creates a completion for bash or zsh. The generated script is written on stdout.


To use a completion script you need to source it first.

$ doit tabcompletion > bash_completion_doit
$ source bash_completion_doit


zsh completion scripts should be placed in a folder in the “autoload” path.

# add folder with completion scripts
fpath=(~/.zsh/completion $fpath)

# Use modern completion system
autoload -Uz compinit
$ doit tabcompletion --shell zsh > _doit
$ cp _doit ~/.zsh/tabcompletion/_doit

hard-coding tasks

If you are creating an application based on doit or if you tasks take a long time to load you may create a completion script that includes the list of tasks from your

$ my_app tabcompletion --hardcode-tasks > _my_app


doit saves internal data in a file (.doit.db by default). It uses a binary format (whatever python’s dbm is using in your system). This command will simply dump its content in readable text format in the output.

$ doit dumpdb


This command uses strace utility to help you verify which files are being used by a given task.

The output is a list of files prefixed with R for open in read mode or W for open in write mode. The files are listed in chronological order.

This is a debugging feature with many limitations.
  • can strace only one task at a time
  • can only strace CmdAction
  • the process being traced itself might have some kind of cache, that means it might not write a target file if it exist
  • does not handle chdir

So this is NOT 100% reliable, use with care!

$ doit strace <task-name>