22 KiB
title, library_name, pypi_package, category, python_compatibility, last_updated, official_docs, official_repository, maintenance_status
| title | library_name | pypi_package | category | python_compatibility | last_updated | official_docs | official_repository | maintenance_status |
|---|---|---|---|---|---|---|---|---|
| Copier: Project Template Renderer with Update Capabilities | copier | copier | project_templating | 3.9+ | 2025-11-02 | https://copier.readthedocs.io | https://github.com/copier-org/copier | active |
Copier: Project Template Renderer with Update Capabilities
Executive Summary
What problem does it solve? Copier solves the problem of project scaffolding AND ongoing template synchronization. Unlike most templating tools that are one-way generators, Copier enables code lifecycle management - you can update existing projects when the template evolves, not just generate new projects.
Core value proposition:
- Generate projects from templates (scaffolding)
- Update projects when templates change (unique feature)
- Version-aware migrations during updates
- Works with local paths and Git URLs
- Preserves customizations during updates
When you'd be "reinventing the wheel" without it:
- Maintaining multiple similar projects that need to stay in sync with best practices
- Rolling out security updates or dependency changes across many projects
- Applying organizational standards to existing codebases
- Managing project boilerplate that evolves over time
Official Information
- Repository: @https://github.com/copier-org/copier
- PyPI Package:
copier(current: v9.10.3) - Documentation: @https://copier.readthedocs.io/
- License: MIT
- Maintenance: Active development, 2,880+ stars
- Original Author: jpsca (Juan-Pablo Scaletti)
- Current Maintainers: yajo, pawamoy, sisp, and community
Installation
# As CLI tool (recommended)
pipx install copier
# or with uv
uv tool install copier
# As library
pip install copier
# With conda
conda install -c conda-forge copier
# Nix (100% reproducible)
nix profile install 'https://flakehub.com/f/copier-org/copier/*.tar.gz'
# Homebrew (macOS/Linux)
brew install copier
Requirements:
- Python 3.9 or newer
- Git 2.27 or newer (for template versioning and updates)
Python Version Compatibility
| Python Version | Support Status | Notes |
|---|---|---|
| 3.9 - 3.12 | ✅ Full support | Production ready |
| 3.13 | ✅ Supported | v9.10.2+ built with Python 3.13.7 |
| 3.14 | ⚠️ Likely compatible | Not explicitly tested, but backward-compatible |
| < 3.9 | ❌ Not supported | Use older Copier versions |
Source: @https://github.com/copier-org/copier/blob/master/pyproject.toml (classifiers section)
Core Purpose: When to Use Copier
Primary Use Cases
-
Project Scaffolding with Future Updates
- Generate new projects from templates
- Apply template updates to existing projects
- Track which template version each project uses
-
Multi-Project Standardization
- Maintain consistency across microservices
- Roll out organization-wide best practices
- Synchronize CI/CD configurations
-
Living Templates
- Templates that evolve with ecosystem changes
- Security patches propagated to all projects
- Dependency updates across project families
-
Template Versioning
- Use Git tags to version templates
- Selective updates to specific versions
- Smart diff between template versions
Copier vs Cookiecutter vs Yeoman
Use Copier when:
- ✅ You need to update projects after generation
- ✅ You manage multiple similar projects
- ✅ Your template evolves frequently
- ✅ You want migration scripts during updates
- ✅ You prefer YAML over JSON configuration
Use Cookiecutter when:
- ✅ You only need one-time generation
- ✅ You want the largest template ecosystem
- ✅ You need maximum stability (mature project)
- ✅ Template updates aren't important
Use Yeoman when:
- ✅ You're in the Node.js ecosystem
- ✅ You want NPM package distribution
- ✅ You need JavaScript-based logic
| Feature | Copier | Cookiecutter | Yeoman |
|---|---|---|---|
| Template Updates | ✅ Yes | ❌ No (requires Cruft) | ❌ No |
| Migrations | ✅ Yes | ❌ No | ❌ No |
| Config Format | YAML | JSON | JavaScript |
| Templating | Jinja2 | Jinja2 | EJS |
| Programming Required | ❌ No | ❌ No | ✅ Yes (JS) |
| Template Suffix | .jinja (configurable) |
None | You choose |
| File Name Templating | ✅ Yes | ✅ Yes | ✅ Yes |
| Ecosystem Size | Medium | Large | Large |
| Maturity | Active | Mature | Mature |
Source: @https://github.com/copier-org/copier/blob/master/docs/comparisons.md
Real-World Examples
1. FastAPI Full-Stack Template
Repository: @https://github.com/fastapi/full-stack-fastapi-template (38,000+ stars)
# Generate a new FastAPI project
pipx run copier copy https://github.com/fastapi/full-stack-fastapi-template my-project --trust
Features demonstrated:
- Multi-service Docker setup
- PostgreSQL integration
- React frontend scaffolding
- Environment variable templating
- Post-generation tasks
Template snippet (@https://github.com/fastapi/full-stack-fastapi-template/blob/main/copier.yml):
project_name:
type: str
help: The name of the project
default: FastAPI Project
secret_key:
type: str
help: |
The secret key for the project, generate with:
python -c "import secrets; print(secrets.token_urlsafe(32))"
default: changethis
_tasks:
- ["{{ _copier_python }}", .copier/update_dotenv.py]
2. Modern Python Package Template (copier-uv)
Repository: @https://github.com/pawamoy/copier-uv (108 stars)
# Create a uv-managed Python package
copier copy gh:pawamoy/copier-uv /path/to/project
Features demonstrated:
- uv package manager integration
- Jinja extensions (custom filters)
- Git integration (auto-detect author)
- License selection (20+ options)
- Multi-file configuration includes
Advanced configuration (@https://github.com/pawamoy/copier-uv/blob/main/copier.yml):
_min_copier_version: "9"
_jinja_extensions:
- copier_template_extensions.TemplateExtensionLoader
- extensions.py:CurrentYearExtension
- extensions.py:GitExtension
- extensions.py:SlugifyExtension
author_fullname:
type: str
help: Your full name
default: "{{ 'Default Name' | git_user_name }}"
repository_name:
type: str
default: "{{ project_name | slugify }}"
3. NLeSC Scientific Python Template
Repository: @https://github.com/NLeSC/python-template (223 stars)
Features demonstrated:
- Modular configuration (YAML includes)
- Profile-based generation
- Research software best practices
- Citation files (CITATION.cff)
Modular structure (@https://github.com/NLeSC/python-template/blob/main/copier.yml):
# Include pattern for maintainability
!include copier/settings.yml !include copier/profiles.yml !include copier/questions/essential.yml !include copier/questions/features_code_quality.yml !include copier/questions/features_documentation.yml
4. JupyterLab Extension Template
Repository: @https://github.com/jupyterlab/extension-template (77 stars)
pip install "copier~=9.2" jinja2-time
copier copy --trust https://github.com/jupyterlab/extension-template .
5. Odoo/Doodba Template
Repository: @https://github.com/Tecnativa/doodba-copier-template (104 stars)
- Complex multi-container applications
- Multiple answer files for different template layers
Integration Patterns
Git Integration
Template versioning with Git tags:
# Copy specific version
copier copy --vcs-ref=v1.2.0 gh:org/template /path/to/project
# Copy latest release (default)
copier copy gh:org/template /path/to/project
# Copy from HEAD (including uncommitted changes)
copier copy --vcs-ref=HEAD ./template /path/to/project
Update to latest template version:
cd /path/to/project
copier update # Reads .copier-answers.yml automatically
Update to specific version:
copier update --vcs-ref=v2.0.0
Template Updates Workflow
The killer feature that distinguishes Copier:
graph TD
A[Template v1.0] --> B[Generate Project]
B --> C[.copier-answers.yml]
A --> D[Template v2.0]
D --> E[copier update]
C --> E
E --> F[Smart 3-way Merge]
F --> G[Updated Project]
F --> H[Migration Scripts]
H --> G
The update process:
- Copier clones template at old version (from
.copier-answers.yml) - Regenerates project with old template
- Compares to current project (detects your changes)
- Clones template at new version
- Generates with new template
- Creates 3-way merge between: old template → your project ← new template
- Runs migration tasks for version transitions
Example migration (from Copier docs):
# copier.yml
_migrations:
- version: v2.0.0
command: rm ./old-folder
when: "{{ _stage == 'before' }}"
- invoke migrate $VERSION_FROM $VERSION_TO
CI/CD Integration
GitHub Actions example:
name: Update from template
on:
schedule:
- cron: "0 0 * * 0" # Weekly
workflow_dispatch:
jobs:
update:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v5
- run: uv tool install copier
- run: copier update --defaults --vcs-ref=HEAD
- run: |
git config user.name "Bot"
git config user.email "bot@example.com"
git checkout -b update-template
git add -A
git commit -m "Update from template"
git push origin update-template
- uses: peter-evans/create-pull-request@v5
Multiple Templates per Project
Apply different templates to different aspects:
# Base framework
copier copy -a .copier-answers.main.yml \
gh:example/framework-template .
# Pre-commit config
copier copy -a .copier-answers.pre-commit.yml \
gh:my-org/pre-commit-template .
# Internal CI
copier copy -a .copier-answers.ci.yml \
git@gitlab.internal.com:templates/ci .
Each gets its own answers file, enabling independent updates:
copier update -a .copier-answers.main.yml
copier update -a .copier-answers.pre-commit.yml
copier update -a .copier-answers.ci.yml
Usage Examples
Basic Template Creation
Minimal template structure:
my_template/
├── copier.yml # Template configuration
├── .git/ # Git repo (for versioning)
├── {{project_name}}/ # Templated folder name
│ └── {{module_name}}.py.jinja # Templated file
└── {{_copier_conf.answers_file}}.jinja # Answers file
copier.yml (question definitions):
project_name:
type: str
help: What is your project name?
module_name:
type: str
help: What is your Python module name?
default: "{{ project_name | lower | replace('-', '_') }}"
python_version:
type: str
help: Minimum Python version
default: "3.9"
choices:
- "3.9"
- "3.10"
- "3.11"
- "3.12"
- "3.13"
Templated Python file ({{project_name}}/{{module_name}}.py.jinja):
"""{{ project_name }} - A Python package."""
__version__ = "0.1.0"
def hello() -> str:
"""Return a greeting."""
return "Hello from {{ module_name }}!"
Answers file template ({{_copier_conf.answers_file}}.jinja):
# Changes here will be overwritten by Copier
{ { _copier_answers | to_nice_yaml - } }
Generating a Project
From local template:
copier copy /path/to/template /path/to/destination
From Git URL:
copier copy https://github.com/org/template /path/to/destination
# or shorthand
copier copy gh:org/template /path/to/destination
copier copy gl:org/template /path/to/destination # GitLab
With pre-answered questions:
copier copy \
--data project_name="My Project" \
--data module_name="my_project" \
gh:org/template /path/to/destination
From data file:
# answers.yml
project_name: My Project
module_name: my_project
python_version: "3.11"
# Use it
copier copy --data-file answers.yml gh:org/template /path/to/destination
Programmatic Usage
from copier import run_copy, run_update
# Generate new project
run_copy(
"https://github.com/org/template.git",
"/path/to/destination",
data={"project_name": "My Project"},
vcs_ref="v1.0.0", # Specific version
)
# Update existing project
run_update(
"/path/to/destination",
vcs_ref="v2.0.0", # Update to v2.0.0
skip_answered=True, # Don't re-ask answered questions
)
Advanced Template Features
Conditional file generation:
# copier.yml
use_docker:
type: bool
help: Include Docker support?
default: true
File/folder structure:
template/
{% if use_docker %}Dockerfile{% endif %}.jinja
{% if use_docker %}docker-compose.yml{% endif %}.jinja
Dynamic choices:
language:
type: str
choices:
- python
- javascript
package_manager:
type: str
help: Which package manager?
choices: |
{%- if language == "python" %}
- pip
- uv
- poetry
{%- else %}
- npm
- yarn
- pnpm
{%- endif %}
File exclusion:
_exclude:
- "*.pyc"
- __pycache__
- .git
- .venv
- "{% if not use_docker %}docker-*{% endif %}"
Post-generation tasks:
_tasks:
- git init
- git add -A
- git commit -m "Initial commit from template"
- ["{{ _copier_python }}", -m pip install -e .]
Jinja2 extensions:
_jinja_extensions:
- copier_templates_extensions.TemplateExtensionLoader
- jinja2_time.TimeExtension
# Install with:
# pipx inject copier copier-templates-extensions jinja2-time
Updating Projects
Update to latest version:
cd /path/to/project
copier update
Update with conflict resolution:
# Inline conflicts (default)
copier update --conflict=inline
# .rej files (like patch)
copier update --conflict=rej
Re-answer questions:
# Re-answer all questions
copier update --vcs-ref=:current:
# Skip previously answered
copier update --skip-answered
Update without interactive prompts:
# Use defaults/existing answers
copier update --defaults
# Override specific values
copier update --data python_version="3.12"
When NOT to Use Copier
Simple File Copying
❌ Don't use Copier for:
# Just copy static files
cp -r template_dir new_project
✅ Use basic tools instead:
cpfor simple directory copyingrsyncfor file synchronization- Git clone for exact repository copies
One-Time Generation Without Updates
If you never plan to update from the template:
- Cookiecutter has larger ecosystem
- Yeoman for Node.js projects
- Manual copying might suffice
Complex Conditional Logic
❌ Not ideal for:
- Heavy business logic in templates
- Complex data transformations
- Runtime configuration (use proper config libraries)
✅ Use instead:
- Python scripts for complex logic
- Dedicated config management (Dynaconf, python-decouple)
- Application frameworks (Django, FastAPI built-in scaffolding)
Single Project Maintenance
If you only maintain one project:
- Template overhead isn't justified
- Direct edits are simpler
- No synchronization benefits
Non-Text Files
Copier focuses on text file templating:
- Binary files copied as-is
- No image/binary manipulation
- No archive extraction
Version Control Conflicts
⚠️ Be cautious when:
- Project has diverged significantly from template
- Many conflicting changes expected
- Team unfamiliar with 3-way merge resolution
Mitigation:
- Test updates in separate branch
- Use
--conflict=rejfor manual review - Document update procedures
Decision Matrix
Use Copier When
| Scenario | Why Copier? |
|---|---|
| Managing 5+ similar microservices | Templates sync security patches across all services |
| Organizational standards evolving | Roll out changes without manual edits to each project |
| Onboarding new projects frequently | Consistent structure + ability to improve template over time |
| Template still experimental | Iterate template, update existing projects with improvements |
| CI/CD pipeline standardization | Update all projects when pipeline requirements change |
| Multi-repo architecture | Maintain consistency without monorepo complexity |
Don't Use Copier When
| Scenario | Why Not? | Alternative |
|---|---|---|
| Single project, no similar projects planned | Overhead > benefit | Direct editing |
| Template is 100% stable forever | Update feature unused | Cookiecutter (larger ecosystem) |
| Heavy runtime configuration needed | Wrong tool for job | Dynaconf, Pydantic Settings |
| Binary file manipulation required | Not designed for this | Pillow, custom scripts |
| Project has deviated >50% from template | Merge conflicts overwhelming | Manual migration |
| No Git repository for template | Can't track versions | Use Git or accept one-shot generation |
Copier vs Cookiecutter Decision Tree
Do you need to update projects after generation?
├─ YES → Use Copier
│ └─ Need version-aware migrations?
│ ├─ YES → Definitely Copier
│ └─ NO → Still Copier (future-proofing)
│
└─ NO → Consider factors:
├─ Prefer YAML config? → Copier
├─ Want larger template ecosystem? → Cookiecutter
├─ Need maximum stability? → Cookiecutter
└─ Might need updates later? → Copier (easier to start with)
Best Practices
Template Design
- Version your templates - Use Git tags (v1.0.0, v2.0.0)
- Keep templates focused - One concern per template
- Provide good defaults - Minimize required answers
- Document migrations - Explain breaking changes
- Test template updates - Generate project, modify, update
Project Maintenance
- Commit
.copier-answers.yml- Essential for updates - Don't edit generated markers - Copier overwrites them
- Test updates in branches - Merge after verification
- Run migrations carefully - Review before executing
- Document deviations - Note why you diverge from template
Organization Adoption
- Start with one template - Prove value before expanding
- Automate update checks - CI job for template freshness
- Train on merge conflicts - 3-way merges need understanding
- Maintain template changelog - Help consumers understand changes
- Version template conservatively - Breaking changes = major version
Common Gotchas
- Answers file location matters - Must be committed and at project root
- Template suffix required by default - Files need
.jinjaunless configured otherwise - Git required for updates - Template must be Git repository with tags
- Jinja syntax in YAML - Must quote templated values properly
- Task execution order - Tasks run sequentially, not in parallel
- Conflict resolution - Learn 3-way merge basics before first update
Performance Considerations
- Generation speed: Fast for typical projects (<1s for small templates)
- Update speed: Depends on project size and Git history
- Memory usage: Minimal, dominated by Git operations
- Caching: Template cloning cached by Git
Related Tools
- cruft - Adds update capability to Cookiecutter templates
- cookiecutter - Popular Python templating (one-way generation)
- yeoman - Node.js ecosystem scaffolding
- copier-templates-extensions - Additional Jinja filters for Copier
- jinja2-time - Time-based Jinja filters
Learning Resources
- Official docs: @https://copier.readthedocs.io/
- Template browser: @https://github.com/topics/copier-template
- Comparisons: @https://github.com/copier-org/copier/blob/master/docs/comparisons.md
- Example templates: See "Real-World Examples" section above
Summary
Copier is the best choice when:
- You maintain multiple related projects
- Your templates evolve over time
- You need to propagate changes to existing projects
- You want version-aware template management
- You prefer declarative YAML configuration
Copier's unique selling point: The ability to update existing projects when templates change, with intelligent 3-way merging and version-aware migrations.
Quick start for evaluation:
# Install
pipx install copier
# Try popular template
copier copy gh:pawamoy/copier-uv test-project
# Make changes to project, then simulate update
cd test-project
# Edit some files...
copier update --defaults --vcs-ref=HEAD
Research completed: 2025-10-21 Sources verified: Official repository, PyPI, documentation, real-world templates Template examples analyzed: 5 major templates (FastAPI, copier-uv, NLeSC, JupyterLab, Doodba)