Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The noya-cli Manual

noyafmt and noyavalidate: format and validate YAML from the command line. noya-cli is one of the six crates of the noyalib family and releases in lockstep with the core library at the identical =0.0.X.

This manual is the rendered form of the Markdown in the repository’s docs/ directory; the repository copy is canonical. The family manual for the core library, with the user guide, migrations, and policies, is at https://sebastienrousseau.github.io/noyalib/manual/.

Pages

Install, quick start, and the full surface are in the README. The CHANGELOG is the complete release record.

CLI flag reference

The full surface for both binaries — noyafmt and noyavalidate — with worked examples for every flag. The same content is available via --help and the man pages installed under /usr/share/man/man1/ (or complete/{noyafmt,noyavalidate}.1 when installed from the tarball).

The clap command tree is regenerated at build time via the same noya_cli::{noyafmt_command, noyavalidate_command} builders that drive the runtime parser, so this file, the manpages, and the shell completions cannot drift from each other.

noyafmt

noyafmt [OPTIONS] [FILE]...

Auto-format YAML via the noyalib CST. Reads YAML from FILE arguments (or stdin via --stdin) and rewrites them through noyalib’s lossless CST formatter. Comments, anchor positions, and document structure are preserved byte-for-byte; only whitespace and quoting are normalised.

Flags

FlagTypeDefaultDescription
--checkbooloffVerify each FILE is formatted; print the list of files that need formatting and exit 1 if any do. Non-destructive. Suitable as a pre-commit / CI gate. Conflicts with --write.
--writebooloffRewrite each FILE in place. Default is to print the formatted source to stdout. Conflicts with --check.
--stdinbooloffRead from stdin, write to stdout. Mutually exclusive with FILE arguments.
--indent N1 to 162Indentation width in spaces; a value outside 1 to 16 is a usage error (exit 2).
-h, --help——Print help (long form on --help).
-V, --version——Print the version.

Positional arguments

ArgumentRepeatableDescription
FILEyesYAML files to format. Pass --stdin to read from stdin instead.

Examples

# Default: read FILE, print formatted YAML to stdout.
noyafmt config.yaml

# Rewrite in place.
noyafmt --write config.yaml

