github marigold-ui/marigold @marigold/cli@3.0.0

3 hours ago

Major Changes

  • e1f2e28: feat(DST-1819): default the CLI to JSON output when stdout is not a terminal

    When --format is omitted, docs, list, search, examples, doctor and validate now print json whenever their output is piped or captured, as it is for an AI agent, a script, CI or a redirect to a file. In an interactive terminal nothing changes: docs, list, search and examples still print markdown, and doctor and validate still print text. An explicit --format always wins.

    Breaking: a script that reads the default output of one of these commands through a pipe now receives JSON. Pass --format markdown, --format plain or --format text to keep the previous output. The programmatic run*() exports are unchanged and keep their markdown/text fallback.

Minor Changes

  • a7c4d00: feat: align the CLI with the Command Line Interface Guidelines (clig.dev)

    • First-run telemetry notice. Because telemetry is opt-out, the CLI now prints a one-time disclosure (to stderr, so JSON/stdout stays clean) explaining that anonymous usage data is collected and how to opt out (marigold telemetry disable or DO_NOT_TRACK=1). Mirrors the .NET SDK model. The "shown" flag is persisted only after the notice actually prints on an interactive terminal, so agent/pipe runs never consume it before a human sees it. The invocation that shows the notice is itself not tracked: no data leaves the machine before the user has seen the disclosure and had a chance to opt out. Tracking begins on the next run.
    • "Did you mean?" suggestions. Unknown commands now suggest the nearest valid command via edit distance (e.g. marigold serach → Did you mean "search"?), matching the error-recovery pattern used by git/cargo/npm.
  • a7c4d00: feat: make CLI telemetry identifier-free, and document it in full

    Telemetry stays on by default, but it no longer carries anything that can single out a machine, user, or session. This is what makes the opt-out default defensible under GDPR and ePrivacy: with no identifier there is no personal data to have a lawful basis for, and the CLI no longer stores an identifier on the user's device, which would otherwise require consent under ePrivacy Art. 5(3) / § 25 TDDDG.

    • Removed the anonymousId. The persistent per-machine UUID is gone from the event payload, from UserConfig, and from the server schema. A stale value written by an older CLI is stripped on the next config read and erased from disk. The trade is deliberate: we can now count invocations, not people, and unique-user numbers come from public npm download counts instead.
    • Corrected the first-run notice. It previously claimed that no arguments and no personal data were collected, while the event did carry args and a persistent UUID. The notice now states exactly what is sent and links to the telemetry section of the CLI docs.
    • Clamped args. Enum flags are recorded as their validated value or as invalid, so a mistyped --format=jsonn is no longer echoed back verbatim. --limit is recorded only as a positive integer. A name passed as a positional or --category is never forwarded as typed: once it resolves against the docs manifest, the manifest's slug is recorded, and anything else is recorded as unknown. Free-text search terms remain recorded as used.
    • Hour-granular timestamps, not expiry. receivedAt is truncated to the hour, and so is the ID each event is stored under, in a stream of its own, so events cannot be stitched back into per-session sequences by timing once the identifier is gone. That is also what lets events be kept for long-run usage trends rather than expiring: with no identifier in a record, an old event says no more about you than a new one. The reasoning is in the telemetry endpoint README.
    • Strict event schema. The endpoint rejects unknown top-level keys rather than stripping them, so a stale anonymousId gets a visible 400 instead of a silent drop. Keys inside args are bounded in length and count. The guarantee that no identifier is sent lives in the CLI, which builds args only from validated values.
    • Endpoint-wide rate limit only. The former per-anonymousId quota is gone, since there is no longer a client identifier to key one on, which leaves the endpoint-wide ceiling as the CLI's only bound. That ceiling is a cost backstop, not a security control. Bounding a single misbehaving caller belongs behind WAF rate limiting, which needs no identifier in the body.
    • Full disclosure in the docs. The marigold telemetry section of the CLI page now documents every field sent, what is never sent, why the default is opt-out, and every way to turn it off. It lives there rather than on a standalone privacy page, which nobody would navigate to. marigold --help links the anchor, so non-interactive users have a discoverable disclosure too.

Patch Changes

Don't miss a new marigold release

NewReleases is sending notifications on new releases.