Skip to content

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.

  1. 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.

  2. 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 once
    namespace app {
    enum class Color { Red, Green, Blue };
    // [[codegen::generated::ToString::app::Color]]
    } // namespace app

    ToString uses anchor-based triggering because C++ doesn’t allow attributes on enum declarations. The anchor doubles as the inline-injection site for the generated declaration.

  3. Run the engine

    Terminal window
    codegen -i ./include -r .codegen/rules -a ToString
    • -i is the input directory (or a single header).
    • -r is the rules root (defaults to .codegen/rules; you can omit it).
    • -a selects which rule to run; repeatable.
  4. Inspect the output

    The engine writes a sibling .g.cpp next 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.

  5. 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 packaged find_package(codegen) flow is on the roadmap).

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.

Read Your First Rule to write a rule from scratch.

Working with an LLM agent?

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.

Key Takeaways
  • codegen selects 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’s node_kinds.
  • The first run rewrites bare anchors into idempotent :begin]] / :end]] blocks.