Anatomy of an Archetype
A fully-featured archetype looks like this:
my-archetype/
├── archetype.yaml # Manifest (required)
├── archetype.lua # Script — entry point
├── interface.yaml # Declarative input contract (optional)
├── contents/ # Templated content (name is by convention)
│ └── {{ project_name }}/
│ ├── README.md
│ └── src/…
├── includes/ # ATL template fragments for {% include %}
│ └── header.atl
├── lib/ # Lua modules (require-able by scripts)
│ └── helpers.lua
└── README.md # For humans browsing the repository
Only the manifest is strictly required; everything else exists in service of what your archetype actually does.
archetype.yaml — the manifest
Identity, requirements, engine configuration, and (optionally) a catalog of dependencies:
description: "Rust CLI application"
summary: "Scaffolds a Rust CLI binary using clap derive macros."
authors: ["Jane Developer <jane@example.com>"]
languages: ["Rust"]
frameworks: ["clap"]
tags: ["rust", "cli"]
requires:
archetect: "3.0.0"
templating:
trim_blocks: true
lstrip_blocks: true
descriptionappears in catalog menus and search results;summary,languages,frameworks, andtagsfeedarchetect search.requires.archetectis the Archetect version contract: the major version must match strictly (Archetect 3 renders only3.xarchetypes), and within the major it's a minimum.templatingtunes the ATL engine — see Templating Configuration.- A
catalog:section declares composed archetypes and libraries — see Composition.
Full schema: Archetype Manifest reference.
archetype.lua — the script
The script is your archetype's main(). It runs top-to-bottom when the archetype renders, with the whole Lua API available as globals — no imports needed for the core:
local context = Context.new()
context:prompt_text("Project Name:", "project-name", {
cases = Cases.programming(),
})
directory.render("contents", context)
Everything interesting about scripting has its own page under Scripting with Lua.
Content directories
Directories of templates, rendered with directory.render("<name>", context). The name is up to you — contents/ is the common convention — and you can have several, rendered conditionally:
directory.render("contents", context)
if archetype.switches.is_enabled("docker") then
directory.render("docker", context)
end
Within a content directory, everything is a template: file contents and file/directory names ({{ project_name }}/ becomes rocket-launcher/).
includes/ — shared template fragments
Fragments referenced from templates with {% include %}. Your archetype's own includes/ is automatically on the search path, and libraries you mount contribute theirs — see Organizing Templates.
lib/ — Lua modules
Lua files that your script (or consumers of your archetype, in library mode) can require. This is how larger archetypes stay organized and how Libraries share logic across an organization.
interface.yaml — declarative inputs
An optional, machine-readable declaration of your archetype's prompts and switches, letting web portals and AI agents build input forms without running the script. See Declarative Interfaces.
How it all executes
The manifest loads first (requirements are checked, library: true catalog entries are staged), then the script runs, prompting and rendering as it goes. When the script ends, the render is complete.