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

@safetnsr/md-kit

v0.6.0

Published

find broken [[wikilinks]] and dead relative links in any markdown workspace

Readme

md-kit

Find broken [[wikilinks]] and dead relative links in any markdown workspace. Zero dependencies. Now with event-driven pipeline automation via md-kit pipe.

install

npx @safetnsr/md-kit check .

Or install globally:

npm i -g @safetnsr/md-kit

usage

check — find broken links

md-kit check [dir]

Scans all .md files recursively. Finds broken [[wikilinks]] and [text](relative-path) links. Suggests fixes.

  FILE                               BROKEN LINK                    TYPE        SUGGESTION
  ──────────────────────────────────────────────────────────────────────────────────────────
  memory/NOW.md                      [[RAEDME]]                     wikilink    README
  docs/guide.md                      [setup](./steup.md)            relative    setup.md
  notes/daily.md                     [[mising-page]]                wikilink    missing-page

✗ 42 files scanned, 87 links checked — 3 broken

Exit code 1 if broken links found — CI-friendly.

fix — auto-fix broken links

md-kit fix [dir]           # dry-run: show fixable links
md-kit fix [dir] --apply   # write fixes to files
md-kit fix [dir] --patch   # write to md-kit-fixes.md for review

mv — move file and update all incoming links

md-kit mv <old-path> <new-path>           # move and update
md-kit mv <old-path> <new-path> --dry-run # preview

watch — watch directory for changes

md-kit watch [dir]   # alert on broken links as files change

pipe — markdown content pipelines

Event-driven automation for markdown directories. Watch files, match by path/frontmatter/tags, run multi-step pipelines.

md-kit pipe init              # scaffold a .md-pipe.yml config file
md-kit pipe watch             # start watching for changes
md-kit pipe once              # run triggers against all files (CI/batch)
md-kit pipe run <pipeline>    # manually run a named pipeline
md-kit pipe test <file>       # show which triggers/pipelines match a file

config example (.md-pipe.yml)

watch: ./docs

# Simple triggers: match + run a command
triggers:
  - name: publish
    match:
      path: "posts/**"
      frontmatter:
        status: publish
    run: "echo Publishing $FILE"

# Pipelines (multi-step)
pipelines:
  - name: publish-post
    trigger:
      path: "posts/**"
      frontmatter: { status: publish }
      frontmatter_changed: [status]
    steps:
      - run: "echo Publishing {{fm.title}}"
      - update-frontmatter: { published_at: "{{now}}", published: true }
      - copy: { to: "./_site/posts" }
      - webhook: { url: "$WEBHOOK_URL" }

trigger match options

| field | description | |---|---| | path | glob pattern against file's relative path (posts/**, *.md) | | frontmatter | frontmatter key-value match (supports negation: !value) | | frontmatter_changed | fire when listed frontmatter fields change | | tags | file must have all listed tags in frontmatter | | content | file body must contain this substring | | content_regex | file body must match this regex |

pipeline step types

| step | description | |---|---| | run | shell command with template vars | | update-frontmatter | write values back to file's frontmatter | | copy | copy file to destination directory | | webhook | POST JSON to a URL | | template | render a template file and write output |

template variables

| variable | value | |---|---| | {{now}} | ISO timestamp | | {{date}} | YYYY-MM-DD | | {{slug}} | filename without extension | | {{file}} | absolute file path | | {{relative}} | relative path from watch dir | | {{fm.title}} | frontmatter field | | {{step.0.stdout}} | output from pipeline step 0 |

pipe flags

| flag | description | |---|---| | --config, -c <path> | path to config file (default: .md-pipe.yml) | | --dry-run | show matches without executing actions | | --json | output in JSON format | | --verbose | show full command output | | --debug | show full interpolated commands | | --state <path> | state file for idempotent once mode |

CI / batch mode

# Run once over all files, skip unchanged (idempotent)
md-kit pipe once --state .md-pipe-state.json

# Dry run to preview
md-kit pipe once --dry-run

# JSON output for scripting
md-kit pipe once --json

flags (check/fix)

| flag | description | |---|---| | --json | output as JSON (agent interface) | | --ignore <pattern> | ignore files/links matching pattern (repeatable) | | --apply | (fix only) apply fixes to files | | --patch | (fix only) write fixes to md-kit-fixes.md | | --dry-run | (mv only) preview without moving | | --quiet-if-clean | (check only) no output if no broken links | | --since <date> | (check only) only files modified after date (YYYY-MM-DD, yesterday, 7days) | | --full | (check only) show all severity levels | | --help | show help | | --version | show version |

agent interface (--json)

{
  "totalFiles": 42,
  "totalLinks": 87,
  "brokenLinks": 3,
  "results": [
    {
      "file": "memory/NOW.md",
      "line": 5,
      "link": "RAEDME",
      "type": "wikilink",
      "suggestion": "README"
    }
  ]
}

what it checks

  • [[wikilinks]] — resolved against all .md files in the workspace
  • [[wikilink|alias]] — alias stripped, target checked
  • [[wikilink#heading]] — heading stripped, file checked
  • [text](relative/path.md) — resolved against filesystem
  • Skips: http://, https://, mailto:, #anchors, ![[embeds]]

pair with

license

MIT