Skip to main content
Version: 1.0

Configuration file reference

One file at the monorepo root describes everything dispat does. dispat init writes a starter one, and Getting started walks through a first configuration. This page documents the top level and is the one home of the resolution rules below; the CLI and packages pages link back here.

The format is inferred from the file extension. JSON, YAML and TOML are the three dispat reads.

Finding the file. With no --config flag, dispat uses the first of dispat.json, dispat.yaml, dispat.yml or dispat.toml that exists in the root, which are the names dispat init writes under its formats. When the root has none, dispat ascends the parent directories, and a file it finds there only ends the ascent when it declares spaces or packages, because a package folder's own in-folder config file is an override rather than a root. When no candidate exists anywhere, the run fails with an error naming every name it tried. An explicit --config is used as-is, with no fallback, so a typo there fails loudly instead of quietly loading a different file.

Unknown keys are rejected, as typo protection. custom is the one place to put keys dispat does not know.

Case. Keys are matched case-insensitively and map keys are lowercased, so script and space names are effectively case-insensitive. The env objects are the exception, because environment variable names are case-sensitive: their keys keep the spelling you write.

Splitting the file. Any value may be a $ref naming another file, which is how a long configuration is spread across several. The referenced file's content becomes the value, and everything on this page holds for the result.

The larger objects have their own pages:

PageCovers
SpacesSpace options, stages and hooks, login, announce, outcome scripts, the versioning modes (shared versions and none) and versioning groups, scripts, the space's packages map and dependencies, the space configuration file, .dispatexclude.
PackagesThe packages maps: per-package overrides and the ladder that orders them, standalone packages via path, package-declared dependencies, in-folder config files.
What counts as a changesrc and ignore: which of a package's files make a scopeless commit address it, and the .dispatignore file.
Tags and baselinestagFormat, initials.
Alias tagsaliasTags: the extra names a release is written under, beside its real tag.
Release recordschangelog, github, commit, the shared entry format options.
Commit parsing optionscommitErrors, nonPackageScopes, parser.
dependenciesConsumer → provider relations between packages.
Script sequencesscripts, binding a name to one command or to several, and what a failure inside a sequence does to the rest of it.
Run-level hooksThe top-level run object: the hooks that observe the run as a whole, the branch guard, the stale-checkout guard.
Static envenv: fixed environment variables added to every script the run executes.
The .env fileThe environment file read from the current directory into the run, --env-file, and what wins over what.
customcustom: free-form data dispat never reads.
Splitting the file$ref: moving any part of the configuration into a file of its own, and what a path inside one means.

Related references: the CLI, the commit message format and the script environment variables. Annotated full examples: dispat.example.json, dispat.example.yaml.

Top-level options

KeyTypeRequiredDescription
scriptsmap name → command or [command, ...]noNamed shell commands, like package.json scripts. A name binds one command, or an array of commands run in order; see One name, several commands. The same key also exists on a space and on a package, and a package looks up a name in the closest level first. See scripts and dispat run.
spacesmap name → spacesee notePackage groups sharing build/publish behaviour; see Spaces. At least one space or one packages entry is required.
packagesmap name → packagenoPer-package configuration: overrides for space packages (key = folder name), and standalone packages outside every space via path; see Packages.
versionGroupsmap name → {versioning}noShared-versioning groups that cut across spaces, joined by name via a space's or package's versionGroup key. A group may share the whole version, the major and minor, or the major alone; see Versioning groups and the Shared versions walkthrough.
dependenciesmap consumer → providersnoConsumer → provider relations between packages; see dependencies below. Spaces and packages declare their own too.
concurrencyint or [int, int]noOne value for both stages, or [build, publish]. 0 (or omitted) means number of CPUs. More than two values is an error.
logLevelstringnoMinimum log level: trace, debug, info (default), warn or error. See what each level carries.
logFormatstringnoLogger output: pretty (default; colored console output) or json (machine-readable lines for CI ingestion).
tagFormatstringnoRelease tag template, overridable per space and per package. Default {name}@{version}; see tagFormat.
aliasTagsarray of objectsnoExtra tags each release is written under, beside the one tagFormat produces. Overridable per space and per package; see Alias tags.
commitErrorsstringnoWhat an error in a commit message does to the run: warn (default) or error; see commitErrors.
nonPackageScopesarray of stringsnoScope names that are deliberately not packages. Default ["release"]; see nonPackageScopes.
changelogobjectnoPer-package changelog file options; see changelog.
githubobjectnoGitHub release options; see github.
initialsmap package → versionnoBaseline versions used when a package's latest tag is missing or unparseable; see initials.
commitobjectnoEnd-of-run release commit, tagging and push; disabled by default. See commit.
shellarray of stringsnoCommand prefix scripts are appended to, e.g. ["bash", "-c"] or ["cmd", "/C"]. Default ["/bin/sh", "-c"].
envmap name → valuenoFixed environment variables added to every script the run executes. Spaces and packages layer their own maps on top; see Static env.
customobjectnoFree-form data dispat never reads: somewhere to keep your own tooling's settings without the unknown-key check rejecting them. Spaces and packages have their own; see custom.
runobjectnoThe branch guard (allowBranch) and the run-level hooks (beforeAll ... afterPush), keyed by name; see Run-level hooks and The branch guard.
srcstringnoDefault scope folder for every package, resolved against each package's own folder; see What counts as a change.
ignorearray of stringsnoDefault change-scope ignore patterns; see What counts as a change.
flowobjectnoDefault stages and hooks for every space; see Stages and hooks. A space, and then a package, replaces the entries it names and keeps the rest. login may be declared here and still runs once per space.
autoVersionobjectnoDefault manifest-rewriting policy; see autoVersion. A level that states one replaces it whole rather than merging into it.
isBuildWaitingPublishboolnoDefault for every space; see Space options. Default false.
revertOnFailboolnoDefault for every space; see Space options. Default false.
versioningstringnoDefault versioning mode, applied under each space's own group: fixed here means every space versions its packages as one, not that all spaces share a version. Joining spaces into one group is what versionGroups is for. Default independent.
parserobjectnoCommit-message parser options; see parser. Everything unset keeps the specification default.
updateCheckboolnoWhether dispat looks for a newer release of itself and mentions one on a command's way out. Default true; never runs under logFormat: json, and never delays a command. See Updating dispat.
unsafeDisableLockboolnoRelease without the release lock, the tag a release pushes to the remote so that two runs at once are refused rather than raced. Default false. For repositories with no remote to coordinate through; DISPAT_UNSAFE_DISABLE_LOCK=true says the same for one invocation.

