rbx2git
v0.5.3
Published
Save a Roblox place into a Git/GitHub repo as readable .luau files, and build a place file back out of them.
Maintainers
Readme
rbx2git
Save a Roblox place into a Git repo — and push it to GitHub — as real, diffable .luau files.
npx rbx2git save --place 1234567890 --remote [email protected]:you/my-game.git --pushEvery save gives you a commit like this:
my-game/
├── src/
│ ├── ReplicatedStorage/Utils/init.luau
│ ├── ReplicatedStorage/Utils/Math.luau
│ ├── ServerScriptService/GameLoop.server.luau
│ └── StarterPlayer/StarterPlayerScripts/Camera.client.luau
├── instances.txt # the whole Explorer tree, one line per instance
├── place.rbxl # the untouched place file, so you can always restore it
├── default.project.json # Rojo project for the scripts
└── rbx2git.json # remembers the place IDScripts follow Rojo naming (.server.luau, .client.luau, .luau, init.* for scripts with children), so GitHub shows exactly which lines changed between saves. instances.txt shows when parts, models or GUIs are added, renamed or removed. place.rbxl is the full backup — open it in Studio to get everything back, including builds and terrain.
Setup
- Go to create.roblox.com/dashboard/credentials and create an API key.
- Add the legacy-asset API system with the legacy-asset:manage scope, and add your experience to it.
- Under Accepted IP addresses add
0.0.0.0/0if you'll run it from GitHub Actions (or just your own IP for local use). - Put the key in your environment:
export ROBLOX_API_KEY=your-key-hereThe place ID is the number in the game's URL (roblox.com/games/<placeId>/...), or in Studio under File → Game Settings → Places.
The other direction: repo -> place file
npx rbx2git buildThat reads the folder you're in (or its src/ if it has one) and writes place.rbxlx — a place file you open in Studio with File → Open from File, or by dragging it onto the Studio window.
If the repo has a default.project.json (a Rojo project), rbx2git reads it and puts every folder exactly where that file says. You don't need Rojo installed — just the one command above.
Without a project file, it goes by folder and file names:
| In the repo | In Studio |
| --- | --- |
| Thing.server.lua / .server.luau | Script named Thing |
| Thing.client.lua / .client.luau | LocalScript named Thing |
| Thing.lua / Thing.luau | ModuleScript named Thing |
| a folder | Folder with the contents inside |
| init.luau in a folder | the folder becomes that ModuleScript |
| a folder named ServerScriptService, ReplicatedStorage, … | that service |
| init.meta.json with a className | a folder of that class (Model, ScreenGui, …) |
Loose files at the top level go where that kind of script actually runs: server scripts into ServerScriptService, local scripts into StarterPlayerScripts, modules into ReplicatedStorage. Use --under <Service> to send everything to one place instead, and --out <file> to change the file name.
The built place contains your scripts only — no parts, models or terrain, because those aren't in the repo. If the repo has a place.rbxl from rbx2git save, open that in Studio to get the whole game back, and use build when you only want the code.
Live sync into a place you already have open
build makes a new, empty-ish place. If you want your code to land in a place that already has its map, models and meshes in it, sync instead:
npx rbx2git plugin # once — installs the Studio plugin
npx rbx2git serve # in your repo folder, leave it runningThen open the place in Studio, go to the Plugins tab and click rbx2git → Sync. Your scripts appear in the Explorer, and every couple of seconds it re-sends whatever you've saved. Click Sync again to stop.
It only ever creates and updates scripts — it never deletes anything in the place, so it can't wipe someone's work. It's one-way: files go to Studio, never the other way. Studio will ask for script injection permission the first time; that's how any plugin writes script source.
Commands
rbx2git save [--place <id>] [--dir .] [--push] [--remote <url>]
rbx2git build [--dir .] [--out place.rbxlx] [--under <Service>] [--force]
rbx2git serve [--dir .] [--port 34872]
rbx2git plugin [--port 34872]
rbx2git init --place <id>| Option | What it does |
| --- | --- |
| --place <id> | Place to save. Only needed the first time; after that it's read from rbx2git.json. |
| --dir <path> | Folder to save into (created and git init-ed if needed). Default: current folder. |
| --remote <url> | Set the GitHub remote (origin). |
| --push | Push after committing. |
| --version <n> | Save an older version of the place. |
| --file <path> | Use a .rbxl / .rbxlx you exported from Studio instead of downloading. No API key needed. |
| --no-commit | Write files only, don't touch git. |
| --force | Let build overwrite an existing output file |
| --no-project | Ignore default.project.json and go by folder names alone |
| --no-binary | Don't store place.rbxl (smaller repo, but scripts only — you can't fully restore from it). |
| -m <message> | Custom commit message. |
If nothing changed since the last save, no commit is made.
Automatic daily backups with GitHub Actions
rbx2git init --place 1234567890
git add . && git commit -m "Add Roblox backup" && git pushThen in the GitHub repo: Settings → Secrets and variables → Actions → New repository secret, name it ROBLOX_API_KEY. The workflow runs every day at 06:00 UTC (change it with --cron), and you can also run it by hand from the Actions tab.
Without an API key
- Export the place from Studio (File → Save to File As…) and run
rbx2git save --file MyGame.rbxl. - Or set
ROBLOX_COOKIEto your.ROBLOSECURITYcookie. That cookie is your full account login — only use it on your own computer, and never put it in a GitHub secret or commit it.
Use from code
import { save, parsePlace } from 'rbx2git';
await save({ dir: './my-game', placeId: 1234567890, apiKey: process.env.ROBLOX_API_KEY, pushToRemote: true });
const place = parsePlace(fs.readFileSync('MyGame.rbxl'));
console.log(place.scripts.map((s) => s.name));Notes
- Reads both binary (
.rbxl/.rbxm, LZ4 and Zstandard chunks) and XML (.rbxlx/.rbxmx) files, with no Roblox tools installed. - Only
Name,ClassName,Sourceand the tree are extracted to files; everything else lives inplace.rbxl. - Instances with characters that aren't allowed in file names get them replaced with
_; siblings with the same name get(2),(3)… added. - Packages and scripts that use
LinkedSourcesave whatever source is stored in the place. - Only works for places you have access to — it's for backing up your own games.
License
MIT
