pip install cookiecutter
pipx install cookiecutter # recommended
# From URL
cookiecutter https://github.com/user/cookiecutter-template.git
# From local path
cookiecutter ./my-template
# Non-interactive
cookiecutter --no-input ./my-template project_name=foo
# Specify branch/tag
cookiecutter https://github.com/user/template.git --checkout v1.0
# Output directory
cookiecutter ./my-template --output-dir /tmp/projects
# Overwrite if exists
cookiecutter ./my-template --overwrite-if-exists
# Skip if exists
cookiecutter ./my-template --skip-if-file-exists
# Subdirectory within repo
cookiecutter https://github.com/user/repo.git --directory templates/python
# Keep project if hook fails
cookiecutter ./my-template --keep-project-on-failure
{
"project_name": "My Project",
"project_slug": "{{ cookiecutter.project_name|lower|replace(' ', '_') }}",
"version": "0.1.0",
"license": ["MIT", "Apache-2.0", "proprietary"],
"use_docker": ["no", "yes"]
}
| Type | Behavior |
|---|
| String | Free text prompt, default value |
| Array | Selection prompt (choices) |
Jinja2 {{ }} | Derived variable, not prompted |
{{ cookiecutter.project_name }} # variable
{{ cookiecutter.project_name|lower }} # filter
{{ cookiecutter.project_name|replace(' ', '_') }} # replace
{{ cookiecutter.project_name|lower|replace(' ', '_') }} # chained
{{ cookiecutter.use_docker|tojson }} # to JSON
{% if cookiecutter.use_docker == "yes" %}...{% endif %} # conditional
{% if %}...{% elif %}...{% else %}...{% endif %} # if/elif/else
{% for item in cookiecutter.items.split(',') %}...{% endfor %} # loop
{%- if %}...{%- endif -%} # whitespace control
{{ "{{ not_jinja }}" }} # literal escape
hooks/
├── pre_gen_project.py # before generating (validate)
└── post_gen_project.py # after generating (clean, git init)
# pre_gen_project.py
import sys
if '{{ cookiecutter.project_name }}' == '':
print('ERROR: project_name is empty')
sys.exit(1)
# post_gen_project.py
import os
if '{{ cookiecutter.use_docker }}' == 'no':
os.remove('Dockerfile')
_copy_without_render # list of paths without Jinja2
_extensions/ # custom Jinja2 filters
# ~/.cookiecutterrc
default_context:
author_name: "Jane Doe"
license: "MIT"
| Filter | Example | Result |
|---|
lower | "My Project"|lower | my project |
upper | "my"|upper | MY |
title | "my project"|title | My Project |
replace | "My Project"|replace(' ', '_') | My_Project |
trim | " foo "|trim | foo |
length | "abc"|length | 3 |
tojson | "yes"|tojson | "yes" |
| Variable | Convention | Example |
|---|
project_name | Human readable | My Awesome Project |
project_slug | snake_case | my_awesome_project |
pkg_name | no separators | myawesomeproject |
repo_name | kebab-case | my-awesome-project |
class_name | PascalCase | MyAwesomeProject |