Skip to content

Config Schema (.yaml)

Each rule lives in <rulesDir>/<RuleName>/ and ships with a config.yaml (always named config.yaml — the directory name is what carries the rule identity). This page is the authoritative schema reference for that file.

version: 1 # required, must be 1
extends: ../base.yaml # optional, path relative to this file
output:
language: cpp # required for non-default; see table below
autoDeduceIncludes: true # default: true
outputDirectory: "" # optional, override default output directory
outputNameTemplate: "" # optional, override output filename pattern
permissions: # optional
http:
allowlist:
- "schema-registry.example.com"
env:
os_allowlist:
- "BUILD_CHANNEL"
params: # optional, free-form, exposed to scripts as `params`
apiVersion: "v1"
emitDocs: true
node_kinds: # optional, defaults to ["Struct"]
- Struct
- Class
- Enum
shared: # optional, controls which shared/*.luau scripts load
include: ["json_*"] # absent = include all; [] = include none
exclude: ["legacy_*"] # subtracted from include

Must be the integer 1. Any other integer emits E002 and aborts. A non-integer version: is silently ignored; omitting the key entirely is accepted.

Optional path (relative to this config file) to a base config. The base is loaded first, then values in this file override matching keys. Chains deeper than 8 levels emit E015. A missing target emits E015.

Selects the default file extension and the C++-specific assembly path (banner, self-include, project-include rebasing). Must be one of:

ValueDefault extension
cpp.g.cpp
csharp.cs
kotlin.kt
swift.swift
typescript.ts
plain.txt
markdown.md
html.html
mdx.mdx

Any other value emits E015. Defaults to cpp when omitted.

Only cpp triggers the C++ assembly path: // Generated with Codegen - DO NOT EDIT!!! banner, #pragma once for header outputs, automatic self-include of the input header, and project-include rebasing when outputDirectory relocates the output.

Default true. When enabled, the engine takes the rule’s emitted includes list and removes any entries already covered by the input header’s transitive include graph (per the analyzer). Set to false to emit every requested include verbatim.

This is not a stdlib auto-detector — it filters explicit includes against the include graph; it does not synthesize includes from generated source text.

Overrides the default output directory (which is the input header’s parent directory). Path is taken as-is — relative paths are resolved against the process working directory.

Overrides the default output filename. Tokens (Go-template style):

TokenSubstitution
{{.InputFile}}Input header filename without extension
{{.InputDir}}Input header’s parent directory (generic-form path)
{{.RuleName}}The rule (attribute) name

Default filename when this is unset:

  • cpp → <stem>.g.cpp
  • everything else → <stem>.<ruleName><ext>

The full path is <outputDirectory or inputDir>/<filename>.

A list of host patterns. Each entry is matched against the host component of the URL passed to http.get(...) (NOT a substring of the full URL). Supported forms:

EntryMeaning
example.comExact host match. evil.example.com is not matched.
*.example.comWildcard: any subdomain (api.example.com, a.b.example.com). Does not match the apex example.com.
*Match any host (escape hatch).

An empty or absent allowlist disables HTTP entirely; calls to http.get raise http.get: url not in allowlist: and emit E010.

The CLI flag --allow-http <pattern> appends entries to the allowlist at run time.

A list of OS environment variable names the rule’s scripts may read. When non-empty, the engine activates the env capability and exposes the named vars to the LuaU env module.

The CLI flag --allow-env <NAME> appends entries to this list at run time.

Dotenv files (<rulesDir>/<RuleName>/.env and <rulesDir>/../shared/.env) are loaded automatically when present and exposed via the same env module; they do not require an allowlist entry. The CLI flag --env KEY=VALUE overrides individual dotenv entries.

Free-form YAML, converted to JSON and exposed to every script as params:

  • Preamble script: params is a key on the JSON context object passed in.
  • Handler (transform) script: params is added under the params key on the entity payload.
  • Grouping script: params is a sibling of entities on the input object.

The CLI flag -P key=value (repeatable) overrides params per invocation — it is applied to every loaded rule’s params, not scoped to one rule. The value is parsed as JSON when possible, otherwise stored as a string. An entry without = is silently dropped.

A list of NodeKind enum names. Defaults to ["Struct"] when omitted. Controls which AST node kinds the rule’s attribute matcher will fire on. Valid entries are the codex NodeKind names; the common ones are Struct, Class, Union, Function, Variable, Constructor, Destructor, Operator and EnumSpecifier.

Entries are forwarded verbatim to the daemon with no client-side validation — an unknown entry does not fail the load and does not warn.

The components this rule requires, by require name:

uses:
- acme/typemap
- acme/codecs

Checked at load time: a rule naming a component that is not installed fails before any script runs and before any file is written, rather than dying per-entity at the first require.

Declaring the key at all — even as an empty list — also opts the rule out of the flat shared/ prelude (see shared below). A rule that names what it needs should not additionally absorb whatever else is sitting in the consumer’s tree; that is the isolation a published rule wants, and it is unavailable to a rule that declares nothing.

Controls which <rulesDir>/../shared/*.luau scripts get prepended to this rule’s transform. Both keys take a list of fnmatch-style globs (*, ?, [abc]) matched against the script’s filename stem (i.e. json_helpers.luau matches as json_helpers).

Applies to the flat scripts only. Namespaced components under shared/<vendor>/ are reached with require and are never part of the prelude, so these globs do not affect them.

KeyBehaviour
shared.include absentInclude every shared/*.luau (default).
shared.include: []Include none — no shared prelude for this rule.
shared.include: ["a", "b_*"]Include only the matching stems.
shared.exclude: [...]Subtract matching stems from whatever the include step yielded.

Independence assumption: flat shared scripts are concatenated in alphabetical filename order with no dependency tracking. If they depend on each other, name them so dependencies sort before dependents — or make them components, where require resolves the order for you.

  • transform.luau — handler script, required.
  • preamble.luau — preamble script, required (an empty return function() return "" end is fine).
  • grouping.luau — grouping script, optional.
  • .env — per-rule dotenv, optional.

Plus the workspace-shared directory:

  • <rulesDir>/../shared/*.luau — auto-loaded in alphabetical filename order, filtered through each rule’s shared.include / shared.exclude, and prepended to that rule’s transform. Skipped entirely for a rule that declares uses.
  • <rulesDir>/../shared/<vendor>/*.luau — components, reached with require("<vendor>/<name>"). Never concatenated.
  • <rulesDir>/../shared/.env — baseline dotenv; per-rule entries override.
config.yaml
version: 1
extends: ../base.yaml
output:
language: cpp
autoDeduceIncludes: false
outputDirectory: generated/advanced
outputNameTemplate: "{{.InputFile}}.{{.RuleName}}.g.cpp"
permissions:
http:
allowlist:
- "schema-registry.internal.example.com"
env:
os_allowlist:
- "BUILD_CHANNEL"
params:
apiVersion: "v1"
emitDocs: true
node_kinds:
- Struct
- Class