Luban's editions, policies and boot profiles are ordinary recipes in this index:
the xpkg format is unchanged, the data is in the recipe, and only
libs/luban.lua writes files. What Luban is, and how editions are used, is in
xlings's Luban docs.
The luban: namespace
What is official and made for Luban is published in the luban namespace:
editions (luban:core, luban:desktop), desktop components (luban:labwc,
luban:lxqt, luban:kde, luban:xdesk), the Qt runtime, the tool sets, and
the bundles built for them. General software stays in xim (fish, mesa, a
kernel), and so do the programs a user runs on a host (xim:luban,
xim:luban-os). Anyone may depend on a luban: package -- any SubOS, any
system: the namespace says who publishes it, not who may use it.
A short name in luban is a name in this namespace: --edition desktop is
luban:desktop, --desktop kde is luban:kde. Adding an official desktop is
adding its recipe here; nothing in luban or the Luban OS app lists them.
xim, luban, subos and config are reserved: index-compat.json
declares them (namespaces.reserved), and a client that knows the field takes
packages in them from this index only -- a recipe elsewhere that says
namespace = "luban" is refused, naming its index and file. The rule is the
client's and generic: any index may reserve its own namespaces the same way.
The published subos:luban-* editions and xim:labwc-desktop are frozen:
kept, resolved as before (instances and older editions name them), never
updated. Their successors declare replaces = "<old name>", which a client
honours from the same index only.
The kinds
| Kind | type |
Namespace | Version | Written by |
|---|---|---|---|---|
| an edition | subos |
luban (frozen ones: subos) |
the release date, YYYY.M.D.N |
luban.edition({id, variant, versions, files}) |
a desktop component (luban:labwc, luban:foot) |
package |
luban |
upstream's, -rN for this index's build |
the recipe; luban_component places it |
a composite (luban:compositor, luban:xdesk) or a tool set (luban:tools-dev) |
package |
luban |
the release date, or what it composes | its deps, its session and configuration |
| a policy | subos-policy |
xim |
the release date | luban.policy(json) |
| a boot profile | package |
xim |
the release date | luban.boot(json) |
| upstream software (kernels, limine, busybox, ...) | package |
xim |
upstream's, -rN when rebuilt |
the recipe |
Each component says, in a comment, the form it takes and why (a bundle, a
runtime, a composite of atomic packages): the name and its conventions (a
session file, X-Luban-Shell, its checks, the default terminal) stay when the
form changes.
An edition's manifest
A luban: edition writes its manifest from a table (luban.manifest): its
keys in a fixed order, replaces the frozen edition it succeeds, and a luban
object -- what a reader that knows Luban is told about it:
| Key | Meaning |
|---|---|
luban.settings |
what it presets (mode, enter, desktop, login_shell): below what the person sets; also written to the root's usr/share/luban/settings.json, which an older luban reads |
luban.os |
how it names itself (name, version): a distribution based on Luban says its own name |
luban.requires |
what it needs of whoever reads or runs it (opencaps names, root-layout>=2); a reader that lacks one says so before making it |
manifest = {
subos_kind = "rootfs", min_client = "2026.10.18.1",
from = "luban:core@2026.10.18.1", replaces = "subos:luban-desktop",
abi = { kernel = "linux", libc = "gnu" },
packages = { "luban:xdesk@2026.10.18.1", "luban:foot@1.27.0-r1" },
luban = { settings = { mode = "machine", enter = "desktop", desktop = "xdesk-classic" } },
workspace = {},
}
The rules
- A published version's output never changes.
tests/fixtures/luban-published.jsonrecords the sha256 and mode of every file each published version writes, andtests/test_luban_published.pycompares. When a version merges tomain, add it:LUBAN_PUBLISHED_ADD=pkgs/l/<recipe>.lua@<version> pytest -k add_published. The fixture only grows. - An edition using a field newer clients read sets
min_client. A new field is designed so an older client ignoring it is still safe (an ignoredboot.profilefalls back toboot.kernel). - Every edition
froms an official layer (except nano) and states itsabi. - A new edition names only
luban-init;xlings-initstays for published versions. - Tools that move fast are not pinned (an agent CLI):
subos newinstalls the newest and records it in the instance, andluban upgrademoves it. Every other package is pinned exactly. - A preview edition (
status = "preview") has no short name in luban. A desktop is not an edition: an edition presets one, andluban new --desktopchooses another (luban-desktopin a package'scategoriesoffers it). - An edition is built for the architectures it declares.
archslists only what was booted and tested; each package it pins exists for each of them, andscripts/test-luban-editions.shruns on x86_64 and aarch64.