Progress output
monochange writes progress information to stderr so stdout can remain stable for text, markdown, and JSON command results.
Selecting a renderer
Use the global --progress-format <FORMAT> flag or set MONOCHANGE_PROGRESS_FORMAT.
Supported values:
auto: default behavior. Human progress output is enabled only when stderr is a terminal.unicode: force the human renderer with Unicode symbols and spinners.ascii: force the human renderer with ASCII-safe symbols.json: emit newline-delimited JSON progress events on stderr.
--quiet suppresses progress output. MONOCHANGE_NO_PROGRESS=1 also disables the automatic human renderer.
Human progress output
The human renderer is designed for interactive terminal runs:
- step labels use each step’s
name = "..."value when present, then fall back to the built-in step kind - long-running steps show a delayed spinner so short steps do not flicker
- command stdout and stderr stream live under the active step
- completed
PrepareReleaseandDisplayVersionssteps print per-phase timings so slow phases are visible without a separate trace
Built-in commands already attach descriptive step names such as prepare release, publish release, and open release request. Custom commands can override those names per step.
JSON event stream
--progress-format json is intended for machines, not humans. It writes one JSON object per line to stderr.
Common lifecycle events:
command_startedstep_startedcommand_outputstep_finishedstep_failedstep_skippedcommand_finished
Shared fields:
sequence: monotonically increasing event sequence number for the command runcommand: CLI command name, such asreleasedryRun: whether the command is running in dry-run modetotalSteps: total step count for the commandstepIndex: 1-based step index for step eventsstepKind: built-in step kind, such asPrepareReleasestepDisplayName: rendered human label for the stepstepName: explicit configuredname, ornullwhen omitted
Event-specific fields:
command_outputaddsstreamandtextstep_finishedaddsdurationMsandphaseTimingsstep_failedaddsdurationMsanderrorstep_skippedmay addconditioncommand_finishedaddsdurationMs
Example:
{"sequence":0,"event":"command_started","command":"release","dryRun":true,"totalSteps":2}
{"sequence":1,"event":"step_started","command":"release","dryRun":true,"stepIndex":1,"totalSteps":2,"stepKind":"PrepareRelease","stepDisplayName":"plan release","stepName":"plan release"}
{"sequence":2,"event":"step_finished","command":"release","dryRun":true,"stepIndex":1,"totalSteps":2,"stepKind":"PrepareRelease","stepDisplayName":"plan release","stepName":"plan release","durationMs":243,"phaseTimings":[{"label":"discover release workspace","durationMs":97}]}
Benchmark integration
The binary benchmark workflow uses --progress-format json to extract PrepareRelease phase timings for both mc release --dry-run and mc release.
Those timings are summarized and compared against scripts/benchmark-phase-budgets.json, which lets pull requests fail when real release-path regressions exceed the configured budget.
For hosted-provider analysis outside CI, pnpm node scripts/benchmark-cli.mjs run-fixture can benchmark an existing repository checkout and render the same markdown summary against a real hosted fixture. See Hosted release benchmarks.