realm.yml
Required metadata file at the realm root.
name: githubdescription: "GitHub integration — analyze and fix issues"version: 0.1.0author: Embabelurl: https://github.com/embabel/realm-githubicon: icon.svgcategory: developertags: - integrations - developer-tools| Field | Required | Description |
|---|---|---|
name |
Yes | Realm name (kebab-case) |
description |
No | What the realm does |
version |
No | Semver version (default: 0.0.0) |
author |
No | Author or organization name |
url |
No | Source repository or documentation URL |
icon |
No | An image the realm ships, as a path relative to the realm root. See Icons. |
category |
No | What the realm is for: one id from the published list of categories. See Category. |
tags |
No | Free-text keywords, for finding the realm. They are not its category. |
maturity |
No | The author’s own readiness claim: experimental, beta, stable or deprecated. Absent means the realm makes no claim — which is not a claim of being finished. See Maturity. |
host |
No | Execution host for the Realm’s Functions: docker or wasm. Absent means the platform infers it from what’s on disk. See Execution hosts. |
optionalLabels |
No | Labels this realm’s views read but do not need: each owned by a companion realm that may be absent, and read only under OPTIONAL MATCH. See Optional labels. |
A realm may ship an image for hosts that draw a realm list — a launcher, a directory, a settings pane:
icon: icon.svg # or assets/movie.png, or anything under the realm rootOptional in every sense. A realm without one is not diminished; hosts that drew a letter tile before keep drawing it. Nothing else in the manifest depends on it, and a host that ignores the field entirely is still conformant.
It must be a file the realm ships, addressed relative to the realm root.
Hosts are required to refuse anything else — an absolute path, a .. that
climbs out of the realm, or a URL:
| Declared | Result |
|---|---|
icon.svg |
Served, if the file is there |
assets/movie.png |
Served, if the file is there |
../../elsewhere.svg |
Refused |
/etc/passwd |
Refused |
https://example.com/pixel.gif |
Refused |
The URL case is the one worth stating plainly, because it looks convenient. A remote icon makes every host that renders a realm list fetch a third party on the user’s behalf — telling whoever serves the image which user is browsing which realms, from what address, and handing the realm author a hit counter on someone else’s UI. A realm’s icon travels with the realm, like the rest of it.
SVG is the sensible default (small, sharp at any tile size). Raster formats — PNG, JPEG, WebP, AVIF, GIF, ICO — are also fine. Keep it square and legible at about 40px: this is a tile, not an illustration.
Apps declare their own, separately and by the web’s usual means — a
<link rel="icon" href="…"> in the app’s <head>, pointing at a file beside
it in apps/. Same principle, existing convention, no new field.
Maturity
Section titled “Maturity”maturity: experimental # or: beta, stable, deprecatedThe author is the only party who knows whether a realm is finished, so this is where that is said. It is a claim, not a measurement — nothing inspects a realm to verify it, and no host may imply otherwise.
Four values, compared case-insensitively: Experimental in a manifest and
experimental in a host’s configuration are one claim. No other cleverness — no
plural folding, no synonyms, and no implied ranking between the four.
Absence is not a claim of being finished. Hosts are required to treat a
missing maturity as unstated, never as stable. Most realms that exist say
nothing, and a host that read stability out of silence would be marking every
one of them as ready. Hosts are required to treat an unrecognized value the
same way — unstated — rather than refusing the realm or guessing at what was
meant: a realm is an arbitrary git repository, and one misspelled line in one
repository must not break a directory everybody browses.
It is not a tag. Tags are free text, for finding things (crime, maps,
open-data). A readiness judgment read off free text fails silently in the one
direction that matters: a realm tagged experimantal is offered to everybody as
though finished, and nothing anywhere says so. So this is its own field, with a
closed set of values.
What a host may do with it (informative — the behaviour of the reference host, not part of the contract):
| Claim | Reference host behaviour |
|---|---|
experimental |
Installing requires the user’s explicit confirmation: the host asks, carrying the realm’s own warning, and only a yes proceeds. Surfaces that list realms leave it out by default, behind a visible opt-in that says how many were left out. An already-installed experimental realm is never hidden — it is part of that world whatever its author thinks of it. |
beta, stable, deprecated |
Shown as a badge where realms are listed. No other behaviour today. |
Two consequences worth stating, because they are easy to get backwards:
- Hiding is a display default, not a gate. A realm left out of a list is still installable by name, and the confirmation is what actually stands between a user and an experimental realm. A host that filtered a list and installed silently would have removed the gate rather than added one.
- A host can only act on a claim it can read. A directory that lists realms
it has not installed has to carry
maturitythrough from wherever it discovers them; one that discovers realms without reading their manifests (a repository scan working within an unauthenticated API budget, say) carries no claims, and must then show everything rather than infer.
Category
Section titled “Category”category: financeWhat the realm is for, as one id from a closed list. It is how a store is browsed by somebody who does not yet know which realm they want: a short list of purposes to choose from, rather than every word any author has used.
The list is published, and it is the authority. It lives at
realm-categories.yml
in embabel/default-installation, and is carried, whole, in the realm catalogue
built from it. Each entry has an id, a label, an icon and a description.
This document does not repeat the ids, because a copy here would drift from the
list realms are judged against. A category is added by a change to that file,
and an id is never renamed or reused once realms declare it.
One value, compared case-insensitively. A realm has one category: the thing it is mainly for. A realm that could sit in two picks the one a person looking for it would try first.
Check it before publishing. A manifest is judged against the list with no token and no network:
python3 scripts/build-realms-index.py --check path/to/realm.ymlfrom a checkout of embabel/default-installation. It fails on a missing category
and on an id that is not listed, naming the ids it could have been.
Absence is not an error. Hosts are required to treat a missing category as
uncategorised, and an unrecognized value the same way, rather than refusing
the realm or guessing at what was meant — for the reason given under
Maturity: one misspelled line in one repository must not break a
directory everybody browses. An uncategorised realm is still listed, still found
by search and still installable.
It is not a tag. Tags are free text, for finding things, and nothing reviews
them. Many say how a realm is built (openapi, skills) rather than what it is
for, and most are used by one realm only. A realm keeps its tags as search
keywords; it says what it is for here.
What a host may do with it (informative — the behaviour of the reference
host, not part of the contract): the catalogue carries a realm’s category only
when it is on the list, and a store may offer the categories as a way to browse,
each with the list’s own label and icon. A host that discovers realms without
reading their manifests carries no categories, and must then show those realms as
uncategorised rather than infer one.

