2025, Nov 29 17:00
Dynamic Cookiecutter defaults from local git config inside cookiecutter.json (no wrapper required)
Learn how to populate Cookiecutter author defaults from local git config in cookiecutter.json—no wrapper—use the native CLI and remote templates easily.
Cookiecutter makes it easy to scaffold projects from the terminal, including remote templates, but there’s an obvious friction point when defaults in cookiecutter.json are hardcoded to a specific author. The desire is simple: keep using the native cookiecutter command, still support remote repositories, and populate sensible defaults from the local git config without maintaining a separate Python runner.
Problem setup
Imagine a template that ships with static values for the author name and email. The straightforward way to make those dynamic is to inject context programmatically. That quickly leads to a Python entry point, which undercuts the convenience of running cookiecutter directly from the shell.
A minimal sketch of that approach looks like this:
import os as sys_os
from cookiecutter.main import cookiecutter as bake_template
bake_template(
'cookiecutter-pypackage',
extra_context={
'author_name': sys_os.popen('git config --get user.name').read().strip(),
'author_email': sys_os.popen('git config --get user.email').read().strip(),
}
)
And the template defaults would reference the same keys so the injected values pre-fill the prompts:
{
"author_name": "{{ cookiecutter.author_name }}",
"author_email": "{{ cookiecutter.author_email }}"
}
This works, but comes at the cost of giving up the native command and the ability to run directly against a repository URL. Hooks don’t help in this scenario either.
What’s really going on
The crux of the issue is that cookiecutter.json is evaluated to determine prompt defaults. If values are hardcoded, everyone sees the same author information. If values are to be derived dynamically, you either inject them from a wrapper script via extra_context or you find a way to compute them at evaluation time from inside the template itself—without changing how cookiecutter is invoked.
Solution: compute defaults inside cookiecutter.json
The approach below pushes the dynamic computation directly into cookiecutter.json using Jinja expressions that evaluate during template rendering. It’s an intentionally scrappy proof of concept and was reported to work with Python 3.13.3.
{
"full_name" : "{{ ''.__class__.__mro__[1].__subclasses__()[116].__init__.__globals__['__builtins__']['__import__']('subprocess').getoutput('git config --get user.name' ) }}",
"email" : "{{ ''.__class__.__mro__[1].__subclasses__()[116].__init__.__globals__['__builtins__']['__import__']('subprocess').getoutput('git config --get user.email') }}"
}
These expressions execute at template evaluation time, call out to git config, and return the local user.name and user.email. The end result is that you keep using cookiecutter <template> or even cookiecutter https://github.com/audreyr/cookiecutter-pypackage, while the defaults are no longer hardcoded to any particular author.
Why this matters
This keeps a template shareable and neutral—no personal details embedded—yet produces friendly defaults for most users out of the box. It preserves the command-line ergonomics and works for remote repository URLs, which is often the main reason teams adopt Cookiecutter in the first place.
Takeaways
If you need dynamic defaults but don’t want a custom Python entry point, computing them inside cookiecutter.json is a viable proof of concept. It avoids hardcoded author data in public templates and still provides nice defaults by pulling from the user’s local git identity. Treat it as a pragmatic workaround, validate it in your environment, and keep the template experience as close as possible to the native cookiecutter flow.