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

claudemd-cli

v0.9.19

Published

Standalone CLI for §10-V banned-vocab + transcript scanning. Companion to the claudemd Claude Code plugin (github.com/sdsrss/claudemd) for use in git pre-commit hooks, GitHub Actions, and other agents.

Readme

claudemd

Claude Code plugin that enforces AI-CODING-SPEC v6.11 HARD rules through shell hooks — and ships the spec itself as part of the plugin.

CI npm License: MIT

claudemd plugs into the Claude Code hook system to block commits, pushes, and bash commands that violate AI-CODING-SPEC v6.11 — banned vocabulary in commit messages, rm -rf $VAR without variable validation, ship-on-red-CI, unread MEMORY.md entries during release flows, and more. The spec itself (CLAUDE.md + CLAUDE-extended.md + CLAUDE-changelog.md) ships with the plugin and installs into ~/.claude/, so the rules Claude Code reads at session start match the rules the hooks enforce.

A standalone CLI (npx claudemd-cli) reuses the same banned-vocab.patterns source for git pre-commit hooks, GitHub Actions, and other agents that don't run inside Claude Code.


Quick start

Run both slash commands inside Claude Code:

/plugin marketplace add sdsrss/claudemd
/plugin install claudemd@claudemd

Then verify on your next session:

/claudemd-status
/claudemd-doctor

status reports plugin version, shipped vs installed spec version, kill-switch state, and rule-hits row count. doctor runs 9+ health checks with [✓] / [△] / [✗] markers.

The spec-file copy into ~/.claude/ runs from the SessionStart hook on the next session. To install in the current session, run the script directly (find <version> with ls ~/.claude/plugins/cache/claudemd/claudemd/ | sort -V | tail -1):

node ~/.claude/plugins/cache/claudemd/claudemd/<version>/scripts/install.js

⚠️ ~/.claude/CLAUDE.md is shared real estate. Claude Code reads this file as your user-global instructions across every project. If you've hand-written personal instructions there (Always reply in 中文, My name is X, etc.), install moves your existing files to ~/.claude/backup-<ISO>/ (last 5 kept automatically) before writing the spec. Since v0.5.3, install prints a [claudemd] WARN: … line to stderr when the existing file does not look like a claudemd spec. To bring your personal instructions back on uninstall, run CLAUDEMD_SPEC_ACTION=restore /claudemd-uninstall.


Prerequisites

| Tool | Required | Why | |---|---|---| | node >= 20 | yes | install / status / doctor / update scripts (package.json engines) | | jq | yes | every hook parses Claude Code event JSON via jq — without it hooks silently fail-open | | git | yes | ship-baseline-check reads HEAD body; session-start-check runs git ls-remote; manual upgrade fallback | | gh | recommended | ship-baseline-check calls gh run list — if absent, the hook fail-opens silently and shipping on red CI is no longer blocked | | coreutils | macOS only | hooks need GNU timeout. Install with brew install coreutils, then prepend $(brew --prefix coreutils)/libexec/gnubin to your PATH |

Verify in one command (Linux): node --version && jq --version && gh --version && git --version && timeout --version | head -1. macOS users can swap timeout for gtimeout if coreutils is bottle-installed without the gnubin shim.


What it installs

| Layer | Contents | |---|---| | 12 shell hooks | banned-vocab-check · pre-bash-safety-check · ship-baseline-check · residue-audit · memory-read-check · sandbox-disposal-check · session-start-check · session-summary · transcript-vocab-scan · transcript-structure-scan · version-sync · mem-audit | | 9 slash commands | /claudemd-status · /claudemd-update · /claudemd-audit · /claudemd-toggle · /claudemd-doctor · /claudemd-uninstall · /claudemd-rules · /claudemd-clean-residue · /claudemd-sparkline | | 1 standalone CLI | claudemd-cli lint · claudemd-cli audit (npm: claudemd-cli) | | Spec v6.11.7 | ~/.claude/CLAUDE.md · CLAUDE-extended.md · CLAUDE-changelog.md (backup-before-overwrite) |

Install moves any existing ~/.claude/CLAUDE*.md to ~/.claude/backup-<ISO>/ (last 5 kept automatically). Uninstall offers keep / restore / delete; delete requires an extra confirmation.

