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

@oneshot101/luau-bundler

v0.4.13

Published

Bundles multiple Luau/Lua source files into a single self-contained script

Readme


Overview

@oneshot101/luau-bundler bundles a directory of .lua and .luau modules into a single Lua file that can run through loadstring() or any environment that needs one pasted/executed script. It walks the source tree, wraps each module in a loader, generates compatible require() aliases, and emits one self-contained script that starts at an entry module.

The package is part of the rbxdev-ls monorepo and is used by the Roblox executor bridge tooling to ship modular Luau source as one runtime script.

Features

  • Single-file output — Converts a folder of Luau/Lua modules into one script
  • Require shim — Preserves module-style require("path/to/module") calls inside the bundle
  • Rojo project support — Reads a default.project.json and uses tree.$path as the source directory
  • Deterministic builds — Sorts discovered files before emitting output
  • Entry module control — Starts from init by default, or any custom module name
  • Header support — Prepends a generated comment header for provenance/versioning
  • CLI and API — Use it from npm scripts or directly from Node/Bun tooling

Table of Contents

Quick Start

Bundle a source folder into one Lua file:

npx -y @oneshot101/luau-bundler --src src --out dist/bundle.lua

Bundle from a Rojo project:

npx -y @oneshot101/luau-bundler --project default.project.json --out dist/bundle.lua

Use a custom entry module and header:

npx -y @oneshot101/luau-bundler --src src --out dist/bridge.lua --entry main --header "rbxdev executor bridge"

How It Works

The bundler recursively collects every .lua and .luau file under the source directory. Each file is emitted into a _modules table as a lazy loader, then a local require() shim resolves module paths at runtime. The output ends by requiring the configured entry module and returning its value.

The generated require() first checks bundled modules. If a path is not bundled, it falls back to the original runtime require when available. That lets bundled code still use runtime-provided modules when the host environment supports them.

The final output is wrapped like this:

return (function(oldRequire, ...)
  -- bundled module registry and require shim
  return require("init")
end)(require or function() end, ...)

Installation

Prerequisites

  • Node.js ≥ 18node --version to verify
  • Source files ending in .lua or .luau

npx (recommended)

No installation required:

npx -y @oneshot101/luau-bundler --src src --out dist/bundle.lua

Global install

If you prefer a persistent CLI:

npm install -g @oneshot101/luau-bundler

Then run:

luau-bundler --src src --out dist/bundle.lua

CLI

luau-bundler --src <dir> --out <file> [--entry <name>] [--header <text>]
luau-bundler --project <rojo.project.json> --out <file> [--entry <name>] [--header <text>]

| Option | Required | Default | Purpose | | ----------- | -------- | ------- | ------------------------------------------------------------ | | --src | Yes* | none | Source directory containing .lua and .luau files | | --project | Yes* | none | Rojo project file; uses tree.$path as the source directory | | --out | Yes | none | Output file path for the generated single-file bundle | | --entry | No | init | Module name to require after all modules are registered | | --header | No | none | Text emitted as leading Lua comments in the generated output |

*Use either --src or --project.

JavaScript API

import { bundle, resolveRojoProject } from '@oneshot101/luau-bundler';

const result = bundle({
  sourceDir: 'src',
  entry: 'init',
  header: 'generated by luau-bundler',
});

console.log(result.output);
console.log(`${result.moduleCount} modules in ${result.elapsedMs.toFixed(1)}ms`);

bundle(options)

| Option | Type | Default | Purpose | | ------------- | --------- | ------- | ---------------------------------------------------- | | sourceDir | string | none | Directory to recursively scan for .lua and .luau | | entry | string | init | Module name required at the end of the bundle | | header | string | none | Comment header prepended to the output | | passVarargs | boolean | true | Whether top-level varargs are forwarded into modules |

Returns:

| Field | Type | Description | | ------------- | -------- | ----------------------------- | | output | string | Bundled Lua source | | moduleCount | number | Number of modules included | | elapsedMs | number | Bundling time in milliseconds |

resolveRojoProject(projectPath)

Reads a Rojo project file and returns the resolved source directory from tree.$path:

const project = resolveRojoProject('default.project.json');
if (project) {
  console.log(project.name, project.sourceDir);
}

Module Resolution

Each file gets aliases that match common Luau module paths:

| File path | Valid require paths | | ---------------------- | --------------------------------------------------------- | | services/player.luau | services/player.luau, services/player | | controllers/init.lua | controllers/init.lua, controllers/init, controllers |

Files are sorted before bundling so repeated builds produce stable output when the source files are unchanged.

Part of rbxdev-ls

This bundler is one workspace in the rbxdev-ls monorepo, which also includes:

  • packages/server — The Roblox/Luau language server with type checking, completions, and diagnostics
  • packages/vscode — The VS Code extension with Game Tree, Properties panel, Remote Spy, and code execution
  • packages/mcp — The MCP server for connecting AI assistants to live Roblox game instances
  • packages/luau-bundler — This package

License

MIT © Andrew