β¨ A Copier template for generating a modern Python project that is uv-first, strict by default, and easy to maintain.
Note
This repository is the template source (a meta-project). To create a project, you generate into a new directory.
- π uv-first + lockfile-first: reproducible installs with
uv lock --frozenanduv sync --frozen - π§Ή Quality gates: ruff (format + lint), basedpyright (type check), pytest with coverage
- π οΈ One-command workflows:
just cimirrors GitHub Actions exactly - π Optional docs: MkDocs scaffolding (toggle during generation)
- π Optional data stack: NumPy and/or pandas support (toggle during generation)
- π Update-friendly: conservative
copier updatebehavior via_skip_if_exists - π€ Automated releases: GitHub Actions workflow for versioning and releases
Prerequisites:
- π Python 3.11+
- π± Git
- π§©
copier - πͺ
just(task runner β used throughout this repo and generated projects)
Warning
Generate from trusted templates: when a template uses Copier tasks, they run with the
same access level as your user.
Generate a project from this repo root:
copier copy . /path/to/new-project --trust --defaultsThen, inside the generated project, run:
just ci- β
--defaults: accept defaults for all questions - π
--trust: allow post-generation tasks (bootstrapsuv, installs deps, runs checks, installs hooks) - π€
--data key=value: provide answers non-interactively (great for scripts) - π
--data-file path.yml: provide answers from a YAML file - π
--vcs-ref ref: generate from a specific git ref (tag/branch/commit) of the template - π§ͺ
--vcs-ref HEAD: when developing a local template clone, use the current working tree (including uncommitted changes). By default Copier may pick the latest PEP 440 tag instead of your dirty tree. - βοΈ
--skip-tasks: render files without running_tasks(faster checks; tasks still run oncopier updateunless you pass--skip-tasksthere too)
During copier copy, youβll be prompted for:
- π·οΈ Project identity:
project_name,project_slug,package_name, description, author, GitHub org/user - π Python baseline: minimum version (3.11 / 3.12 / 3.13)
- β Add-ons:
- π MkDocs (
include_docs) - π NumPy (
include_numpy) - πΌ pandas (
include_pandas_support)
- π MkDocs (
Tip
For Codecov, add the GitHub repository secret CODECOV_TOKEN (where to click in GitHub: docs/github-repository-settings.md section 11) rather than providing a token at generation time.
Generated projects store answers in .copier-answers.yml.
For the update to work best, ensure:
- The template includes a valid
.copier-answers.yml - The template is versioned with git tags
- The destination folder is versioned with git
Then, from inside the generated project folder (make sure git status is clean), run:
copier update --trustUse copier update --defaults to reuse all previous answers without re-prompting. To change one answer only:
copier update --defaults --data key=value, or put overrides in a YAML file and use --data-file. To refresh answers against the template without bumping template version: copier update --vcs-ref=:current:.
copier recopy reapplies the template while keeping stored answers; it does not use Copierβs smart merge used by copier update. Prefer copier update for day-to-day sync; use recopy when recovering from a broken update or when you explicitly want a full re-application (then reconcile with Git).
copier check-update reports whether a newer template version exists (--output-format json, --quiet exits 2 when an update is available β useful in automation).
If Copier cannot apply some changes automatically, it either writes inline conflict markers (default, --conflict inline) or separate *.rej files (--conflict rej). Review and resolve before committing. Generated projects include pre-commit hooks: check-merge-conflict (inline) and a hook that rejects *.rej files if you use rejection-file mode.
Important:
- Never manually edit
.copier-answers.ymlβ it can break Copierβs update algorithm. - This template is intentionally conservative about overwriting user-edited files (see
copier.ymlβ_skip_if_exists). - Prefer SSH or a clean Git remote URL for the template so credentials do not end up inside
.copier-answers.yml.
-
Generated projects include a
template/.claude/configuration with TDD-oriented hooks and commands (strict test-first enforcement, coverage warning gate, refactor test reminders). SeeCLAUDE.mdfor the authoritative list of hooks and slash commands. -
Version tags: Consumers get the best
copier updateexperience when this template uses PEP 440-compatible Git tags (Copier compares tags to choose versions). -
_migrations: When a template change is breaking (e.g. renaming paths or reshaping answers), consider adding_migrationsincopier.ymlwith aversionthreshold so update-time scripts run in the right order. See Copierβs configuring and updating docs. -
Shallow clones of the template repo can make Copierβs Git usage heavier; prefer full clones in CI if you see resource issues.
Install dev dependencies for this template repo (uses the committed lockfile):
just syncRun the full local CI mirror:
just ciOther useful commands:
- π§Ή
just fix: auto-fix lint issues - β¨
just fmt: format code - π
just lint: lint check - π§
just type: type check (basedpyright standard mode) - π
just docs-check: Google-style docstrings (ruffDonly) - β
just review:fixβlintβtypeβdocs-check(no tests; pre-merge static checks) - π§ͺ
just test: run template integration tests (renders the template and asserts output) - π
just coverage: run tests with coverage report - β‘
just test-parallel: run tests in parallel (faster) - π
just precommit: run pre-commit on all files - π©Ί
just doctor: print toolchain and project versions - π
just sync-check: validate root/template sync policy (scripts/check_root_template_sync.py) - β
just check: read-only gate (fmt-check, lint, types, sync-check, docstrings,test-ci, pre-commit). For the full Python 3.11β3.13 matrix locally, usejust test-ci-matrix. Dependency audit:just audit(also runs insecurity.ymlon GitHub).
The test suite (tests/integration/test_template.py, tests/unit/test_root_template_sync.py, tests/unit/test_repo_file_freshness.py) uses pytest to:
- Render the template with various configurations
- Validate generated project structure
- Check that generated projects have valid Python syntax
- Verify CI/CD workflow files are valid YAML
- Enforce root/template sync policy (
check_root_template_sync.py) - Test all combinations of optional features (docs, NumPy, pandas)
This repo uses a manually-triggered GitHub Actions workflow to bump the template repo version, tag it, and create a GitHub Release.
To cut a release:
- Go to GitHub Actions β workflow
Release - Click βRun workflowβ
- Choose either:
bump:patch/minor/major, orversion: an explicitX.Y.Z(overridesbump)
The workflow will:
- Update
[project].versioninpyproject.toml - Commit the change
- Create and push a tag
vX.Y.Z - Create a GitHub Release with auto-generated release notes
Yes. Copier understands this use case (it powers features like updating).
No. Updates rely on that file; editing it manually can lead to unpredictable diffs.
Both this template repo and generated projects expect a committed uv.lock. In CI and locally, uv sync --frozen keeps installs reproducible and fails fast on drift.
If you enable coverage upload in your CI setup, configure a GitHub repository secret named CODECOV_TOKEN (docs/github-repository-settings.md section 11). You typically do not need to provide a token as a Copier answer.
- Copier docs:
https://github.com/copier-org/copier - Copier docs (official): generating, updating, configuring, FAQ
https://copier.readthedocs.io/en/stable/creating/https://copier.readthedocs.io/en/v6.0.0/updating/https://copier.readthedocs.io/en/stable/configuring/https://copier.readthedocs.io/en/stable/faq/