Since v0.1.5, hook registration lives in the plugin's own hooks/hooks.json — the Claude Code harness expands ${CLAUDE_PLUGIN_ROOT} there automatically on every invocation, so hooks track the active plugin version without manual re-registration. install.js's remaining jobs are (1) copy spec/CLAUDE*.md into ~/.claude/ (with backup-before-overwrite), (2) evict any legacy claudemd hook entries from prior installs (≤0.1.1 absolute-path form, 0.1.2-0.1.4 ${CLAUDE_PLUGIN_ROOT}-in-settings.json form), and (3) write the installed manifest. It never touches other-plugin hooks. Claude Code's plugin-lifecycle postInstall field is not honored, so the script runs from SessionStart instead.


Hooks (what fires when)

Once installed, hooks run silently in the background. Verbose log: ~/.claude/logs/claudemd.jsonl (one row per hook decision). Aggregate via /claudemd-audit.

| Trigger | Hook | What happens | |---|---|---| | git commit with banned vocab (e.g. significantly, 70% faster, should work) | banned-vocab-check | Blocks the commit with a message pointing to the §10-V spec rule. | | Bash command with rm -rf $VAR (unvalidated expansion) or unpinned npx <pkg> | pre-bash-safety-check (v0.5.0+) | Blocks at PreToolUse:Bash per §8 SAFETY. Bypass via [allow-rm-rf-var] / [allow-npx-unpinned] token in the command, or pin/validate the variable. | | git push while base-branch CI is red | ship-baseline-check | Blocks the push (2-second gh run list timeout; fail-open if gh absent or times out). | | Bash command matching ship/push/deploy/release with an unread matched MEMORY.md entry | memory-read-check | Blocks the command with a list of memory files to Read first. | | Session end with ~/.claude/tmp/ growth > 20 entries | residue-audit | Advisory stderr warning; never blocks. | | Session end with fresh tmp.XXXXXX-style directories | sandbox-disposal-check | Advisory stderr warning. | | Stop event with Why:-less hard-rule citations in the assistant turn | mem-audit (v0.9.4+) | Detects spec-citation patterns missing the Why: rationale token; advisory log. | | Session end | session-summary (v0.8.0+) | Writes ~/.claude/.claudemd-state/last-session-summary.json; banner emit at next SessionStart. | | New session start with GitHub remote tag newer than local cache max version | session-start-check (v0.4.0+) | Injects an "upgrade available" banner via additionalContext. Rate-limited to once per 24h via ~/.claude/.claudemd-state/upstream-check.lastrun sentinel. 3-second git ls-remote timeout, fail-open. | | First UserPromptSubmit after a mid-session /plugin install upgrade | version-sync (v0.3.1+) | Backgrounds install.js once per session when the manifest version diverges from the active plugin's package.json. Sentinel-gated; fail-open. | | PostToolUse after assistant text containing banned vocab | transcript-vocab-scan | Advisory; logs to rule-hits without blocking. | | Session end with last assistant turn carrying §10 four-section out of order, Done: lines lacking evidence fingerprints, or Uncertain: short hedges without because | transcript-structure-scan (v0.9.10+) | Stop advisory — closes the audit gap that ~7 self-enforced HARD rules (§iron-law-2 / §10-four-section-order / §10-honesty) had no hook-side feedback signal. Opt-in (TRANSCRIPT_STRUCTURE_SCAN=1, default OFF) for FP signal collection; FP-tightened so single-section Done: lines never trigger. |

Execution order (PreToolUse:Bash)

CC runs all configured PreToolUse hooks for Bash sequentially in declaration order. First deny stops the rest and the tool call is denied. The 4 Bash hooks fire in this order (declared in hooks/hooks.json):

  1. pre-bash-safety-check (§8 SAFETY immutable) — rm -rf $VAR, unpinned npx <pkg>. First so a §8 violation can never be overridden by a downstream hook.
  2. banned-vocab-check (§10-V) — git commit message scan.
  3. ship-baseline-check (§7) — git push while base CI is red.
  4. memory-read-check (§11) — ship/release/deploy commands matching unread MEMORY.md tags.

Per-hook timeout (3-5s in hooks.json); timeout = treated as exit 0 (pass) per fail-open contract. Stop / SessionStart / UserPromptSubmit / PostToolUse hooks run all declared hooks regardless (none can block; advisories accumulate). Internal hook errors (missing jq, malformed event JSON, unreadable patterns file) fail-open; failures do NOT propagate to subsequent hooks.

Opt-in BASH_READONLY_FAST_PATH=1 short-circuits hooks 1, 2, and 4 when the command is a definitely-read-only shape (no shell-meta, first token in safe-reader whitelist — ls, cat, git log, etc.). Hook 3 only fires on git push so the fast-path doesn't apply.

