npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

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.

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 --push

Every 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 ID

Scripts 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

  1. Go to create.roblox.com/dashboard/credentials and create an API key.
  2. Add the legacy-asset API system with the legacy-asset:manage scope, and add your experience to it.
  3. Under Accepted IP addresses add 0.0.0.0/0 if you'll run it from GitHub Actions (or just your own IP for local use).
  4. Put the key in your environment:
export ROBLOX_API_KEY=your-key-here

The 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 build

That 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 running

Then 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 push

Then 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_COOKIE to your .ROBLOSECURITY cookie. 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, Source and the tree are extracted to files; everything else lives in place.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 LinkedSource save 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