Skip the work that is already done.

mmz is a memoized command runner. Prefix any command with it and it runs — then skips, for as long as the inputs you declared are byte-for-byte unchanged since that command last succeeded.

declare · .mmz/config.yaml
# yaml-language-server: $schema=../../../schema/mmz.schema.json
# The docs fixture's manifest. www/generate.sh runs the real `mmz` against a
# throwaway copy of this project and captures the output verbatim, so every
# transcript on the docs site is this file's actual behaviour rather than a
# hand-typed illustration.
#
# The two commands are deliberately fast and dependency-free (`sh` and `jq`,
# both already on the docs build's PATH): a fixture whose checks took a minute
# would make every docs build take a minute, and a fixture needing a toolchain
# would make the site unbuildable wherever that toolchain is missing. Between
# them they exercise all four things a rule can declare — scopes, a probe,
# declared outputs, and tags.

scopes:
# The pipeline's real inputs: the data it reads and the scripts that read it.
data: ["data/*.json"]
bin: ["bin/*.sh"]

probes:
# Both scripts shell out to jq, so a jq upgrade must bust both rules. jq is
# not a file in this project, which is exactly the gap a probe closes.
jq-version:
run: jq --version

on_hit: "mmz: skipped {cache:command} (inputs unchanged)"

commands:
# A verdict command: it passes or it fails, and leaves nothing behind.
- name: ./bin/validate.sh
inputs: [data, bin, jq-version]
tags: [gate]

# A producer command: its record is void once the artifact it promised is
# gone, however unchanged the inputs are.
- name: ./bin/report.sh
inputs: [data, bin, jq-version]
outputs:
- out/report.txt
tags: [gate, report]
run · once, then again
validate: 4 orders, 2 customers OK

mmz: skipped ./bin/validate.sh (inputs unchanged)
inspect · mmz --status
RULE               STATE  AGE
./bin/validate.sh fresh 0s ago
./bin/report.sh fresh 0s ago

One rule, three moments: what you declared, what it cost, what it is worth now.

One question per run

Is this rule’s work still done?

That is the whole of it. A rule declares a command and the inputs that command depends on. mmz hashes those inputs, compares the digest against the record the last successful run left behind, and either skips or runs. There is no task graph to satisfy, no artifact to replay, no daemon to keep alive.

Built for gates

mmz --is-fresh inverts the wrapper: instead of running a stale command, it refuses one. A pre-push hook can require that an expensive check was already run and memoized, without paying to run it at the least convenient moment — see Gating with tags. mmz gates its own repository that way.

Fail closed

The failure this design fears is the silent one: a command skipped that should have run. So the asymmetry is baked in.

Every ambiguous case therefore errors rather than guessing. A missing or invalid manifest is an error; a command matching no rule is an error; a rule whose inputs resolve to zero files is an error. Relax those last two per project with strict when you mean to — never by default. Concepts has the full contract.

What it is not

mmz is not a build system, and the boundary is deliberate — see Comparison for the whole rubric.