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

@mrsf/cli

v0.4.1

Published

CLI and library for the Markdown Review Sidecar Format (MRSF)

Readme

MRSF CLI

License: MIT MRSF v1.0 Draft @mrsf/cli on npm npm downloads (cli)

Command-line tool and Node.js library for Sidemark — the Markdown Review Sidecar Format (MRSF v1.0).

Validate sidecars, add and resolve review comments, re-anchor comments after document edits, and integrate MRSF into CI/CD pipelines — all from the terminal.

  ╔╦╗╦═╗╔═╗╔═╗
  ║║║╠╦╝╚═╗╠╣
  ╩ ╩╩╚═╚═╝╚
  Markdown Review Sidecar Format

Quick Start

# Install globally
npm install -g @mrsf/cli

# …or run without installing
npx @mrsf/cli --help

From source

git clone https://github.com/wictorwilen/MRSF.git
cd MRSF/cli
npm install
npm run build
node dist/bin.js --help

Commands

mrsf validate [files...]

Validate sidecar files against the JSON Schema and MRSF spec rules.

# Validate a single sidecar
mrsf validate docs/architecture.md.review.yaml

# Validate all sidecars discovered in the workspace
mrsf validate

# Treat warnings as errors (useful for CI)
mrsf validate --strict

| Option | Description | |---|---| | -s, --strict | Treat warnings as errors (exit non-zero) |


mrsf add <document>

Add a review comment to a document's sidecar file. Creates the sidecar if it doesn't exist. Automatically populates selected_text from the document when a line is specified, and stamps the current git commit.

# Add a line comment
mrsf add docs/api.md \
  --author "alice" \
  --text "Clarify the rate limit behavior" \
  --line 42

# Add a column-span comment with type and severity
mrsf add docs/api.md \
  --author "bob" \
  --text "Typo: should be 'response'" \
  --line 18 --start-column 10 --end-column 18 \
  --type suggestion --severity low

# Reply to an existing comment
mrsf add docs/api.md \
  --author "alice" \
  --text "Good catch, fixed in abc123" \
  --reply-to 3eeccbd3

# Attach tool-specific x_* metadata
mrsf add docs/api.md \
  --author "bot" \
  --text "Flagging this for follow-up" \
  --line 27 \
  --ext x_source=triage-bot \
  --ext x_score=0.91 \
  --ext 'x_labels=["needs-review","docs"]'

| Option | Description | |---|---| | -a, --author <name> | Comment author (required) | | -t, --text <text> | Comment body (required) | | -l, --line <n> | Line number (1-based) | | --end-line <n> | End line (inclusive) | | --start-column <n> | Start column (0-based) | | --end-column <n> | End column (0-based) | | --type <type> | Category: suggestion, issue, question, accuracy, style, clarity | | --severity <level> | Importance: low, medium, high | | --reply-to <id> | Reply to an existing comment by ID | | --selected-text <text> | Override auto-detected selected text | | --ext <key=value> | Add an x_* extension field; repeat for multiple fields |

--ext values are stored as flat x_* fields in the sidecar. Primitive JSON literals like numbers, true, false, and null are parsed automatically, and objects/arrays can be passed as JSON.


mrsf resolve <sidecar> <id>

Resolve (or unresolve) a comment by ID.

# Resolve a comment
mrsf resolve docs/api.md.review.yaml 1d3c72b0

# Unresolve it
mrsf resolve --undo docs/api.md.review.yaml 1d3c72b0

# Resolve and cascade to all direct replies
mrsf resolve --cascade docs/api.md.review.yaml 1d3c72b0

| Option | Description | |---|---| | --cascade | Also resolve direct replies | | -u, --undo | Unresolve instead of resolving |


mrsf list [files...]

List and filter comments across one or more sidecar files.

# List all open comments
mrsf list --open docs/api.md.review.yaml

# Filter by author and severity
mrsf list --author alice --severity high

# Summary view (counts, types, severities)
mrsf list --summary

# Machine-readable JSON output
mrsf list --json --open

| Option | Description | |---|---| | --open | Show only open (unresolved) comments | | --resolved | Show only resolved comments | | --orphaned | Show only orphaned comments | | --author <name> | Filter by author | | --type <type> | Filter by comment type | | --severity <level> | Filter by severity | | --summary | Show aggregate summary instead of individual comments | | --json | Output as JSON |


