Create & publish a package
A tutorial for library authors: package reusable Serez Code so others import it, expose a runnable command with bin, and publish it so anyone can sz install it.
serez.json manifest, exporting your API, exposing a command with bin so consumers run it with sz run, and publishing. Requires serez-code ≥ 4.6.2 for bin.Step 1 — Lay out the package
A package is a folder with an index.sz (the entry that import resolves to) and a serez.json manifest. A runnable command, if any, is a separate .sz file:
greet-kit/
index.sz ← what `import "greet-kit"` resolves to
src/
greeter.sz ← your modules
cli.sz ← (optional) a runnable command entry
serez.json ← the manifestStep 2 — Write the library and export its API
index.sz wires up the modules consumers will use. Mark everything reachable from outside with export:
// index.sz
import "src/greeter"// src/greeter.sz
export public class Greeter {
public Greeter(name) { this.name = name }
public hello() { return "Hello, " + this.name + "!" }
}exported is invisible from another module — even internal helpers (including ones starting with _) must be export fn if an exported class or function calls them.Step 3 — Write the manifest
serez.json describes the package. Only name and version are required:
{
"name": "greet-kit",
"version": "1.0.0",
"description": "A tiny greeting library",
"author": "you",
"dependencies": {},
"permissions": []
}| Field | What it is |
|---|---|
name / version | Package identity (version is bumped on each release) |
description / author | Metadata shown in the registry |
dependencies | Other packages this one needs — installed with it |
permissions | Capabilities your code uses: OS, File, Env, etc. |
scripts | Named commands for your own dev workflow (sz run <script>) |
bin | Commands this package exposes to consumers (see below) |
Step 4 — Expose a command with bin
If your package ships a tool or CLI (a packer, a generator, a migrator…), declare it in bin. Each entry maps a command name to an entry .sz file. Consumers then run it from their project root with sz run <command> — no path to your file required:
{
"name": "greet-kit",
"version": "1.0.0",
"bin": { "greet": "cli.sz" }
}The entry receives the consumer's extra arguments through Env.args() (passed as key=value tokens, no dashes):
// cli.sz
fn getOpt(argv, key, def) {
let prefix = key + "="
let i = 0
while (i < argv.length()) {
if (argv[i].startsWith(prefix)) {
return argv[i].substring(prefix.length(), argv[i].length())
}
i = i + 1
}
return def
}
let name = getOpt(Env.args(), "name", "world")
out "Hello, " + name + "!"A consumer of your package runs:
sz run greet name=Sergio # → Hello, Sergio!sz run <name> resolves: (1) a script in the consumer's serez.json, then (2) a bin command from an installed package (local ./packages, then the global store), then (3) an error listing what is available. Extra arguments are forwarded to your entry, and it runs with the consumer's project root as the working directory. If two packages expose the same command name, consumers disambiguate with sz run <package>:<command>.Step 5 — Publish
From the package root, publish the current version to the registry:
sz publishBump version in serez.json for every release — installs resolve a version, so a new version must be published before consumers can get it.
Step 6 — Install and use
Anyone can now add it to their project:
sz install greet-kitImport the library…
import "greet-kit"
let g = new Greeter("world")
out g.hello() // → Hello, world!…and run the command you exposed with bin:
sz run greet name=world // → Hello, world!Next steps
- See the package manager reference.
- Real examples of
bin: the serez-apipack and serez-pack packers run viasz run apipack/sz run pack.