A small but pleasant release: spec files round-trip with human-readable multiline strings instead of \n-laden one-liners, and three completion-side bugs are fixed across zsh, nushell, and the parser.
Added
-
Multiline KDL strings for descriptions (#639 by @gaojunran). When the spec serializer encounters a string value containing newlines — typically
long_help,help_md, multi-linecomplete runscripts, etc. — it now emits a KDL raw multiline string literal instead of a single-line string with embedded\nescapes:cmd bash help="Execute a shell script using bash" { long_help #""" Execute a shell script with the specified shell Typically, this will be called by a script's shebang. If using `var=#true` on args/flags, they will be joined with spaces using `shell_words::join()` to properly escape and quote values with spaces in them. """# ... }
The number of
#delimiters is computed automatically so values containing embedded"""sequences are always escaped safely.
Fixed
-
zsh: consistent single-quoting for choice values with spaces (#635).
usage complete-word --shell zshnow emits two tab-separated columns per match — a display string for_describe's menu rendering and a pre-shell-quoted insert string — and the generated completion script wires them through_describe ... -U -Q -S ''. Choice values likeAlice AliceorA B & Care inserted verbatim as'Alice Alice'instead of zsh's default mix of backslash and single-quote styles, and values starting with'correctly switch to menu-insert mode so the leading quote isn't truncated as a longest-common-prefix. If you have existing generated zsh completion scripts, regenerate them to pick up the fix. -
nushell: invoke commands as externals with
^(#638 by @silvanshade). Generated nushell completion scripts now prefix the user's CLI and theusagecallback with^, e.g.^mybin usage | collect | save $spec_fileand(^usage complete-word ...). Without the caret, nushell parsed baremybinas an internal function and errored withExtra positional argumentwhen loading the completion file. -
parser: keep inherited global flags when a subcommand re-declares them as non-global (#649 by @JamBalaya56562). A value-taking global flag (e.g.
-C/--cd) placed before a mounted subcommand whose definition re-declares the same flag withoutglobal=#truewas being dropped from the recognized-flag set on descent. The leftover token was then mis-parsed as a positional — producing errors likeInvalid choice for arg profile: -C, expected one of alpha, beta, gamma— and the flag's value was silently omitted fromas_env()and from the environment passed to mount scripts. This was the parser-side root cause referenced by jdx/mise#10069.
New Contributors
- @silvanshade made their first contribution in #638
- @JamBalaya56562 made their first contribution in #649
Full Changelog: v3.3.0...v3.4.0
💚 Sponsor usage
usage is built by @jdx at en.dev — an independent developer-tooling studio behind mise, aube, hk, and more. Work on usage is funded by sponsorships.
If usage powers CLI specs, docs, or completions for a tool you maintain or use, please consider sponsoring at en.dev. Every sponsorship helps the project stay independent and moving.