Commands

| Command | Purpose | |---|---| | /claudemd-status | Plugin version + spec version + kill-switch state + logs line count. | | /claudemd-update | Interactive diff against plugin-shipped spec, then apply-all or cancel (spec trio is lockstep — per-file select would dangle §EXT cross-references). | | /claudemd-audit [--days N] | Aggregate rule-hits over last N days (default 30). Top banned-vocab patterns, per-hook deny counts. | | /claudemd-toggle <hook-name> | Enable/disable a specific hook by toggling DISABLE_*_HOOK in settings.json env. | | /claudemd-doctor [--prune-backups=N] | Health checks; optionally prune ~/.claude/backup-* dirs older than N. v0.7.1+ also flags rule sections whose bypass:deny ratio > 50% (R-N6 §0.1 demotion candidates). | | /claudemd-rules [N] | v0.8.0+ — audit spec/hard-rules.json manifest over last N days (default 90, matches §13.1 quarterly cadence). Surfaces demoteCandidates (hook-enforced rules with 0 hits) and staleReviews (rules whose last_demote_review is null/old). | | /claudemd-sparkline [--days=A,B,C] | v0.8.4+ R-N9 — per-spec_section cumulative counts of signal events across 3 windows (default 30/60/90d). Trend arrow compares per-period rate; (newly active) / (silenced) annotations flag activation/deactivation transitions. Markdown block suitable for CHANGELOG header pre-release. | | /claudemd-clean-residue [--apply] | Dry-run-by-default cleanup of stale claudemd-sync-* sentinels and historical claudemd-(mockgh\|work).* test sandboxes. | | /claudemd-uninstall | Pre-uninstall cleanup: clears manifest + state + log + legacy settings.json hook entries. Run BEFORE /plugin uninstall claudemd@claudemd (see Uninstall). |


Standalone CLI

The same banned-vocab.patterns source the in-CC hook uses is also exposed as a Node CLI for git pre-commit hooks, GitHub Actions, and other agents (Codex, Cursor, OpenClaw) — anywhere outside the Claude Code process.

# After npm publish (operator-driven, not part of plugin install):
npx claudemd-cli lint "your commit message here"
npx claudemd-cli lint --stdin < message.txt
npx claudemd-cli audit ~/.claude/projects/<encoded>/<session>.jsonl
npx claudemd-cli audit transcript.jsonl --json

# Dev mode (this repo, before npm publish):
node bin/claudemd-lint.js lint "your commit message here"
node bin/claudemd-lint.js audit ~/.claude/projects/<encoded>/<session>.jsonl

| Subcommand | Purpose | |---|---| | lint <text> / --stdin | Scan commit-message text for §10-V banned vocab. Exit 0 clean / 1 hits. | | audit <jsonl-path> | Scan all assistant-text turns in a Claude Code transcript jsonl. Skips @ratio patterns by default (chat prose has different baseline conventions); pass --include-ratio to include them. | | --json | JSON output (machine-readable for CI). | | --version / --help | Standard. |

Pre-commit example (.git/hooks/commit-msg):

#!/usr/bin/env bash
npx claudemd-cli lint --stdin < "$1" || exit 1

The CLI does NOT depend on ~/.claude/ state — pure stateless input → stdout/stderr + exit code. Same enforcement, anywhere Node 20+ runs.


Kill-switches

All visible in /claudemd-status. Three tiers:

1. Plugin-wide. Short-circuits every hook before any logic runs:

export DISABLE_CLAUDEMD_HOOKS=1

2. Per-hook. Disable one, leave others active:

export DISABLE_BANNED_VOCAB_HOOK=1         # or
export DISABLE_PRE_BASH_SAFETY_HOOK=1      # or
export DISABLE_SHIP_BASELINE_HOOK=1        # or
export DISABLE_RESIDUE_AUDIT_HOOK=1        # or
export DISABLE_MEMORY_READ_HOOK=1          # or
export DISABLE_SANDBOX_DISPOSAL_HOOK=1     # or
export DISABLE_SESSION_START_HOOK=1        # or
export DISABLE_SESSION_SUMMARY_HOOK=1      # v0.8.0+ — Stop hook writing summary
export DISABLE_USER_PROMPT_SUBMIT_HOOK=1   # transcript-vocab-scan

2a. Per-sub-feature (v0.4.0+). Sub-flags inside an enabled hook, named without the _HOOK suffix:

export DISABLE_UPSTREAM_CHECK=1            # only the upstream-tag-check sub-feature
                                           # of session-start-check; bootstrap-on-mismatch
                                           # behavior remains active.

export DISABLE_SESSION_SUMMARY_BANNER=1    # v0.8.0+ — only the SessionStart banner-emit
                                           # half of session-summary; the Stop-side write
                                           # of last-session-summary.json continues so
                                           # the data is captured for /claudemd-audit
                                           # but no additionalContext line is injected.

3. Per-invocation escape hatches. Embed in the command itself, no env var needed:

| Escape | Where | Bypasses | |---|---|---| | [allow-banned-vocab] | commit message | banned-vocab-check | | known-red baseline: <reason> | commit body | ship-baseline-check | | [skip-memory-check] | bash command string | memory-read-check | | [allow-rm-rf-var] | bash command string | pre-bash-safety-check (rm-with-var path only) | | [allow-npx-unpinned] | bash command string | pre-bash-safety-check (unpinned npx path only) |


Update

Claude Code has no /plugin update slash command — it's silently ignored as unrecognized. The canonical upgrade sequence is:

/plugin marketplace update claudemd                 # refresh local marketplace clone (git fetch)
/plugin uninstall claudemd@claudemd                 # remove old plugin version
/plugin install claudemd@claudemd                   # install latest from refreshed clone
/reload-plugins                                     # apply changes to current session

Or open the interactive UI via /pluginInstalled tab → select claudemd → follow upgrade prompts.

After the plugin upgrade, sync the shipped spec into ~/.claude/:

/claudemd-update

The command prints per-file diff summary, then prompts apply-all or cancel. Per-file select is intentionally not supported — the spec trio (CLAUDE.md + CLAUDE-extended.md + CLAUDE-changelog.md) evolves lockstep, and mixing versions would dangle §EXT §X-EXT cross-references in Core. Backup is automatic (retained to 5). /claudemd-update never fetches from GitHub — it only diffs the plugin-cache spec against your ~/.claude/CLAUDE*.md. The network fetch is Claude Code's job (via /plugin marketplace update).


Uninstall

Claude Code's marketplace lifecycle does not fire preUninstall, so /plugin uninstall claudemd@claudemd alone leaves orphan state behind (~/.claude/.claudemd-manifest.json, ~/.claude/.claudemd-state/, ~/.claude/logs/claudemd.jsonl). Use the two-step flow:

/claudemd-uninstall                    # clear manifest + state + log (plugin still installed)
/plugin uninstall claudemd@claudemd    # CC removes plugin cache itself

Reversing the order is the orphan-state vector — ${CLAUDE_PLUGIN_ROOT} and scripts/uninstall.js are gone after /plugin uninstall, with no in-tree tool to clean up afterwards. /claudemd-doctor flags [△] plugin cache: orphan manifest … if you've already hit this.

Spec disposition

/claudemd-uninstall defaults to keep (leaves ~/.claude/CLAUDE*.md in place). Override via env vars before the slash command:

| Option | Env vars | Behavior | |---|---|---| | keep (default) | (none) | ~/.claude/CLAUDE*.md left in place; settings.json hook entries cleared. | | restore | CLAUDEMD_SPEC_ACTION=restore | Copies the most recent ~/.claude/backup-<ISO>/*.md back to ~/.claude/. Use this if your install-time stderr showed [claudemd] WARN: existing ~/.claude/CLAUDE.md does not look like a claudemd spec — your hand-written user-global instructions are sitting in the backup waiting to be brought back. | | delete | CLAUDEMD_SPEC_ACTION=delete CLAUDEMD_CONFIRM=1 | Hard-AUTH: removes the three spec files. |

CLAUDEMD_PURGE=1 (env var) on /claudemd-uninstall also drops ~/.claude/.claudemd-state/ and your rule-hits log.

Direct script invocation (advanced fallback)

If /claudemd-uninstall is unavailable (you already ran /plugin uninstall first and want to clean up by reaching into the cache before it gets pruned, or you need to script the uninstall outside CC):

CLAUDEMD_SPEC_ACTION=keep     node ~/.claude/plugins/cache/claudemd/claudemd/<version>/scripts/uninstall.js
CLAUDEMD_SPEC_ACTION=restore  node ~/.claude/plugins/cache/claudemd/claudemd/<version>/scripts/uninstall.js
CLAUDEMD_SPEC_ACTION=delete CLAUDEMD_CONFIRM=1 node ~/.claude/plugins/cache/claudemd/claudemd/<version>/scripts/uninstall.js

The slash command and the script are equivalent — the slash command just supplies ${CLAUDE_PLUGIN_ROOT} for you.


Troubleshooting

Plugin "claudemd" not found in any marketplace — you forgot the /plugin marketplace add sdsrss/claudemd step. Re-run it, then retry install.

Hooks don't fire / ~/.claude/CLAUDE*.md not present after install — Claude Code's postInstall lifecycle is not honored, so install.js runs from the SessionStart hook on your next session, not at install time. Either start a fresh Claude Code session, or run the script manually right now (replace <version> with the installed version dir):

node ~/.claude/plugins/cache/claudemd/claudemd/<version>/scripts/install.js

Verify with /claudemd-status — the "log.lines" count should increment after the next hook fires.

/plugin update claudemd does nothing / empty stdout/plugin update is not a valid Claude Code slash command; CC silently ignores unrecognized commands. Use the canonical sequence in the Update section: /plugin marketplace update claudemd/plugin uninstall claudemd@claudemd/plugin install claudemd@claudemd/reload-plugins. If that also fails (marketplace clone refuses to refresh), manually git -C ~/.claude/plugins/marketplaces/claudemd fetch origin main --tags && git merge --ff-only origin/main, then git archive v<version> | tar -x -C ~/.claude/plugins/cache/claudemd/claudemd/<version>/, then run that version's scripts/install.js.

Hook command references ${CLAUDE_PLUGIN_ROOT} but the hook is not associated with a plugin (5 errors on every Bash tool call + every session end) — you're on claudemd 0.1.2 / 0.1.3 / 0.1.4. Those releases wrote hook commands into ~/.claude/settings.json under the literal ${CLAUDE_PLUGIN_ROOT} token, but the CC harness only expands that variable for hooks defined in a plugin's own hooks/hooks.json — never in settings.json. The fix is v0.1.5+, which moves hook registration into the plugin's hooks/hooks.json (where the token expands correctly) and evicts the stale settings.json entries on install. Upgrade via the canonical sequence in the Update section, then restart the Claude Code session to clear the cached hook registry.

ship-baseline-check silently passes on red CIgh CLI is not installed, or authentication failed. Install with brew install gh / apt-get install gh and run gh auth login. Check with /claudemd-doctor — it reports gh: missing if absent.

CI matrix fails on macOS — our own CI installs coreutils for GNU timeout. If you're running hooks outside the bundled CI, ensure timeout is on PATH (brew install coreutils && export PATH="$(brew --prefix coreutils)/libexec/gnubin:$PATH").

/claudemd-doctor reports backup growth — run /claudemd-doctor --prune-backups=5 to keep only the 5 most recent.

PreToolUse:Bash hook error ... No such file or directory pointing at ~/.claude/hooks/banned-vocab-check.sh — Claude Code loaded settings.json at session start and cached the old hand-install hook entry in memory. install.js migrated the on-disk entry to the cache path and moved the original shell file to ~/.claude/backup-*/hooks/, but the running session's hook registry is still stale. Exit and restart the Claude Code session — settings.json is re-read from disk, and the error stops. (This applies to any mid-session settings.json change, not just claudemd.)


Project layout

claudemd/
├── .claude-plugin/
│   ├── plugin.json           # minimal manifest (name, version, author, license, keywords)
│   └── marketplace.json      # marketplace catalog entry
├── hooks/                    # 11 shell hooks + hooks/lib/ (hook-common, rule-hits, platform)
│   └── hooks.json            # authoritative hook registration (v0.1.5+); CC expands ${CLAUDE_PLUGIN_ROOT} here
├── commands/                 # 9 slash-command markdown files
├── bin/                      # standalone CLI entrypoint (claudemd-lint.js → `npx claudemd-cli` on npmjs.org)
├── scripts/                  # 10 Node.js management scripts + scripts/lib/ (single-source registry, lint, etc.)
├── spec/                     # shipped v6.11.7 CLAUDE*.md trio + hard-rules.json manifest
├── tests/                    # hook shell tests + Node.js tests + integration + fixtures
├── docs/                     # ADDING-NEW-HOOK.md + RULE-HITS-SCHEMA.md + superpowers/
└── .github/workflows/        # ci.yml (ubuntu+macOS × node 20) + npm-publish.yml (tag-triggered)

Extending


License

MIT — see LICENSE.