steuermaschine
sm is a reusable coordinator that steers a change from commit to live release for projects in which AI agents do
the work. It keeps resumable state per head (a commit on a work branch) and per release, always knows the one next
command, and stops at review points where only the owner or an independent reviewer may continue. The core knows no
project; pipelines, providers, gates and traps come from plugins (core plus plugins, wired with pluggy).
The name: not a Steuermann or Steuerfrau, a human helmsman, but the artificial one: a Maschine that steers. The owner sets the destination and decides at the review stops.
Status
Pre-release and private. Version 0.0.1. Every command is native; no command starts an old script
(sm tools gaps --wrapped prints 0, sm tools gaps the rows not ported yet). The binding goal for the first
release is docs/DEFINITION-OF-DONE.md. The plugin API (steuermaschine.API_VERSION)
may still change.
Install
From a clone, for now (PyPI later, project name steuermaschine):
git clone <repository-url> steuermaschine && cd steuermaschine
uv tool install . # puts `sm` and `steuermaschine` on your PATH
For development use uv sync and bin/sm-dev instead (see Development).
Quick start (toy plugin, no account needed)
uv sync && export PATH="$PWD/.venv/bin:$PATH"
mkdir /tmp/toy && cd /tmp/toy && git init -q -b main && git commit -q --allow-empty -m init
printf '[project]\nname = "toy-demo"\nplugin = "toy"\n' > steuermaschine.toml
git checkout -q -b feat/hello && echo hi > hello.txt && git add hello.txt && git commit -q -m hello
sm # PHASE idle
sm head ship . # dry run: stops before the first write outside this machine, prints what it would do
sm head ship . --live # pushes, opens the PR, then WAITING on CI
sm sim ci green . # play the outside world: CI turns green
sm head ship . --live # continues where it stopped: merge, tag, finished
Run the uv sync line in the clone, the rest in the scratch directory. The toy's forge and CI are a simulation in
.sim/world.json; the engine, state, dry run, waiting and resuming are real. State lives under
~/.local/state/steuermaschine/<project> (STEUERMASCHINE_HOME moves it).
The go contract
Bare sm (same as sm go) is read-only and prints, in this order:
PHASE: where the project stands.NEXT: the one command to type now.TRAP: the mistake that is most likely at exactly this step. Read it before you run NEXT.
WAITING appears when the run waits on the outside world (CI, a reviewer); run the same command again later.
Exit codes: 0 done or a planned stop, 1 refused, 2 usage, 3 alarm, 70 tool error or plugin not loaded, 75 waiting.
Every command has --format json with exactly one document and a published schema (sm self schema).
The review gate
-
A command that writes outside this machine, or changes state other commands act on, is a write command.
-
Write commands stay closed (exit 70, naming the review file) until an independent review approves them.
-
The approval names the exact digest of the reviewed code unit: the module, its
*_libpackage and every first-party file it imports, transitively. Any edit to one of them voids it, also an edit to the core. -
The reviewer is never the author:
sm review verdict DIGEST --approve --reviewer NAMErecords it. -
sm self reviewslists every write command, its unit, its digest and its state. -
bin/promoterefuses a build in which a gated write command is not approved: promoting it would switch that command off.
Writes that a pipeline step makes also need --live; without it a run stops with a dry-run plan. A pipeline
(sm head admit, sm release cut in the Heinzelmännchen plugin) runs each step as a native command through that
command's own gate, and stops at its review points until a different agent approved the digest.
Writing a plugin
A plugin is an object (or module) with functions marked @hookimpl; the core calls the ones it implements:
sm_api_version, sm_settings, sm_pipelines, sm_gates, sm_traps, providers such as sm_forge and sm_ci,
sm_native (commands: @native functions that return a result model) and more. Every command follows the help
contract (sm self lint, strict) and prints one typed JSON document with --format json. Register it as an
entry point in group steuermaschine.plugins and name it in the project's
steuermaschine.toml (plugin = "...", or plugins = ["base", "outer"]; later entries are outer layers).
sm self hooks lists the specifications, sm self plugins the loaded stack. Start from examples/toy (a complete
plugin in one file), examples/layer (a second plugin layered on the first), src/steuermaschine/hookspecs.py and
section 5 of docs/DESIGN.md. Test with steuermaschine.testing (fake_providers, invoke,
conformance kit).
Development
uv sync # workspace: core, plugins/heinzel, examples/toy, examples/layer
uv run pytest # all tests, sandboxed (see docs/INTEGRATION.md section 8.5)
bin/sm-dev ... # run the development tree
bin/check # the quality gate: tests, coverage >= 90, help lint, typos, ruff, mypy strict,
# pyright, dead code, the plugin's debt ratchet (docs/debt.json); --fast skips coverage
bin/promote --check # everything a promote would test, without switching
bin/promote # build the committed HEAD into the stable install and switch to it
bin/rollback # switch the stable install back to the previous release (again: forward)
A stable install differs from the development tree: sm on the PATH runs a commit built with git archive into
its own directory and virtual environment, non-editable, and nothing in it points at the checkout. Only
bin/promote changes it, so editing or breaking the tree never breaks the live tool.
Docs
- docs/DESIGN.md: purpose, pipelines as state machines, providers, plugins, help contract, output.
- docs/INTEGRATION.md: the contract for every change handed to the integrator.
- docs/DEFINITION-OF-DONE.md: the binding goal for the first release.
- docs/NATIVE-PORT.md and docs/GAPS.md: how the old tools were ported.
- docs/RUNBOOK-release-cut.md: a release with
sm release cut. - docs/SWITCH-queue-daemon.md: switching the live queue daemon.
- AGENTS.md: instructions for coding agents working in this repository.
Metadata
Release files for steuermaschine 0.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| steuermaschine-0.0.1.tar.gz | 3.7 MB | With provenance | Details for steuermaschine-0.0.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| steuermaschine-0.0.1-py3-none-any.whl | Python 3 | none | any | Details for steuermaschine-0.0.1-py3-none-any.whl |
Total release size: 3.9 MB
Release files / steuermaschine-0.0.1.tar.gz
| Download URL | steuermaschine-0.0.1.tar.gz |
|---|---|
| Size | 3.7 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
795488f74da478982e7ba5e4797f6c5b01b0c8e6409598faf728e876f19194a8
|
|
BLAKE2b-256 checksum How to use checksums |
6289d0664a8c639b527dd336a6a5e0d1b4c0c42666291d21aa74e492706bac79
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 14, 2026.
Transparency logRelease files / steuermaschine-0.0.1-py3-none-any.whl
| Download URL | steuermaschine-0.0.1-py3-none-any.whl |
|---|---|
| Size | 177.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
42b418050e0383e53cce7d9f0bd5134cf862cc61b93ce08d95d08620dfc12a9f
|
|
BLAKE2b-256 checksum How to use checksums |
4830630139c559d5c4f2a3b34f3d766ff9c38d0f32cc4cf32ceb0c25a4a94323
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 14, 2026.
Transparency logSecurity for steuermaschine 0.0.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for steuermaschine-0.0.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 14, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.