Quick Start
This guide walks through the ToString example: annotating a C++ enum and generating a std::string_view toString() function from it. The shipping example is at clis/codegen/examples/ToString/ in the source tree.
-
Set up the rule directory
Terminal window mkdir -p .codegen/rules/ToString# Copy config.yaml, transform.luau, and preamble.luau# from clis/codegen/examples/ToString/ into .codegen/rules/ToString/The four files in a rule directory are documented in Rule Anatomy.
-
Annotate your enum
Add an anchor comment near the enum. The third anchor segment is the entity’s qualified name (with namespaces):
include/color.hpp #pragma oncenamespace app {enum class Color { Red, Green, Blue };// [[codegen::generated::ToString::app::Color]]} // namespace appToStringuses anchor-based triggering because C++ doesn’t allow attributes on enum declarations. The anchor doubles as the inline-injection site for the generated declaration. -
Run the engine
Terminal window codegen -i ./include -r .codegen/rules -a ToString-iis the input directory (or a single header).-ris the rules root (defaults to.codegen/rules; you can omit it).-aselects which rule to run; repeatable.
-
Inspect the output
The engine writes a sibling
.g.cppnext to the input header by default:include/color.g.cpp // Generated with Codegen - DO NOT EDIT!!!#include <string_view>#include "color.hpp"std::string_view toString(app::Color e){switch (e){case app::Color::Red: return "Red";case app::Color::Green: return "Green";case app::Color::Blue: return "Blue";default: return "<unknown>";}}The header itself is patched: the bare anchor expands into a paired
:begin]] / :end]]block that holds the forward declaration. Subsequent runs replace only the content between the markers. -
Add the generated file to your build
CMakeLists.txt target_sources(mylib PRIVATE include/color.g.cpp)To re-trigger codegen automatically when the header changes, drive the binary from
add_custom_command— see CMake Integration for the current pattern (the packagedfind_package(codegen)flow is on the roadmap).
What just happened
Section titled “What just happened”The engine collected .h/.hpp files under ./include, parsed them via codex, and matched the anchor comment against the ToString rule. It called transform.luau once with the enum’s AST node serialised as JSON. The script returned a source (the switch implementation) and a single-item inline list (the forward declaration). The engine wrote color.g.cpp and rewrote the anchor in color.hpp into the paired-marker block.
Next step
Section titled “Next step”Read Your First Rule to write a rule from scratch.
The full docs are bundled as a single plain-text file at /llms-full.txt.
Paste it into your assistant’s context (Claude Code, Cursor, Copilot Chat, etc.) and it will
have everything it needs to write rules, debug configs, and explain the AST schema — no
crawling required. A condensed index is also available at /llms-small.txt.
codegenselects rules by name with-a; the input is a path with-i.- Default outputs land next to the input header unless the rule config sets
outputDirectory. - Anchor comments (
// [[codegen::generated::Rule::QualifiedName]]) trigger anchor-based rules and mark the inline-injection site. - Attribute annotations (
[[codegen::Rule]]) are the alternative trigger for declaration-level rules — any node kind listed in the rule’snode_kinds. - The first run rewrites bare anchors into idempotent
:begin]] / :end]]blocks.