copier

repository·master·Indexed 25 days ago

https://github.com/copier-org/copier

A library and CLI application for rendering project templates. Copier allows developers to scaffold new projects or update existing ones from local paths or Git URLs, supporting dynamic value replacement via Jinja2. It provides a Python API with functions like run_copy(), run_recopy(), and run_update(), as well as a CLI for bootstrapping, updating, and checking for template updates.

Tokens
18.9K
Snippets
44
Records
136
Agent score
85%

What's inside copier

  1. Understand the difference between Settings and Answers in Copier

    master

    Copier distinguishes between two types of configuration:

    1. Settings: Configuration for the Copier tool itself. This includes metadata like the required minimal Copier version, the subdirectory to render, or tasks to run. Settings in a copier.yml file must start with an underscore (e.g., _min_copier_version).
    2. Answers: Configuration specific to the template being used. These are the variables provided by the user (e.g., project name, author) that are available to the template during the rendering process.
  2. Understand Copier's unique positioning as a lifecycle management tool

    master
    While Copier is often used for code scaffolding, it is designed as a code lifecycle management tool. Unlike many other scaffolders, Copier supports Migrations and Template updates (specifically for Git templates), allowing you to update existing projects when the underlying template changes.
  3. Generate a project from a template

    master

    You can generate a project from a template using either the Copier CLI or the Python API. If the destination directory does not exist, Copier will create it. If it does exist, it must be writable.

    CLI Usage

    Use the copier copy command followed by the template path/URL and the destination path.

    Python API Usage

    Use the copier.run_copy() function.

    Template Sources

    The template parameter supports:

    • Local file paths
    • URLs
    • GitHub shortcuts: gh:namespace/project
    • GitLab shortcuts: gl:namespace/project

    Note: If using a remote URL that is not automatically detected as a Git repository, ensure it starts with git+https://, git+ssh://, git@, or git://, or ends with .git.

    copier copy path/to/project/template path/to/destination
    copier.run_copy("path/to/project/template", "path/to/destination")
  4. Generate dynamic directory structures

    master

    You can use user answers to generate complex directory structures by templating folder names. You can use any separator (like .) and replace it with _copier_conf.sep to ensure cross-platform compatibility, or simply use / (which works on Windows).

    Example: Converting a dot-separated package name into a directory tree

    copier.yml

    package:
        type: str
        help: Package name

    Template file path

    your_template
        copier.yml
        {{ package.replace('.', _copier_conf.sep) }}{{ _copier_conf.sep }}__main__.py.jinja

    If the user enters your_package.cli.main, Copier generates:

    your_project
        your_package
            cli
                main
                    __main__.py
  5. Configure template questions in `copier.yml`

    master

    The copier.yml (or copier.yaml) file in the template root is the main entrypoint for managing configuration. It is used to prompt users for information and apply template settings. For each key defined, Copier will prompt the user to provide a value.

    Basic usage involves defining keys with simple values:

    name_of_the_project: My awesome project
    number_of_eels: 1234
    your_email: ""
  6. Create conditional files and directories

    master

    You can make files and directories conditional by using Jinja logic in their names. This allows you to only generate certain files based on user answers in copier.yml.

    Rules for conditional names:

    • Files: The template suffix (e.g., .jinja) must appear outside of the Jinja condition. If the suffix is inside the condition, Copier will treat the file as a static file rather than a template.
    • Directories: Directories must not end with the template suffix.
    • Windows Compatibility: Use single-quotes for paths in Jinja expressions to avoid issues with double-quotes in Windows file paths.

    Example: Conditional pre-commit configuration

    copier.yml

    use_precommit:
        type: bool
        default: false
        help: Do you want to use pre-commit?

    File structure

    your_template
        copier.yml
        {% if use_precommit %}.pre-commit-config.yaml{% endif %}.jinja
  7. Regenerate a project

    master

    Running copier recopy $project on an existing project will reapply the template. This process keeps previous answers but ignores previous history.

    Warning: This is not the recommended approach for updating a project. For standard updates that respect project evolution, refer to the project update documentation.

  8. Specify a template version or Git reference

    master

    By default, Copier uses the latest PEP 440 compliant release tag found in the template repository. To use a specific branch, tag, or commit, use the --vcs-ref CLI argument or the vcs_ref parameter in the Python API.

    Examples

    Use the latest master branch from a public repository:

    copier copy --vcs-ref master https://github.com/foo/copier-template.git ./path/to/destination

    Use the current checked out revision of a local template (including uncommitted/dirty changes):

    copier copy --vcs-ref HEAD path/to/project/template path/to/destination
  9. Use `UNSET` to force user input

    master

    If a default value should only apply under certain conditions, you can use the special UNSET variable. When UNSET is rendered, the default is removed, forcing the user to provide an answer (or making the variable undefined in the render context if the question is skipped).

    database_url:
        type: str
        default: >-
            {%- if database_engine == 'postgres' -%}
            postgresql://user:pass@localhost:5432/dbname
            {%- elif database_engine == 'mysql' -%}
            mysql://user:pass@localhost:3306/dbname
            {%- else -%}
            {{ UNSET }}
            {%- endif -%}
  10. Configure the .copier-answers.yml file

    master

    The .copier-answers.yml file stores the answers provided by the user during the initial generation. When updating a project, Copier uses this file to pre-fill answers, making updates smoother.

    Requirements

    • Naming: The file must be named exactly #!jinja {{ _copier_conf.answers_file }}.jinja (or end with your chosen templates_suffix) in your template's root folder to support applying multiple templates to the same subproject.
    • Content: The file must contain the following Jinja2 snippet to ensure Copier can manage it:
    # Changes here will be overwritten by Copier; NEVER EDIT MANUALLY
    {{ _copier_answers|to_nice_yaml -}}

    Important Notes

    • Do not edit manually: The file is managed by Copier. Manual edits can break the update process.
    • Variable _copier_answers: This built-in variable contains all JSON-serializable values from your copier.yml questions. Keys starting with an underscore (_) are reserved for Copier internal use.
    • Pathing: The path to the answers file must be relative to the project root.
  11. Locate the Copier configuration directory

    master

    Copier settings are stored in <CONFIG_ROOT>/settings.yml. The <CONFIG_ROOT> depends on your operating system:

    • Linux: $XDG_CONFIG_HOME/copier (typically ~/.config/copier)
    • macOS: ~/Library/Application Support/copier
    • Windows: %USERPROFILE%\AppData\Local\copier

    Note for Windows users: The previous directory %USERPROFILE%\AppData\Local\copier\copier is deprecated and will be removed in a future version.

    You can override this location by setting the COPIER_SETTINGS_PATH environment variable.