Commands
Run commands from a catalog. Stemma discovers its Git root and stemma.yaml.
--root selects another project directory; --config selects a Project file.
HTTPS trust
HTTPS uses the runner's system trust store, including Keychain trust on macOS and the certificate store on Windows. Install private CAs there for ordinary use. Trust belongs to the runner environment, outside catalog and destination settings.
To supply a PEM trust bundle for a run, set SSL_CERT_FILE before starting Stemma:
SSL_CERT_FILE=/absolute/path/ca-bundle.pem stemma plan
SSL_CERT_DIR selects certificate directories. These are Go's standard trust
overrides, inherited by plugin processes. With Go 1.27+, setting either also
replaces native certificate verification on macOS and Windows. Supply all roots
the run needs, including public CAs when it connects to public services; a private
CA file does not extend the native trust store. See
Go's certificate loading rules.
Catalog workflow
| Command | Purpose |
|---|---|
stemma validate | Check the catalog as written, without environment values or acquisition |
stemma update [Kind/name...] | Discover current inputs and update their locks |
stemma prepare [Kind/name...] | Prepare resources from the lockfile without publication |
stemma signature [Kind/name...] | Derive signed or unsigned expectations for each signing subject |
stemma artifact Kind/name | Prepare one resource from the lockfile and print the path of its artifact |
stemma icon [Kind/name...] | Create missing declared icons from the software's own artwork |
stemma plan [Kind/name...] | Read destinations and report proposed changes |
stemma apply [Kind/name...] | Re-read and reconcile destinations once |
For example, stemma plan MacSoftware/chrome selects one document. Required build
references are prepared first. Use apiVersion/Kind/name when needed to resolve an
ambiguous identity. Omitting selectors processes every resource that declares no
profile and is not
suspended. --profile NAME processes the
resources in that profile instead; repeat it to add profiles. A selector runs
the resource it names, profiled or suspended, and the builds it references.
--profile and selectors cannot be combined.
A selector scopes evaluation as well as execution. Only the selected resources
and the resources they consume are checked against their operation contracts, so
an unrelated document that fails its own validation does not block the run. Use
stemma validate to check the whole catalog, including suspended resources.
update, artifact and icon never reach a destination, so they skip the
destination checks the other commands make.
update writes the input locks and locks plugin tags and local paths. Every
other command uses the reviewed lockfile as it is: an input without a current
entry fails that resource until stemma update records it, and a plugin whose
entry is missing or stale does not load.
prepare --changed-since REV prepares only the resources whose preparation
differs from the catalog at the commit where REV and HEAD meet: their source
and preparation settings after components merge, their lock entries, resource
and input resolver operation identities, and Git changes under declared local
input paths. Destination metadata does not select
resources. Local paths containing environment expressions or outside the Git
root are selected only by declaration and lock changes. Plugin resolvers with
local inputs are selected for any changed project file because they do not
declare which files they read. New resources count as changed, and a changed build selects
the resources that consume it. The command compares the resources a run without
selectors takes: suspended resources stay out, and profiled resources are
compared only with --profile, which compares that profile in place of the
rest. The lockfile must hold entries for exactly the declared inputs of the
compared resources and the builds they reference, and none for resources the
catalog no longer declares; entry and environment values are read only for the
resources the command prepares. Each catalog is interpreted by
the plugins its declarations and lock select, so comparison can execute both base
and current plugin code. Destination operation identities do not select resources
for preparation. A base catalog or required operation that cannot be loaded or
compared fails the comparison; verify such a change with an explicit preparation
run. The checkout needs its history back to that commit.
stemma prepare --changed-since origin/main
icon writes declared icons to icons/<name>.png from
locked software. --presentation raw extracts the original artwork;
--presentation glassy uses the macOS renderer at --size pixels (512 by default).
The default, auto, chooses glassy on macOS and raw elsewhere.
Use --input NAME to read a locked input of the selected resource or its build
dependencies, with --path to select an application, installer or artwork file.
The selected resource must declare spec.icon, which names the asset:
stemma icon MacSoftware/example --input vendor --path Installer.app
Input names inherited from build dependencies must be unambiguous. Only an input that references a resource output requires preparation.
Without --input, --path names an application in one resource's prepared
installer, for a package that holds several and selects none:
stemma icon MacSoftware/suite --path "Payload/Example.app"
Use --from PATH to take the artwork from a local application, installer or
artwork file, for software that carries none of its own:
stemma icon MacSoftware/fonts --from "/System/Applications/Font Book.app"
It writes the icon of one resource that declares spec.icon. The resource needs
no source or lock entry, and --path selects within the local source as it does
within an input.
Existing icons stay unchanged unless --force is set. Only resources needing an
icon are prepared. The command leaves the lockfile unchanged and does not contact
destinations. Commit the icons so publication sends the same bytes on every host.
signature acquires and prepares inputs like prepare, records each subject's
signed or unsigned state and prints a complete signatures fragment. It never
writes documents and ignores existing signing expectations while deriving their
replacement. Invalid or unsupported signatures still fail. For BuildMacPkg, the
command reports the signing subjects its resolved layout consumes, labelled with
their input. It reports nothing for the package a build produced, which needs no
expectation. See macOS,
Windows and
builder signing expectations.
artifact prepares one resource and prints only the absolute path of its
installer output, or of the output --output names. --no-input-lock instead
resolves the inputs of the resource and the builds it consumes from their sources
as they are now, to show what an update would prepare. No destination receives
the artifact. By default the path is a disposable copy in the cache; normal
maintenance protects it for 24 hours after use. cache prune --all removes it
immediately after active runs finish. Use --output-file PATH to export to a new
file or directory outside the cache. Its parent directory must exist; an existing
output is never overwritten. Exports belong to the caller and are never pruned. Progress and errors stay on
stderr, and the live display needs only stderr to be a terminal, so the command
composes with other tools:
stemma inspect "$(stemma artifact MacSoftware/foo)"
stemma inspect "$(stemma artifact MacSoftware/foo --no-input-lock)"
pkgutil --check-signature "$(stemma artifact MacSoftware/foo)"
stemma artifact MacSoftware/foo --output-file ./foo.pkg
--read PATH prints one file inside the artifact instead of its path. The cached
artifact is verified and read where it is; nothing is copied out. Inside a
package, name an entry such as Distribution, or a file in a component's
Scripts or Payload archive, which is decoded up to that file. Inside a disk
image, archive or folder, name a path; it continues into a package found there. A
directory prints the names it holds, and . names the root. The path stays inside
the artifact: it takes no absolute or parent path and follows no symlink. A
redirect or pipe receives the file's bytes as they are. Terminal output rejects
NUL and escape bytes but does not require UTF-8:
stemma artifact MacSoftware/foo --read .
stemma artifact MacSoftware/foo --read Distribution
stemma artifact MacSoftware/foo --read Foo.pkg/Scripts/postinstall
--offline requires cached network inputs and plugins; destination calls
are still allowed. Only plan is the publication dry run. See
sources for lock behaviour.
Automation
stemma reconcile
reconcile publishes the reviewed branch of the checkout you run it in and
proposes lock updates as pull requests in one finite run. The Project's
spec.reconcile.source_control names the provider; see
automating updates.
Agents
stemma mcp
mcp serves the catalog's tools to an agent over the Model Context Protocol on
standard input and output. describe answers what documents can declare, from
the built-in operations and the catalog's plugins; inspect reads a named input's
static facts before a build; prepare tries documents
against their current sources without the lockfile and reports the inspected
artifact, its signer and each destination's publications; update, icon and check match the commands. A
relative from given to icon starts at the catalog root. No tool contacts a
destination.
Inspection and configuration
stemma inspect installer.pkg
stemma validate --resolved
stemma validate --locked
stemma schema --output-file stemma.schema.json
stemma schema --offline --output-file -
stemma version
validate --resolved and schema --output-file - print JSON documents.
schema requires an explicit output file and includes the locally loaded plugins.
--builtins generates the default schema without loading a catalog; it uses the
same registry and schema composition as project generation.
inspect inventories a local file, directory or archive without executing it or
loading a project. --json prints its facts; --path filters by subject path. Pass it
the path artifact prints to inspect what Stemma prepares for a resource.
--read PATH prints one file inside it instead, as artifact --read does.
To inspect a named input before its build expressions can resolve, use:
stemma inspect BuildMacPkg/example --input vendor --path Installer.app --json
This reads the locked input without building the selected resource. Omit --path
to inventory the source; add --no-input-lock to inspect current sources without
writing the lockfile. MCP inspect takes resource, input and an optional path
and uses current sources. Both return the subject IDs and static facts used by
inputs.<name>.facts expressions. --read PATH, or MCP read, returns one file
inside the input instead; MCP returns UTF-8 text up to 256 KiB, including control
characters escaped by JSON. Selecting a package inside an archive returns
its inventory entry. Inspect the package itself to read its receipts and payload.
validate needs no credentials. validate --resolved also evaluates every
environment value, as runs do, and prints the merged configuration with connection
settings resolved. It needs every referenced variable and may expose secrets: do
not share it without reviewing it.
validate --locked also requires the lock to answer every declared input: each
entry records the resolver, resolver version and declaration its input has now,
and no document locks a resource that is no longer declared. It compares
declarations only, without acquiring or reading input content. It does not verify
that the pinned bytes remain available or match their digest: prepare verifies
content. Validation still loads the project's plugins. A
suspended resource may have no entries. An input whose declaration reads the
environment is not compared: the command names it as unresolved and still
succeeds, and --resolved compares it with the evaluated value. MCP check takes
locked for the same comparison and returns the count compared with the
unresolved inputs.
Plugins and cache
stemma plugins list
stemma plugins inspect
stemma plugins inspect --verify
stemma plugins update [NAME...]
stemma plugins publish IMAGE --goreleaser dist
stemma cache path
stemma cache info
stemma cache prune --dry-run
stemma cache prune
stemma cache prune --all
plugins list shows declarations and recorded pins without acquiring or running
plugins. plugins inspect loads the pinned code and reports its capabilities;
--verify also compares each installed plugin with its pinned code. plugins update locks the named plugins, or all of them, to what their
declarations select now: it resolves a tag again and snapshots local files.
update locks the plugins whose entries are missing or stale; no other command
changes plugin entries. See using plugins.
plugins publish pushes a GoReleaser release of plugin bundles as an OCI platform
index; see creating plugins.
The disposable cache defaults to the system's user cache directory under stemma.
--cache-dir / STEMMA_CACHE_DIR overrides it; cache path prints its location.
reconcile --state-dir / STEMMA_STATE_DIR relocates the applied marker from
.stemma/state under the project root. See reconciliation state.
--cache-max-size / STEMMA_CACHE_MAX_SIZE sets the soft retained-cache budget
(default 32GiB, 0 disables automatic content eviction). Normal pruning
protects content used in the last 24 hours; --all overrides that protection.
cache info and cache prune accept --json. Pruning reports reclaimed bytes
and never removes published packages, reconciliation state or user exports.
See cache and offline runs for lifecycle and
accounting details.
Reports and diagnostics
Outcome commands name their work, write each resource's report to stdout as it
finishes, then the run's totals. Plan shows proposed changes, including initial values for new
objects. Apply reports confirmed publication actions. Update shows input changes,
prepare keeps a completion line for every resource, icon names the artwork file it writes,
and signature shows derived signers. Multi-line values such as scripts show line
counts instead of their text. Explicitly selected resources are shown even when
unchanged. --all includes unchanged resources in human
reports. Preparation shows filenames for newly prepared artifacts; cached resources
use one line unless explicitly selected or expanded with --all. Totals always
describe the whole run. JSON includes all resources in the
selected scope, regardless of --all. For each prepared resource, publications
has an entry for every destination, made with no connection to it. Built-in
destinations return metadata with the declared settings and values derived from
the artifact, and null or an empty value for a field the
destination clears. It describes the fields this publication manages, not the
complete remote item; plan compares them with the destination's current state.
Artifact versions describe prepared files; destination versions remain in their managed
metadata, such as pkginfo.version or an included application's version.
origins names where each field's value came from, such as explicit,
expression, artifact.version or installer.receipts. An entry without
metadata is not a preview of the publication, and its deferred says why: the
metadata reads environment values, or a plugin does not return derived metadata.
Jamf previews retain category, policy and patch-title names; planning resolves
their server IDs and checks whether the title defines the requested patch version.
Reconcile prints the reviewed commit's
publication followed by proposal outcomes, under separate applying and update-checking
sections.
stemma plan
stemma plan --json --all > plan.json
stemma prepare --all
stemma prepare MacSoftware/foo --json | jq '.resources[].publications'
Human reports use ➤ for headings, ✓ for successful or unchanged outcomes,
✗ for failures and – for skipped or blocked work. Notices use ! for warnings
and i for information. → marks proposed actions, before/after changes,
redirects and publication destinations. Versions follow names in parentheses;
statuses and field values follow a colon. Details indent by two spaces per level,
with one space between parts of a line. Blank lines separate sections; compact
outcomes stay adjacent. Colour
reinforces these markers; the same text remains readable without it. Diff lines
retain + and -, and literal payloads, YAML fragments and machine output retain
their own syntax.
Pipeline commands start with their resources. Reconcile separates Applying reviewed branch from Proposing updates with neutral section titles. The reviewed branch result includes its elapsed time.
When stderr is a suitable terminal, a live region shows the resource being worked
on: its heading, the step that is running, and above it completed transfers and
other finished steps that took a second or longer. Pipeline steps sit under
Acquire, Prepare and a section for each destination: Check during preparation,
Plan during planning, or Publish during application. Phase labels are subdued,
with a blank line between phases; resource headings stay prominent. Only phases
with visible work appear. Known-size transfers show a bar and counts. A step
that runs again within a phase continues its earlier line. Work that belongs to the command
rather than a resource shows while no resource operation is running. A block taller than the
terminal scrolls into history instead of being cut. The resource's result
replaces its live block, and durable results have the same content in terminals
and pipes. Results remain on stdout even when it is redirected. JSON, generated
documents, CI and dumb terminals suppress the live display; --no-progress
disables it explicitly. NO_COLOR controls colour.
Warnings go to stderr as they happen; in JSON mode they are part of the document.
Resource notices appear once per command, including for cached or unchanged
resources, and remain visible with --no-progress. JSON keeps them in each resource's
notices with a level, rule code, message and optional hint. A missing signature
expectation produces a recommendation to run stemma signature: on directly sourced
MacSoftware, on WindowsSoftware whose setup entry point is an MSI, EXE or DLL, and on
a BuildMacPkg input that supplies an application or package. Declared signers,
explicit unsigned expectations and resource-built outputs do not.
A verified Developer ID application signature without a secure timestamp produces a
warning and stays valid.
Failed commands retain available results and end with a concise stderr diagnostic.
Interrupting with Ctrl-C clears activity, preserves completed results and exits 130.
Press Ctrl-C again to exit immediately if cleanup or a native operation is
taking too long.
Acquisition, preparation and destination failures are local: independent resources
continue, and consumers of unavailable resource outputs are reported as blocked
with blocked_by resource keys in JSON. The command emits the selected results
before exiting nonzero. Global configuration or structural failures and context
cancellation stop the run immediately and can leave a partial report.
Do not infer success solely from an artifact appearing in a report. Update records
the inputs of successful resources even when it exits nonzero; failed or blocked
resources keep their reviewed entries. An update report without lock_changed
did not complete the lockfile comparison.
Standalone packaging
stemma package pkg --help
stemma package intunewin --help
These expose low-level packaging for direct use. Catalogs normally use
BuildMacPkg or the Intune destination instead. stemma <command> --help is the
reference for the flags supported by your installed binary.