0.3.0 (2026-08-19)
⚠ BREAKING CHANGES
dgnow exits non-zero when a command fails: 1 for errors (including crashes and usage errors), 2 for user interrupt, 0 on success. Every command previously exited 0 regardless of outcome, so scripts and CI steps that ignored the exit code will surface failures they were silently swallowing. No command that succeeds changes its exit code.
Bug Fixes
- correct web command examples, document Flux TTS/STT, and honor -o json across account commands (#97) (55984ec)
- dependency floors that let dg update skip this release, and exit-code + error-stream correctness (#102) (fd1e8a4)
- deps: cap mcp <2 (fixes broken dg mcp), commit uv.lock, require twine >=7 (#95) (997cd36)
- deps: raise deepctl-core floor to 0.2.16 in the eight packages that import get_status_console (98f9e91)
- deps: raise root dependency floors to the versions this release publishes (c0b0023)
- exit 1, not 2, when a command crashes or is misused (914e132)
- keep exit 2 when Ctrl-C interrupts a running command (b0e80e2)
- keys: honor -o json so stdout stays parseable (completes the #97 sweep) (#101) (e430a77)
- release: bump pypi-publish action to v1.14.2 for Metadata-Version 2.5 (#94) (582cd83)
- send root error and interrupt output to stderr, not stdout (f4b7c48)
- web: repair broken Heap snippet, upgrade astro 6→7, clear all 20 npm alerts (#96) (11928fe)
Behavior changes
Alongside the exit-code change above, upgrading to 0.3.0 changes these:
- The full exit-code contract is now enforced end to end:
0= success,1= error,2= user interrupt. Crashes and usage errors (bad flag, unknown command, baredg) exit1;2is reserved for cancellation, so Ctrl-C during a running command and Ctrl-D at a prompt both still exit2. - Error and cancellation messages are written to stderr instead of stdout.
dg -o json …therefore keeps stdout machine-readable when a command fails — previously a failure printedError: …prose to stdout, so a script piping stdout intojqparsed the error text instead of JSON. Successful commands still write their payload to stdout. -o yamland-o csvno longer drop square-bracketed text from values. Output was passed through a renderer that read[...]as style markup and deleted it, so an API key comment of[ci] runnerwas emitted asrunner. Long values are also no longer hard-wrapped mid-field.dg keys --delete KEY_IDnow asks for confirmation on stderr instead of always reportingCancelled by userwithout deleting. In a non-interactive context it exits1and tells you to pass--yes.dg keys --create --dry-runnow reports what it would create. It previously failed with an internalTypeError.
Previously unreleased
0.2.27 was tagged on 2026-08-17 but never reached PyPI — its publish step failed with InvalidDistribution: Invalid distribution metadata: '2.5' is not a valid metadata version, which #94 and #95 then fixed. PyPI therefore goes straight from 0.2.26 to 0.3.0, and this release is the first published build to include the 0.2.27 changes:
- SDK 7.7.0 — Flux TTS controls, Flux STT fix, listen redact/numerals (#92) (50d96cf)
- speak: default to Flux TTS (
flux-alexis-en) instead of Aura 2 (#89) (5a0b698). This changes the default model fordg speak, so synthesised audio differs unless you pass anaura-*model explicitly. - mcp: swallow broken/closed-pipe on dg mcp startup notifications and error path (#88) (b24396e)
Six packages tagged in that cycle also reach PyPI for the first time here: deepctl-cmd-listen 0.0.14, deepctl-cmd-login 0.1.17, deepctl-cmd-skills 0.0.7, deepctl-cmd-speak 0.0.4, deepctl-cmd-update 0.2.6 and deepctl-telemetry 0.0.6.
Because 0.2.27 never published, dg update on pip also had to be repaired for this release to arrive at all: root's inter-package dependency floors were lower than the versions being published, so pip's default only-if-needed strategy left most sub-packages stale and dg --version reported the new number while the fixes never landed. Floors now match the published versions exactly.