mrsf reanchor [files...]

Re-anchor comments after the source document has been edited. Uses a multi-step resolution algorithm (§7.4):

  1. Diff-based shift — uses git diff to calculate line offsets
  2. Exact text match — searches for selected_text verbatim
  3. Fuzzy match — token-level LCS + Levenshtein similarity
  4. Line/column fallback — checks whether original position is still plausible
  5. Orphan — retains unresolvable comments and marks them for review
# Dry run — see what would change without writing
mrsf reanchor --dry-run docs/api.md.review.yaml

# Re-anchor with a higher fuzzy threshold (stricter matching)
mrsf reanchor --threshold 0.8

# Only process sidecars for staged files (pre-commit hook)
mrsf reanchor --staged

# Disable git (pure text-based matching only)
mrsf reanchor --no-git

# Override the from-commit for all comments
mrsf reanchor --from abc1234

# Also update selected_text to match the current document text (opt-in)
mrsf reanchor --update-text

| Option | Description | Default | |---|---|---| | -n, --dry-run | Report without modifying files | false | | -t, --threshold <n> | Fuzzy match threshold (0.0–1.0) | 0.6 | | --staged | Only process sidecars for git-staged documents | false | | --no-git | Disable git integration entirely | git enabled | | --from <commit> | Override from-commit for diff calculation | per-comment commit field | | --update-text | Also replace selected_text with current document text | false |

Text preservation (§6.2): By default, re-anchoring preserves the original selected_text and records the current document text in anchored_text. Use --update-text to opt in to overwriting selected_text directly.


mrsf status [files...]

Assess anchor health for each comment.

mrsf status docs/api.md.review.yaml
mrsf status --json

Health states:

| State | Meaning | |---|---| | fresh | selected_text matches at the recorded position | | stale | selected_text matches but at a different position, or commit differs | | orphaned | selected_text not found in the document | | unknown | No selected_text to verify |

| Option | Description | |---|---| | --json | Output as JSON |


mrsf init <document>

Create an empty sidecar file for a Markdown document.

mrsf init docs/new-feature.md
mrsf init --force docs/existing.md   # overwrite

| Option | Description | |---|---| | -f, --force | Overwrite an existing sidecar |


mrsf rename <old-document> <new-document>

Update a sidecar after its source document has been renamed or moved.

mrsf rename docs/old-name.md docs/new-name.md

Updates the document field inside the sidecar, writes it to the new path, and removes the old sidecar file.

mrsf watch [files...]

Watch files for changes and continuously validate (and optionally reanchor).

# Validate all sidecars on every change
mrsf watch

# Watch specific files
mrsf watch docs/api.md docs/guide.md

# Auto-reanchor when Markdown files change
mrsf watch --reanchor

# Preview reanchor changes without writing
mrsf watch --reanchor --dry-run

# Custom threshold and strict validation
mrsf watch --reanchor --threshold 0.8 --strict

Trigger rules (avoids feedback loops):

| File type | Action | |---|---| | .md (Markdown) | Reanchor (if --reanchor is set), then validate sidecar | | .review.yaml / .review.json | Validate only |

| Option | Description | |---|---| | --reanchor | Auto-reanchor when Markdown files change | | -n, --dry-run | Preview reanchor changes without writing | | -t, --threshold <n> | Fuzzy match threshold 0.0–1.0 (default 0.6) | | -s, --strict | Treat validation warnings as errors | | --no-git | Disable git integration | | --from <commit> | Override from-commit for reanchor | | --update-text | Update selected_text on reanchor | | -f, --force | Force reanchor — update commit, clear audit fields | | --debounce <ms> | Debounce interval in ms (default 300) |

Press Ctrl+C to stop — a summary of events, reanchors, and errors is printed.

Global Options

These apply to all commands:

| Option | Description | |---|---| | --cwd <dir> | Override the working directory | | --config <path> | Path to .mrsf.yaml configuration | | --no-color | Disable coloured output | | -q, --quiet | Suppress informational output | | -V, --version | Print version | | -h, --help | Show help |

CI/CD Integration

GitHub Actions

name: MRSF Review Lint
on: [pull_request]
jobs:
  mrsf:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npx @mrsf/cli validate --strict
      - run: npx @mrsf/cli reanchor --staged --dry-run

Git Pre-commit Hook

