A fast, Rust-native Lua toolchain. Multi-runtime management + reproducible project dependencies in one CLI.
pluv install lua@5.4.6
pluv install luajit@2.1
pluv install luau@latest
pluv init
pluv add luasocket
pluv lock
pluv sync
pluv run main.lua
brew install rustq/tap/pluvcargo install --git https://github.com/rustq/pluv pluv-cliDownload pre-built binaries from GitHub Releases.
pluv install lua@5.4.6 # Install Lua
pluv install luajit@2.1 # Install LuaJIT
pluv install luau@latest # Install Luau
pluv uninstall lua@5.4.6 # Remove a runtime
pluv use lua@5.4.6 # Set global default
pluv local luajit@2.1 # Set project runtime (.lua-version)
pluv which # Show active runtime
pluv list # List installed runtimes
pluv setup-shims # Install lua/luac/luau shims to ~/.local/binpluv init # Create pluv.toml
pluv add luasocket # Add dependency
pluv add busted --dev # Add dev dependency
pluv remove luasocket # Remove dependency
pluv lock # Resolve deps and write pluv.lock
pluv sync # Install from pluv.lock (or pluv.toml)
pluv sync --frozen # Install exactly from pluv.lock (CI mode)
pluv sync --frozen --no-dev # Skip dev dependencies (production)
pluv sync --offline # Install from cache only (no network)
pluv sync --binary # Install with binary caching (fast reinstall)
pluv sync --from-source # Build natively only (no LuaRocks fallback)
pluv sync --prefer-binary # Try binary cache → native → LuaRocks
pluv build # Build all packages natively (no LuaRocks)
pluv build luasocket # Build a specific package
pluv doctor --build # Check build tools (make, cmake, gcc)
pluv deps # Show project dependencies
pluv run main.lua # Run with project environment
pluv run --runtime luajit@2.1 main.lua # Run with specific runtime
pluv run busted # Run rocks binarypluv cache dir # Print global cache path
pluv cache list # List cached packages
pluv cache list --binaries # List binary cache entries
pluv cache build # Build binary cache for project deps
pluv cache push # Push binary cache to remote registry
pluv cache pull # Pull binary cache from remote registry
pluv cache sync # Sync binary cache (push + pull)
pluv cache clean # Remove all cached packages
pluv cache clean --binaries # Remove binary cache onlypluv registry list # List configured registries
pluv registry add company https://packages.example.com --priority 10
pluv registry remove company # Remove a registry
pluv registry default company # Set default registry
pluv registry login --token <token> # Store auth token for default registry
pluv registry login company --token <token> # Specific registry
pluv registry logout # Remove auth token for default registry
pluv registry logout company # Remove auth token for specific registrypluv mirror check # Check health and latency of all registries| Runtime | Versions |
|---|---|
| Lua | 5.1, 5.2, 5.3, 5.4 |
| LuaJIT | 2.0, 2.1 |
| Luau | latest |
- Lua 5.1 != Lua 5.4 (different ABI)
- LuaJIT ~= Lua 5.1 (compatible)
- Luau != Lua (separate runtime)
Each runtime gets an isolated dependency tree under .pluv/rocks/<runtime>/.
pluv.toml:
[project]
name = "myapp"
[runtime]
name = "luajit"
version = "2.1"
[luarocks]
version = "3.11.1"
[registries]
default = "company"
[registries.company]
url = "https://packages.example.com"
priority = 10
[registries.luarocks]
url = "https://luarocks.org"
[cache.remote]
url = "https://packages.example.com/lua-cache"
upload = true
[network]
timeout-seconds = 30
retries = 3
[dependencies]
luasocket = "*"
[dev-dependencies]
busted = "*"Dependencies can come from LuaRocks (default), git, or local paths:
[dependencies]
luasocket = "*"
[dependencies.my-lib]
git = "https://github.com/user/my-lib"
ref = "main"
[dependencies.local-lib]
path = "../local-lib"pluv lock uses a custom Rust-native resolver that:
- Fetches the LuaRocks package index directly via HTTP
- Parses rockspec files natively to extract dependency trees
- Resolves version constraints (
>=,<=,>,<,==,~>) - Detects conflicts with clear error messages
- Outputs a resolved lockfile without installing anything
LuaRocks is only used as a fallback for package installation when native building is not available.
pluv sync can build Lua packages natively without LuaRocks for common build types:
| Build type | Description |
|---|---|
builtin / module |
Pure Lua packages — copies .lua files |
make |
Makefile-based C modules |
cmake |
CMake-based C modules |
command |
Custom build commands |
When the lockfile records a package's build type, pluv sync tries the native builder first and falls back to LuaRocks on failure. Packages with unsupported build types go directly to LuaRocks.
pluv build # Build all packages natively
pluv build luasocket # Build a specific package
pluv doctor --build # Check that make/cmake/gcc are availableThe native builder fetches source tarballs, unpacks them, runs the appropriate build backend, and installs artifacts into .pluv/rocks/<runtime>/.
pluv sync --binary caches compiled build artifacts so subsequent installs skip compilation entirely.
pluv sync --binary # First run: compile and cache
pluv sync --binary # Second run: restore from cache (fast)
pluv cache build # Explicitly build cache for all deps
pluv cache list --binaries # See what's cachedCache key format: name@version:runtime:platform:compiler:build-options
Example: luasocket@3.1.0-1:lua-5.4.6:linux-x86_64:gcc:default
Cache layout:
~/.cache/pluv/builds/
luasocket/3.1.0-1/lua-5.4/linux-x86_64/package.tar.gz
Artifacts include SHA256 checksums for integrity verification.
For CI, cache ~/.cache/pluv/ and use pluv sync --binary --frozen for fast reproducible installs.
pluv supports configurable package registries with priority-based fallback, auth tokens, and remote binary cache.
Configure registries globally at ~/.config/pluv/registries.toml:
default = "luarocks"
[luarocks]
url = "https://luarocks.org"
[company]
url = "https://packages.example.com"
priority = 10Higher priority registries are tried first. Project-level [registries] in pluv.toml override global config.
pluv registry login --token <token> # Default registry
pluv registry login company --token <token> # Specific registryTokens are stored at ~/.config/pluv/auth.toml and sent as Authorization: Bearer headers.
Environment variables take priority over file-based tokens:
| Variable | Scope |
|---|---|
PLUV_REGISTRY_<NAME>_TOKEN |
Registry-specific (e.g. PLUV_REGISTRY_COMPANY_TOKEN) |
PLUV_REGISTRY_TOKEN |
Fallback for all registries |
This allows CI to inject tokens without modifying auth files.
Push and pull compiled binary cache entries to/from your registry:
pluv cache push # Upload local binary cache to default registry
pluv cache pull # Download missing binary cache from registries
pluv cache sync # Push + pullBinary cache entries are keyed by runtime/platform/package/version.
Uploads require upload = true in [cache.remote]:
[cache.remote]
url = "https://packages.example.com/lua-cache"
upload = truepluv.lock is machine-generated by pluv lock and should be committed to version control. It records exact resolved versions per runtime for reproducible builds.
pluv lock # Generate/update pluv.lock
pluv sync --frozen # CI: fail if lockfile missing or staleLockfile version 4 includes runtime tags, dependency graphs, and registry source identity per package.
- Runtimes are built from source (Lua, LuaJIT) or downloaded as binaries (Luau) to
~/.local/share/pluv/toolchains/ - LuaRocks is auto-installed and managed at
~/.local/share/pluv/luarocks/ - Resolution is done natively by
pluv-resolver— fetches the LuaRocks manifest and parses rockspecs in pure Rust - Native builder compiles supported packages (builtin, make, cmake) without LuaRocks, with automatic fallback
- Dependencies are installed into
.pluv/rocks/<runtime>/per project (isolated per runtime) pluv.lockv4 pins exact versions with runtime tags, dependency graphs, and registry sourcepluv runinjectsLUA_PATH,LUA_CPATH, andPATHfor the active runtimepluv run --runtimeoverrides the project runtime for a single execution- Resolution:
pluv.tomlruntime >.lua-version> global default - Binary cache:
pluv sync --binarystores compiled rocks as tar.gz archives keyed by package+version+runtime+platform - Registry proxy: Configurable registries with priority-based fallback, auth tokens, and remote binary cache
- Cache:
~/.cache/pluv/stores reusable rockspecs, manifest index, archives, and binary builds
| Crate | Description |
|---|---|
pluv-build-backends |
Native build backends (builtin, make, cmake, command) |
pluv-build-cache |
Binary cache for compiled rock artifacts |
pluv-builder |
Build orchestration (fetch, unpack, select backend, build) |
pluv-cache |
Global package cache management |
pluv-cli |
CLI interface |
pluv-core |
Shared types (Toolchain, Config, Runtime) |
pluv-env |
Environment variable injection (LUA_PATH, LUA_CPATH, PATH) |
pluv-installer |
Install built artifacts into rocks tree |
pluv-lock |
Lockfile (pluv.lock) v4 parsing and generation |
pluv-manifest |
pluv.toml parsing with DepSpec (luarocks, git, path) |
pluv-mock-registry |
Mock HTTP registry server for integration tests |
pluv-registry |
Registry proxy (config, auth, mirror check, remote cache) |
pluv-resolver |
Native dependency resolver (rockspec parsing, constraint solving) |
pluv-rocks |
LuaRocks wrapper (fallback installation) |
pluv-runner |
Script and binary execution engine |
pluv-runtime |
Runtime install, uninstall, resolve, and shim management |
pluv-runtime-matrix |
Runtime compatibility rules and version detection |
pluv-ui |
Terminal output, progress reporting, and styling |
MIT