'\" t .\" Title: zoi-lua .\" Author: [see the "AUTHOR(S)" section] .\" Generator: Asciidoctor 2.0.26 .\" Date: 2026-10-16 .\" Manual: Zoi Lua Manual .\" Source: zoi-lua .\" Language: English .\" .TH "ZOI\-LUA" "5" "2026-10-16" "zoi\-lua" "Zoi Lua Manual" .ie \n(.g .ds Aq \(aq .el .ds Aq ' .ss \n[.ss] 0 .nh .ad l .de URL \fI\\$2\fP <\\$1>\\$3 .. .als MTO URL .if \n[.g] \{\ . mso www.tmac . am URL . ad l . . . am MTO . ad l . . . LINKSTYLE blue R < > .\} .SH "NAME" zoi-lua \- Lua scripting environment for defining Zoi packages .SH "SYNOPSIS" .sp .if n .RS 4 .nf .fam C metadata { name = "hello", repo = "core", version = "1.0.0", description = "A friendly greeting", maintainer = { name = "Jane", email = "jane@example.com" }, license = "MIT", types = { "source" }, } dependencies { build = { "zoi:core/cmake" }, } function prepare() UTILS.EXTRACT("https://example.com/hello\-1.0.0.tar.gz", "src") end function build() cmd("cmake \-S src \-B build && cmake \-\-build build") end function package() zcp("build/hello", "${pkgstore}/bin/hello") zman("hello.1", "1") end .fam .fi .if n .RE .SH "DESCRIPTION" .sp A Zoi package is defined by a \f(CR.pkg.lua\fP script. Zoi runs the script in a sandboxed Lua environment that provides host system information, staging paths, build helpers, and download utilities. The script declares package metadata and lifecycle functions; the contents of the staging directory become the package archive. .sp Build a definition with \fBzoi package build\fP (see \fBzoi\fP(1)), and use \fBzoi package init\-lsp\fP to get Lua language\-server support while authoring. Longer guides live at \c .URL "https://zillowe.qzz.io/docs/zds/zoi" "" "." .SH "PROJECT AND REPOSITORY MANIFESTS" .sp A \f(CRzoi.lua\fP manifest is separate from \f(CR.pkg.lua\fP package definitions. It may declare \fBproject\fP, \fBpackages\fP, \fBregistries\fP, \fBtasks\fP, \fBenvironments\fP, \fBshell\fP, \fBchecks\fP, \fBimports\fP, and a repository \fBpackage\fP export. .sp \fBimports\fP(\fItable\fP) .RS 4 Map aliases to repository definitions with \fBrepo\fP and optional \fBrev\fP. Zoi clones each repository and resolves \f(CRalias:selector\fP package exports. Exact commits and manifest hashes are recorded in \f(CRzoi.lock\fP. .RE .sp \fBpackage\fP(\fIstring\fP or \fItable\fP) .RS 4 Export a repository package. A string is shorthand for a \f(CRmain\fP export. A table may define \fBmain\fP and a \fBpackages\fP selector map containing \f(CR.pkg.lua\fP files or folders. This declaration is distinct from the \f(CR.pkg.lua\fP lifecycle function \f(CRpackage(args)\fP. .RE .SH "GLOBAL VARIABLES" .sp \fBSYSTEM\fP .RS 4 Host system information: \fBOS\fP, \fBARCH\fP, \fBDISTRO\fP, \fBDISTRO_VER\fP, \fBDE\fP, \fBSERVER\fP, \fBKERNEL_VER\fP, \fBINIT\fP, \fBCPU\fP, \fBGPU\fP, and \fBMANAGER\fP (native package manager). Later entries are only present when detected. Use it for conditional logic such as \f(CRif SYSTEM.OS == "linux" then .\|.\|. end\fP. Also exported to \f(CRcmd\fP subshells as \f(CRSYSTEM_*\fP variables. .RE .sp \fBZOI\fP .RS 4 Zoi environment information: \fBVERSION\fP (resolved package version), \fBscope\fP (\f(CRuser\fP, \f(CRsystem\fP, or \f(CRproject\fP), \fBCREATE_PKG_DIR\fP, \fBPATH\fP (user and system paths), plus copies of the \fBZOI.PKG\fP and \fBZOI.LOCATION\fP tables. .RE .sp \fBZOI.PKG\fP .RS 4 Paths for the current package: the store, the template root, the system root, the home directory, and the script path. .RE .sp \fBLOCATION\fP .RS 4 Absolute staging paths. During builds, \fBPKGSTORE\fP points into the staging area while \fBHOME\fP, \fBROOT\fP, and \fBTEMPLATE\fP mirror the real install roots; \fBPKGLUADIR\fP is the directory of the \f(CR.pkg.lua\fP script, and \fBBUILDDIR\fP/\fBSTAGINGDIR\fP are the active work directories. .RE .sp \fBPKG\fP .RS 4 The resolved metadata table. Every key passed to \fBmetadata\fP is mirrored here, so \f(CRPKG.name\fP and \f(CRPKG.version\fP are readable after the declaration. .RE .sp \fBBUILD_DIR\fP and \fBSTAGING_DIR\fP .RS 4 The temporary build directory (also the working directory of \fBcmd\fP) and the staging directory whose contents become the package archive. .RE .sp \fBBUILD_TYPE\fP .RS 4 The requested build method: \f(CRsource\fP or \f(CRpre\-compiled\fP. Also exported to \f(CRcmd\fP subshells as \f(CR$BUILD_TYPE\fP. .RE .sp \fBSUBPKG\fP .RS 4 The sub\-package name while split packages are processed, otherwise nil. Lifecycle functions also receive it as \f(CRargs.sub\fP. .RE .SH "PACKAGE DEFINITIONS" .sp \fBmetadata\fP(\fItable\fP) .RS 4 Define package properties. Required keys: \fBname\fP, \fBrepo\fP, \fBdescription\fP, \fBmaintainer\fP (a table with \fBname\fP and \fBemail\fP), and \fBtypes\fP (for example \f(CR{"source"}\fP or \f(CR{"pre\-compiled"}\fP). Common optional keys: \fBversion\fP, \fBrevision\fP, \fBepoch\fP, \fBlicense\fP (SPDX identifier), \fBwebsite\fP, \fBgit\fP, \fBauthor\fP, \fBplatforms\fP (such as \f(CR"linux\-amd64"\fP), \fBscope\fP or \fBscopes\fP, \fBsub_packages\fP and \fBmain_subs\fP, \fBtype\fP (\f(CRpackage\fP, \f(CRapp\fP, \f(CRcollection\fP, or \f(CRextension\fP), \fBconflicts\fP, \fBreplaces\fP, \fBprovides\fP, \fBtags\fP, \fBbins\fP, \fBversions\fP (channel map), \fBrollback\fP, and \fBzoios\fP. .RE .sp \fBdependencies\fP(\fItable\fP) .RS 4 Define build\-time and runtime requirements with the keys \fBruntime\fP, \fBbuild\fP, and \fBtest\fP. Each group is a list of dependency strings, or a table with \fBrequired\fP, \fBoptional\fP, \fBoptions\fP (named optional sets with their own dependencies), and \fBsub_packages\fP. The \fBbuild\fP group may additionally be keyed by build type through a \fBtypes\fP table, or be a list of \f(CR{type, packages}\fP entries (the form used by published registry indexes). A dependency string looks like \f(CR[manager:]package[@version][:description]\fP; the manager defaults to \f(CRzoi\fP, for example \f(CR"zoi:core/foo@1.2.3"\fP or \f(CR"pacman:zip"\fP. Local definitions use paths relative to the declaring \f(CR.pkg.lua\fP, such as \f(CR"zoi:./helper.pkg.lua"\fP or \f(CR"zoi:../shared/utility"\fP. A directory must contain \f(CR.pkg.lua\fP or exactly one \f(CR.pkg.lua\fP file. .RE .sp \fBupdates\fP(\fIlist\fP) .RS 4 Update messages shown to the user during upgrades. Each entry has \fBtype\fP (\f(CRupdate\fP, \f(CRchange\fP, or \f(CRvulnerability\fP) and \fBmessage\fP. .RE .sp \fBhooks\fP(\fItable\fP) .RS 4 Shell commands run at lifecycle points: \fBpre_install\fP, \fBpost_install\fP, \fBpre_upgrade\fP, \fBpost_upgrade\fP, \fBpre_remove\fP, and \fBpost_remove\fP. Each value is a command list, optionally keyed by OS. .RE .sp \fBservice\fP(\fItable\fP) .RS 4 Define a background service managed through \fBzoi service\fP, with \fBrun\fP, \fBrun_at_load\fP, \fBworking_dir\fP, \fBenv\fP, \fBlog_path\fP, and \fBerror_log_path\fP. .RE .SH "LIFECYCLE FUNCTIONS" .sp Zoi calls these in order when building a package. Each takes an optional \f(CRargs\fP table carrying \f(CRsub\fP for split packages. .sp \fBprepare\fP([\fIargs\fP]) .RS 4 Fetch source code or binaries into \fBBUILD_DIR\fP. Also runs for \fBzoi package bundle\fP and \fBzoi package test\fP. .RE .sp \fBbuild\fP([\fIargs\fP]) .RS 4 Compile the package in \fBBUILD_DIR\fP. Optional; runs only for \fBzoi package build\fP, between \fBprepare\fP and \fBpackage\fP. .RE .sp \fBpackage\fP([\fIargs\fP]) .RS 4 Stage files into \fBSTAGING_DIR\fP using the staging functions below. Runs once per sub\-package and scope combination. .RE .sp \fBverify\fP([\fIargs\fP]) .RS 4 Verify the integrity of the fetched files; return \f(CRtrue\fP or \f(CRfalse\fP. Runs after pooling, before the archive is written. .RE .sp \fBtest\fP([\fIargs\fP]) .RS 4 Validate the staged files during \fBzoi package test\fP. Must return a boolean explicitly. .RE .sp \fBuninstall\fP() .RS 4 Clean up state outside the package store when the package is uninstalled, using \fBzrm\fP. .RE .SH "STAGING FUNCTIONS" .sp Destination paths must use the placeholders \f(CR${pkgstore}\fP, \f(CR${usrroot}\fP, and \f(CR${usrhome}\fP; source paths are relative to \fBBUILD_DIR\fP or use \f(CR${pkgluadir}\fP for files next to the script. Staging calls are queued and executed atomically by Zoi, except \fBzsed\fP and \fBzpatch\fP, which act immediately. .sp \fBzcp\fP(\fIsource\fP, \fIdestination\fP) .RS 4 Stage a file or directory into the package. .RE .sp \fBzlicense\fP(\fIsource\fP) .RS 4 Stage a license file into the package license directory. .RE .sp \fBzdoc\fP(\fIsource\fP) .RS 4 Stage a documentation file. .RE .sp \fBzman\fP(\fIsource\fP, [\fIsection\fP]) .RS 4 Stage a manual page or a directory of pages. The section is inferred from the file extension when omitted. .RE .sp \fBzshell\fP(\fIsource\fP, \fIshell\fP) .RS 4 Stage a shell completion file for \f(CRbash\fP, \f(CRzsh\fP, \f(CRfish\fP, or \f(CRelvish\fP, and register it for global linking. .RE .sp \fBzln\fP(\fItarget\fP, \fIlink\fP) .RS 4 Create a symbolic link in the package. .RE .sp \fBzchmod\fP(\fIpath\fP, \fImode\fP) .RS 4 Set file permissions, for example \f(CR0755\fP. .RE .sp \fBzchown\fP(\fIpath\fP, \fIowner\fP, \fIgroup\fP) .RS 4 Set file ownership. .RE .sp \fBzmkdir\fP(\fIpath\fP) .RS 4 Create a directory in the package. .RE .sp \fBzrm\fP(\fIpath\fP) .RS 4 Remove files outside the package store while running \f(CRuninstall()\fP. .RE .sp \fBzsed\fP(\fIpattern\fP, \fIreplacement\fP, \fIfile\fP) .RS 4 Apply a regular expression replacement to a file in the build directory, immediately. .RE .sp \fBzpatch\fP(\fIpatch_file\fP, [\fIstrip\fP]) .RS 4 Apply a patch file with the \f(CRpatch\fP command (default strip level 1), immediately. .RE .SH "UTILITY FUNCTIONS" .sp \fBcmd\fP(\fIcommand\fP) .RS 4 Execute a shell command in a persistent session shared across calls in the same phase. Returns \fBstdout\fP, \fBstderr\fP, and \fBexit_code\fP; a nonzero exit does not abort the script, so check \fBexit_code\fP. .RE .sp \fBIMPORT\fP(\fIfile_name\fP) .RS 4 Read a file located next to the script. JSON, YAML, and TOML files are parsed into tables; anything else is returned as a string. .RE .sp \fBINCLUDE\fP(\fIfile_name\fP) .RS 4 Execute another Lua script located next to this one. .RE .sp \fBverifyHash\fP(\fIfile\fP, \fI"algo\-hash"\fP) .RS 4 Verify a file checksum such as \f(CR"sha256\-"\fP. Returns boolean. .RE .sp \fBverifySignature\fP(\fIfile\fP, \fIsignature\fP, \fIkey\fP) .RS 4 Verify a detached PGP signature. The key may be a path, a URL, or a keyring name. Returns boolean. .RE .sp \fBaddPgpKey\fP(\fIurl_or_path\fP, \fIname\fP) .RS 4 Import a PGP key into the Zoi keyring for verification. Returns boolean. .RE .SH "UTILS LIBRARY" .sp \fBUTILS.FETCH.url\fP(\fIurl\fP) .RS 4 GET a URL body as a string. .RE .sp \fBUTILS.FETCH.GITHUB\fP / \fBGITLAB\fP / \fBGITEA\fP / \fBFORGEJO\fP .RS 4 Query forge APIs for the latest tag, release, or commit of a repository, for example \f(CRUTILS.FETCH.GITHUB.LATEST.tag({repo = "owner/name"})\fP. .RE .sp \fBUTILS.PARSE.json\fP / \fByaml\fP / \fBtoml\fP(\fIstring\fP) .RS 4 Parse a document into a Lua table. .RE .sp \fBUTILS.PARSE.checksumFile\fP(\fIcontent\fP, \fIfilename\fP) .RS 4 Extract a hash from a \f(CRsha256sums\fP\-style checksum file. .RE .sp \fBUTILS.FILE\fP(\fIurl\fP, \fIpath\fP) .RS 4 Download a URL to an exact path with progress reporting. .RE .sp \fBUTILS.DOWNLOAD\fP(\fIurl\fP, [\fIout_name\fP], [\fIhash\fP]) .RS 4 Download into \fBBUILD_DIR\fP (default: URL basename) with optional hash verification and retries. Returns the filename. .RE .sp \fBUTILS.EXTRACT\fP(\fIsource\fP, [\fIout_name\fP]) .RS 4 Unpack an archive (zip, tar variants, zstd, 7z, deb, and more; dmg and .pkg on macOS) into a subdirectory of \fBBUILD_DIR\fP. Accepts URLs directly. .RE .sp \fBUTILS.ARCHIVE.list\fP(\fIpath\fP) .RS 4 List archive entries. .RE .sp \fBUTILS.MAKE_ARCHIVE\fP(\fIsource\fP, \fIoutput\fP, [\fIalgo\fP]) .RS 4 Create an archive from \fBBUILD_DIR\fP\-relative paths. .RE .sp \fBUTILS.FS.exists\fP / \fBcopy\fP / \fBmove\fP / \fBchmod\fP .RS 4 Immediate filesystem operations. .RE .sp \fBUTILS.FIND.file\fP(\fIdir\fP, \fIname\fP) .RS 4 Recursively find a file under \fBBUILD_DIR\fP and return its relative path. .RE .SH "EXAMPLES" .sp Minimal source package: .sp .if n .RS 4 .nf .fam C metadata { name = "hello", repo = "core", version = "1.0.0", description = "A friendly greeting", maintainer = { name = "Jane", email = "jane@example.com" }, license = "MIT", types = { "source" }, } function prepare() UTILS.EXTRACT("https://example.com/hello\-1.0.0.tar.gz", "src") end function build() cmd("cmake \-S src \-B build && cmake \-\-build build") end function package() zcp("build/hello", "${pkgstore}/bin/hello") end .fam .fi .if n .RE .sp Conditional dependency per operating system: .sp .if n .RS 4 .nf .fam C local runtime = { "zoi:core/zlib" } if SYSTEM.OS == "linux" then table.insert(runtime, "pacman:glibc") end dependencies { runtime = runtime } .fam .fi .if n .RE .SH "SEE ALSO" .sp \fBzoi\fP(1), \fBzoi\-rs\fP(3) .sp Online documentation: \c .URL "https://zillowe.qzz.io/docs/zds/zoi" "" "" .sp Project repository and issue tracker: .URL "https://gitlab.com/zillowe/zillwen/zusty/zoi" "" "" .SH "COPYING" .sp Copyright \(co Zillowe Foundation. Licensed under Apache\-2.0.