npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

cadence-lint

v0.1.1

Published

Lint prose structure and cadence from Markdown.

Downloads

15

Readme

Cadence Lint

Cadence Lint v1 is a Markdown structure linter. It checks sentence-count patterns in normal Markdown paragraphs wrapped by cadence markers.

v1 only checks Markdown paragraph structure. It does not lint heading flow, author roles, section order, style tone, or deferred cadence features.

Setup

Use Node 20 or newer.

npm install
npm test
npm run build

After the package is published:

npm install cadence-lint
npx cadence-lint README.md

CLI

npm run dev -- README.md

After publishing or linking the package:

cadence-lint README.md

Pass one or more Markdown files, directories are not supported:

cadence-lint docs/intro.md docs/*.md

Use --format json for machine-readable diagnostics:

cadence-lint --format json docs/intro.md

Configure section structures on the CLI with --section:

cadence-lint --section intro=1/3/1 docs/intro.md
cadence-lint --section intro=1/3/1,1/5/1 docs/intro.md
cadence-lint --section overview=1 --section details=2/1 docs/guide.md

--section-rule <section=pattern> is still accepted as a compatibility alias for --section.

Use --language <language> to choose sentence-splitting built-ins. Supported languages are en, fr, and pt.

Markers

Cadence sections are standalone HTML comments:

<!-- cadence:overview -->

One sentence.

First sentence. Second sentence. Third sentence.

Last sentence.

<!-- /cadence:overview -->

The opening marker is <!-- cadence:name -->. The matching closing marker is <!-- /cadence:name -->. Marker names may contain letters, numbers, underscores, and hyphens. Use any section name that matches a configured section rule, such as overview, details, or takeaway.

Markers must be standalone Markdown blocks. Inline comments are treated as normal paragraph text:

This paragraph contains <!-- cadence:intro --> inline text, not a marker.

Nested sections, unmatched closing markers, unmatched opening markers, malformed marker comments, and marked sections not present in configured section rules are reported as errors.

Normal Markdown paragraphs outside cadence markers are reported as warnings:

This paragraph is outside a cadence section.

When you run the CLI, every marker name must have a matching configured section rule. With no sections, --section, or --section-rule values, normal paragraphs are linted for marker coverage, but marked sections have no known names or structures to validate against.

Structures

A structure is a slash-separated list of sentence counts, one number per paragraph. 1/3/1 means:

<!-- cadence:intro -->

One sentence.

First sentence. Second sentence. Third sentence.

Last sentence.

<!-- /cadence:intro -->

The observed structure above is 1/3/1: the first paragraph has one sentence, the second has three sentences, and the third has one sentence.

Each structure segment must be a positive integer. Sections can allow more than one structure:

cadence-lint --section intro=1/3/1,1/5/1 docs/intro.md

Allowed structures can repeat to cover longer marked sections. For example, intro=1/3/1 also accepts a six-paragraph section with observed structure 1/3/1/1/3/1.

Different allowed structures can repeat in the same marked section. For example, intro=1/3/1,1/5/1 accepts an observed structure of 1/3/1/1/5/1.

Only normal Markdown paragraphs are counted. Headings, lists, code blocks, and HTML comments are not paragraph structure segments.

Config

Cadence Lint auto-discovers cadence.config.jsonc from the current working directory when it exists. A missing auto-discovered config is allowed. Use --config <path> to load a specific config file. A missing explicit config is an error.

{
  "language": "en",
  "sections": {
    "overview": ["1/3/1", "1/5/1"],
    "details": ["2/1"]
  },
  "exceptions": ["Dr\\."]
}

sections maps cadence section names to allowed sentence-count structures. A section value may be a single string or an array of strings.

For richer diagnostics, a pattern may describe the whole structure and each paragraph-count segment:

{
  "sections": {
    "overview": {
      "pattern": [
        { "count": 1, "description": "Introduce the idea" },
        { "count": 3, "description": "Develop the idea" },
        { "count": 1, "description": "Conclude the idea" }
      ],
      "description": "Opening overview"
    }
  }
}

For anchored sections, use start, middle, and end buckets. middle patterns repeat to consume the body:

{
  "sections": {
    "overview": {
      "start": ["1/3/1"],
      "middle": ["1/5/1"],
      "end": ["1/2/1"]
    }
  }
}

exceptions is an array of regex strings protected during sentence splitting. Use it for abbreviations or other punctuation that should not end a sentence.

Defaults:

  • language: en
  • sections: no configured section structures
  • exceptions: none

Precedence:

  • Auto-discovered cadence.config.jsonc is used when no explicit config path is provided.
  • --config <path> uses that config instead of auto-discovery.
  • --language overrides the config language.
  • Any --section or --section-rule flag replaces the config sections set. Include every section rule you want active when using section flags.
  • CLI flags do not override config exceptions.

Diagnostics and Exit Codes

Human output is one diagnostic per line:

docs/intro.md:1:1 warning Normal paragraph is not covered by cadence markers.
docs/intro.md:3:1 error Cadence section 'intro' structure does not match expected structures. [observed: 1/2, expected: 1/3/1, context: previous "One sentence." | "This paragraph has two sentences." | "It does not match."; mismatch paragraph 2 expected 3 sentences but observed 2 sentences "This paragraph has two sentences."]

JSON output wraps diagnostics in a diagnostics array:

{
  "diagnostics": [
    {
      "severity": "error",
      "message": "Cadence section 'intro' structure does not match expected structures.",
      "location": {
        "filePath": "docs/intro.md",
        "line": 3,
        "column": 1
      },
      "observedStructure": "1/2",
      "expectedStructures": ["1/3/1"]
    }
  ]
}

Exit-code behavior:

  • Exit code 0: no diagnostics, or warnings only.
  • Exit code 1: at least one error diagnostic, invalid CLI input, unsupported language, missing target, or config load/parse error.

Library

import { lintMarkdown } from "cadence-lint";

const result = lintMarkdown("# Title\n\nPlain prose.\n");
console.log(result.diagnostics);

Package Release

The npm package is prepared as cadence-lint with MIT licensing, public npm access, provenance-enabled CI publishing, a cadence-lint binary, ESM library exports, and TypeScript declarations.

Before publishing, run the local release check:

npm run release:check

This runs type-checking, tests, a production build, and a package dry-run verification that checks the built CLI, library entry points, declaration files, README, and license. To inspect npm's packed file list without the full check:

npm run pack:dry

Publishing is intentionally manual. See RELEASE.md for the confirmation checklist, first-time package creation flow, trusted-publisher setup, and GitHub Actions workflow steps.