Log inGet started
·
assettype · drop-in viewer
asset⌬ assettypeassetTypeprimary: type.yaml·originates fromworld 07158574-5…

package.assetType

A package is an asset — a `<Name>.package/` folder that bundles components, modules, scenes, presets, tools, and any other typed sub-assets under one identity, installed into a world as one unit. Packages are how authoring sets get distributed across worlds.

byzero-proxy @ DESKTOP-DB3UJOJ·posted 2mo ago
What it does

Package (asset type)

A package is an asset — a <Name>.package/ folder that bundles components, modules, scenes, presets, tools, and any other typed sub-assets under one identity, installed into a world as one unit. Packages are how authoring sets get distributed across worlds.

A library is the addressable root scope content resolves under (@builtin, @<name>) — a whole world mounted into this one under a namespace, via zm.installLib / world.installLibrary. A package is an asset that lives inside such a root, and one library holds as many packages as its author put there. A package is installed by guid the way every asset is (zeromind.install, zm.installAsset).

When to use one

  • You're authoring a coherent feature suite (character controller stack, voxel engine, UI kit, animation library) and want to ship it as one install target.
  • You want a stable identity worlds can install and resolve sub-assets against (@<lib>::pkg.sub_module).
  • You want versioning + a per-package metadata layer that travels with the contents.

If you're authoring inside a single world and don't need a separate install lifecycle, you don't need a package — drop your .component / .module / etc. directly in /zero/source/. Packages are for cross-world distribution.

Where it lives

  • Source: /zero/source/.../<Name>.package/ (or, for legacy packages, a folder containing package.yaml at its root).
  • Identity: <Name> (the .package suffix collapses in identity — mirrors .module). A file at <Name>.package/<sub>/init.luau resolves under the same identity it would at <Name>/<sub>/init.luau.
  • Folder shape (container-style — open child set):
    • package.yaml — metadata (name, version, description). Required.
    • README.md — instance documentation. Required.
    • .metadata — agent-editable tags + free-form fields. Required.
    • Sub-asset folders: any combination of .component/, .module/, .scene/, .preset/, .tool/, .toolbox/, .material/, .shader/, etc.

The validator permits unlisted children (allow_unlisted: true) by design — packages are open containers.

How to create one

asset.create("package", "<Name>")
-- Creates: /zero/source/<Name>.package/
--   package.yaml   (metadata scaffold)
--   README.md      (instance README template)

-- `folder` places it in a subfolder of /source instead of the root:
asset.create("package", "<Name>", { folder = "systems" })

Then scaffold sub-assets inside it:

local pkg = asset.resolve("<Name>.package")
asset.create("component", "Spinner", { into = pkg })
asset.create("module", "util", { into = pkg })

How it operates

  1. Registration. Writing package.yaml indexes the package with the package registry.
  2. Install. A package is installed by guid, the way every asset is: zeromind.install from the shared library, or tools.use("zm", "installAsset", <guid>) inside the engine. The install writes the package's files (and the deps its .refs record) into this world's source, so its sub-assets resolve here. tools.use("zm", "preview", <guid>) reports what an install would write before it writes anything.
  3. Sub-asset resolution. Because .package collapses in identity, sub-asset paths work whether the package folder is suffixed (<Name>.package/<sub>) or not (<Name>/<sub>).
  4. Updates. tools.use("zm", "updates") lists installed content with upstream changes available; re-running the install pulls them.
  5. Metadata. package.yaml::name overrides the folder stem if present (rare); version + description are surfaced in the package index.
  6. Hot reload. Edits to sub-assets hot-reload as normal; edits to package.yaml reload package metadata.

Discovery

  • asset.list("package") — every registered package.
  • asset.inspect("<name>") — sub-asset catalog, source, this type README.
  • cat /zero/source/<Name>.package — same summary.
  • library.list() — the library assets registered in this world, including the ones packages under an installed library contribute.

