CreateChangeFile
What it does
CreateChangeFile writes a .changeset/*.md file from typed CLI inputs.
It supports both:
- explicit non-interactive authoring from inputs such as
package,bump,caused_by,reason, anddetails - interactive authoring when
interactive = true
Why use it
Use CreateChangeFile when you want monochange itself to remain the source of truth for authored change files.
That gives you a few advantages over rolling your own shell template generator:
- package and group references resolve through the same config model used for release planning
- default bump/type behavior stays aligned with monochange parsing rules
- interactive mode can guide authors instead of forcing them to remember frontmatter details
- the generated file shape stays compatible with
mc step:validate,PrepareRelease, and diagnostics tooling
Inputs
interactive— boolean; use interactive prompting instead of explicit package argumentspackage— list of package or group ids to targetbump—none,patch,minor, ormajorversion— explicit version pin for the changereason— summary linetype— optional release-note typecaused_by— optional list of package or group ids that explain dependency-only follow-up changesdetails— optional long-form bodyoutput— optional explicit file path
Step-level when condition
All CLI steps support an optional when = "..." condition.
If the expression resolves to false at runtime, monochange skips the step and continues with the next step.
when = "{{ inputs.enabled }}"
Step-level always_run flag
All CLI steps support an optional always_run = true flag.
When set, the step executes even if a previous step in the same command has failed. This is useful for cleanup, notification, or dry-run preview steps that must run regardless of earlier outcomes.
always_run = true
Prerequisites
None. CreateChangeFile is standalone.
Side effects and outputs
- writes a new changeset file
- reports the written path
- does not prepare release state for later steps
- automatically hides the progress spinner during interactive prompting so the selector UI stays readable
- automatically wraps package/group ids in quotes when the authored frontmatter key contains YAML-sensitive characters such as
@or/
Example
[cli.change]
help_text = "Create a change file for one or more packages"
[[cli.change.inputs]]
name = "interactive"
type = "boolean"
short = "i"
[[cli.change.inputs]]
name = "package"
type = "string_list"
[[cli.change.inputs]]
name = "bump"
type = "choice"
choices = ["none", "patch", "minor", "major"]
default = "patch"
[[cli.change.inputs]]
name = "version"
type = "string"
[[cli.change.inputs]]
name = "type"
type = "string"
[[cli.change.inputs]]
name = "caused_by"
type = "string_list"
[[cli.change.inputs]]
name = "reason"
type = "string"
[[cli.change.inputs]]
name = "details"
type = "string"
[[cli.change.inputs]]
name = "output"
type = "string"
[[cli.change.steps]]
type = "CreateChangeFile"
inputs = [
"interactive",
"package",
"bump",
"version",
"type",
"caused_by",
"reason",
"details",
"output",
]
Composition ideas
Non-interactive wrapper for contributors
[cli.change-fix]
help_text = "Create a patch changeset for one package"
[[cli.change-fix.inputs]]
name = "package"
type = "string_list"
required = true
[[cli.change-fix.inputs]]
name = "reason"
type = "string"
required = true
[[cli.change-fix.steps]]
type = "CreateChangeFile"
inputs = { bump = "patch", package = "{{ inputs.package }}", reason = "{{ inputs.reason }}" }
This is a good example of why built-in step inputs matter: the wrapper command is still using CreateChangeFile semantics rather than generating markdown manually.
Interactive authoring command
You can also create a dedicated interactive authoring command that always opts in to prompts.
[cli.change-interactive]
help_text = "Create a change file interactively"
[[cli.change-interactive.steps]]
type = "CreateChangeFile"
show_progress = false
inputs = { interactive = true }
Good fit / bad fit
Good fit:
- contributor-facing commands
- wrappers that standardize bump policies
- interactive authoring helpers
Bad fit:
- release execution
- commands that need
release.*context
Common mistakes
- omitting
packagein non-interactive mode - expecting
CreateChangeFileto release anything immediately - using raw manifest paths when configured package ids are the stable interface
- forgetting
caused_bywhen a dependent package only changed because another package or group moved first