These docs are under active development.
On this page
reference 15 min read

Recipe format reference

This is the normative schema for the two TOML files at the heart of a pekit recipe: pekit.toml (the recipe proper) and package.pekit.toml (what to package). It enumerates every section, every key, its type, whether it is required, and its meaning. Behaviour that a key merely triggers is cross-linked to the concept pages; this page is the field-by-field contract.

Two strictness rules hold throughout and are called out per-section below:

  • Unknown keys are hard errors. Every table the loader owns has a fixed set of accepted keys. Any other key — including a camelCase spelling of a known snake_case key, such as outDir — is rejected with an unknown_key diagnostic. There is no lenient/forward-compatible mode.
  • Types are checked on decode. A key declared here as a string must be a string, a table must be a table, and so on; a mismatch is an invalid_type error.

pekit.toml

Worked example

out_dir = "dist"

[env]
CFLAGS = "-O2"
PREFIX = "/usr"

[wrap]
command = ["pesb", "run", "--", "{{command}}"]

[source.git]
url = "https://github.com/example/tool.git"
ref = "v{{version}}"
versions = ">=1.0"
tag_regex = "^v(?P<version>[0-9.]+)$"

[build]
command = "make PREFIX=$PREFIX"

[build.docs]
command = ["make", "docs"]
needs = ["main"]

[build.linked]
command = "make link"
dependencies.pesb-dev.libc = ">=2.38"

[test]
command = "make check"

[install]
command = "make install DESTDIR=$PEKIT_OUT"

[clean]
command = "make clean"

Top-level keys

The recipe file accepts exactly these top-level keys. Anything else is an unknown recipe key error.

Key Type Required Meaning
out_dir string no Output directory name, relative to the recipe root. Default "out".
env table no Environment variables exported to every target command. See [env].
wrap table no Command wrapper applied to every target. See [wrap].
source table no Where the recipe's source tree comes from. See [source].
delegate bool or table no Borrow build/env/wrap/package definitions from the source tree. See [delegate].
build table no Build target(s). See [build] / [test] / [install] / [clean].
test table no Test target(s).
install table no Install target(s).
clean table no Clean target(s).

[env]

A flat table of environment-variable name → value. Every entry is exported into each target command's environment (layered on top of the PEKIT_* contract; see Anatomy of a recipe).

Key Type Required Meaning
<NAME> string Value for variable NAME.

Each NAME must match ^[A-Za-z_][A-Za-z0-9_]*$; anything else is an invalid_env error. Values must be strings. Declaration order in the file is preserved, so a later entry may reference an earlier one via shell expansion in the target command.

[wrap]

Wraps every target command in another command (for example, running it inside a sandbox launcher).

Key Type Required Meaning
command string or array of strings no The wrapper. Must contain the placeholder {{command}} exactly once.

No other key is permitted under [wrap]. The {{command}} rules mirror a target command:

  • String form: the whole string is run through a shell; it must contain the substring {{command}} exactly once.
  • Array form: {{command}} must appear as a complete argument (not a substring of a larger argument) exactly once, and never as the first element (element 0 is the wrapper program itself).

An omitted command yields an empty wrap (no wrapping).

[source]

Selects and configures the source tree. It has three sub-tables. At most one reproducible source (git or url) may be present — declaring both is a mixed_source error. A local source may be combined with a reproducible one (the local path acts as an override). Unknown keys directly under [source] are rejected.

Sub-table Meaning
[source.git] Clone from a git repository.
[source.url] Download from a URL (optionally an archive).
[source.local] Use a directory on disk.

See Sources for materialisation, caching, and provenance behaviour.

[source.git]

Key Type Required Meaning
url string yes Git remote URL to clone.
ref string no Ref (tag/branch/commit) to check out. Templated. Default "{{version}}".
versions string no Version cap: a constraint string filtering enumerated or requested versions (see Versions).
tag_regex string no Regex extracting version numbers from tag names during enumeration.

[source.url]

Key Type Required Meaning
url string yes URL to download. Templated with the version.
extract bool no Treat the download as an archive and extract it. Default false.
root string no Sub-directory within the extracted tree to use as the source root. Default ".".
versions string no Version cap: a constraint string filtering enumerated or requested versions (see Versions).
file_regex string no Regex extracting version numbers when enumerating from a listing.
checksum string or table no Expected checksum. A bare string applies to all versions; a table maps version → checksum.

[source.local]

Key Type Required Meaning
path string yes Path to the source directory, resolved relative to the recipe root.

[delegate]

Lets a recipe borrow definitions that live inside the fetched source tree rather than in the recipe directory. May be written as a bare boolean (delegate = true, equivalent to all = true) or as a table.

