--- title: Quickstart --- > IMPORTANT: If you're using an agentic coding solution, you can provide [gluelang.dev/llms.txt](https://gluelang.dev/llms.txt) as a reference, which contains all of these docs in Markdown format. > It will be able to figure out how to bootstrap Glue in your project. # 1. Install Glue ```shell # Homebrew brew install guywaldman/tap/glue # Linux/macOS curl -fsSL https://github.com/guywaldman/glue/releases/latest/download/install.sh | bash # Windows (PowerShell) iwr -useb https://github.com/guywaldman/glue/releases/latest/download/install.ps1 | iex ``` # 2. Create a Glue file Start by creating a Glue file that defines your data models and intefaces using the [Glue IDL](/docs/language-reference). You can also generate code from a URL or from standard input (stdin). Example: ```glue // models.glue /// Use triple slash for comments that should be included in generated code as docstrings model Apartment { /// The apartment number, e.g. "1A" number: int // Use double slash for internal comments and not included in generated code residents: Person[] } model Person { name: string age: int residence_end_date?: string // Optional fields are denoted with a `?` is_employed: bool = false // Default values are supported } model Building { name: string apartments: Record // Complex types like maps, lists, etc. are supported address: Address // Nested models are supported model Address { street: string city: string country_code: string zipcode: string } } // Glue supports endpoints (like OpenAPI), which you can optionally define with sane defaults. /// Get building information by the building ID endpoint "GET /building/{building_id}" GetBuilding { responses: { 200: Building 4XX: ApiError 5XX: ApiError } } model ApiError { code: Code message: string enum Code: "INVALID_REQUEST" | "NOT_FOUND" | "INTERNAL_ERROR" } ``` Glue also support imports, so you can split your models into multiple files and import them: ```glue import * from "models/person.glue" import * as common from "models/common.glue" // Namespaced import import { Address } from "models/building.glue" // Direct symbol import ``` # 3. Generate code Pick a target (e.g., `typescript`, `python`, `rust`, `go`, `openapi`, `jsonschema`, `protobuf`) and generate code: ```shell glue gen typescript -i models.glue -o ./generated # If you wish to validate the Glue file without generating code, run: glue check models.glue ``` # 4. Configure code generation (optional) To support different use-cases, you can configure code generation with a `.gluerc` file. For example: ```yaml # .gluerc.yaml global: output_base_dir: "./src/generated" # Base output directory for all generated code config: watermark: "none" # Don't generate a watermark lint_suppressions: false # Don't generate lint suppression comments in generated code gen: - mode: typescript files: - "models/*.glue" output: "{file_name}.ts" # Output path template (relative to output_base_dir) config_overrides: typescript: zod: true # Emit Zod types for TypeScript generation - mode: python files: - "schemas/*.glue" output: "schemas/{file_name}.py" config_overrides: python: data_model_library: "dataclasses" # Use Python dataclasses instead of the default Pydantic ``` # 5. Install VS Code extension (optional) For a better development experience, install the [Glue VS Code extension](https://marketplace.visualstudio.com/items?itemName=guywaldman.glue) for syntax highlighting, error diagnostics, hover definitions, go-to definitions and more for Glue files (by default, those ending with `.glue`). --- title: Overview --- Glue is a language for modeling data structure and interfaces, with an ecosystem of tooling for code generation, IDE support, and more. It is designed from the ground up to be simple, human-friendly, AI-friendly, and language-agnostic. For the motivation behind Glue and the challenges it aims to solve, see [this blog post](https://guywaldman.com/posts/introducing-glue) by its creator. If you're familiar with OpenAPI, Protobuf, Smithy or even Avro IDL, you can think of Glue as a batteries-included and minimalistic alternative to those, with a focus on ease of use and flexibility. Glue's philosophy is: 1. **Easy for common users, extensible for power users**. Glue wants you (or your LLM) to write as little code as possible. There should be sane defaults for everything. 1. **Generic with escape hatches** Code generation is a never ending arms race against the complexity of target languages and frameworks. Glue should be as generic as possible, but provide escape hatches for advanced use cases. 1. **Just Work™** Glue should be fast and reliable. It should "just work" for the vast majority of use cases, without needing to fight with it. In addition, Glue should provide helpful error messages when it doesn't work, and ideally even suggest fixes (inspired by Rust's compiler). # Motivation Glue empowers you to define your data models and interfaces in a single source of truth, and revolve your business logic around them. It alleviates the need for multiple disparate tools for generating code (e.g., web servers/clients, OpenAPI specs, Protobuf schemas) in favor of a single unified toolchain. The design goal for a single, simple, fast and reliable toolchain is inspired by projects such as [Rust's Cargo](https://doc.rust-lang.org/cargo/) and [uv](https://docs.astral.sh/uv/). In fact, [**Glue's configuration is itself written in Glue**](https://github.com/guywaldman/glue/blob/main/glue/assets/config_schema.glue) and is used to generate **Rust code** which defines the models (with serialization/deserialization) as well as a **JSON schema**! # Quickstart Refer to the [Quickstart](/docs/quickstart) page for a quick introduction to using Glue, or if you're using an agentic coding solution, provide [gluelang.dev/llms.txt](https://gluelang.dev/llms.txt) as a reference, which contains all of these docs in Markdown format. # The Glue toolchain ## Glue IDL An Interface Definition Language (IDL) for modeling data models and API endpoints in a way that aims to be as simple and generic as possible, while providing adequate "escape hatches" for advanced use cases. For more information, see the [Language Reference](/docs/04-language-reference) page. An example Glue model definition: ```glue model User { name: string age: int email?: string active: bool = true } ``` ## Glue CLI & code generation A command-line interface (CLI) tool for working with Glue files, generating code, and more. For more information, see the [CLI Reference](/docs/cli-reference) page. Example usage: ```shell glue check user.glue # Lint and validate a Glue file glue gen typescript -i user.glue -o ./generated # Generate TypeScript code from a Glue file ``` ### Installation Glue supports multiple platforms (Linux, macOS, Windows) and multiple architectures (x86, ARM). To install: ```shell # Homebrew brew install guywaldman/tap/glue # Linux/macOS curl -fsSL https://github.com/guywaldman/glue/releases/latest/download/install.sh | bash # Windows (PowerShell) iwr -useb https://github.com/guywaldman/glue/releases/latest/download/install.ps1 | iex ``` ## IDE support Glue has a [VS Code extension](https://marketplace.visualstudio.com/items?itemName=guywaldman.glue) that provides syntax highlighting, error diagnostics, hover definitions, go-to definitions and more for Glue files (by default, those ending with `.glue`). ### Usage Glue has a command-line interface (CLI) tool that you can install and use to work with Glue files, generate code, and more. Below is a simple Glue model definition for a `User` type, with some fields. ```glue model User { name: string age: int email?: string active: bool = true } ``` Then use the CLI to validate and generate code: ```shell glue check user.glue glue gen typescript -i user.glue -o ./generated ``` Glue currently supports generation for `typescript`, `python`, `rust`, `go`, `protobuf`, `openapi`, and `jsonschema`. --- title: CLI reference --- # Available commands ```shell $ glue --help Usage: glue Commands: check Checks for validity of a Glue file gen Generates code from a Glue file ast Emits Glue IR as JSON help Print this message or the help of the given subcommand(s) Options: -h, --help Print help -V, --version Print version ``` # Code generation Glue generates code from Glue files using the `gen` command. The generated code can be used for: 1. Serialization/deserialization 1. Data schemas (e.g. JSON Schema, Protobuf messages) 1. Generating OpenAPI spec from which you can generate API clients or server stubs Glue currently supports these languages and formats for code generation (click for more details): 1. [OpenAPI](./codegen-openapi) 1. [JSON Schema](./codegen-jsonschema) 1. [TypeScript](./codegen-typescript) (including Zod types) 1. [Python](./codegen-python) (including support for `pydantic`, `dataclasses`, `attrs`, and `msgspec`) 1. [Rust](./codegen-rust) 1. [Go](./codegen-go) 1. [Protobuf](./codegen-protobuf) To generate code from a Glue file: ```shell # Generate code from a Glue file glue gen api.glue -o ./generated # ...or from a URL: glue gen python https://raw.githubusercontent.com/guywaldman/glue/refs/heads/main/examples/basic.glue -o ./models.py # ...or from stdin: cat api.glue | glue gen -o ./generated # ...or into stdout: glue gen -i api.glue > ./generated ``` # Configuration If you have a `.gluerc` YAML file (or `.gluerc.yaml`, `.gluerc.yml`, `.gluerc.json`) at the same directory level, Glue will automatically use it for configuration. You can also specify a config file with `--config path/to/config`. You can also override specific config options inline with `--set key=value` (e.g. `--set watermark=none` to disable the watermark in generated code). ```shell # Use `.gluerc` in the current directory if it exists glue gen # ...or specify a config file explicitly glue gen --config path/to/.gluerc.yaml # ...or override specific config options inline: glue gen go https://raw.githubusercontent.com/guywaldman/glue/refs/heads/main/examples/basic.glue --set "watermark=none" ``` For configurations, see [Configuration](/docs/configuration). # Static validation Glue files can be statically validated with the `check` command: ```shell glue check api.glue glue check --config path/to/.gluerc.yaml api.glue ``` ## Imports Glue resolves imports recursively for both `check` and `gen`. - Local file inputs resolve imports relative to the importing file. - URL inputs resolve imports relative to the base URL. - Import cycles are handled safely (already-visited sources are skipped). - Imports must be declared at the top of the file (before `const`, `type`, `model`, `endpoint`, and `enum` declarations). # Advanced usage ## Inspect Glue IR Glue can emit the intermediate representation (IR) it uses for code generation, which can be useful for debugging and understanding how Glue processes your files: ```shell glue ast https://raw.githubusercontent.com/guywaldman/glue/refs/heads/main/examples/basic.glue ``` --- title: Quickstart --- Create a Glue file, validate it, and generate code in a few commands. ## 1) Create a model Create a file named `person.glue`: ```glue model Person { name: string age: int address: Address model Address { street: string city: string country_code: string zipcode: string } } ``` ## 2) Validate it ```shell glue check person.glue ``` If the model is valid, the command exits successfully without errors. ## 3) Generate code Generate TypeScript code into `./generated`: ```shell glue gen typescript -i person.glue -o ./generated ``` You can replace `typescript` with any supported target: - `python` - `rust` - `go` - `protobuf` - `openapi` - `jsonschema` ## 4) Use project configuration (optional) If your project has a `.gluerc` (or `.gluerc.yml`, `.gluerc.yaml`, `.gluerc.json`), run: ```shell glue gen --config path/to/.gluerc ``` See the [Configuration](./03-configuration) page for full details. --- title: Configuration --- Use a `.gluerc` file to set defaults and per-target overrides for code generation. ## Supported config files Glue auto-detects these files next to your input file: - `.gluerc` (YAML) - `.gluerc.yaml` - `.gluerc.yml` - `.gluerc.json` If no config file is found, Glue uses built-in defaults. To use a specific config file: ```shell glue gen --config path/to/.gluerc ... ``` ## How the config is structured - `global`: defaults applied to every generation entry. - `gen`: a list of per-input rules (`mode`, `files`) with optional output and overrides. `files` can be a single glob string or a list of glob strings. ## JSON schema Glue ships a JSON schema for config files at [`glue/assets/config_schema.json`](https://github.com/guywaldman/glue/blob/main/glue/assets/config_schema.json). Use it with VS Code's YAML support to get autocomplete and validation in `.gluerc.yaml` files. ## Example ```yaml # yaml-language-server: $schema=https://raw.githubusercontent.com/guywaldman/glue/main/glue/assets/config_schema.json global: output_base_dir: ./generated diagnostics: suppress_warnings: - constant_case config: lint_suppressions: true preserve_generated_identifiers: false watermark: short typescript: zod: false python: data_model_library: pydantic base_model: pydantic.BaseModel rust: include_yaml: true serde_struct_derives: true extra_derives: structs: ["PartialEq", "Eq", "Hash"] enums: ["Ord", "PartialOrd"] unions: ["PartialEq"] type_aliases: ["Ord", "PartialOrd"] go: package_name: glue protobuf: package_name: glue gen: - mode: typescript files: "**/*.glue" output: "src/types/{file_name}.ts" config_overrides: typescript: zod: true - mode: python files: - "schemas/api/*.glue" - "schemas/shared/*.glue" output: "src/generated/{file_name}.py" config_overrides: python: data_model_library: dataclasses lint_suppressions: false - mode: protobuf files: "models/*.glue" output: "proto/{file_name}.proto" config_overrides: protobuf: package_name: myapp.v1 ``` ## Notes - Run `glue gen` to use an auto-discovered config file, or `glue gen --config path/to/.gluerc.yaml` to use one explicitly. - `output` supports `{file_name}` and `{file_ext}` placeholders. - `watermark` supports `full`, `short`, or `none`. - `global.diagnostics.suppress_warnings` suppresses source diagnostics for both `glue check` and `glue gen`. Currently supported warning codes: `constant_case`. - `preserve_generated_identifiers` keeps user-provided identifiers exactly as written, such as model names and fields. Glue may still normalize identifiers it synthesizes from values, such as enum variant constants. - `python.data_model_library` supports `pydantic`, `dataclasses`, `attrs`, or `msgspec`. - `rust.serde_struct_derives` controls serde derives and serde attributes on generated Rust structs, enums, union enums, and type alias newtypes. - `rust.extra_derives` appends additional Rust derive paths by generated shape: `structs`, `enums`, `unions`, or `type_aliases`. --- title: Language reference --- > NOTE: This page explains the Glue syntax in pseudo EBNF form. It is not a formal specification, but rather a reference guide to the language features and syntax, so that it's easier to grok. > If you are interested in the exact grammar, Glue uses [pest](https://pest.rs/) and you can check out the Pest file in the Glue codebase. The Glue IDL is designed to be simple and intuitive, with a syntax that is easy to read and write. Below is a reference of the language features and syntax. # Primitive types Glue supports the following primitive types: - `string` - `int` - `uint` - `i8`, `i16`, `i32`, `i64` - `u8`, `u16`, `u32`, `u64` - `float` - `any` - `bool` # Compound types - `model` (a structured type with named fields) - `enum` (enumeration of string values) - `type` alias declarations (e.g., `type UserID = string`) - `const` declarations (e.g., `const MAX_PAGE_SIZE: int = 100`) - `T[]` (an array/list of type `T`) - `(T, U)` (a fixed-length tuple) - `Record` (a map/dictionary type with keys of type `T` and values of type `U`) - `A | B` (a union type) - `endpoint` (an API endpoint definition with method, path, parameters, and responses) - `service` (a Protobuf service definition with RPC methods) # Block member separators Model, anonymous model, endpoint, service, and RPC blocks accept either whitespace/newlines or commas between members. Commas are useful for compact one-line shapes: ```glue model User { id: string, email?: string, profile: { name: string, age?: u8 } } endpoint "GET /users/{id}" GetUser { responses: { 200: User, 4XX: ApiError } } ``` # Type aliases Glue supports type aliases, which let you define reusable names for existing types. ```glue type UserId = string type UserIds = UserId[] model User { id: UserId related: UserIds } ``` Notes: - Aliases declared inside a model are scoped to that model. - Alias targets can be any valid type expression. # Constants Glue supports top-level and model-scoped constants for reusable literal values. ```glue const MAX_PAGE_SIZE = 100 const DEFAULT_LIMIT = MAX_PAGE_SIZE * 2 const USER_ALIAS = "user_" + "id" const _RETRY_MS = (100 + 50) * 2 // Optional explicit annotation const FEATURE_ENABLED: bool = true model FieldNames { const SUFFIX = "_id" const USER_ID_ALIAS = "user" + SUFFIX const _INTERNAL_ALIAS = "internal_id" } model Tags { const USER_ID = 1 } model User { @field(alias=FieldNames.USER_ID_ALIAS, proto_tag=Tags.USER_ID) user_id: int } ``` Notes: - Constant types are inferred from folded values. Optional annotations can be integer primitives, `string`, or `bool`. - Int expressions support `+`, `*`, parentheses, and references to int constants. - String expressions support `+`, parentheses, and references to string constants. - Bool expressions support literals and references only. - Constants can be referenced before they are declared. Cycles are rejected. - Constants declared inside a model are scoped to that model. Public model constants can be referenced as `Model.CONSTANT`; nested model constants can be referenced as `Outer.Inner.CONSTANT`. - Names should use `CONSTANT_CASE`. A leading `_` marks a constant as private in generated language targets. Private model constants cannot be referenced from outside their owning model as `Model._CONSTANT`. - Constants can be used in field defaults and decorator arguments, including `@field(alias=...)` and `@field(proto_tag=...)`. - TypeScript, Python, Rust, and Go emit standalone constants. Model-scoped constants are emitted with model-path prefixes. OpenAPI, JSON Schema, and Protobuf only consume folded constant values. # Models **Models** are the foundation of Glue data models. They are defined using the `model` keyword, followed by the model name and a block of fields. ```glue /// Optional public documentation model { [?]: [= ] ... } ``` For example: ```glue /// A user of the system model User { name: string age?: int // Optional fields are denoted with a `?` active: bool = true // Default values are supported contact: ContactInfo // Models can be nested model ContactInfo { email: string phone?: string } } ``` Fields can also use anonymous structs for one-off inline shapes: ```glue model User { profile: { bio: string age?: int } } ``` ## Model decorators Fields can be decorated with the `@field` decorator, which allows you to specify additional metadata for the field that can be used by code generators. ```glue model FieldNames { const USER_EMAIL_ALIAS = "email" } model User { @field(alias=FieldNames.USER_EMAIL_ALIAS, example="user@example.com") email_address: string } ``` For Protobuf generation, fields can use `@field(proto_tag=)` to set stable field tags. If one field in a model has `proto_tag`, every field in that model must have one. # Enums **Enums** are defined using the `enum` keyword, followed by the enum name and pipe-separated primitive string values. ```glue enum : "" | "" | ... ``` For example: ```glue enum Color: "red" | "green" | "blue" ``` Enums can be nested inside models as well: ```glue model Product { name: string category: Category enum Category: "electronics" | "clothing" | "books" } ``` # Imports Glue supports explicit imports, which must appear at the top of the file (before any `const`, `type`, `model`, `endpoint`, `service`, or `enum` declarations). ```glue // Import all exported symbols import * from "models/common.glue" // Import all symbols under a namespace alias import * as common from "models/common.glue" // Import selected symbols (with optional aliasing) import { User, Address as PostalAddress } from "models/domain.glue" ``` Notes: - Import sources are string literals. - Imports are supported for both local files and HTTP(S) URLs (for URL-based inputs). # Endpoints **Endpoints** are defined using the `endpoint` keyword, followed by the HTTP method and path, endpoint name, and a block of parameters and responses. They mostly follow what you expect from the OpenAPI specification, with defaults such that typing out endpoints is as frictionless as possible. ```glue endpoint " " { // Optional body (e.g., for POST/PUT/PATCH requests) // Flavor A - single type (implicitly for "application/json") body: // Flavor B - multiple types with explicit MIME types body: { "application/json": "application/xml": ... } // Optional schema for respones responses: { : } // Optional schema for headers headers: { /// An optional unique request identifier for tracing. "X-Request-ID"?: string } } ``` For example: ```glue /// List posts for a user endpoint "GET /users/{user_id}/posts" ListUserPosts { responses: { 200: PostListResponse 4XX: ApiError 5XX: ApiError } } ``` # Services **Services** are defined using the `service` keyword. They are currently used by Protobuf generation. ```glue service { rpc { body: returns: } } ``` For example: ```glue model GetUserRequest { @field(proto_tag=1) user_id: int } model User { @field(proto_tag=1) user_id: int } service UserService { rpc GetUser { body: GetUserRequest returns: User } } ``` # Current limitations Below is a non-exhaustive list of features that are commonly requested or expected in an IDL like Glue, but are not currently supported. If Glue gains some traction, these will be managed as issues and prioritized accordingly, however for now this acts as a reference for common features you may expect to see in Glue but are not yet implemented: * Endpoints - proper typing of query/path parameters, authentication/authorization schemes, and some other common API features are not yet supported * Services - RPC `body` and `returns` currently support message types only * Intersections of types (e.g., `type A = B & C`) * Generics (e.g., `model Response { data: T }`) If you would like to see any of these supported in Glue, please open (or upvote) a feature request in the [Glue GitHub repo](https://github.com/guywaldman/glue). --- title: AI & LLMs --- To make Glue LLM-friendly, [/llms.txt](/llms.txt) includes the entirety of these docs. Simply provide it to your favorite agentic coding solution. It is roughly 4K tokens, and can be reduced if there is popular demand for it. We hope that Glue gains adoption and will be included favorably in the training data of future LLMs, so that it can be used out-of-the-box without needing to provide the docs. Note that Glue is designed to be human-friendly and additionally LLM-friendly, at least to a reasonable extent. LLMs can excel at structured formats (such as OpenAPI specs written in JSON/YAML), however they can often make small mistakes due to the verbose and strict nature of those formats. Therefore, you will find that Glue's syntax is a bit more concise and forgiving, while still being unambiguous and easy to parse for both humans and machines. --- title: OpenAPI section: Code generation --- Glue supports `openapi` as a code generation target, allowing you to generate OpenAPI specifications from Glue files. This can be useful for defining RESTful APIs and generating client libraries or server stubs in various programming languages. Glue currently supports OpenAPI v3.0, and only JSON output. Simply run: ```shell glue gen openapi -i api.glue -o ./openapi.json ``` All integer primitive variants emit OpenAPI `"type": "integer"`. `i32`/`u32` use `format: int32`, and `i64`/`u64` use `format: int64`. ## Example For this Glue spec: ```glue /// Returns a user by ID. endpoint "GET /users/{id}" { responses: { 2XX: User 4XX: ApiError 5XX: ApiError } } /// Create a new user. endpoint "POST /users" { body: User responses: { 201: User 4XX: ApiError 5XX: ApiError } } model User { id: string name: string email: string } model ApiError { error_code: Code message?: string enum Code: "USER_NOT_FOUND" | "INVALID_REQUEST" | "INTERNAL_ERROR" } ``` ...generating an OpenAPI spec... ```shell glue gen openapi -i api.glue -o ./openapi.json ``` ...will produce: ```json { "openapi": "3.0.0", "info": { "title": "Generated API", "version": "1.0.0" }, "paths": { "/users/{id}": { "get": { "summary": "Returns a user by ID.", "description": "Returns a user by ID.", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "4XX": { "description": "4XX response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } } }, "2XX": { "description": "2XX response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/User" } } } }, "5XX": { "description": "5XX response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } } }, "200": { "description": "2XX response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/User" } } } } } } }, "/users": { "post": { "summary": "Create a new user.", "description": "Create a new user.", "responses": { "4XX": { "description": "4XX response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } } }, "5XX": { "description": "5XX response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } } }, "201": { "description": "201 response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/User" } } } } } } } }, "components": { "schemas": { "ApiError": { "type": "object", "required": [ "error_code" ], "properties": { "error_code": { "$ref": "#/components/schemas/Code" }, "message": { "type": "string" } } }, "User": { "type": "object", "required": [ "id", "name", "email" ], "properties": { "name": { "type": "string" }, "email": { "type": "string" }, "id": { "type": "string" } } } } } } ``` # Current limitations * Proper typing of query/path parameters, authentication/authorization schemes are not yet supported * Tuples are downcast to bounded arrays because OpenAPI 3.0 does not support positional tuple validation --- title: JSON Schema section: Code generation --- Somewhat similarly to OpenAPI, Glue offers `jsonschema` as a code generation target, allowing you to generate JSON Schema specifications from Glue files. This can be useful for validating data structures and generating client libraries or server stubs in various programming languages. In fact, this is used internally in the Glue codebase for Glue's configuration! See [glue/assets/config_schema.glue](https://github.com/guywaldman/glue/blob/main/glue/assets/config_schema.glue) Simply run: ```shell glue gen jsonschema -i config.glue -o ./config.json ``` All integer primitive variants emit JSON Schema `"type": "integer"`. ## Example For this Glue spec: ```glue /// Represents a person. // IMPORTANT: If your file has multiple top-level models, specify `@root` on exactly one model. // In this case, not required. model Person { /// The person's name. name: string /// The person's age. age: int /// The person's address. address: Address /// The person's address. model Address { /// The street of the address. // NOTE: Not case-sensitive. street: string /// The city of the address. city: string /// The country code of the address. country_code: string /// The zipcode of the address. zipcode?: string } } ``` ...generating a JSON Schema spec... ```shell glue gen jsonschema -i config.glue -o ./config.json ``` ...will produce: ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "Person", "type": "object", "properties": { "address": { "$ref": "#/$defs/Person::Address", "description": "The person's address." }, "age": { "type": "integer", "description": "The person's age." }, "name": { "type": "string", "description": "The person's name." } }, "$defs": { "Person": { "type": "object", "properties": { "address": { "$ref": "#/$defs/Person::Address", "description": "The person's address." }, "age": { "type": "integer", "description": "The person's age." }, "name": { "type": "string", "description": "The person's name." } } }, "Person::Address": { "type": "object", "properties": { "city": { "type": "string", "description": "The city of the address." }, "country_code": { "type": "string", "description": "The country code of the address." }, "street": { "type": "string", "description": "The street of the address." }, "zipcode": { "type": "string", "description": "The zipcode of the address." } } } } } ``` ## Notes - Tuples are emitted as fixed-length arrays using `prefixItems`, `minItems`, and `maxItems`. --- title: Protobuf section: Code generation --- Glue supports `protobuf` as a code generation target, allowing you to generate `.proto` schemas from Glue models, enums, and services. Simply run: ```shell glue gen protobuf -i models.glue -o ./models.proto ``` ## Configuration You can configure the emitted protobuf package name: ```yaml global: config: protobuf: package_name: myapp.v1 ``` ## Example For this Glue spec: ```glue model User { id: int nickname?: string name: string tags: string[] } enum Role: "admin" | "user" ``` ...generating protobuf... ```shell glue gen protobuf -i models.glue -o ./models.proto ``` ...will produce: ```proto syntax = "proto3"; package glue; message User { int32 id = 1; optional string nickname = 2; string name = 3; repeated string tags = 4; } enum Role { ADMIN = 0; USER = 1; } ``` Enum constants are generated in `CONSTANT_CASE` from the Glue string values. Values that normalize to the same Protobuf identifier are rejected because Protobuf enum value names share the package scope. Integer primitives map to Protobuf scalar integer types where available. `i64` and `u64` emit `int64` and `uint64`; `uint`, `u8`, `u16`, and `u32` emit `uint32`; other signed integer primitives emit `int32`. ## Field tags By default, Glue assigns Protobuf field tags from field declaration order, starting at `1`. You do not need to annotate fields for simple or early schemas. Use `@field(proto_tag=)` when you need stable Protobuf wire compatibility across field reordering: ```glue model User { @field(proto_tag=1) id: int @field(proto_tag=2) name: string } ``` If one field in a message has `proto_tag`, every field in that message must have one. Untagged messages keep source-order numbering. `proto_tag` can use folded int constant expressions, including model-scoped constants: ```glue model Tags { const USER_ID = 1 } model User { @field(proto_tag=Tags.USER_ID) id: int } ``` ## Optional fields Optional Glue fields generate `optional` Protobuf fields: ```glue model User { nickname?: string display_name: string? tags?: string[] metadata?: Record } ``` ```proto message User { optional string nickname = 1; optional string display_name = 2; repeated string tags = 3; map metadata = 4; } ``` Protobuf does not track field presence for repeated or map fields, so optional repeated/map Glue fields are emitted as regular `repeated` and `map` fields. ## Services Glue services generate Protobuf service definitions: ```glue model GetUserRequest { @field(proto_tag=1) user_id: int } model User { @field(proto_tag=1) user_id: int } service UserService { rpc GetUser { body: GetUserRequest returns: User } } ``` ```proto service UserService { rpc GetUser (GetUserRequest) returns (User); } ``` ## Notes - Endpoint declarations are ignored by the Protobuf generator. ## Current limitations - `Record` is emitted as `map` for supported Protobuf key/value types. - Homogeneous tuples are downcast to `repeated T`; heterogeneous tuples are rejected because Protobuf has no positional tuple type. - Anonymous structs are emitted as generated messages named from the owning field path. - Unions are emitted as `oneof` only when every member is valid inside a Protobuf `oneof`; repeated fields, maps, optional members, and explicit `proto_tag` unions are rejected with an error. - RPC `body` and `returns` must be message types. --- title: Python section: Code generation --- Glue supports `python` as a code generation target, allowing you to generate Python models and enums from Glue files. Simply run: ```shell glue gen python -i models.glue -o ./models.py ``` ## Supported model libraries Glue can generate Python models using: - `pydantic` (default) - `dataclasses` - `attrs` - `msgspec` Configure this in `.gluerc`: ```yaml global: config: python: data_model_library: pydantic base_model: pydantic.BaseModel ``` `base_model` is used only for `pydantic`. ## Example For this Glue spec: ```glue model User { id: int @field(alias="firstName") first_name: string email?: string } enum UserRole: "admin" | "user" ``` ...generating Python... ```shell glue gen python -i models.glue -o ./models.py ``` ...will produce code similar to: ```python from pydantic import BaseModel from pydantic import Field from enum import StrEnum from typing import Any, Annotated, Optional, Union class User(BaseModel): id: Annotated[int, Field()] first_name: Annotated[str, Field(alias="firstName")] email: Annotated[Optional[str], Field(default=None)] class UserRole(StrEnum): ADMIN = "admin" USER = "user" ``` ## Notes - Nested Glue models are emitted as flattened class names (e.g. `Parent_Child`). - `@field(alias="...")` is applied in all supported Python model libraries. - All integer primitives emit Python `int`. - Tuples are emitted as Python tuple annotations, e.g. `tuple[str, int]`. - Glue `type` aliases are emitted as public `TypeAlias` declarations; model fields still use the concrete resolved annotations. Aliases starting with `_` are inlined instead. - Anonymous structs are emitted as generated classes named from the owning field path. --- title: TypeScript section: Code generation --- Glue supports `typescript` as a code generation target. Simply run: ```shell glue gen typescript -i models.glue -o ./models.ts ``` ## Output modes TypeScript generation supports: - **Types only** (default): emits `export type ...` - **Zod mode**: emits Zod schemas and inferred types Enable Zod mode in `.gluerc`: ```yaml global: config: typescript: zod: true ``` ## Example For this Glue spec: ```glue model User { name: string age: int email?: string } enum UserRole: "admin" | "user" ``` ...generating TypeScript... ```shell glue gen typescript -i models.glue -o ./models.ts ``` ...will produce code similar to: ```ts export type User = { name: string; age: number; email?: string | null; }; export type UserRole = "admin" | "user"; ``` With `typescript.zod: true`, output is schema-first: ```ts import { z } from "zod"; export const UserSchema = z.object({ name: z.string(), age: z.number(), email: z.string().nullable().optional(), }); export type User = z.infer; ``` ## Notes - Nested Glue models are emitted as flattened names (e.g. `Parent_Child`). - All integer primitives emit `number` (or `z.number()` in Zod mode). - `Record` is emitted as `Record` (or `z.record(...)` in Zod mode). - Tuples are emitted as TypeScript tuple types, e.g. `[string, number]` (or `z.tuple(...)` in Zod mode). - Glue `type` aliases are emitted as exported TypeScript type aliases. Aliases starting with `_` are inlined instead. - Anonymous structs are emitted inline in both types-only and Zod output. --- title: Go section: Code generation --- Glue supports `go` as a code generation target, allowing you to generate Go structs and enums from Glue models. Simply run: ```shell glue gen go -i models.glue -o ./models.go ``` ## Configuration You can configure the emitted package name: ```yaml global: config: go: package_name: myapi ``` ## Example For this Glue spec: ```glue model User { id: string @field(alias="first_name") firstName: string tags?: string[] } enum Status: "active" | "inactive" ``` ...generating Go... ```shell glue gen go -i models.glue -o ./models.go ``` ...will produce code similar to: ```go package glue type User struct { Id string `json:"id"` FirstName string `json:"first_name"` Tags *[]string `json:"tags,omitempty"` } type Status string const ( StatusActive Status = "active" StatusInactive Status = "inactive" ) ``` ## Notes - Optional fields are emitted as pointers and include `,omitempty` in JSON tags. - `int`/`uint` and fixed-width integer primitives emit their Go equivalents (`int`, `uint`, `int8`, `uint64`, etc.). - Unions are emitted as `interface{}`. - `Record` is emitted as `map[K]V`. - Tuples with arity 2 through 4 are emitted as generated `TupleN[...]` helper types that marshal as JSON arrays; larger tuples fall back to fixed `[N]interface{}` arrays. - Glue `type` aliases are emitted as exported Go aliases when their generated names are exported. Aliases starting with `_` are inlined instead. - Anonymous structs are emitted as generated structs named from the owning field path. --- title: Rust section: Code generation --- Glue supports `rust` as a code generation target, allowing you to generate Rust structs and enums with Serde derives. Simply run: ```shell glue gen rust -i models.glue -o ./models.rs ``` ## Configuration Rust generation currently supports: ```yaml global: config: rust: include_yaml: true serde_struct_derives: false extra_derives: structs: ["PartialEq"] enums: ["Ord", "PartialOrd"] unions: ["PartialEq"] type_aliases: ["Ord", "PartialOrd"] ``` When `include_yaml` is enabled, generated models include `from_yaml`/`to_yaml` helper methods. Set `serde_struct_derives: false` to omit serde `Serialize`/`Deserialize` derives and serde attributes from generated structs, enums, union enums, and type alias newtypes. If both options are combined, provide serde impls yourself before using the YAML helpers. Use `extra_derives` to append additional Rust derive paths by generated shape. Entries must be Rust paths such as `Hash`, `serde::Serialize`, or `schemars::JsonSchema`. ## Example For this Glue spec: ```glue model User { id: int @field(alias="first_name") firstName: string email?: string metadata: Record } enum Status: "active" | "inactive" ``` ...generating Rust... ```shell glue gen rust -i models.glue -o ./models.rs ``` ...will produce code similar to: ```rust use std::collections::HashMap; #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Default)] pub struct User { pub id: isize, #[serde(rename = "first_name")] pub firstName: String, #[serde(skip_serializing_if = "Option::is_none")] pub email: Option, pub metadata: HashMap, } #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Status { #[serde(rename = "active")] Active, #[serde(rename = "inactive")] Inactive, } ``` ## Notes - Optional fields are emitted as `Option`. - Arrays are emitted as `Vec`. - `int` emits `isize`, `uint` emits `usize`, and fixed-width integers emit their Rust equivalents (`i8`, `u64`, etc.). - Tuples are emitted as native Rust tuples, e.g. `(String, isize)`. - `Record` is emitted as `HashMap`. - Glue `type` aliases are emitted as public tuple newtype structs. Aliases starting with `_` are inlined instead. - Type alias newtypes derive `Copy`, `PartialEq`, `Eq`, and `Hash` by default only for conservative copy/hash-safe shapes such as integers, bools, regular enums, and tuples of safe members. - Regular enums derive `Copy` and `Hash` by default. - By default, unions are emitted as generated `#[serde(untagged)]` enums. - Anonymous structs are emitted as generated structs named from the owning field path.