Skip to content Documentation index for agents (llms.txt)
Glotto Beta
Get started

glotto.yml reference

glotto.yml is the single config for a project: it describes your organization, the API spec to read, the SDK targets to emit, your API surface, and how the generated clients behave. This reference documents every key across this overview and the linked optional-reference pages. Where a key has its own page, it links there rather than repeating detail.

Editor validation

Generate the JSON Schema for glotto.yml and reference it from the file for inline completion and validation in VS Code, Cursor, Neovim, and other editors with the YAML language server:

glotto schema --out glotto.schema.json
# yaml-language-server: $schema=./glotto.schema.json
organization:
  name: Acme
  # …

glotto schema (no flags) prints the schema to stdout instead. It’s the same byte-stable schema core-config exports as glottoConfigJsonSchema().


Required keys

organization

organization:
  name: Acme
  contact: support@acme.com
  homepage: https://acme.com   # optional

  # optional: security metadata → a SECURITY.md in every generated repo
  security_contact: security@acme.com
  security_policy_url: https://acme.com/security
  security_policy_terms: Reports are acknowledged within two business days.

name and contact are required; homepage is optional.

Security metadata → SECURITY.md

Setting any of security_contact, security_policy_url, or security_policy_terms makes glotto generate write a SECURITY.md into every generated repo — the file GitHub’s “Report a vulnerability” affordance keys off, so a researcher who finds an issue in your SDK has a documented route to you. Set none of them and nothing is emitted; your output is byte-for-byte what it was.

Each key contributes one section, and an unset key contributes none:

Key Section it adds
security_contact Reporting a Vulnerability — the address, plus a note directing researchers away from public issue trackers. Must be an email address.
security_policy_url Disclosure Policy — a link to your published policy, named with organization.name. Must be an absolute http/https URL.
security_policy_terms Additional Terms — your prose, verbatim. Free text, no grammar.

The document is deterministic: it embeds no date or other ambient value, so regenerating an unchanged config reproduces it byte-for-byte.

Input source — exactly one of openapi / asyncapi / graphql

openapi:
  source: ./spec/openapi.yaml          # a local path or an http(s) URL
  code_samples:
    formats: [x-codeSamples, readme]   # optional: code-sample formats to emit

source accepts a string — a local path (resolved against the directory holding your glotto.yml, so it means the same thing wherever you run Glotto from) or an http(s):// URL — or one of three structured objects: command (run your own exporter), introspect (read a framework’s source directly), or git (below). asyncapi takes a source; graphql takes a source plus optional operations and autogenerate. Exactly one input source must be present.

The same source forms apply to all three inputs, and to graphql’s second document: a git-hosted AsyncAPI channel document, or a GraphQL schema produced by your own exporter, is written exactly the way the OpenAPI equivalent is.