Key Type Required Meaning
all bool no Delegate everything (build, env, wrap, packages).
build bool no Delegate build targets.
env bool no Delegate [env].
wrap bool no Delegate [wrap].
packages bool no Delegate package definitions.

Any other key is an unknown delegate key error. A category is delegated when either its own flag or all is set.

[build] / [test] / [install] / [clean] {#targets}

These four sections define targets — the commands pekit runs. Each section takes one of two shapes, distinguished by whether a command key is present directly in the section:

  • Bare target: command (and the other target keys) sit directly under the section, e.g. [build] with command = "make". This defines a single target named main.
  • Named targets: the section contains sub-tables, e.g. [build.docs] and [build.linked], each a target. Each name must be a valid selector.

Mixing the two — a bare command alongside a named sub-table in the same section — is a mixed_targets error. (A sub-table whose key is itself a target key, such as [build.dependencies], is read as part of the bare target, not as a named target.)

Fields of a single target:

Key Type Required Meaning
command string or array of strings yes The command. String form runs through a shell; array form is an argv executed directly. An empty array is rejected.
needs array of strings no Names of other targets in the same section that must run first.
clear_out bool no Wipe this target's output directory before running. Default true.
dependencies table no Build targets only. Build-time dependencies the target needs provisioned. See below.

Any other key in a target table is an unknown target key error. dependencies is accepted only in [build] targets; using it in test/install/clean is an unknown key.

The dependencies table is keyed by provider (a selector), each mapping dependency names to version constraints:

[build.linked.dependencies]
pesb-dev.libc = ">=2.38"
pesb-dev."pkgconfig(zlib)" = "*"
Level Type Meaning
provider table A dependency-provider selector.
provider.<name> string Version constraint for the capability name. Must be non-empty; use "*" for any version.

Dependency names may be real package names or virtual capabilities (sonames, pkgconfig(...), etc.) and are validated against peipkg's capability grammar. See Commands and targets.

package.pekit.toml

The package file describes one or more package artifacts to emit from the built source. The same schema applies to the base file (package.pekit.toml) and to per-member member files (<name>.package.pekit.toml); see Multi-package recipes and Supporting files for how the files are discovered and layered.

Worked example

format = "peipkg"
builds = ["main"]

[package]
name = "tool"
version = "{{version}}"
architecture = "x86-64-v3"
description = "An example tool"
license = "MIT"
homepage = "https://example.com/tool"
default_root = "opt.tool"

[dependencies]
libc = ">=2.38"
zlib = { constraint = ">=1.3", root = "opt.tool" }

[optional_dependencies]
libcurl = ">=8.0"

[provides]
tool = "{{version}}"

[files]
"main:bin/tool" = "usr/bin/tool"
"@recipe:share/" = { path = "usr/share/tool/", override = true }

[symlinks]
"usr/bin/t" = "tool"

excludes = ["@recipe:share/*.tmp"]

[claims.provides.editor.default]
path = "usr/bin/editor"
target = "usr/bin/tool"

[[publish.localdir]]
path = "dist"
overwrite = false

Top-level keys

The package file accepts exactly these top-level keys; anything else is an unknown package key error.

Key Type Required Meaning
format string no Artifact format: "tar" or "peipkg". Default "tar".
clear_out bool no Wipe the package stage directory before building. Default true.
builds array of strings no Names of build targets this package requires before staging.
package table no Package metadata. See [package].
files table no Payload file mappings. See [files].
symlinks table no Symlinks to embed in the payload. See [symlinks].
excludes array of strings no Refs/globs to drop from directory payloads. See excludes.
multipack table no Expand into a family of instances. See [multipack].
publish table no Where to copy finished artifacts. See [publish].
dependencies table no Runtime dependencies. See [dependencies].
optional_dependencies table no Optional runtime dependencies (same schema as dependencies).
conflicts table no name → constraint of packages this one conflicts with.
provides table no name → version of capabilities this package provides.
replaces table no name → constraint of packages this one replaces.
side_effects array of strings no Declared install-time side effects.
sd_overrides table no path → SDDL security-descriptor overrides.
claims table no Claim slots on provides/dependencies. See [claims].

The tar format carries payload only: it cannot express manifest metadata. If a tar package sets version, architecture, description, license, homepage, or any of dependencies, optional_dependencies, conflicts, provides, replaces, side_effects, or sd_overrides, the build fails with unsupported_manifest_field. The peipkg format requires both [package].version and [package].architecture.

Most string-valued fields (metadata, dependency names/constraints, file refs and destinations, claim paths/targets) are run through the template engine, where {{version}} and {{multipack}} are available. See Versions and Multi-package recipes.

[package]

Package metadata. Accepts exactly these keys; any other is an unknown package metadata key error. All values are strings.

Key Type Required Meaning
name string no Package name. Defaults to the package selector (suffixed with the multipack value for multipack instances) when omitted.
version string no Package version. Required for peipkg.
architecture string no Target architecture. Required for peipkg.
description string no Human-readable description.
license string no License identifier.
homepage string no Project homepage URL.
default_root string no Preferred named root for a top-level install. Must be a dotted named reference matching [a-z0-9][a-z0-9_-]* per segment, never a filesystem path (a / is rejected).

Note that dependencies, provides, conflicts, and the rest are top-level tables, not sub-keys of [package].

[dependencies]

Runtime dependency constraints. [optional_dependencies] has the identical schema. Each entry is either a bare constraint string (the short form) or a table that additionally places the dependency in a named root.

Form Type Meaning
<name> = "constraint" string Version constraint; the dependency lands in the depender's own root.
<name> = { constraint, root } table Table form (below).

Table form keys — only these two are accepted (unknown_key otherwise):

Key Type Required Meaning
constraint string no Version constraint. Omitting it matches any version.
root string no Named root to place the dependency in. Same grammar as default_root.

Dependency names may be real or virtual capabilities. See Dependencies and claims.

[files]

Maps a source ref (the key) to a destination path within the package payload (the value). The value is either a string destination or a table.

Value form Meaning
"ref" = "dest/path" Copy the ref to dest/path.
"ref" = { path, override } Table form (below).

Table form keys — only these are accepted:

Key Type Required Meaning
path string yes Destination path in the payload. Must be non-empty.
override bool no Mark the payload as an override entry (skips manifest payload validation for peipkg). Default false.

The source ref selects where the file is read from. A bare path with no prefix is resolved against the recipe root (or the layer's owner). Explicit forms: @recipe:<path>, @source:<path>, @workspace:<path>, and <build-target>:<path> (reading a build target's output; :<path> alone uses the main build target). Destinations ending in / and glob patterns are supported. See Packages for ref resolution and glob semantics.

Maps a destination path within the payload (the key) to a symlink target (the value).

Value form Meaning
"usr/bin/x" = "target" Create a symlink at usr/bin/x pointing at target.
"usr/bin/x" = { target, override } Table form (below).

Table form keys — only these are accepted:

Key Type Required Meaning
target string yes Symlink target text. Must be non-empty.
override bool no Mark as an override entry. Default false.

excludes

An array of refs/globs. During directory payload expansion, files matching an exclude pattern (resolved against the same root as the file mapping being expanded) are dropped from the payload. Patterns use the same ref forms as [files] keys.

[multipack]

Expands one definition into a family of package instances, one per enumerated value. The only accepted key is enum, which takes one of two shapes:

Explicit list:

[multipack]
enum = ["gtk3", "gtk4"]

Each value must be a valid selector, non-empty, and unique.

Enumerated from files:

[multipack.enum.files]
path = "@source:themes/*/theme.ini"
regex = "^(?P<value>.+)$"

[multipack.enum.files] accepts exactly path and regex, both required:

Key Type Required Meaning
path string yes A ref glob (templated) whose matches are enumerated.
regex string yes Regex applied to each match's basename. Must have exactly one capture group, or a single named value group, which supplies the instance value.

See Multi-package recipes.

[publish]

Where finished artifacts are copied. The only accepted target is localdir, written as an array of tables:

[[publish.localdir]]
path = "dist"
overwrite = false

Each entry accepts only path and overwrite:

Key Type Required Meaning
path string yes Destination directory, relative to the workspace root (or recipe root outside a workspace). Templated. The artifact keeps its own filename.
overwrite bool no Allow replacing an existing file at the destination. Default true.

[claims]

Attaches claim slots to provides and dependency entries (a claim is a symlink slot a provider fills or a consumer expects). The [claims] table has two sides — provides and dependencies — each keyed by the provides or dependency name, then by slot, then to a descriptor. Any side other than provides/dependencies is an unknown_key error.

[claims.provides.<name>.<slot>]
path = "usr/bin/editor"
target = "usr/bin/tool"

[claims.dependencies.<name>.<slot>]
path = "usr/bin/editor"

A slot descriptor accepts exactly these two keys (anything else is rejected); both are strings and both are templated:

Key Type Required Meaning
path string no The symlink location (set on a consumer, or as a provider default).
target string no The holder file within this package (set on a provider). A provider's target must point at a file the package ships.

Provider-side slots (claims.provides) attach to matching [provides] entries by name; consumer-side slots (claims.dependencies) attach to matching [dependencies]/[optional_dependencies] entries. See Dependencies and claims and the Peios claims model for the resolution behaviour.