Skip to main content

Autistic stability
for ADHD projects.

dispat turns conventional commits into versions, then builds and publishes changed packages in dependency order. Mathematical version rules make the plan repeatable: identical history and configuration produce the same versions. Saga recovery preserves recorded publications so the next run can finish the remaining packages. Preview the work with dispat status before releasing.

Build and publish stages run your own shell commands, so a package in any language can take part. Automatic manifest editing covers a defined list of supported formats. dispat works with one package, a monorepo, or several repositories joined through a control repository or a choreographed fleet. Independent source histories and choreographed fleets require the 1.11 release candidate; the default installers select the latest stable release.

Mathematical planning. Saga recovery.

Loading distribution count

GitHub release asset downloads + Docker Hub pulls

Loading count…

see it work

Follow a release from commit to publish​

Choose an example to see how dispat selects packages, orders their work, and handles failures.

built for your project

Keep the tools your team already uses​

Release across languages​

Build a Go service, publish an npm library, and push a Docker image in one run. dispat calls the shell commands you configure for each package.

Put dependencies in order​

A package waits for the packages it needs. Independent packages can build and publish in parallel. Preview the selected packages and next versions with dispat status.

Use one or several repositories​

Start with a single package or a monorepo. For work spread across repositories, link them as Git submodules in a control repository: it can read each linked repository's own commits and tags, or hold every release decision in its own history.

Know what to do when a release stops​

dispat writes a Git tag after each successful publish. A package that fails leaves those publications in place, its consumers are held back rather than published from a stale plan, and the next run re-plans the remaining work from the tags. Uploads are never rolled back for you: if a publisher succeeded before its tag was written, check that destination before retrying. Read the recovery guide.

in production

Projects using dispat​

The first monorepo dispat releases is its own: every tag, changelog, GitHub release and container image of this project, and this documentation site, ship through a dispat run.

dispat itself: this repository is a polyglot Go, npm, and Docker workspace. It is released by the dispat binary built from its own checkout, and it has been since the very first release. The first stable run cut eleven packages in one release. It rewrote the go.mod files of six Go modules to the released versions, regenerated go.sum files, and tagged each module the way Go expects (pkg/ccme/v1.0.0, services/dispat/v1.0.0). This keeps go install github.com/yohimik/dispat/services/dispat@latest working. It also attached six cross-compiled binaries to the CLI's GitHub release, published the four container images, and released the versioned documentation site. Every package received its own tag, changelog entry, and GitHub release. The release also announces itself: its announce stage renders a card from the release notes it just wrote and posts it to Instagram, LinkedIn, and Discord with crier, from the same Actions run, which the announcement page describes.

crier: a single-package repository, one Go module and one binary, which renders HTML templates to images and video and posts them to fourteen social platforms. It shows that dispat needs no monorepo. Its first release was a breaking change on the rc channel, and eighteen release candidates followed in two days, each with its own changelog entry and its own GitHub release flagged as a prerelease. One transition commit then graduated the train to 1.0.0: the stable version is computed over the whole train rather than counted by hand, and the graduation collects every candidate's notes into the one entry stable readers see. This is the train and graduation flow that Kubernetes runs its own releases through, here driven by conventional commits alone. A moving v1 alias tag is scoped to the stable channel, so uses: yohimik/crier@v1 never picks up a candidate. crier also shows how a release integrates with dispat: the announce stage of the run renders a card from the release-notes variables dispat sets and posts it from the binary the run just built, and its release-changelog example wires the same card into any dispat release as one more publish step. It installs with dispat install yohimik/crier.

get started

Install once. Preview your first release.​

The installer downloads the binary for your platform and verifies its checksum. No language runtime is required.

macOS and Linux
curl -fsSL https://raw.githubusercontent.com/yohimik/dispat/main/install.sh | sh
Windows PowerShell
irm https://raw.githubusercontent.com/yohimik/dispat/main/install.ps1 | iex

Start in your Git repository​

Generate a starter configuration, edit its package paths and build and publish commands, then inspect the plan. status leaves your project unchanged.

Configure and preview
dispat init
# Edit dispat.json for your packages
dispat status

read on

The documentation​

libraries

Lightweight libraries, usable on their own​

Use dispat's Go libraries in your own tools. Parse commit messages, inspect dependencies, or update manifest versions without running the CLI. The reader and writer share format definitions through pkg/manifest.

