rbxmk - Transform and build your projects

logo-flat-name

rbxmk is a tool for modifying, manipulating, building, and compiling Roblox files. Be it quick, one-off transformations, or the main driver behind your project, rbxmk is a versatile toolbelt for aiding the development of games, plugins, models, modules, and so on.

Download

The latest released version of rbxmk is v0.9.1, and is available for a number of platforms:

See the Release page for more information on the latest version.

The rbxmk repository contains the latest unreleased version. Instructions for compiling and installing manually are available there.

rbxmk is fully featured, but thorough testing of all features is still a work in progress. Please practice redundancy and use backups to reduce the risk of data loss. Be sure to report issues as you encounter them!

Changelog

v0.9.1

Highlights:

  • Add support for .luau extension.
  • When a descriptor is set while encoding or decoding an instance, the service status is determined by the Service tag from instance’s class descriptor instead of the instance’s IsService field.
    • This improves conversion from XML Roblox formats to binary Roblox formats.
  • Add support for Optional types.
    • If a descriptor is set, optional properties are handled transparently by accepting either nil (for None), or a value of the optional’s type (for Some).
    • Add types.none to create an empty Optional exprim.
    • Add types.some to create an Optional exprim that contains a value.
    • Currently, this only affects the “Model.WorldPivotData” property, which is an optional CFrame.
  • Add support for UniqueId type.
  • Improve interface of the doc command.
    • Frag mode is the default. List mode is enabled with the --list flag.
  • Add RootDesc.Copy method.

Fixes:

  • Fix descriptor IsA checks failing when superclass matches current class.
  • Fix encoding of PhysicalProperties type in rbxl format.
  • Fix options not working for the rbx formats.
  • Fix SetAttribute throwing an error when setting an attribute to nil.
  • Fix SetAttributes pulling wrong argument for dictionary.
  • Fix nondeterministic order of encoded SharedStrings in rbxl format.

Internal:

  • Switch to cobra for handling CLI.
    • When the program is executed from a GUI, a message is displayed indicating that it is a command-line tool.
    • Adds completion command for generating autocompletion scripts for various shells.

See a comparison with the previous version for a thorough list of changes.

The Documentation page provides a complete reference for this version of rbxmk.

Usage

rbxmk uses Lua scripts to produce and retrieve data, transform it, and send it off to a variety of sources, including the file system, assets on the Roblox website, general HTTP resources, and even the clipboard.

This section will provide an overview of the features of rbxmk. The Documentation pages provide a complete reference on how rbxmk is used.

Commands

rbxmk is a program with a command-line interface, consisting of a number of sub-commands:

Command Description
run Execute a script.
i Enter interactive mode.
download-asset Download an asset.
upload-asset Upload an asset.
dump Dump the script API.
help Display help.

run is the primary command, which is used to run Lua scripts.

rbxmk run file.lua

Arguments can be passed to the script, received within the script from the ... operator.

rbxmk run file.lua hello 3.14159 true

The i command is like the run command, but starts an interactive session similar to lua -i, where lines of Lua code can be written and evaluated directly.

The download-asset and upload-asset commands provide shortcuts for quickly downloading or updating assets on the Roblox website. The same actions can be performed within rbxmk scripts as well.

The dump command produces machine-readable descriptions of rbxmk’s Lua environment, including a general JSON format, as well as the selene TOML format.

The help command provides a description for any command. In addition to the documentation, this can be used to learn more about a particular command.

Lua environment

The environment of rbxmk script is meant to emulate Roblox. No Luau-specific features are available, but the libraries and variables included in the environment closely match those of Roblox. There are of course additional libraries exclusive to rbxmk.

Instances

Instances are one of the main types of data that rbxmk deals with. As in Roblox, they can be created from scratch:

local brick = Instance.new("Part")
brick.Name = "Brick"
brick.BrickColor = BrickColor.Red()
brick.Anchored = true

Instances include many of the basic methods, such as GetChildren, FindFirstChild, and Destroy, as well as the common properies ClassName, Name, and Parent.

Notably, child indexing is deliberately not implemented. That is, if a “Model” instance contains a child named “Brick”, then Model.Brick cannot be used to get the child. Instead, rbxmk provides the Descend method to recursively acquire descendants in a safe manner:

local brick = game:Descend("Workspace", "Model", "Brick")

Attributes are also accessible with the usual attribute methods. Additionally, rbxmk provides the SetAttributes method to efficiently set all attributes at once.

Descriptors

By default, rbxmk has no knowledge of the class of an instance. Properties are assumed based on how they are decoded, and the types used when set. Descriptors provide extra information about the classes, members, and enums of an implementation, used to enforce the content of instances.

rbxmk provides no descriptors by default, but there are several flags available for including descriptors automatically.

# Use local API dump as global descriptor.
rbxmk run --desc-file dump.desc.json file.lua

# Automatically download API dump for latest version of Roblox.
rbxmk run --desc-latest file.lua

This concept of descriptors allows rbxmk scripts to be as forward- or backward-compatible as required by your project. Solutions without descriptors are also available.

Libraries

