Guidance for AI coding agents working on this Copier template.
copier.yml: questions, validators and post-generation tasks.template/: the generated project. Files ending in.jinjaare rendered; everything else is copied verbatim. Conditional files and folders use names like{% if api %}api.py{% endif %}.jinja.tests/test_template.py: renders variants with Copier and runs each one's owninvoke lintandinvoke test.tasks.py: tasks for the template repo itself. CI runs the same tasks.
uv run invoke lint # ruff and mypy on tasks.py and tests
uv run invoke test # render every variant and check it
uv run invoke render --dest /tmp/demo --api # inspect a rendered projectAfter changing anything under template/, run invoke test. For changes touching Docker, Bruno or invoke smoke/api-test, also render a project and run those tasks inside it.
- Generated projects must pass their own CI. Every change to
template/keepslint,test,audit,smokeand (for the API variant)api-testgreen. - Jinja and GitHub Actions both use
{{ }}. Wrap Actions expressions in rendered files in{% raw %}...{% endraw %}. Bruno.brufiles aren't rendered, so their{{baseUrl}}needs no escaping. - Keep the CLI and API variants in step. Shared behaviour belongs outside the
{% if api %}blocks. - Keep example code small and obviously replaceable; the template is a starting point, not a framework.
- Keep the generated
CLAUDE.mdin step with the generated project's tooling.
- Branch as
<type>/<issue>-<short-description>; start from an issue. - Commits are
<type>: <description>with typesfeat,fix,refactor,test,docs,chore,perf. CI and tooling changes arechore. - Never add AI attribution (
Co-Authored-Bytrailers or "Generated with" footers) to commits, pull requests, issues or comments. - Comments explain why, not what.