Managing Packages with LuaRocks
Lua ships with a small standard library. For everything else — HTTPS networking, JSON parsing, filesystem access, markdown processing — there is LuaRocks. It is the package manager for Lua: a command-line tool that queries the central repository at luarocks.org and installs self-contained packages called rocks onto your system or into a local directory.
If you have used pip (Python), Bundler (Ruby), or npm (Node), LuaRocks will feel immediately familiar.
Installing LuaRocks
On Linux, your package manager probably has it:
# Debian/Ubuntu
sudo apt install luarocks
# Fedora/RHEL
sudo dnf install lua-rocks
The version in your distribution’s package repository may lag behind the latest release, but it is usually recent enough to get started. If you need the absolute newest version — for example, to use a freshly released rockspec feature — you can also compile from source by cloning the LuaRocks repository and running ./configure && make && sudo make install.
On macOS, install with Homebrew or compile from source:
brew install luarocks
Homebrew keeps LuaRocks up to date more frequently than most Linux package managers, so macOS users typically get the latest stable release with minimal friction. If Homebrew is not an option, the source build path described above works identically on macOS.
On Windows, follow the instructions on the LuaRocks wiki.
To verify it installed correctly:
luarocks --version
You should see something like luarocks 3.x.x followed by the Lua version it was built against. If the version does not print, check that the luarocks binary is on your PATH and that your Lua installation is reachable — LuaRocks needs a working Lua interpreter to function, even for the —version command.
Finding packages
Before installing, search the repository:
luarocks search luafilesystem
The search command queries the central LuaRocks index at luarocks.org. By default it searches both rock names and descriptions, so a search for “json” will return packages named dkjson, lua-cjson, and any package whose description mentions JSON handling. If you know the exact package name, use search --exact to get only that result and avoid noise from unrelated packages.
Search results:
==============
Rockspecs and source rocks:
---------------------------
luafilesystem
1.8.0-1 (rockspec) - https://luarocks.org
1.8.0-1 (src) - https://luarocks.org
1.7.0-1 (rockspec) - https://luarocks.org
...
The search lists available versions and whether they are rockspecs (source descriptions that get compiled at install time) or pre-built rock archives. A rockspec entry means the package will be compiled from C source on your machine; a source rock is a pre-packaged tarball. Most packages list both formats, and LuaRocks picks the appropriate one based on your platform and Lua version automatically.
Installing packages
The default install is system-wide, which requires write access to wherever LuaRocks is configured (often /usr/local):
luarocks install luafilesystem
A system-wide install places the package where every Lua script on the machine can find it. This is convenient for global tools — moonscript and tl (the Teal compiler) are good candidates for system install — but it is overkill for project-specific libraries where you want each project to control its own dependency versions. System installs also require sudo on most Linux distributions, which adds a permission step that can trip up automated build scripts and CI pipelines.
For a local install, which is what you want in most development scenarios, use --local:
luarocks install --local luafilesystem
Local installs go to ~/.luarocks. This keeps your user directory tidy and does not require root or admin privileges. The --local flag also makes your setup reproducible across machines: you can document a list of luarocks install --local <name> commands in your project’s README and expect them to work on any machine with LuaRocks installed, without worrying about system paths or permissions.
Project-local trees
For individual projects, you can install into a custom directory:
mkdir myproject/vendor
luarocks install --tree=myproject/vendor luatex
The --tree option creates an isolated vendor directory for that project’s dependencies. Unlike --local, which puts everything into a shared per-user directory, --tree gives each project its own sandbox. This is essential when different projects need different versions of the same package — project A can use luafilesystem 1.8.0 while project B stays on 1.7.0, and they will never conflict. When you run your Lua code, add that tree to package.path:
package.path = package.path .. ";myproject/vendor/share/lua/5.4/?.lua"
package.cpath = package.cpath .. ";myproject/vendor/lib/lua/5.4/?.so"
local lfs = require("lfs") -- now finds lfs from your project tree
This pattern is the LuaRocks equivalent of a node_modules directory. The key difference is that LuaRocks does not create a lock file or manifest automatically — you are responsible for tracking which versions your project needs, typically by listing luarocks install commands in a Makefile or shell script. Some teams commit the vendor tree itself to version control to lock dependencies, while others prefer to regenerate it from a script during the build step. Either approach works, but the former guarantees reproducible builds across environments with different LuaRocks configurations.
Listing installed packages
See everything you have installed:
luarocks list
The list command without arguments shows every rock across all trees visible to your current LuaRocks configuration. If you are using --local, only packages under ~/.luarocks appear; if you ran a system install, it shows both system and local rocks. This is helpful for auditing what your Lua environment actually has available before writing require calls, since missing dependencies produce cryptic runtime errors rather than clear build-time failures.
Installed rocks:
----------------
luafilesystem
1.8.0-1 (installed) - /home/user/.luarocks/lib/luarocks/rocks
luasocket
3.1.0-1 (installed) - /home/user/.luarocks/lib/luarocks/rocks
luasec
1.3.0-1 (installed) - /home/user/.luarocks/lib/luarocks/rocks
Listing shows the version, install location, and whether each rock is current or has newer versions available. The (installed) tag confirms the package is ready to use; if a newer version exists upstream, LuaRocks will note that in the same output column. This is your first debugging step when a require call fails — check whether the expected version is actually present in any tree that your Lua installation can see.
Getting package information
luarocks show prints details about an installed rock:
luarocks show luafilesystem
The show command is the equivalent of npm info or pip show — it dumps metadata about a single package including its description, license, homepage, and exact install path. This is useful when you inherit a project and need to check which version of a dependency is actually in play, or when you need to cite a package’s license in your own project’s legal documentation.
luafilesystem 1.8.0-1
-------------------------
LuaFileSystem is a Lua library developed to complement the
and filesystem functions.
License: MIT
Homepage: https://github.com/lunarmodules/luafilesystem
Installed in: /home/user/.luarocks
This tells you what the package does, its license, the project homepage, and where it is installed. The install path is particularly important for debugging: if a package appears in the wrong tree, it means an earlier install command targeted the wrong scope.
Removing packages
To uninstall a locally installed rock:
luarocks remove --local luasec
The remove command needs the same scope flag that was used during install. If you installed with --local, you must remove with --local; a system install needs no flag. Mismatching the scope will cause LuaRocks to look in the wrong tree and report that the package is not found, even though it is installed in a different tree.
To remove everything installed in the current tree:
luarocks purge
Be careful with purge — it wipes all rocks from that tree, not just one. This is a destructive operation with no confirmation prompt, so double-check that you are targeting the right tree before running it. If you used --tree, specify the same --tree with purge to avoid accidentally clearing your global or user-local rocks.
Requiring installed modules
Once installed, require works as normal:
local socket = require("socket")
local https = require("ssl.https")
local lfs = require("lfs")
LuaRocks configures the module search paths automatically. You do not need to manually adjust package.path unless you are using a project-local tree with --tree. When LuaRocks installs a rock, it adds the rock’s lua and lib directories to the Lua search paths through environment variables or a site-config script, so the standard require mechanism finds modules without any extra setup. This is the most important difference between using LuaRocks and manually copying .lua files into your project — LuaRocks handles the path wiring so you never think about it.
To see what paths LuaRocks is currently using:
luarocks path
This prints LUA_PATH and LUA_CPATH values you can source or paste into your shell profile. If you source this output in your shell startup file (.bashrc, .zshrc), every new terminal session will automatically find rocks installed in your user tree without needing the --local flag on subsequent commands.
Configuring the Lua version
If you have multiple Lua versions installed, specify which one to use:
luarocks install --lua-version=5.4 luafilesystem
LuaRocks tracks which Lua version each rock was built against. A C extension compiled for Lua 5.4 will not load under Lua 5.1 because the binary ABI is incompatible between major versions. The --lua-version flag ensures the rock’s native components are compiled against the correct Lua headers, so you can maintain separate rock trees for different Lua installations on the same machine.
Or set a default:
luarocks config --lua-version 5.4
This is useful when working on projects that require a specific Lua version. For example, a legacy codebase on Lua 5.1 can coexist on the same machine alongside a newer project using Lua 5.4, just prefix your commands with --lua-version=5.1 or set the config globally per project directory.
Publishing your own package
To share a library on LuaRocks, create a rockspec file: mylib-1.0-1.rockspec:
package = "mylib"
version = "1.0-1"
source = {
url = "git://github.com/username/mylib"
}
dependencies = {
"lua >= 5.1",
"luafilesystem"
}
build = {
type = "builtin",
modules = {
mylib = "src/mylib.lua"
}
}
A rockspec is a declarative build file. The version field uses a dual numbering scheme — 1.0-1 means upstream version 1.0, rockspec revision 1 — which lets you update the build instructions without changing the source. The source.url can point to a Git repository, a tarball, or a local directory, and LuaRocks handles fetching it automatically. The build.modules section maps Lua module names to their source file paths, so require("mylib") finds src/mylib.lua regardless of where the rock was installed.
Then upload it:
luarocks upload mylib-1.0-1.rockspec
You need an account at luarocks.org. After uploading, your package appears in the search index.
Common packages to know
| Package | What it does |
|---|---|
luafilesystem | Filesystem operations (lfs) |
luasocket | TCP/UDP networking |
luasec | HTTPS support via OpenSSL |
dkjson | JSON encoding/decoding |
lua-cjson | Fast JSON (C library) |
penlight | Utility library |
moonscript | Compile-to-Lua language |
tl | Teal typed Lua |
markdown | Markdown to HTML |
See Also
- lua-moonscript-intro — Moonscript, installable via LuaRocks, compiles to Lua
- lua-penlight-utilities — Penlight, a popular pure-Lua utility library on LuaRocks
- lua-lfs-filesystem — LuaFileSystem (lfs), one of the most commonly installed rocks