Learn the Basics of Cookiecutter by Creating a Cookiecutter

The easiest way to understand what Cookiecutter does is to create a simple one and see how it works.

Cookiecutter takes a source directory tree and copies it into your new project. It replaces all the names that it finds surrounded by templating tags {{ and }} with names that it finds in the file cookiecutter.json. That’s basically it. [1]

The replaced names can be file names, directory names, and strings inside files.

With Cookiecutter, you can easily bootstrap a new project from a standard form, which means you skip all the usual mistakes when starting a new project.

Before you can do anything in this example, you must have Python installed on your machine. Go to the Python Website and follow the instructions there. This includes the pip installer tool. Now run:

$ pip install cookiecutter

Your First Cookiecutter

To get started, create a directory somewhere on your computer. The name of this directory will be the name of your Cookiecutter template, but it doesn’t constrain anything else—the generated project doesn’t need to use the template name, for example. Our project will be called HelloCookieCutter1:

$ mkdir HelloCookieCutter1
$ cd HelloCookieCutter1

Inside this directory, we create the directory tree to be copied into the generated project. We want to generate a name for this directory, so we put the directory name in templating tags:

$ mkdir {{cookiecutter.directory_name}}
$ cd {{cookiecutter.directory_name}}

Anything inside templating tags can be placed inside a namespace. Here, by putting directory_name inside the cookiecutter namespace, cookiecutter.directory_name will be looked up from the cookiecutter.json file as the project is generated by Cookiecutter.

Now we are inside the directory tree that will be copied. For the simplest possible Cookiecutter template, we’ll just include a single file. Again, we want the file name to be looked up from cookiecutter.json, so we name it appropriately:

$ touch {{cookiecutter.file_name}}.py

(touch creates an empty file; you can just open it up in your editor). Now edit the file so it contains:

print("Hello, {{cookiecutter.greeting_recipient}}!")

To finish, we create the cookiecutter.json file itself, so that Cookiecutter can look up all our templated items. This file goes in our HelloCookieCutter1 directory, and contains all the names we’ve used:

    "directory_name": "Hello",
    "file_name": "Howdy",
    "greeting_recipient": "Julie"

Now we can actually run Cookiecutter and create a new project from our template. Move to a directory where you want to create the new project. Then run Cookiecutter and hand it the directory where the template lives. On my (Windows, so the slashes go back instead of forward) machine, this happens to be under the Git directory:

$ cookiecutter C:\Users\bruce\Documents\Git\HelloCookieCutter1
directory_name [Hello]:
file_name [Howdy]:
greeting_recipient [Julie]:

Cookiecutter tells us what the default name for each item is, and gives us the option of replacing that name with something new. In this case, I just pressed Return for each one, to accept all the defaults.

Now we have a generated directory called Hello, containing a file Howdy.py. When we run it:

$ python Howdy.py
Hello, Julie!

Voila! Instant generated project!

Note: The project we’ve created here happens to be Python, but Cookiecutter is just replacing templated items with names it looks up in cookiecutter.json, so you can produce projects of any kind, including projects that aren’t programs.

This is nice, but what if you want to share your Cookiecutter template with everyone on the Internet? The easiest way is to upload it to a version control repository. As you might have guessed by the Git subdirectory, this example is on GitHub. Conveniently, Cookiecutter can build a project directly from an internet repository, like the one for this very example. For variety, this time we’ll replace the values from cookiecutter.json with our own:

$ cookiecutter https://github.com/BruceEckel/HelloCookieCutter1
Cloning into 'HelloCookieCutter1'...
remote: Counting objects: 37, done.
Unpacking objects:  21% (8/37)
remote: Total 37 (delta 19), reused 21 (delta 3), pack-reused 0
Unpacking objects: 100% (37/37), done.
Checking connectivity... done.
directory_name [Hello]: Fabulous
file_name [Howdy]: Zing
greeting_recipient [Julie]: Roscoe

$ cd Fabulous

$ python Zing.py
Hello, Roscoe!

Same effect, but this time produced from the Internet! You’ll notice that even though it says Cloning into 'HelloCookieCutter1'..., you don’t see any directory called HelloCookieCutter1 in your local directory. Cookiecutter has its own storage area for cookiecutters, which is in your home directory in a subdirectory called .cookiecutters (the leading . hides the directory on most operating systems). You don’t need to do anything with this directory but it can sometimes be useful to know where it is.

Now if you ever find yourself duplicating effort when starting new projects, you’ll know how to eliminate that duplication using cookiecutter. But even better, lots of people have created and published cookiecutters, so when you are starting a new project, make sure you look at the list of pre-defined cookiecutters first!

[1]You can also run hooks before and/or after generation, but that’s more complex than what we want to cover here.