# CI gate — exit 1 if any file needs formatting.
noyafmt --check ci/*.yaml

# Editor integration: pipe through stdin.
cat config.yaml | noyafmt --stdin

# Custom indent width.
noyafmt --write --indent 4 config.yaml

# Multiple files at once.
noyafmt --write services/*.yaml deployments/*.yaml

Exit codes

CodeMeaning
0All files are formatted (or were rewritten when --write)
1At least one file is not formatted (--check) or a parse error occurred
2Usage error (conflicting flags, missing argument)
3I/O error (file not found, permission denied)

noyavalidate

noyavalidate [OPTIONS] [FILE]...

Check YAML syntax (and optional JSON Schema). Reads the YAML documents in each FILE (or stdin), reports syntax errors via the miette fancy renderer, and — when --schema PATH is given — validates each parsed document against a JSON Schema 2020-12 contract (the schema may itself be written in YAML or JSON).

--fix rewrites the input in-place through the lossless CST formatter, normalising whitespace and quoting without changing semantics. When the input is stdin, the formatted output is written to stdout instead.

Flags

FlagTypeDefaultDescription
-s PATH, --schema PATHpath—Validate each document against the JSON Schema 2020-12 at PATH (the schema may itself be YAML or JSON).
--fixbooloffRewrite FILE in place via the CST formatter (lossless: byte-faithful for everything except normalised whitespace and line endings). With stdin input, the formatted bytes go to stdout.
-q, --quietbooloffSuppress success output.
-h, --help——Print help (long form on --help).
-V, --version——Print the version.

Positional arguments

ArgumentRequiredDescription
FILEoptionalYAML files to validate. Use - (alone) or omit for stdin. Every file is checked; the exit code is the highest any file produced.

Examples

# Syntax-only check, errors via miette fancy renderer.
noyavalidate config.yaml

# Schema validation against a YAML-flavoured JSON Schema.
noyavalidate --schema schemas/config.schema.yaml config.yaml

# Schema validation against a JSON-flavoured schema.
noyavalidate --schema schemas/config.schema.json config.yaml

# Read from stdin.
cat config.yaml | noyavalidate

# Format-fix in place.
noyavalidate --fix config.yaml

# Format-fix from stdin to stdout.
cat config.yaml | noyavalidate --fix > clean.yaml

# Combined: schema-validate then format-fix.
noyavalidate --schema schema.yaml --fix config.yaml

# Quiet mode for CI: only errors are printed.
noyavalidate --quiet --schema schema.yaml ci/*.yaml

Exit codes

CodeMeaning
0All documents valid (and fixed if --fix)
1Parse error or schema violation
2Usage error
3I/O error

Shell completions

Pre-generated completion scripts ship in the release tarball under complete/:

ShellFile
bashcomplete/noyafmt.bash, complete/noyavalidate.bash
fishcomplete/noyafmt.fish, complete/noyavalidate.fish
zshcomplete/_noyafmt, complete/_noyavalidate
PowerShellcomplete/_noyafmt.ps1, complete/_noyavalidate.ps1

System packages install them to the right location automatically. For local install (cargo install noya-cli), regenerate via cargo xtask completions.

Man pages

Roff-format man pages ship as doc/noyafmt.1 and doc/noyavalidate.1. System packages install to /usr/share/man/man1/; for local install, regenerate via cargo xtask manpages.

  • Recipes — common workflows (CI gates, pre-commit hooks, schema validation patterns)
  • Crate README — installation, package channels, build-from-source

noyafmt + noyavalidate recipes

Common workflows. Each recipe is a self-contained snippet you can drop into your project or CI.

CI: format gate

Block PRs that introduce unformatted YAML.

GitHub Actions

# .github/workflows/yaml-fmt.yml
name: YAML format
on: [pull_request]
jobs:
  fmt:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: cargo install noya-cli --locked
      - run: noyafmt --check $(git ls-files '*.yaml' '*.yml')

GitLab CI

yaml-fmt:
  image: rust:1.89-bookworm
  before_script:
    - cargo install noya-cli --locked
  script:
    - noyafmt --check $(git ls-files '*.yaml' '*.yml')

Pre-commit hook

# .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: noyafmt
        name: noyafmt --check
        entry: noyafmt --check
        language: system
        files: \.(yaml|yml)$

CI: schema gate

Block PRs that violate a JSON Schema contract.

GitHub Actions

name: YAML schema
on: [pull_request]
jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: cargo install noya-cli --locked
      - name: Validate Kubernetes manifests
        run: |
          for f in k8s/**/*.yaml; do
            noyavalidate --schema schemas/k8s.schema.yaml "$f" || exit 1
          done

Editor integration

VS Code on save

Pair noyafmt with VS Code’s editor.formatOnSave. The recommended path is the dedicated noyalib-lsp extension, which provides format-on-save, diagnostics, and hover. For lighter-weight integration:

// .vscode/tasks.json
{
  "version": "2.0.0",
  "tasks": [{
    "label": "noyafmt: write",
    "type": "shell",
    "command": "noyafmt",
    "args": ["--write", "${file}"],
    "problemMatcher": []
  }]
}

Neovim

-- ~/.config/nvim/lua/yaml-fmt.lua
vim.api.nvim_create_autocmd("BufWritePost", {
  pattern = { "*.yaml", "*.yml" },
  callback = function()
    vim.fn.system("noyafmt --write " .. vim.fn.expand("%"))
    vim.cmd("e!") -- reload buffer
  end,
})

For the richer experience (diagnostics, hover, code actions) use noyalib-lsp via nvim-lspconfig.

Bulk operations

Format every YAML in a tree

find . -name '*.yaml' -o -name '*.yml' | xargs noyafmt --write