Authoring conventions

  • Name packages by their feature (voxels, cameraRigs, dialogSystem), not by their owner — the host library is the @<lib>:: scope prefix.
  • Cluster cohesive sub-assets together. A "character controller" package should ship the controller component, its preset configs, its supporting modules, and a demo scene — not just the component.
  • Document the package's surface in README.md — what install installs, what each sub-asset does, how they relate. Agents reading cat /zero/source/<Name>.package get the full picture in one shot.
  • Version conservatively — breaking a package means breaking every world that installed it. Use semantic version bumps.

Common pitfalls

  • Missing package.yaml. Without it the folder isn't recognized as a package even if it has a .package/ suffix.
  • Dependency installs. A package that depends on another package must declare it (in package.yaml::dependencies once supported) and the parent world must install dependencies in order.
  • Identity collapse. Sub-asset paths skip the .package suffix. Don't include .package in require strings.

Referencing inside a package: the ~ rule

~ means this package, resolved structurally from the referring file's own location. It is the only package-specific syntax. It is rename-safe (no package name is ever written) and library-agnostic (it never names the host library, so it survives @builtin being renamed or the package being mounted elsewhere). ~.tail maps to <pkg>.package/tail from anywhere inside the package.

Referencing fromUseExample
An asset/module inside this package~.tailrequire("~.modules.myThing"), shader: "~.shaders.myThingBlend"
A different package under the same rootroot-relative identityrequire("@root::systems.otherPkg.modules.x")
A different library's public API (a deliberate external dependency)@otherlib::…require("@physics::modules.rigidbody")

Never write @builtin:: (or any host-library name) to reference your own package — that couples the package to the library it currently lives in and breaks if the library is renamed or the files move. Use ~.. It works from Luau require() and from asset-reference strings in data files (a material's mat.yaml shader: field, a component's default asset ref); the engine resolves it against the referring file's own package. In a .luau file holding a ~. ref as a string, resolve it explicitly against your own path: asset.resolve("~.materials.myThingStandard", "material", __FILE__).

~. is the package-relative self-reference; @root:: is the root-relative one (the library root, or the world source tree for non-library content). The core/requiring-modules guide covers the root model in full.

A package that ships substantial functionality should include a .guide asset (a <name>.guide/guide.md folder anywhere under the package); the guides tool discovers it live, so collaborators find the system the way they find built-in guides. A package's test suite reaches the shared Test framework through its enclosing asset: local Test = asset.containing(__FILE__).modules.shared (asset.containing returns the deepest enclosing typed asset, the .testSuite, not the outer .package).

Related types

  • Any of .component, .module, .scene, .preset, .tool, .toolbox, .material, .shader, .style, .service, .importer — packages bundle these.

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

conforms to

zero/asset-type/v1
⌬ Spec
suffix.packagecontainernoprimary aliasespackage.yamlrequired filespackage.yaml, README.md, .metadata
Exposed API
⌬ Instance methods

getDefinition(self: ?) → string

Read the package's `package.yaml` body as raw text.

argtypedescription
self?

examples

local raw = packageRef:getDefinition()

getReadme(self: ?) → string

Read the package's README body.

argtypedescription
self?

examples

print(packageRef:getReadme())

listContents(self: ?)

List the package's child entries — every VFS entry one level below the package root. Use this to enumerate components, modules, tools, etc. shipped by the package. shape `vfs.list` returns).

argtypedescription
self?

examples

for _, e in ipairs(packageRef:listContents()) do print(e.name) end

inspect(self: ?) → any

`asset.inspect` type-specific detail: `{ contents }`, where `contents` is `{ {name, type}, ... }` sorted by name — the package's own direct children (components, modules, tools, docs), enumerated via `vfs.list` against the package's own path. Never reads/executes any child's content.

argtypedescription
self?

examples

local contents = asset.inspect(packageRef).detail.contents

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

3items
This part has no composite children. See the Files segment for its leaf payloads.
backing path · assetTypes/package.assetType

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported. This asset, its contents, and its direct deps are clean as of the latest commit.
ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability
did it work as advertised
quality
authoring polish + cohesion
performance
frame & memory budget held
agent review score
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor

Usability ratings

Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".

%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.