Skip to content

Hooks

Hooks are scripts that run during project generation. They’re written in Rhai, a sandboxed scripting language compiled into the diecut binary. No shell, no external dependencies, identical behavior on every platform.

Two hook points:

  • pre_generate — runs before files are rendered
  • post_generate — runs after files are written

Configure hooks in diecut.toml:

[hooks]
pre_generate = ["hooks/pre_generate.rhai"]
post_generate = ["hooks/post_generate.rhai"]

Paths are relative to the template root. A typical file structure looks like this:

my-template/
diecut.toml
hooks/
pre_generate.rhai
post_generate.rhai
template/
...

All template variables are injected into the Rhai scope as variables:

// If your diecut.toml has [variables.project_name]
print(`Project name: ${project_name}`);

Post-generate hooks also get output_dir:

print(`Files written to: ${output_dir}`);
diecut typeRhai type
stringString
boolbool
inti64
floatf64
selectString
multiselectString (serialized)
hooks/post_generate.rhai
print(`Created ${project_name} at ${output_dir}`);
print("Next: cd into the directory and run `cargo build`");
hooks/pre_generate.rhai
if project_name.len() < 2 {
throw "Project name must be at least 2 characters";
}

throw in a pre-generate hook aborts generation with an error message.

hooks/post_generate.rhai
if use_ci {
print(`CI configured for ${ci_provider}`);
} else {
print("No CI configured. You can add it later.");
}

Rhai is sandboxed for security. Hooks cannot:

  • Access the filesystem directly
  • Make network requests
  • Execute shell commands
  • Access environment variables

Safety limits:

LimitValue
Max call depth32 levels
Max operations100,000
Max string size10 MB

If a hook exceeds these limits, it fails with an error. These limits exist to prevent runaway scripts from untrusted templates.

A brief cheat sheet for hook authors. For the full language reference, see the Rhai book.

let name = "diecut";
let count = 42;
let flag = true;
print(`Hello, ${name}!`);
if count > 10 {
print("Big number");
} else {
print("Small number");
}
for i in range(0, 5) {
print(i);
}
fn greet(name) {
print(`Hello, ${name}!`);
}
greet("world");
throw "Something went wrong";