Validate every Kubernetes manifest

find k8s -name '*.yaml' -exec \
  noyavalidate --schema schemas/k8s.schema.yaml --quiet {} +

Generate canonical diff after a refactor

When mass-renaming keys across many YAML files, format both before and after to reduce the diff to the actual semantic change:

git stash                                            # save WIP
noyafmt --write **/*.yaml && git commit -m 'fmt'     # format baseline
git stash pop                                        # apply WIP
noyafmt --write **/*.yaml                            # format after
git diff                                             # only semantic changes

Pipeline integration

kubectl apply only when format-clean

noyafmt --check k8s.yaml && kubectl apply -f k8s.yaml

Helm chart linting

helm template ./chart \
  | noyavalidate --schema schemas/k8s.schema.yaml -

Render-then-validate Argo CD application

argocd app manifests my-app \
  | noyavalidate --schema schemas/argo-app.schema.yaml -

Troubleshooting

“permission denied” rewriting a file

--write opens FILE for writing. If the file is read-only or owned by another user, the write fails with exit 3 (I/O error). Use chmod +w FILE or sudo.

Schema validation passes locally, fails in CI

The schema file path is resolved relative to the working directory of the noyavalidate invocation, not relative to the input file. In GitHub Actions, ${{ github.workspace }} is the repo root; ensure your --schema path is relative to that.

--fix changed more than I expected

The CST formatter normalises whitespace, quoting, and indentation to a canonical form. It does not change document semantics: keys, values, comments, anchors, and tags survive byte-for-byte. If a --fix produced unexpected output, file an issue with the input — the formatter is documented as preserving everything that isn’t trivia.

Stdin closes the process before output

When piping --stdin you may need to terminate the input with Ctrl-D (^D) on a new line:

noyafmt --stdin
key: value
^D

For programmatic use (CI scripts), redirect a file or use <<< heredoc syntax.

CLI ecosystem comparison

This comparison describes delivery and workflow characteristics. It is not a claim that every tool has the same scope.

ProjectComment-preserving formatJSON SchemaNative packagesGenerated manpages
noya-cliYes2020-12deb and rpmYes
yqOperation-dependentNoProject-dependentProject-dependent
yamllintLint onlyNoProject-dependentProject-dependent
Prettier YAMLReprints documentsNonpmNo

The meaningful distinction is the editing model. noyafmt and noyavalidate --fix use noyalib’s concrete syntax tree, so an edit need not reprint unrelated comments or whitespace. Use each upstream project’s current documentation before making a tool-selection decision.

For the complete command surface, see CLI reference.

Benchmarks

The cli_dispatch Criterion harness measures command dispatch and representative format and validation workloads in release mode.

cargo bench --bench cli_dispatch

Record the CPU, operating system, Rust version, commit, input size, feature set, and full command with any reported result. Compare measurements from the same machine and power profile. CI compiles and smoke-runs benchmark targets, but does not reject a change using noisy shared-runner wall-clock thresholds.

The headline format measurement in the README is descriptive project data, not a cross-machine performance guarantee.

Architecture

noya-cli ships two binaries, noyafmt and noyavalidate, over one shared library so the binaries, their manpages, and their shell completions are generated from a single definition and cannot drift.

Layers

  • src/lib.rs defines the command-line surface once: the clap derive structs NoyafmtCli and NoyavalidateCli, and the builders noyafmt_command and noyavalidate_command that return the underlying clap::Command trees. Both binaries parse argv through these; the build script consumes the same trees.
  • src/bin/noyafmt.rs formats YAML through noyalib’s CST formatter with rustfmt-style ergonomics: --check for CI gates, --write for in-place rewrites, stdin to stdout for editors.
  • src/bin/noyavalidate.rs validates syntax, renders errors with miette, validates each document against a JSON Schema 2020-12 contract when --schema is given (the schema may be YAML or JSON), and with --fix rewrites the input through the CST formatter, normalising whitespace and quoting without changing meaning. The README documents the exit codes.
  • build.rs generates the manpages (clap_mangen) and the bash, fish, zsh, and PowerShell completions (clap_complete) into OUT_DIR at build time. make assets copies them into docs/ and complete/ so the committed copies never lag --help; the version gate checks the manpages carry the crate version.

