Starting a catalog
A catalog is a Git repository with a stemma.yaml Project and imported resource
documents. The Project owns composition, named destination connections, plugins
and the source-control integration of its repository. Resource
documents describe individual builds or software items.
Start with our catalog: its Project, software definitions and plugins show how these pieces fit together. Adapt the destination connections and shared settings to your environment. For a minimal catalog built from scratch, follow getting started.
Files and identities
Keep related definitions and their assets together. For example:
stemma.yaml
stemma.lock/
MacSoftware/
chrome.yaml
icons/
chrome.png
software/
chrome.yaml
fonts/
buildmacpkg.yaml
macsoftware.yaml
Fonts/
Names and directories are your choice. spec.imports accepts paths and globs such
as software/**/*.yaml; every pattern must match. Asset paths are relative to the
document containing the declaration; absolute paths name a host location. icons/ is
the one fixed name: a resource's icon: chrome publishes icons/chrome.png. See
icons.
Each document has a literal apiVersion, kind, metadata.name and spec.
Kinds are case-sensitive: use MacSoftware, not macsoftware. Lowercase filenames
such as macsoftware.yaml are just a convention.
A family can share one file using YAML document separators:
apiVersion: stemma/v1alpha1
kind: MacSoftware
metadata:
name: chrome
spec:
source:
url: https://dl.google.com/dl/chrome/mac/universal/stable/gcem/GoogleChrome.pkg
application:
bundle_id: com.google.Chrome
destinations:
munki:
pkginfo:
description: Google Chrome.
---
apiVersion: stemma/v1alpha1
kind: WindowsSoftware
metadata:
name: chrome
spec:
extends: windows-win32
source:
url: https://dl.google.com/dl/chrome/install/googlechromestandaloneenterprise64.msi
destinations:
intune:
description: Google Chrome.
This uses the munki connection from getting started and the
intune connection and windows-win32 component from Windows apps in Intune.
A resource's identity is apiVersion/kind/name, independent of its filename or
native destination name. Mac and Windows documents can share a name, including on
the same connection. Each destination owns its native publication identity.
Two dependency graphs
Resource-output dependencies, such as source.resource, consume another resource's
immutable output. They order preparation and include the producer when selecting a
consumer. output selects the artifact and defaults to installer.
Publication relationships, such as Munki requires / update_for and Intune
dependencies / supersedes, refer to another resource's publication on the same
named destination connection. They order selected publications without selecting or
mutating unselected peers. An unselected peer contributes its declared destination
metadata so the destination can find an existing publication.
Both use an explicit kind and name; apiVersion defaults to
stemma/v1alpha1. Publication references have no output. Missing resources,
missing publications on the named connection and publication cycles are errors.
See publication relationships.
Choose a kind
| Kind | Use it for |
|---|---|
MacSoftware | A vendor installer or application, or a source-free native deployment such as Munki nopkg |
WindowsSoftware | An existing vendor MSI, EXE or setup directory and its destination settings |
BuildMacPkg | Constructing a package from declared files, directories and installer scripts |
A build reference selects an artifact, not an installed application dependency.
For example, a MacSoftware source can reference the installer output of a
BuildMacPkg. Intune dependencies instead connect native app objects. See
building packages and publishing.
Share defaults when they help
Project components contain reusable spec values:
spec:
components:
mac-software:
destinations:
munki:
pkginfo:
catalogs:
- testing
retention:
keep: 1
A resource uses spec.extends: mac-software. Maps merge recursively; supplied
lists and explicit nulls replace inherited values. A component is optional. Keep
values in the individual document when sharing them would obscure the app's intent.
Within one document, YAML anchors and aliases repeat a value, such as a publisher
name used for both publisher: &publisher Vendor and developer: *publisher.
Inspect the result with stemma validate --resolved. Treat resolved output as
configuration: it may contain values supplied through your environment.
Group opt-in work in profiles
Some resources run on one prepared machine or on their own schedule, such as
applications captured from a Mac that has them installed. Name the workload they
belong to with profiles beside metadata:
apiVersion: stemma/v1alpha1
kind: MacSoftware
metadata:
name: pages
profiles:
- apple-apps
spec:
source:
path: /Applications/Pages.app
Runs without selectors process the resources that declare no profile.
--profile processes the resources in that profile instead, and repeating it
adds profiles:
stemma update
stemma apply
stemma update --profile apple-apps
stemma apply --profile apple-apps
stemma apply MacSoftware/pages
A selector runs a profiled resource by name. Any run also prepares the builds its
resources reference, whatever profiles those builds declare, so only the
resources you start from need the profile. A profiled resource keeps its reviewed
lock entries between its runs and is still checked by stemma validate;
reconciliation skips it. --profile takes a name some resource
declares and cannot be combined with selectors.
Suspend a resource
Some resources need files the repository does not carry, such as licensed fonts
or a vendor package kept out of version control. Declare them and set
suspend: true beside metadata:
apiVersion: stemma/v1alpha1
kind: BuildMacPkg
metadata:
name: fonts
suspend: true
spec:
inputs:
fonts:
path: Fonts
package:
identifier: edu.example.fonts
version: "1.0"
payload:
/Library/Fonts:
$input: fonts
A suspended resource keeps its reviewed lock entries and is still checked by
stemma validate, but runs without selectors, runs of its profiles and
reconciliation skip it. On a machine
holding the files, stemma apply MacSoftware/fonts runs it together with the
builds it references. A resource that is not suspended cannot consume a suspended
resource's outputs: suspend both and select the consumer.
Expressions and editor support
Use expressions for environment values and inspected metadata:
client_secret: "{{ env.INTUNE_CLIENT_SECRET }}". Stemma reads the process
environment when a command uses the value; it does not source .env. Expressions
can fill a whole value or interpolate into text. Document identities, mapping keys and resource references
remain literal.
The default schema describes built-in operations and accepts arbitrary destination names. Generate a catalog-specific schema from the local registry, including installed plugins and the Project's named destinations:
stemma schema --offline --output-file stemma.schema.json
Track the generated file in the catalog and head each document with a YAML language-server modeline using its raw repository URL:
---
# yaml-language-server: $schema=https://raw.githubusercontent.com/OWNER/CATALOG/main/stemma.schema.json
apiVersion: stemma/v1alpha1
kind: BuildMacPkg
# ...
---
# yaml-language-server: $schema=https://raw.githubusercontent.com/OWNER/CATALOG/main/stemma.schema.json
apiVersion: stemma/v1alpha1
kind: MacSoftware
# ...
The language server applies a modeline to one document, so a file holding several
repeats it after each ---. A comment above a --- belongs to the document
before it.
For agents, stemma mcp exposes the same contracts through
its describe tool, including field descriptions from built-ins and plugins.
Regenerate the editor schema when plugin declarations or destination names change.
--output-file is required; use --output-file - to print JSON to stdout. Schema generation does not need destination
credentials or acquire software, but OCI plugin bundles must already be cached
when using --offline. Go validation also checks semantic rules that are broader
in the editor schema, such as valid Microsoft product/channel combinations.