Log levels

The levels are not just volume knobs. Each one answers a different question, so the right level to reach for depends on what you are trying to find out:

LevelWhat it carries
errorSomething failed. A package that could not be built or published, a record that could not be written after a release was already out.
warnSomething happened that you would want to know about but that did not stop the run: every W diagnostic lives here, from a package riding a versioning group to a range caught up to a provider released in an earlier run.
infoThe default, and the story of the run: what the plan is, which package published at which tag, what the run ended with. Enough to read a CI log and know what shipped.
debugHow the run decided. Which config file was read and which folder it treated as the monorepo root, which folder each package is scoped to, and the plan's phases as it works through them. This is the level for "why did it pick that".
traceEvery operation, one line each. Every git command with its arguments and how long it took, every dependency edge, and every package's baseline, window size, computed bump and next version, releasing or not. Verbose on purpose: this is the level to attach to a bug report.

--log-level overrides the configured value for one invocation, so you can re-run a puzzling release with --log-level trace without editing anything.

Where a setting can live

Most of what configures a package can be written at more than one level, and the nearest one to the package wins:

package → space → root

The root file says what everything does by default, a space narrows it for its packages, and a package entry (or a package's own config file) settles it for one package. A level that says nothing inherits, which is why the boolean options are three-state: writing false in a space is not the same as leaving it out, and only the first of those overrides a true above it.

Settingrootspacepackage
flowyesyesyes, except flow.login
scriptsyesyesyes
envyesyesyes
customyesyesyes
tagFormatyesyesyes
aliasTagsyesyesyes
autoVersionyesyesyes
isBuildWaitingPublishyesyesyes
revertOnFailyesyesyes
versioningyesyesyes
versionGroupnoyesyes
dependenciesyesyesyes
changelog, githubyesyesyes
src, ignoreyesyesyes
concurrencyyes, as the budgetyes, as a weightyes, as a weight
manifestNamesnonoyes
pathnoyes, the space's own folder or list of foldersyes, one folder, for a standalone package

How a level combines with the one below it depends on the setting:

  • Replaced. Single values such as tagFormat, versioning and src. The nearest statement is the answer.
  • Merged entry by entry. flow, scripts, env. A level replaces the entries it names and keeps the rest, so flow: {build: build-libs} in a space changes the build and leaves publish alone. In flow, an explicit empty array clears an inherited entry; in scripts it is an error, since a name bound to no command is a name that resolves to nothing. An entry is replaced whole however many commands it binds, so restating a multi-command script is a new sequence rather than an addition to the inherited one.
  • Replaced whole. autoVersion, aliasTags, manifestNames. Their empty fields carry meaning against their siblings, so a partial overlay could not express what they mean. An empty aliasTags: [] is how a package opts out.
  • Overlaid field by field. changelog and github. A level can flip enabled and keep the titles it inherited.
  • Merged, never overridden. dependencies. Every declaration at every level adds to one graph.
  • Concatenated. ignore. Later levels add patterns, and a ! pattern re-includes what an earlier level excluded.

One warning about concurrency: at the root it is the budget, the number of slots a stage may use at once, and 0 means the number of CPUs. On a space or a package it is a weight, the number of slots that package's task occupies, and 0 or absent means 1. They are the two sides of the same number and they are not interchangeable.

Everything else is repository-wide and only exists at the root: spaces, packages, versionGroups, initials, commit, shell, run, parser, commitErrors, nonPackageScopes, logLevel, logFormat, updateCheck and unsafeDisableLock.

The full order for one package, from weakest to strongest, is in the override ladder.