Install contract

GNUmakefile implements the Unix contract: make, make test, make install and make uninstall honouring PREFIX (default /usr/local) and DESTDIR, installing binaries, manpages, and completions to FHS paths. CI stages an install into a temporary DESTDIR on every push. pkg/ carries the Homebrew formula, Scoop manifest, AUR PKGBUILD, and flake.nix, all generated from the release build; the channel manifests roll after each release’s artefacts exist because they embed checksums.

Testing

Integration tests run the binaries as processes. Two libFuzzer targets feed arbitrary argv through the clap trees (fuzz_argv) and the derive structs (fuzz_derive_parse); CI replays the seed corpus on every push.

Lockstep

The crate pins noyalib at the identical =0.0.X and releases with it (core ADR-0005).

Engineering policies

Version and dependency policy

noya-cli releases in strict lockstep with noyalib. Version 0.0.58 must pin the core at exactly =0.0.58. Release work uses feat/v0.0.58; each subsequent iteration increments exactly 0.0.1.

Minimum Rust version

The minimum supported Rust version is 1.89.0. The manifest declares the floor and CI verifies it. A change to the floor is a breaking-axis change and requires a changelog entry.

Generated assets

Manpages and completions are generated from the Clap definitions. Change the command source and run make assets; never edit generated copies directly.

Compatibility

Exit codes, command names, flags, configuration semantics, and formatting output are public behaviour. During 0.0.x, the patch component is the breaking axis.

Family-wide policies live in the core POLICIES.md.

Repository standard compliance grade

Assessment date: 2026-09-20. Source rubric: /Users/seb/Code/REPO-STANDARD.md. The workspace auditor evaluates checked-in signals conservatively and does not treat a workflow file as proof that a run passed.

Result

17/24 signals (71%). README template: pass. Strict candidate tier: L1.

CategorySignalsSummary
Identity and README3/3Canonical structure, policy, badges, and toolchain evidence
Documentation2/3Manual and architecture present; complete L3 evidence remains open
Build and install UX2/3Native build, generated manpages and completions; static L2 detector does not recognize the GNUmakefile shape
Releases and binaries3/3Automated multi-platform release and provenance signals
Packaging1/3Packaging exists; Repology and reproducibility evidence remain incomplete
CI quality gates2/3Matrix and coverage signals present; full L3 powerset evidence remains open
Supply chain3/3Audit, signing, provenance, and policy signals present
Community1/3Foundation files present; template and docs-lint detection remain gaps

The cumulative tier remains L1 because every L2 category must pass. Priority work is explicit Repology tracking, reproducible-build verification, and making the existing GNUmakefile, issue/PR templates, and markdown lint gates legible to the portfolio audit.

Detailed README reference

Noyalib logo

noya-cli

noyafmt and noyavalidate — the YAML formatter and validator built on the noyalib library.

Build Crates.io Docs.rs GitHub Release OpenSSF Scorecard OpenSSF Best Practices


Contents


Install

ChannelCommand
Pre-built binariesdownload for 8 targets (Linux gnu/musl, macOS, Windows on x86_64/aarch64) from the latest release — each with manpages, completions, SHA-256, and SLSA provenance
Linux packages.deb and .rpm on the latest release
Homebrew (macOS/Linux)brew install sebastienrousseau/tap/noya-cli
Scoop (Windows)scoop bucket add sebastienrousseau https://github.com/sebastienrousseau/scoop-bucket then scoop install noya-cli
AUR (Arch)noyalib-bin, e.g. yay -S noyalib-bin
Cargo (crates.io)cargo install noya-cli --locked
Cargo (from source)cargo install --locked --path .
GNU Make (binaries + manpages + completions)make install — honors PREFIX (default /usr/local) and DESTDIR; make uninstall reverses it
Container (GHCR)docker run --rm -v "$(pwd):/work" -w /work ghcr.io/sebastienrousseau/noya-cli:latest config.yaml validates; add --entrypoint noyafmt to format. Multi-arch, SLSA-attested, cosign-signed; first published with v0.0.41.

