cargo-generate: scaffold a project from a git template repo. Use when bootstrapping a Rust or Bevy project from a template, or authoring one.
Scanned 9/3/2026
Install to Claude Code
npx -y skills add laurigates/claude-plugins --skill cargo-generate --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Cargo Generate?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/laurigates-cargo-generate)More formats (shields.io, HTML) on the badges page.
---
created: 2026-07-29
modified: 2026-07-29
reviewed: 2026-07-29
name: cargo-generate
description: "cargo-generate: scaffold a project from a git template repo. Use when bootstrapping a Rust or Bevy project from a template, or authoring one."
user-invocable: false
allowed-tools: Bash, Read, Write, Edit, Grep, Glob, TodoWrite
---
# cargo-generate — Project Scaffolding from Git Templates
cargo-generate expands a **git repository of real files** into a new project,
substituting [Liquid](https://shopify.github.io/liquid/) expressions in file
contents *and* in path names. It is the Rust ecosystem's standard scaffolding
tool — Bevy, wasm-pack, and most framework starters ship templates for it.
## When to Use This Skill
| Use this skill when... | Use the alternative instead when... |
|---|---|
| Starting from a published template (`bevy_new_2d`, `wasm-pack-template`) | Starting a plain binary or library — `cargo new` is enough (see `rust-development`) |
| Authoring a template so a project shape can be reproduced | Applying standards to an **existing** repo — cargo-generate only generates once (see `configure-plugin`) |
| A scaffold needs prompts, variants, or derived values | The scaffold is a fixed file set with no substitution — copy it |
## Installation
```bash
cargo install cargo-generate --locked
cargo generate --version
```
It is a cargo subcommand (`cargo generate`) and also a standalone binary
(`cargo-generate`), which is what a test harness should invoke.
## Generating a project
```bash
# From a GitHub template (gh:/gl:/bb:/sr: prefixes also work)
cargo generate --git https://github.com/TheBevyFlock/bevy_new_2d --name my_game
# From a local directory — the form to use while authoring a template
cargo generate --path ./templates/my-template --name my-project
# Pin to a branch, tag, or revision
cargo generate --git <url> --branch main --name my-project
# Expand into the current directory instead of creating a new one
cargo generate --git <url> --init
```
Nothing about the tool is Rust-specific: a template needs **no `Cargo.toml`**,
and generating a TypeScript, Python, or config-only project works the same way.
## Non-interactive use
This is what makes cargo-generate usable from a skill or CI job — prompts would
otherwise block:
```bash
cargo generate --path ./templates/my-template \
--name my-project \
--define 'display_name=My Project' \
--define variant=app \
--vcs none \
--silent
```
| Flag | Effect |
|---|---|
| `--define KEY=VALUE` | Supply one placeholder; repeatable |
| `--template-values-file <toml>` | Supply them all from a file |
| `--silent` | Never prompt; fail if a value is missing and has no default |
| `--vcs none` | Skip the automatic `git init` in the output |
| `--destination <dir>` | Where the project directory is created |
## Authoring a template
A template is a directory (usually a git repo) with a `cargo-generate.toml` at
its root:
```toml
[template]
cargo_generate_version = ">=0.23.0"
ignore = ["hooks"] # dropped from the output entirely
exclude = ["ci.yml"] # copied verbatim, never rendered
[hooks]
pre = ["hooks/derive.rhai"] # runs after placeholders resolve
[placeholders]
display_name = { type = "string", prompt = "Human-readable title" }
variant = { type = "string", prompt = "Shape", choices = ["basic", "app"], default = "basic" }
enable_ci = { type = "bool", prompt = "Add CI?", default = true }
# `ignore` drops files when the expression is TRUE, so name the cases that
# should NOT get the file.
[conditional.'variant != "app"']
ignore = ["src/app.ts", "templates"]
```
| Key | Meaning |
|---|---|
| `[template] ignore` | Files removed from the output |
| `[template] include` / `exclude` | Which files are *rendered*; mutually exclusive. Excluded files are still copied |
| `[placeholders]` | Prompted values — types `string`, `text`, `editor`, `bool`, `array`; supports `default`, `choices`, `regex` |
| `[conditional.'<expr>']` | Applies `ignore` (and nested `.placeholders`) when the expression holds |
| `[hooks] init` / `pre` / `post` | Rhai scripts, before placeholders / after them / after rendering |
### Built-in variables and filters
`project-name` (as given, kebab-cased), `crate_name`, `crate_type`, `authors`,
`username`, `os-arch`, `is_init`, `within_cargo_project`.
Case filters: `kebab_case`, `snake_case`, `pascal_case`, `lower_camel_case`,
`upper_camel_case`, `title_case`, `shouty_snake_case`, `shouty_kebab_case`.
Path names are rendered too, so `styles/{{ module_id }}.css` works.
### Rhai hooks
Use a hook for values that should be **derived, not asked for** — anything a
prompt could get inconsistent with something else:
```rhai
let name = variable::get("project-name");
if !name.starts_with("prefix-") {
abort("name must start with 'prefix-'");
}
variable::set("short_name", name.sub_string(7));
let now = system::date();
variable::set("year", "" + now.year); // strings only — see gotchas
```
Available: `variable::get/set/is_set/prompt`, `file::exists/rename/delete/write/listdir`,
`system::date`, `system::command` (needs `--allow-commands`), `abort`, and the
`to_kebab_case()`-style converters.
## Gotchas
**Liquid eats other `{{ }}` languages.** GitHub Actions `${{ … }}`, Handlebars,
Jinja, and Vue interpolations all render to the empty string if the file is
templated. Two fixes:
| Situation | Fix |
|---|---|
| The file needs no substitution | `[template] exclude` it — copied verbatim, never rendered |
| The file needs both | Wrap the foreign expressions in `{% raw %}…{% endraw %}`, or assign the literal brace once: `{%- assign hb = "{{" -%}` then `{{ hb }}localize "…"}}` |
Only an opening `{{` needs escaping; a bare `}}` means nothing to Liquid.
**`variable::set` takes strings only.** Passing an integer — including
`system::date().year` — fails with
`Function not found: variable::set (…, i64)`. Concatenate with `""` first.
**The project name is kebab-cased before hooks run.** `--name My_Project`
becomes `my-project` silently. A hook cannot reject a malformed name because it
never sees one; if the exact spelling matters, validate before invoking.
**`.liquid` is a magic suffix.** A file named `x.rs.liquid` is rendered and
emitted as `x.rs`. To ship a literal `.liquid` file, double the extension.
## Agentic Optimizations
| Context | Command |
|---|---|
| Fully non-interactive | `cargo generate --path <dir> --name <n> --define k=v --silent --vcs none` |
| Many values | `cargo generate --git <url> --template-values-file values.toml --silent` |
| Template dev loop | `cargo generate --path ./templates/<t> --name probe --vcs none --silent -d …` |
| Diff a template change | Generate before and after into temp dirs, then `diff -ru` |
| Keep generating past a failure | `--continue-on-error` (template debugging only) |
## Quick Reference
| Flag | Purpose |
|---|---|
| `--git <url>` / `--path <dir>` | Template source (remote / local) |
| `--branch` / `--tag` / `--revision` | Pin the template version |
| `--name <n>` | Project name (populates `project-name`) |
| `--destination <dir>` | Parent directory for the new project |
| `--init` | Expand into the current directory |
| `--define k=v` | Set a placeholder |
| `--template-values-file <toml>` | Set placeholders from a file |
| `--silent` | Never prompt |
| `--vcs none\|git` | Control the automatic `git init` |
| `--force` / `--overwrite` | Skip name-case correction / overwrite existing files |
| `--allow-commands` | Permit `system::command` in hooks |
## Templates in this marketplace
`foundryvtt-plugin/templates/foundryvtt-module/` is a worked example — three
variants via `[conditional]`, a derived id via a Rhai pre-hook, both brace
collisions above, and a parity test against the generator it ports. See
[`foundryvtt-plugin/templates/README.md`](../../../foundryvtt-plugin/templates/README.md).
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!