Skip to content

Attribute Syntax and Scopes

Normal attributes use square brackets and apply to the next model, enum, or field.

[SerializationType("json")]
model AuthGuestAnswer {
[JsonPropertyName("rpc_id")]
RpcId: uint16;
}

Hash-prefixed attributes apply beyond a single model or field.

#[SerializationType("json")]
#file:[OutputFileGroup("api")]
#namespace:[OutputFileGroup("shared")]

Supported scopes:

  • #[Attr] or #global:[Attr]: global scope.
  • #file:[Attr]: current source file.
  • #namespace:[Attr]: current namespace.

When an attribute is resolved for a model, CCL checks model-local attributes first, then file scope, namespace scope, parent namespace scope, and global scope.

Enum generation settings check the enum first, then its owning model, followed by the same scoped fallbacks. Enum mapping targets and fallback members must be declared directly on their enum.

Prefix an attribute with one or more target language selectors to apply it only to those generators.

[$go:OutputFileGroup("server")]
[$go,$ts:SerializationType("json")]
#namespace:[$cs:OutputFileGroup("contracts")]

Common selectors include go, gd, godot, gdscript, cs, csharp, py, python, js, javascript, ts, and typescript.

Attributes can use unnamed parameters, named parameters, and identifier values.

[Attr("value", 123)]
[Attr(Name = "value")]
[Attr(SomeGlobalValue)]