asyncapi:
  source:
    git: { repo: https://github.com/acme/api-definitions.git, ref: main, path: events/chat.yaml }

# or
graphql:
  source: { command: npm, args: [run, print-schema], output: { kind: stdout } }
  operations: ./operations.graphql

The one exception is introspect, which is accepted on openapi.source only: introspection reads a framework’s source and synthesizes an OpenAPI document, so it cannot be what an asyncapi or graphql key means. Writing it anywhere else is a glotto generate error (GLOTTO_CONFIG_INTROSPECT_SOURCE_OPENAPI_ONLY).

Specs in another repository

When your OpenAPI document lives in a different git repository — the usual shape when a separate API-definition repo produces the spec — point source at it directly instead of vendoring a copy you then have to keep in step by hand:

openapi:
  source:
    git:
      repo: https://github.com/acme/api-definitions.git
      ref: main                    # a branch, tag, or commit sha
      path: openapi/petstore.yaml  # relative to the repository root

All three keys are required. path is resolved inside the cloned repository, never against your glotto.yml — a path escaping the repository is rejected. Glotto shallow-clones repo at ref on each generation, reads that one file, and removes the clone; authentication uses your ambient git configuration. The same { git: … } object is accepted wherever a spec or overlay is referenced — asyncapi.source, graphql.source, graphql.operations, every docs.versions[] snapshot, docs.changelog.previous_spec.source, and an apply_overlay source.

Because ref can be a moving branch, the verification report records the exact bytes it read, under the machine-independent origin git:<repo>#<ref>:<path>.

Multi-file specs

Glotto ingests a single OpenAPI document. If your spec is split across multiple files ($refs into sibling files — common for large APIs and a frequent migration case), bundle it into one document first. Glotto does not merge multiple sources itself, so the bundling stays in your control — there are two ways to wire it:

Pre-bundle — run a bundler as a build step and point source at the result:

redocly bundle ./openapi/main.yaml -o ./openapi/bundled.yaml
openapi:
  source: ./openapi/bundled.yaml

Bundle inline — let Glotto run the bundler at generate time via the command form of source; its stdout (or a file it writes) is ingested directly, with no committed intermediate:

openapi:
  source:
    command: redocly
    args: [bundle, ./openapi/main.yaml]
    output: { kind: stdout } # or { kind: file, path: ./.glotto/bundled.yaml }

environments

environments:
  production: https://api.acme.com
  staging:    https://staging-api.acme.com

A map of environment name → base URL, with at least one entry.

default_environment

environments:
  dev:        https://dev.acme.com
  production: https://api.acme.com

default_environment: production

Which environment everything Glotto emits points at when it needs one base URL — your SDK clients and their README quickstarts, the code samples on your docs site, your docs playground, and your MCP server’s upstream. Optional; it must name one of the keys under environments.

Leave it out and Glotto resolves the default for you, in this order:

  1. an environment named production, if you declared one — the name glotto init writes;
  2. otherwise the first environment by sorted name.

That second rule exists so your generated code depends only on what your config says, never on the order you happened to type it in. It is a determinism rule, not a guess at what you meant — so when it is what decides the answer (two or more environments, none of them named production, none declared), glotto generate tells you, with GLOTTO_CONFIG_DEFAULT_ENVIRONMENT_INFERRED. Naming an environment that isn’t declared is an error, GLOTTO_CONFIG_DEFAULT_ENVIRONMENT.

targets

targets:
  typescript:
    package_name: "@acme/sdk"
  react_native:
    package_name: "@acme/sdk-react-native"
    secure_storage: keychain    # or 'mmkv', 'expo'
    expo_plugin: true           # optional explicit opt-in for the public ./plugin subpath
  csharp:
    package_name: Acme.Commerce  # NuGet PackageId (publish identity)
    namespace: Acme.Commerce     # C# namespace (code identity)
  go:
    namespace: github.com/acme/commerce-go   # go.mod module path
  java:
    namespace: com.acme.commerce             # Java package + Gradle group
  dart:
    secureStorage: true          # emit the flutter_secure_storage token-store adapter
  python: {}

A map of language slug → per-target config. Every target accepts:

  • package_name — the published/registry identity stamped on the manifest (npm name, PyPI name, NuGet <PackageId>, …).

  • namespace — the SDK’s code identity, interpreted idiomatically per engine: the C# namespace/<RootNamespace>, Java/Kotlin package (+ source directory + Gradle group), Go go.mod module path, PHP PSR-4 namespace, Ruby/Elixir top-level module, Python’s import package (dots nest into directories, so acme.commerce gives from acme.commerce import Client), and Rust’s Cargo [lib] name (a lib name is a flat identifier, so dots collapse — acme.commerce gives use acme_commerce). Optional — absent means each engine’s default (Glotto / com.glotto / glotto_sdk). Engines whose code identity is the published package — typescript/react_native (npm name), dart, swift — have no separate code identity to set: package_name is the only knob, and setting namespace on one of them warns, GLOTTO_CONFIG_NAMESPACE_NOT_APPLIED, rather than being silently ignored.

  • repo — the target’s release repo (owner/name; Azure Repos org/project/repo), with an optional repo_provider (github, gitlab, bitbucket, or azure-repos) naming the VCS host. Used by the hosted platform’s targets sync, which derives each project’s SDK-target records from this file — where release PRs and tags for that language’s SDK go. Optional — omit both for registry-only targets; repo_provider requires repo.

  • repo_path — for a monorepo release repo: the repo-relative directory this language’s SDK lives under (e.g. sdks/typescript). Several targets may share one repo when each names a distinct repo_path — each gets its own subtree, release branch, and release PR. Optional (requires repo) — absent means the SDK owns the repo root, the one-repo-per-SDK layout.

  • release — this target’s branch names, overriding the project-level release block one name at a time. Three optional keys, all defaulting to Glotto’s generatednextmain vocabulary:

    targets:
      typescript:
        repo: acme/acme-typescript
        release:
          branch: sdk-next            # the release PR's head — the merged result
          baseline_branch: sdk-generated  # the pristine generator output (the merge base)
          base_branch: trunk          # the release PR's base — released code

    branch and baseline_branch must differ — one branch cannot be both the merged result and the base it merges against. Two targets releasing to the same repo may not name the same branch. Use base_branch when a repository’s released branch is not called main: Glotto refuses to open the PR rather than guessing at a branch you never named.

  • variantsspec_repo only: which documents the published spec repo carries. A non-empty list of base (your spec as supplied, exclude-pruned), with_transforms (after every transforms correction — the document your SDKs were generated from), and with_code_samples (with per-operation SDK samples embedded as x-codeSamples). Optional — absent means all three. An unknown member, and a member listed twice, are both glotto generate errors rather than being ignored or deduplicated: a variant you asked for and did not get is never silently dropped. Asking for one your input cannot produce fails loudly — see which variants each input can publish.

  • formatsspec_repo only: the serializations each variant is published in. A non-empty list of yaml and json, same duplicate/unknown-member rules. Optional — absent means yaml alone. Emitted file names are a function of the selection’s content, never of the order you listed it in.

React Native additionally accepts secure_storage and expo_plugin. The Expo plugin is emitted by default only when the API has an intrinsic plugin capability. An API without OAuth or bearer-style/secure-storage auth capability—for example, one using only custom or API-key auth—has no ./plugin export by default. Set expo_plugin: true to opt that target in explicitly, then import <your-sdk>/plugin from the generated package in your Expo config. Dart accepts secureStorage: true (emit the flutter_secure_storage-shaped token-store adapter — see Dart). Each target is an open object, so language-specific keys are allowed. See React Native for the RN-specific options.

resources

resources:
  invoices:
    models:
      invoice: '#/components/schemas/Invoice'
    methods:
      createInvoice:   post /v1/invoices
      getInvoice:       get /v1/invoices/{id}
      listInvoices:    { endpoint: get /v1/invoices, paginated: cursor }
    subresources:
      line_items:
        methods:
          addInvoiceLine: post /v1/invoices/{invoice_id}/lines

Your API surface, grouped into resources. A method is either a "VERB /path" string or an object { endpoint, paginated?, streaming?, polling?, default_request_options? }. resources recurse through subresources arbitrarily deep.

Set default_request_options on a resource or method to configure routing headers, attempt timeouts and retry limits for its calls.

The method key declares the emitted method name. Writing list: get /v1/invoices emits client.invoices.list() in every language, whatever the operation’s operationId says. Declare nothing and the emitted name is the operationId exactly as before — naming is opt-in per operation, so a config with no methods keys produces a byte-identical SDK.

The resource tree itself is still derived from your spec’s paths: the key names the method, not the resource, and never moves a method between resources.

Two things are refused rather than guessed, and both stop glotto generate (GLOTTO_CONFIG_RESOURCE_METHOD_NAME) — a name you asked for and did not get is never silently dropped:

  • an endpoint matching no operation in your spec (the verb and path must match exactly, placeholder names included);
  • two operations on one resource ending up with the same method name. Glotto names both and stops, rather than picking a winner or appending a suffix — you wrote both names, so you hold the fix.

Renaming a method your customers already call is an API-compatible change if you say so: keep the old name working with aliases and mark it with deprecated, and breaking-change detection reports the rename as non-breaking.


Optional-key reference pages

Optional settings are grouped by the part of the generated surface they shape:

  • Client behavior — client runtime defaults, transforms, naming, custom casings, positional parameters, and enum naming.
  • Model shaping — model names and inlining, enum types, soft-required inputs, and auto-populated values.
  • API surface — target filtering, global exclusion, client methods, aliases and deprecations, streaming, and query serialization.
  • Project settings — diagnostics, project-wide settings, code owners, MCP, generated docs, licensing, releases, README examples, and hosted binding.

See the CLI reference for the commands that read this config, the pipeline concept for how it’s consumed, or Getting started for a walkthrough.