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 | shWindows (PowerShell):
irm https://synclangs.com/install.ps1 | iexThe script installs uv if needed, then the CLI. Prefer to install from PyPI yourself? Use pip or uv:
pip install synclangs# oruv tool install synclangsEither way you get both the syln and synclangs commands. Verify, then scaffold a project:
syln versionsyln initQuick 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 dateWire 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}structdefines a record;typedefines an alias or string union.- A trailing
?marks a field optional;= valuesets a default. list<T>andmap<K, V>nest to any depth.
Type mapping
Each primitive and collection maps to the idiomatic type in every target language:
| .syln | TypeScript | Python | Go | Rust |
|---|---|---|---|---|
| string | string | str | string | String |
| int | number | int | int64 | i64 |
| float | number | float | float64 | f64 |
| bool | boolean | bool | bool | bool |
| datetime | Date | datetime | time.Time | DateTime<Utc> |
| list<T> | T[] | list[T] | []T | Vec<T> |
| map<K,V> | Record<K,V> | dict[K,V] | map[K]V | HashMap<K,V> |
| T? | T | null | Optional[T] | *T | Option<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 codeConfiguration
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.