The environment includes the standard math, string, table, and os libraries, and most of the global functions. Additionally included are the Roblox-specific extensions, such as math.clamp, string.split, and table.find. rbxmk also provides several of its own libraries.

The rbxmk library contains functions related specifically to rbxmk, which includes running files and strings as scripts, setting global configuration, or decoding and encoding from a variety of formats.

The fs library provides an interface to the file system.

The path library provides functions for working with file paths.

The clipboard library provides an interface to the operating system’s clipboard.

The rbxassetid library provides an interface to assets on the Roblox website.

The http enables general HTTP requests. Requests run concurrently, but can be resolved or canceled.

Many more features are available. Once again, the documentation provides a complete reference.

Examples

Download a Roblox asset to a local file

Start with the following script, saved as download-asset.rbxmk.lua:

local id, output = ...
local asset = rbxassetid.read({
	AssetID = id,
	Format = "bin",
})
fs.write(output, asset, "bin")

Then, to download Crossroads to a local file, run the following command:

rbxmk run download-asset.rbxmk.lua 1818 Crossroads.rbxl

Convert URL in clipboard to model

Start with the following script, saved as copy-model.rbxmk.lua:

-- Read a model asset URL from the clipboard, then copy the content of the model
-- to the clipboard, ready to be pasted into Studio.
local useStudioCookies = ...
local url = clipboard.read("txt")
local id = tonumber(url:match("%d+"))
if not id then
	error(string.format("failed to parse asset ID from URL %q", url), 0)
end
local options = {
	AssetID = id,
	Format = "rbxm",
}
if useStudioCookies then
	options.Cookies = Cookie.from("studio")
end
local asset = rbxassetid.read(options)
clipboard.write(asset, "rbxm")

Then, run the following command:

rbxmk run copy-model.rbxmk.lua

To use Studio cookies for authentication:

rbxmk run copy-model.rbxmk.lua true
50 Likes

This is an incredibly exciting redux of Rbxmk - I’m probably going to move over from Remodel to this since I’m more comfortable with the API (and Go!) :slight_smile:

One key driver here on that decision: I’m going to be operating this in a sensitive environment and I must be especially security conscious of running virtualised code that I don’t sign. You’ve already put in controls but I want to have more fine grained control over the environment to limit it to the bare essentials of what I need.

Would there be significant issues if I just removed certain environment library files from my build? (For example clipboard, file system access, etc). I’m not familiar with Lua internals and I hope nothing would break if I removed access to some of the more sensitive operations!

this is Cool man!! i am gonna Download this and hope everyone loves this

All this sounds like a foreign language to me… I hate to put myself out there… but… would you mind to explain what this is in a … “dumb down” way? like, what it does and how could be used?

I’ve worked to make libraries relatively modular, so it can be done right now if your willing to modify the source. By default, the initializer just loops through all libraries that have been registered, but it’s possible to selectively open individual libraries as needed.

One concern is type registration. I’d need to check to know for sure, but some libraries may just assume that types from another library have been registered, so there could be subtle dependencies. Even so, it’s also possible to selectively register needed types in the same way as libraries. I’ve already thought up away to make this more modular, so it shouldn’t be too difficult to just implement an option to include or exclude specific libraries. I’ll add it to my todo list.

1 Like

It’s similar to Rojo. You might have a project that contains a number of separate script and model files, and you could use rbxmk to compile them into a single place file. Rojo does this particular thing, but rbxmk is more focused on taking information, modifying it, and putting it somewhere else. In fact, it’s flexible enough that a script can be written to interpret Rojo projects.

For example, I’ve used rbxmk to build my Hotswap plugin. This project is just a bunch of Lua script files, and rbxmk is used to combine them all into a single model, which is then uploaded as a plugin.

It isn’t a tool for everyone. Most developers will be comfortable with working in Roblox Studio. rbxmk targets developers that require more complicated workflows.

3 Likes

Brillo - I’ll let you know how it goes. Just in case you’re curious, I am using this to extract all of the Lua source containers from a model and put them through some basic fingerprinting & heuristics to establish if they are, for example, a malicious plugin or not. This then gets fed into a Chrome extension and tells you before you download the plugin of how suspicious you should be of it (relatively!).

1 Like

v0.7.1 has been released. See the OP for download links.

Changelog

From v0.6.2 to v0.7.1, the following changes were made:

Highlights:

  • Add Instance[sym.Properties] to get or set all properties of an instance at once.
  • Add rbxmk i command to enter an interactive prompt.
  • Add flags to run command that preset a global descriptor.
    • The --desc-latest flag uses the latest API dump from Roblox.
    • The --desc-file flag uses a file in the descriptor format (API dump).
    • The --desc-patch flag uses a file in the descriptor patch format.
  • Add --libraries flag to run and i to include and exclude libraries.

Fixes:

  • Fix download-asset flags not working.
  • Fix error handling in download-asset.
  • Fix error when getting certain string exprim types.
  • Fix path security error when running a file outside of working directory.
  • Fix runtime error produced by os.split.

v0.7.2 has been released. See the OP for download links.

Changelog