Formatter only, if you do not need noyavalidate

cargo install noya-cli --locked --no-default-features --features noyafmt

The default install includes noyavalidate, whose schema errors are rendered by miette with source excerpts and carets — worth the weight for a validator, since pointing at the offending line is the job. It does mean the default pulls 130 crates against 32 for the formatter alone, most of the difference being miette’s fancy renderer and its backtrace stack.

If you only ever run noyafmt, the command above is a smaller supply chain and a faster build. Nothing is degraded for anyone who wants the diagnostics — it is a choice, not a default.

Releases ship the crate archive with a CycloneDX SBOM and sigstore bundles, plus the pre-built binary archives and Linux packages above, each with SHA-256 and a SLSA build-provenance attestation — see Verification.

MSRV: Rust 1.89.0, the floor shared across the noyalib family and the maintainer’s other Rust crates (noyalib ADR-0014). The toolchain-driven floor is lower: criterion 0.8 (the benchmark dev-dependency) declares rust-version = 1.86, so cargo check --all-targets and the bench suite fail on 1.85 (criterion@0.8.2 requires rustc 1.86), though cargo check --lib still builds. clap_builder 4.6 in the CLI dep tree is edition-2024. We publish the number we verify.


Requirements

  • Rust 1.89.0 or newer to build from source: rust-version in the manifest, enforced by the msrv-core CI job on every push.
  • Any tier-1 platform. CI runs the tests on Linux, macOS, and Windows with the stable, beta, and nightly toolchains; stable is the gate, beta and nightly are early warning.
  • The matching core. This crate pins noyalib at the identical =0.0.X and releases in lockstep with it; Cargo resolves that pin for you.
  • Nothing at runtime: the binaries are static where the platform allows (musl on Linux) and link only the C runtime elsewhere.

Quick Start

# Format a file in-place; comments + indentation preserved.
noyafmt --write config.yaml

