Creating Templates
Your first template
Section titled “Your first template”Three files. That’s all you need.
hello/ diecut.toml template/ hello.txt.teraThe config — diecut.toml:
[template]name = "hello"
[variables.name]type = "string"prompt = "Your name"default = "world"The template file — template/hello.txt.tera:
Hello, {{ name }}!Run it:
diecut new ./hello -o outputYour name [world]: Aliceoutput/ hello.txtHello, Alice!That’s a template. You just made one.
The template/ directory contains your project files. Files ending in .tera are rendered through the Tera template engine, then have the .tera suffix stripped. Everything else is copied as-is.
Variable types
Section titled “Variable types”diecut supports six variable types.
string
Section titled “string”Text input.
[variables.project_name]type = "string"prompt = "Project name"default = "my-project"Yes or no.
[variables.use_ci]type = "bool"prompt = "Set up CI?"default = trueInteger.
[variables.port]type = "int"prompt = "Default port"default = 8080Decimal number.
[variables.version]type = "float"prompt = "Initial version"default = 0.1select
Section titled “select”Pick one from a list.
[variables.license]type = "select"prompt = "License"choices = ["MIT", "Apache-2.0", "GPL-3.0"]default = "MIT"multiselect
Section titled “multiselect”Pick multiple from a list.
[variables.features]type = "multiselect"prompt = "Features to include"choices = ["logging", "docker", "ci"]default = ["logging"]Conditional prompts
Section titled “Conditional prompts”Use when to only ask a question when a previous answer makes it relevant.
[variables.use_ci]type = "bool"prompt = "Set up CI?"default = true
[variables.ci_provider]type = "select"prompt = "CI provider"choices = ["github-actions", "gitlab-ci"]when = "{{ use_ci }}"ci_provider is only prompted when use_ci is true. The when field takes a Tera expression.
Conditional files
Section titled “Conditional files”Include or exclude entire files based on variable values.
[files]conditional = [ { pattern = ".github/**", when = "use_ci and ci_provider == 'github-actions'" }, { pattern = ".gitlab-ci.yml", when = "use_ci and ci_provider == 'gitlab-ci'" },]Files matching the pattern are only included when the expression is true.
A real-world example from a Python template:
[files]conditional = [ { pattern = "src/cli.py*", when = "use_cli" },]This excludes src/cli.py.tera when the user says no to the CLI entry point. The glob matches both the .tera source and any related files.
Computed variables
Section titled “Computed variables”Variables derived from other variables. Never prompted.
[variables.project_slug]type = "string"computed = "{{ project_name | slugify }}"Computed variables are available in templates but never shown to the user. Use them for derived values like slugs, lowercase versions, or formatted strings.
A computed variable must not have a prompt field. If it does, diecut will report an error.
File handling
Section titled “File handling”Excluding files
Section titled “Excluding files”Keep files out of the generated output:
[files]exclude = ["*.pyc", ".DS_Store", "__pycache__/**"]Copying without rendering
Section titled “Copying without rendering”Some files contain {{ }} or {% %} syntax that isn’t meant for Tera. Binary files, images, or files with their own template syntax.
[files]copy_without_render = ["assets/**/*.png", "fonts/**"]Files matching these patterns are copied verbatim. Tera syntax inside them is left alone.
Tera template basics
Section titled “Tera template basics”Five things you’ll actually use.
Variables
Section titled “Variables”Insert a value:
{{ project_name }}Conditionals
Section titled “Conditionals”Include a block only when a condition is true:
{% if use_ci %}ci: true{% endif %}Iterate over a list:
{% for feature in features %}- {{ feature }}{% endfor %}Filters
Section titled “Filters”Transform values inline:
{{ project_name | slugify }}{{ name | upper }}{{ description | truncate(length=50) }}slugify turns “My Project” into “my-project”. upper uppercases. truncate cuts to length.
Comments
Section titled “Comments”{# This won't appear in output #}A complete example
Section titled “A complete example”A Cargo.toml.tera from a Rust CLI template:
[package]name = "{{ project_name }}"version = "0.1.0"edition = "{{ rust_edition }}"description = "{{ description }}"{% if author %}authors = ["{{ author }}"]{% endif %}license = "{{ license }}"Tera has much more. See the full Tera documentation for everything else.
Validating your template
Section titled “Validating your template”Check for errors
Section titled “Check for errors”diecut check ./my-templateReports format detection, variable definitions, and any issues it finds.
Ready for distribution
Section titled “Ready for distribution”diecut ready ./my-templateready is stricter. It checks whether the template is suitable for sharing: description present, variables have prompts, no orphaned references.
Variable validation
Section titled “Variable validation”Add a regex to constrain user input:
[variables.project_name]type = "string"prompt = "Project name"validation = '^[a-z][a-z0-9_-]*$'validation_message = "Must start with a letter. Only lowercase letters, numbers, hyphens, underscores."If the input doesn’t match, the user is re-prompted with the validation message. No bad data gets through.