#!/usr/bin/env bash
# .git/hooks/pre-commit
npx @mrsf/cli reanchor --staged
npx @mrsf/cli validate --strict

Git Post-merge Hook

#!/usr/bin/env bash
# .git/hooks/post-merge
npx @mrsf/cli reanchor

Library Usage

The CLI is built library-first. All functionality is available as importable functions:

import {
  parseSidecar,
  parseSidecarLenient,
  writeSidecar,
  validate,
  reanchorDocument,
  addComment,
  resolveComment,
  removeComment,
  filterComments,
  summarize,
  discoverSidecar,
  discoverAllSidecars,
} from "@mrsf/cli";

// Validate a sidecar programmatically
const doc = await parseSidecar("docs/api.md.review.yaml");
const result = await validate(doc);
console.log(result.valid, result.errors, result.warnings);

// Add a comment
const updated = addComment(doc, lines, {
  author: "ci-bot",
  text: "Auto-generated review comment",
  line: 10,
});
await writeSidecar("docs/api.md.review.yaml", updated);

Browser-safe reanchoring

The default @mrsf/cli entrypoint is Node-oriented and includes file system and git-backed helpers such as parseSidecar, readDocumentLines, and reanchorFile. For browser bundles and editor integrations, use the @mrsf/cli/browser subpath instead.

@mrsf/cli/browser exports the pure text-based matching and reanchoring primitives only:

import {
  applyReanchorResults,
  reanchorDocumentText,
} from "@mrsf/cli/browser";

const results = reanchorDocumentText(sidecar, markdownText);
const changed = applyReanchorResults(sidecar, results);

console.log(changed, results.map((result) => result.status));

Use this entrypoint when you already have the document text and sidecar object in memory. It intentionally excludes Node-only helpers such as sidecar discovery, file parsing, file writing, and git-aware diff reanchoring.

Configuration

Place a .mrsf.yaml at your repository root to configure sidecar discovery:

# Store all sidecars in a central directory instead of co-located
sidecar_root: .reviews

With this config, the sidecar for docs/architecture.md is resolved as .reviews/docs/architecture.md.review.yaml.

See §3.2 Alternate Sidecar Location in the spec for details.

Extension Fields (x_*)

MRSF reserves the x_ prefix for tool-specific, non-standard extension properties (see §10 Extension Fields). These fields may appear on the top-level document object or on individual comments. The CLI preserves them during round-trip writes and exposes them through the catch-all index signature on both MrsfDocument and Comment.

Built-in x_ fields

The CLI and Sidemark VS Code extension use the following extension fields:

| Field | Scope | Type | Set by | Description | |---|---|---|---|---| | x_reanchor_status | comment | "anchored" | "shifted" | "fuzzy" | "orphaned" | mrsf reanchor | Result of the most recent reanchor pass. orphaned means the anchor text could not be found in the current document. | | x_reanchor_score | comment | number (0–1) | mrsf reanchor | Confidence score from the reanchor algorithm. 1.0 = exact match, lower values indicate fuzzy or shifted matches. |

Adding your own fields

Any property whose key starts with x_ is valid on both the document root and on each comment. The CLI and Sidemark will silently preserve these fields through all operations (validate, add, resolve, reanchor, etc.).

comments:
  - id: abc123
    author: ci-bot
    timestamp: "2025-01-15T10:00:00Z"
    text: Possible security concern
    resolved: false
    line: 42
    # Custom extension fields
    x_ai_confidence: 0.92
    x_tool_name: security-scanner
    x_category: injection

Rules (from the spec):

  • Keys MUST start with x_ (underscore, not hyphen).
  • Implementations MUST NOT assign semantic meaning to x_ fields defined by other tools.
  • Future MRSF spec versions will never introduce normative fields with the x_ prefix.
  • Unknown x_ fields are preserved by the CLI's round-trip writer and never stripped or modified.

Programmatic access

import { parseSidecar } from "@mrsf/cli";

const doc = await parseSidecar("file.md.review.yaml");
for (const comment of doc.comments) {
  // Access built-in x_ fields
  if (comment.x_reanchor_status === "orphaned") {
    console.log(`Comment ${comment.id} is orphaned`);
  }
  // Access custom x_ fields
  const confidence = comment.x_ai_confidence as number | undefined;
}

Requirements

  • Node.js 18 or later
  • Git (optional — enables diff-based re-anchoring, commit stamping, rename detection)

License

MIT — see LICENSE.