Documentation

Everything you need to ship one schema

Install the CLI, write a .syln schema, and generate type-safe code for seven languages from a single source of truth.

Introduction

SyncLangs eliminates type drift in polyglot systems. You describe your data structures once in the .syln DSL, and the compiler emits idiomatic, type-safe definitions for TypeScript, Python, Go, Rust, Java, C++ and C#.

Generation happens at build time. There is no runtime, no reflection and nothing shipped to production. The schema is the contract, and every service is generated from it, so the targets cannot disagree.

Installation

Install with one command. macOS and Linux:

curl -fsSL https://synclangs.com/install.sh | sh

Windows (PowerShell):

irm https://synclangs.com/install.ps1 | iex

The script installs uv if needed, then the CLI. Prefer to install from PyPI yourself? Use pip or uv:

pip install synclangs# oruv tool install synclangs

Either way you get both the syln and synclangs commands. Verify, then scaffold a project:

syln versionsyln init

Quick start

syln init creates a starter schema and a syln.config.json. Edit the schema, then generate:

$ syln generate          # generate all configured targets$ syln watch        # regenerate on every save$ syln check        # fail if generated code is out of date

Wire syln check into CI to fail the build whenever generated code drifts from the schema.

Schema syntax

The DSL is small and intentional. It supports enums, structs, type aliases, defaults, optionals and nested collections.

1# user.syln2type Role = "admin" | "member" | "guest"3 4struct User {5  id:        string6  email:     string7  role:      Role8  tags:      list<string>9  metadata:  map<string, string>10  createdAt: datetime11  active:    bool = true12  bio:       string?13}
  • struct defines a record; type defines an alias or string union.
  • A trailing ? marks a field optional; = value sets a default.
  • list<T> and map<K, V> nest to any depth.

Type mapping

Each primitive and collection maps to the idiomatic type in every target language:

.sylnTypeScriptPythonGoRust
stringstringstrstringString
intnumberintint64i64
floatnumberfloatfloat64f64
boolbooleanboolboolbool
datetimeDatedatetimetime.TimeDateTime<Utc>
list<T>T[]list[T][]TVec<T>
map<K,V>Record<K,V>dict[K,V]map[K]VHashMap<K,V>
T?T | nullOptional[T]*TOption<T>

Try every mapping live in the playground.

Commands

The CLI ships as the syln command:

syln init                     # scaffold a project + syln.config.jsonsyln generate                 # generate every enabled targetsyln generate --out-ts ./gen  # emit one target by naming its outputsyln watch                    # regenerate on savesyln check                    # validate schemas, non-zero exit on errorsyln infer ./src              # derive a .syln schema from existing code

Configuration

syln.config.json declares your input directory, which targets are enabled, where each one is written, and per-language options:

1{2  "version": "1.0",3  "input": "./shared",4  "outputs": {5    "typescript": { "enabled": true, "outDir": "./generated/ts", "exportStyle": "named" },6    "python":     { "enabled": true, "outDir": "./generated/py", "useDataclasses": true }7  },8  "options": {9    "caseConversion": { "fields": { "typescript": "camelCase", "python": "snake_case" } }10  }11}

Type safety

The compiler performs full parsing and semantic validation before it emits anything. Unknown types, duplicate fields and invalid defaults are reported with the file and line.

Because every target is generated from the same validated schema, a change in one place propagates everywhere. If a change would break a downstream service, syln check exits non-zero so CI catches it before merge.