# CI gate — exits 1 if any file would change.
noyafmt --check ci/*.yaml

# Validate syntax + JSON Schema 2020-12.
noyavalidate --schema schema.yaml deploy.yaml

# Validate + auto-fix obvious type slips (port: "8080" → 8080).
noyavalidate --schema schema.yaml --fix deploy.yaml

noyafmt

YAML formatter mirroring the rustfmt / prettier ergonomics:

noyafmt config.yaml                # print formatted source to stdout (default)
noyafmt --write config.yaml        # rewrite in place
noyafmt --check ci/*.yaml          # CI gate
noyafmt --indent 4 config.yaml     # override default 2-space indent
cat foo.yaml | noyafmt --stdin     # editor pipe (Vim, Emacs, …)
git ls-files '*.yaml' | xargs noyafmt --check

The formatter runs through noyalib’s lossless CST: comments, anchor positions, and document structure are preserved byte-for-byte; only whitespace and quoting are normalised.

FlagEffect
--checkVerify each FILE is formatted; print files that need formatting; exit 1 if any do. Non-destructive.
--writeRewrite each FILE in place. Default is to print to stdout. Mutually exclusive with --check.
--stdinRead from stdin, write to stdout. Mutually exclusive with FILE arguments.
--indent NIndentation width in spaces, 1 to 16 (default: 2).

noyavalidate

YAML syntax checker with optional JSON Schema 2020-12 enforcement and schema-driven autofix.

noyavalidate manifest.yaml                          # syntax only
noyavalidate --schema schema.yaml deploy.yaml       # + schema check
noyavalidate --schema schema.yaml --fix deploy.yaml # + autofix
cat manifest.yaml | noyavalidate                    # stdin

The autofix engine (coerce_to_schema) rewrites string-shaped scalars into the schema’s expected type when the parse succeeds. Loops until convergence; unparseable inputs (port: "abc" against type: integer) are left in place so a follow-up validate_against_schema call surfaces the residue.

Diagnostics use miette for rustc-style source pointers:

× schema violation: "8080" is not of type "integer"
   ╭─[deploy.yaml:3:7]
 2 │ replicas: 3
 3 │ port: "8080"
   ·       ─┬───
   ·        ╰── here
 4 │ host: api
   ╰────
   help: pass --fix to coerce string-shaped scalars to the
         schema's declared type.
FlagEffect
-s, --schema PATHValidate each document against JSON Schema 2020-12 at PATH (the schema may itself be YAML or JSON).
--fixRewrite FILE in place via the CST formatter (lossless: byte-faithful for everything except normalised whitespace / line endings). With stdin input, the formatted bytes go to stdout.
-q, --quietSuppress success output.

GitHub Action and pre-commit

One step in CI, no toolchain on the runner:

- uses: sebastienrousseau/noya-cli@v0.0.58
  with:
    paths: config/ deploy.yaml
    schema: schema.json   # optional

The action downloads the release binaries for the runner’s platform and verifies their build provenance attestation with gh attestation verify (built by this repository’s release workflow at the requested tag); where the gh CLI or a token is missing it checks only the SHA-256 published in the same release and says so with a warning. It then runs noyafmt --check and noyavalidate (with the schema when given) over the YAML under paths; directories are searched for *.yaml and *.yml. Either failure fails the step, and tool output cannot issue workflow commands. version must be X.Y.Z.

The same checks as hosted pre-commit hooks:

repos:
  - repo: https://github.com/sebastienrousseau/noya-cli
    rev: v0.0.58
    hooks:
      - id: noyafmt-check
      - id: noyavalidate

noyafmt (runs noyafmt --write, so the hook fails when it reformatted a file), noyafmt-check and noyavalidate (checks every staged file) are the three hook ids; pass --schema schema.json through args to validate. pre-commit builds the hooks with cargo install without --locked, so dependencies resolve to their newest compatible versions rather than this repository’s Cargo.lock. For a locked build, run cargo install noya-cli --locked and point a repo: local hook with language: system at the installed binaries.

Exit codes

Codenoyafmtnoyavalidate
0success (or no changes if --check)all valid
1parse / I/O error, or --check found unformatted file(s)parse error or schema violation
2invalid usage (bad arg combination)invalid usage
3—I/O error (read / write)

Examples

End-to-end runnable demos under examples/:

ScriptWhat it shows
format-precommit.shDrop-in git pre-commit hook gating commits on noyafmt --check.
validate-k8s.shCI step that runs noyavalidate --schema over a directory of Kubernetes manifests.
fix-quoted-numbers.shWalkthrough of the --fix autofix flow: quoted scalar → schema-typed integer, with the surrounding comment preserved.
chmod +x crates/noya-cli/examples/*.sh
crates/noya-cli/examples/fix-quoted-numbers.sh

Shell completions and man pages

Tarball releases ship pre-built completions for bash, fish, zsh, and PowerShell, plus roff man pages. Distro packages drop them into the standard system locations (/usr/share/bash-completion/completions/, /usr/share/man/man1/, …).

make install places all of them in the standard locations. If installing via cargo install, the pre-built copies live in this repository (complete/, docs/*.1) — or regenerate them from the clap definitions:

git clone https://github.com/sebastienrousseau/noya-cli
cd noya-cli
make assets    # regenerates complete/* and docs/*.1 via build.rs

CI enforces that the committed copies are bit-identical to what the clap definitions generate (make check-assets), so they cannot drift from --help.


Verification

Every release artefact (crate archive, SBOM) ships with a cosign keyless signature and a SLSA build-provenance attestation. Verify before trusting a download:

COSIGN_EXPERIMENTAL=1 cosign verify-blob \
  --certificate-identity-regexp '^https://github\.com/sebastienrousseau/noya-cli/\.github/workflows/release\.yml@refs/tags/v[0-9]+\.[0-9]+\.[0-9]+$' \
  --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
  --bundle <artefact>.bundle \
  <artefact>

gh attestation verify <artefact> --repo sebastienrousseau/noya-cli --signer-workflow sebastienrousseau/noya-cli/.github/workflows/release.yml

Full cookbook including the offline / FIPS-bound flow: pkg/VERIFY.md.


When not to use these tools

  • You need to format YAML faster than human-perceivable latency. noyafmt runs end-to-end on a 1 MiB document in ~10 ms; for <100 KB documents that’s already invisible. But for a streaming editor pipeline that wants per-keystroke formatting, the LSP server (noyalib-lsp) issues incremental TextEdit[]s instead.
  • You need YAML 1.1-only behaviour, top to bottom. noyavalidate follows YAML 1.2; the legacy_booleans opt-in is exposed at the library level but not yet plumbed through the CLI.
  • You need to embed the formatter or validator in your own Rust binary. Use the noyalib library directly — every CLI feature flows through public library APIs (cst::format_with_config, validate_against_schema, coerce_to_schema).

Documentation

The four entry points, identical across every repo in the family:


Conformance

Every push runs the official yaml-test-suite through noyavalidate’s exit code, from the same vendored suite and the same core commit as the noyalib core: 406 of 406 (valid cases exit 0, invalid cases exit non-zero). A two-document configuration that uses most of YAML at once (tests/fixtures/ultra-complex/) validates, and noyafmt’s output parses to exactly the same JSON. Details and the family table: noyalib.com/conformance.

License

Dual-licensed under Apache 2.0 or MIT, at your option.

noya-cli v0.0.17 Release Notes

Lockstep release with noyalib v0.0.17 (ADR-0005: publishes =0.0.17 pinned to the core).

What changed

  • crossbeam-epoch bumped to 0.9.20 (RUSTSEC-2026-0204, invalid-pointer-dereference), previously present via a transitive dep.
  • noyalib pin =0.0.16 -> =0.0.17; crate version bumped in lockstep.

Repository hardening (CI/docs only)

Coverage, MSRV, CodeQL, and OpenSSF Scorecard gates plus upstream cargo-vet audit imports were added across the satellites in this cycle; branch protection now makes commit signing unskippable. No user-facing change.

Upgrading

Requires Rust 1.86.0+.

noya-cli v0.0.16 Release Notes

Lockstep release with noyalib v0.0.16 (ADR-0005 strict-lockstep: the noyafmt / noyavalidate binaries publish =X.Y.Z pinned to the core). No change to the CLI contract (flags, exit codes, output).

What changed

  • noyalib pin =0.0.15 → =0.0.16 and the crate version bumped in lockstep.
  • MSRV raised 1.85.0 → 1.86.0, matching the single lockstep floor adopted in v0.0.16.
  • Release workflow publish steps made idempotent for clean re-runs.

Corrected after release (ships in v0.0.17)

  • crossbeam-epoch RUSTSEC-2026-0204 (invalid-pointer-dereference) was present in the v0.0.16 lockfile via a transitive dependency and bumped to the patched 0.9.20 on main afterward.

Engineering / CI (post-release, no user-facing change)

  • Signed-history enforcement, upstream audit imports, and a dependabot-vet auto-refresh workflow.
  • New CI gates brought toward the core’s bar: a coverage gate, an MSRV gate, CodeQL, and OpenSSF Scorecard. src/lib.rs (the shared clap command tree) is at 100 % coverage; the enforced binary floor is set at the honest testable ceiling, since the residual is defensive I/O and parser-disagreement error arms unreachable via valid input.

What did not change

  • The noyafmt / noyavalidate flag surface, exit codes, and output.
  • #![forbid(unsafe_code)] — intact.

Upgrading

cargo install noya-cli --version 0.0.16 --locked

Requires Rust 1.86.0+.