Generating a project non-interactively¶
For CI or scripted generation, answer the questionnaire from a file instead of a
terminal. The Create a new project tutorial covers
the shipped CLI's --preset <name>, which is the shortest non-interactive form;
this page is the copier-level reference.
Every question has a default, so a minimal answers file plus --defaults fully
determines the project; anything in the file overrides that default:
# Create answers file
cat > answers.yml << 'EOF'
---
project_type: library
package_name: my_package
description: My awesome package
git_platform: github.com
github_org: my-org
EOF
# Generate project
uvx copier copy --trust --defaults \
--data-file answers.yml /path/to/my-project
Notes:
--defaultsanswers every question it would ask with its default, so it never prompts. A value from--data-filecounts as answered, which also drives thewhengating of the follow-up questions (e.g.use_recommended_integrations: falsereveals the integration details and--defaultsfills them in).- Values supplied for a question whose
whenis false (e.g.docs_typewhileuse_recommended_docsis true) are still validated against the choices — pass the gate answer too, or drop the unused value. --answers-filemust be a path relative to the destination directory (copier requirement), e.g..copier-answers.yml.
Tell the template what you want¶
The inverse question comes up just as often: for the features you want, which
answers produce them? The 248 witness leaves in tests/matrix/witnesses.jsonl
each carry a full answer set whose render context copier has already computed,
so "features -> answers" is an exact filter over verified configurations, not
a guess — tools/answers_for.py is that filter:
# Name the features as constraints over any question or derived internal
uv run --locked python tools/answers_for.py \
--require use_gpu_effective=true --require kaggle=true
# ...and prove the top match by rendering it: every constraint is checked
# against the rendered tree (context pass over the render's recorded answers,
# plus the artifacts the internals gate, e.g. Dockerfile.gpu)
uv run --locked python tools/answers_for.py \
--require zensical=true --require web_api=true --render --keep
Each constraint is name, name=value, -name or name!=value. A name may
be an asked question (docker, docs_type, license, ...) or a derived
internal (mcp_effective, use_gpu_effective, sphinx,
license_effective, ...); an unknown name is rejected with the closest real
names. Every match is reported with its full answers as a --data-file-ready
YAML block and the artifacts its class ships; when nothing matches, the tool
names the constraint that eliminated the most leaves and the nearest leaf
with what it misses — the match is exact over the declared leaf space, so a
combination no leaf carries (docker=true, say: every leaf keeps that
question's default) is reported as such, not guessed. --json puts the same
payload on stdout, task answers-for is the task wrapper, and the MCP server
exposes it as recommend_answers
(see Drive the template's tools over MCP).
Troubleshooting¶
- Exit status 4, nothing generated → you omitted
--trust - "Question X is required" → add X to your answers file (see
questions/*.ymlfor every question and its default) - "Invalid choice for X" → check the valid choices in
questions/*.yml
For a whole batch of requests, judged and reported as machine-readable results, see Run a batch of generation requests.