From v0.7.1 to v0.7.2, the following changes were made:

Fixes:

  • Fix fragments failing to resolve due to case-sensitivity.
1 Like

v0.8.0 has been released. See the OP for download links.

Changelog

From v0.7.2 to v0.8.0, the following changes were made:

Incompatibilities

Highlights:

  • Improve handling of values in the rbx formats.
  • Add “Desc” option to the rbx formats to set a descriptor used when encoding or decoding.
  • Add “DescMode” option to the rbx formats to set how deviations from the descriptor are handled.
  • Including --desc-* flags causes the “Enum” global variable to be set to the enums generated from the resulting descriptor.
  • Implement members for the DescAction type.
  • Add DescAction.new constructor.
  • xpcall can receive extra arguments that are passed to the called function.
  • Add path.clean function to clean file paths.
  • Add Enum field to rbxmk library to contain enums defined by rbxmk. Note that there are currently no such enums.

Fixes:

  • Fix missing properties from sym.Properties when instance has a descriptor.
  • Fix unexpected conversion failures when getting certain property types while an instance has descriptor.
  • Fix type conversion error when encoding desc-patch.json format.
  • Fix type conversion error when encoding Objects with rbx formats.
  • Fix encoding of SharedStrings in rbxlx/rbxmx formats.
  • Fix incorrect use of CDATA sections in rbxlx/rbxmx formats.
  • Fix interactive command not having descriptor flags.
  • Fix Cookie.from returning incorrect values when no cookies are found.
  • Fix Instance.new handling DataModel incorrectly.
  • Fix Instance.ClassName being settable to “DataModel”.
  • Fix typeof returning “userdata” for Symbol values.
  • Fix incorrect behavior when select is called with index 0.
  • Fix Envelope field being printed as Time field when ColorSequenceKeypoint or NumberSequenceKeypoint is converted to a string.
  • Fix bounds error when calling ColorSequence.new or NumberSequence.new.
  • Fix ColorSequence.new and NumberSequence.new not verifying order of keypoints.
  • Fix NumberRange.new not verifying interval.

See a comparison with the previous version for a thorough list of changes.

The Documentation page provides a complete reference for this version of rbxmk.

1 Like

How do you download it? I have the file, I open it and a window pops up in in milliseconds leaves. Then I’m not able to open it again

rbxmk is a command-line tool, so it needs to be run in a command-line interface, such as PowerShell.

Here’s an example in PowerShell. In the video, I extract the downloaded archive, navigate to the extracted folder, and run the rbxmk.exe command, which displays a help message since no subcommand was included. I then run the rbxmk i subcommand, which starts interactive mode. Then I type out a script to print “Hello world!”, and finally call the os.exit function to exit interactive mode.

If you need more information, I recommend searching for tutorials on how to use a command-line interface. For rbxmk in particular, the documentation provides information about how to use it.

1 Like

v0.9.1 has been released. See the OP for download links.

Changelog

From v0.8.0 to v0.9.1, the following changes were made:

Highlights:

  • Add support for .luau extension.
  • When a descriptor is set while encoding or decoding an instance, the service status is determined by the Service tag from instance’s class descriptor instead of the instance’s IsService field.
    • This improves conversion from XML Roblox formats to binary Roblox formats.
  • Add support for Optional types.
    • If a descriptor is set, optional properties are handled transparently by accepting either nil (for None), or a value of the optional’s type (for Some).
    • Add types.none to create an empty Optional exprim.
    • Add types.some to create an Optional exprim that contains a value.
    • Currently, this only affects the “Model.WorldPivotData” property, which is an optional CFrame.
  • Add support for UniqueId type.
  • Improve interface of the doc command.
    • Frag mode is the default. List mode is enabled with the --list flag.
  • Add RootDesc.Copy method.

Fixes:

  • Fix descriptor IsA checks failing when superclass matches current class.
  • Fix encoding of PhysicalProperties type in rbxl format.
  • Fix options not working for the rbx formats.
  • Fix SetAttribute throwing an error when setting an attribute to nil.
  • Fix SetAttributes pulling wrong argument for dictionary.
  • Fix nondeterministic order of encoded SharedStrings in rbxl format.

Internal:

  • Switch to cobra for handling CLI.
    • When the program is executed from a GUI, a message is displayed indicating that it is a command-line tool.
    • Adds completion command for generating autocompletion scripts for various shells.

See a comparison with the previous version for a thorough list of changes.

The Documentation page provides a complete reference for this version of rbxmk.

I am trying to use rbxmk and keep getting runtime error: invalid memory address or nil pointer dereference when trying to write an .rbxm file. I’m not sure if I’m doing something wrong or what but it happens even on this super simple script:

local game = fs.read("place.rbxl")
local models = game:Descend("Workspace", "Models")
fs.write("models.rbxm", models, "rbxm")

With “place.rbxl” being an existing place in the same directory as the script
Any help would be appreciated

What version of rbxmk are you using? Can you provide an .rbxl file that will reproduce the error? If you don’t want to post it publicly, you can send me a PM.

As a follow up, this issue has been fixed, and will be included in the next release of rbxmk.