- Go 93%
- TypeScript 5%
- Lua 2%
- JavaScript <1%
- Assembly <1%
- 3 more languages <1%
TypeScript in, Roblox out — at native speed.
rotor is an all-in-one Roblox toolchain, written in Go. At its core is a native rewrite of the roblox-ts compiler built on typescript-go — a drop-in rbxtsc replacement with byte-identical Luau output — plus a native Luau toolchain and Open Cloud asset + deployment pipelines, all in one binary.
bun add -d @rotor-rbx/rotor # or: npm i -D @rotor-rbx/rotor — see Install for more ways
📖 Documentation · 🤝 Contributing · 🗺️ Roadmap
Features #
Compile & check — the rbxtsc replacement:
rotor check ./my-game -w # native full-strictness typecheck: 222 files in 161 ms
rotor build ./my-game -w # byte-identical Luau, watch mode, incremental rebuilds
rotor doctor # diagnose tsconfig, @rbxts packages, plugins, Rojo, cloud setup
Same tsconfig.json, same @rbxts/* packages, same transformer plugins (Flamework etc.), same CLI flags — plus built-in compile-time macros rbxtsc doesn't have (no plugins, no Node sidecar, fully typed):
| Macro | Inlines |
|---|---|
$env("KEY", "fallback") · $env.KEY |
env vars from .env / .env.<NODE_ENV> |
$asset("logo.png") |
a rbxassetid://… string (cached, auto-uploads on miss) |
$keys<T>() |
a type's string keys (checker-powered) |
$nameof(expr) |
the trailing identifier name as a string |
$file("data.json") |
a file's contents as a Luau value (JSON→table, text→string) |
$git("sha"|"branch"|"tag"|"dirty") · $buildTime() |
build/VCS stamps |
$getModuleTree("shared/systems") |
a folder's module tree (no index.ts required) |
Luau toolchain — works on any Rojo project, no rbxts required:
rotor dev # watch + incremental compile + rojo serve to Studio
rotor bundle entry.luau -o bundle.luau --minify # inline a require graph, still runnable
rotor minify file.luau # strip comments/whitespace, keep --! directives
rotor pack --as luau # whole project -> one self-reconstructing script (or rbxm/rbxmx)
rotor sourcemap -o sourcemap.json # Rojo-compatible, for luau-lsp
Cloud — assets and deployment from one typed config (see below):
rotor asset sync # upload new/changed assets, lockfile, typed codegen
rotor deploy plan -e prod # diff config vs live state (terraform-style, no network writes)
rotor deploy apply -e prod # publish places, settings, badges — only what drifted
Scaffolding — rotor init runs an interactive wizard (template, Biome/oxlint, starter packages, asset/deploy config) or scripts cleanly with --yes/--template.
Configuration — rotor.toml #
One typed TOML config drives the cloud tools. rotor init writes it with a #:schema directive that points at the schema hosted in this repo (served via raw GitHub), so taplo / Even Better TOML give validation + autocomplete with no per-project rotor.schema.json to generate or commit. Need a local copy for offline editing? rotor schema > rotor.schema.json. (Upgrading from a 1.x rotor.config.ts? Run rotor migrate.)
#:schema https://raw.githubusercontent.com/uproot/rotor/master/rotor.schema.json
[assets]
mode = "macro" # "module" (assets.luau) | "macro" ($asset transformer)
paths = ["assets/**/*.png", "assets/**/*.ogg"]
[assets.creator]
type = "group"
id = 12345
[deploy.environments.prod]
universeId = 333
[deploy.environments.prod.places.start]
file = "build/game.rbxl"
placeId = 444
maxPlayers = 30
versionType = "published"
[deploy.environments.prod.experience]
name = "My Game"
playability = "public"
[deploy.environments.prod.gamepasses.vip]
name = "VIP"
price = 250
icon = "assets/vip.png"
[deploy.environments.prod.socials.discord]
title = "Join us"
url = "https://discord.gg/x"
type = "discord"
rotor asset syncscans the globs, uploads new/changed files via Open Cloud (SHA-256 lockfilerotor-lock.json— unchanged files never re-upload, updates keep asset ids stable). Inmode = "module"it generatesassets.luau+assets.d.ts; inmode = "macro"you reference assets inline with$asset("assets/logo.png"), which resolves from the cache and auto-uploads any miss whenROBLOX_API_KEYis set.rotor deployis infrastructure-as-code: it diffs the config against per-environment state (.rotor/deploy/<env>.json), shows a plan, and applies only the drift — place file publishing + place settings, experience settings, badges and game passes (icons upload automatically first, shared icons dedupe), experience icon + thumbnails, developer products, and social links. Deletes require--allow-deletes.- Auth is an Open Cloud key in
ROBLOX_API_KEY(scopes: Assets R/W, Universe Places W, Universe R/W).rotor doctorchecks your config and key setup.
Full config shape, every command flag, and all the macros: docs.md.
Install #
Grab a binary from GitHub Releases, or use a toolchain manager:
# mise
mise use -g github:uproot/rotor@2.0.0
# rokit
rokit add uproot/rotor@2.0.0
# aftman.toml
[tools]
rotor = "uproot/rotor@2.0.0"
# foreman.toml
[tools]
rotor = { github = "uproot/rotor", version = "2.0.0" }
Install via npm / bun #
For rbxts projects that already live in the JS ecosystem, install @rotor-rbx/rotor as a dev dependency — a postinstall step downloads the prebuilt binary for your platform:
bun add -d @rotor-rbx/rotor
npm i -D @rotor-rbx/rotor
pnpm add -D @rotor-rbx/rotor
yarn add -D @rotor-rbx/rotor
Installing straight from GitHub works too: bun add -d github:uproot/rotor (npm/pnpm/yarn equivalents likewise).
bun note: bun skips postinstall scripts by default. Either add
"trustedDependencies": ["@rotor-rbx/rotor"]to your project'spackage.json(thenbun install), or do nothing — therotorshim downloads the binary on first run. pnpm similarly asks you to approve build scripts (pnpm approve-builds), with the same first-run fallback.
Or build from source (Go 1.25+):
git clone https://github.com/uproot/rotor && cd rotor
go build ./cmd/rotor
Benchmarks #
Measured on real production rbxts games, with output byte-identical to rbxtsc 3.0.0:
| Workload | rotor |
|---|---|
| Full strict typecheck — 222-file production game | 161 ms |
| Full build — 95-file production game | 355 ms |
| Incremental watch rebuild — same game | 180 ms |
The JS toolchain spends longer than this booting Node. The ~10× speedup is structural: rotor runs Microsoft's native, parallel TypeScript compiler (typescript-go) instead of the single-threaded JS one.
Contributors #
Contributions welcome — see CONTRIBUTING.md.
License #
MIT. rotor stands on roblox-ts (MIT) and typescript-go (Apache-2.0) — see credits.