pkg/ccme: the commit parser​

Parse Conventional Commits and dispat's package scopes, dependency propagation, and prerelease channels. The parser scans the input once. Its formal rules live in SPEC.md.

pkg/scanner: the manifest reader​

Read package names, versions, and dependencies from the formats below. Results have a consistent shape and order. Scanning uses bounded local reads and returns valid results alongside any parsing errors.

pkg/writer: the manifest writer​

Update supported version declarations while preserving surrounding formatting where the format allows it. Each file is validated before an atomic replacement. The result tells you which edits were applied, missing, or skipped because a value is inherited or calculated.

Languages and manifests the reader and the writer support​

Language / ecosystemManifests read and rewritten
JavaScript, TypeScript: npm, pnpm, Yarnpackage.json
Gogo.mod
Rust: CargoCargo.toml
Python: PEP 621, PEP 735, Poetry, pippyproject.toml, requirements*.txt
PHP: Composercomposer.json
Java, Kotlin, Scala: Mavenpom.xml
C#, F#, VB: .NET, NuGet*.csproj, *.fsproj, *.vbproj, *.nuspec, Directory.Packages.props, packages.config
Dart, Flutter: pubpubspec.yaml
Ruby: Bundler, RubyGemsGemfile, *.gemspec
Swift, Objective-C: iOS, CocoaPodsInfo.plist, project.pbxproj, Podfile, *.podspec
Kotlin, Java: Android, GradleAndroidManifest.xml, libs.versions.toml, build.gradle(.kts)
Docker: images and ComposeDockerfile, Containerfile, compose.yaml, docker-compose.yml, and their .override spellings
UnityPackages/manifest.json, ProjectSettings/ProjectSettings.asset
Godotproject.godot, plugin.cfg, export_presets.cfg
Unreal Engine*.uproject, *.uplugin, Config/DefaultGame.ini, Config/DefaultEngine.ini
Defoldgame.project
O3DEproject.json, gem.json
Aqua tool managementaqua.yaml, aqua.yml, hidden and directory variants

dispat compute reads these manifests to derive package dependencies. Enable autoVersion to update supported declarations during a release. Mobile build numbers are separate from package versions; change them explicitly with --set-build. See Aqua manifest support for supported imports and version declarations.

lineage

Inspiration​

dispat draws on tools and ideas that make complex work easier to inspect, compose, and recover:

  • Linux and Git guided the CLI design: focused commands, explicit inputs, useful exit codes, and tools that work together. The shell tools used on Linux inspired dispat if and dispat for, which expose familiar conditional and looping control flow as commands. Linux's permission classes (others, group, owner) also inspired the configuration scopes: global defaults for all packages, space settings for a group of packages, and a package's own settings. Git also supplies the history and release records that let you inspect how a release was planned and what it completed.
  • Docker Compose, Swarm, and Kubernetes inspired the move from local configuration to coordinated systems. Compose describes services in YAML, and compatible service definitions can become a Swarm stack running across machines. Kubernetes uses declarative manifests to describe cluster workloads. dispat brings that idea to releases: start with packages in one repository, then link repositories into a coordinated release workflow while keeping each repository's package configuration.
  • Database recovery and sagas inspired the approach to reliable releases: record completed work, coordinate concurrent runs, and recover after partial failure. Garcia-Molina and Salem's Sagas (1987) describes long transactions made of smaller, independently committed steps. dispat applies that structure to publishing: it writes a Git tag after each successful publish and uses those records to plan unfinished work. A release lock coordinates concurrent runs, without a separate release database or lock service. If a publisher succeeds before its tag is written, check the destination before retrying. See recovery behavior.
  • Lerna, and the workspaces of npm and pnpm it grew up beside. Between them they proved that many packages in one repository can share a dependency graph. They also proved that versioning and publishing all of them can be one command. dispat takes that idea beyond JavaScript and rebuilds it around an explicit dependency graph and an explicit error model.
  • Conventional Commits: commit messages as machine-readable release intent. The dispat parser, pkg/ccme, implements a strict superset of Conventional Commits 1.0.0 that adds the monorepo dimension. It treats scopes as packages and handles propagation depth and prerelease channels.

community

Have questions or issues?​

Want to share a project you release with dispat? Come and say hello on Discord. Bugs and feature requests are welcome as GitHub issues too, whichever suits you better.