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

compare-cli

v0.4.0

Published

Clause-aware drift detection between two contract versions. Pre-signature gate for legal teams and agent pipelines. Part of the contract-ops suite.

Readme

compare-cli

npm version CI License: MIT Node ≥ 20

Clause-aware drift detection between two contract versions. Pre-signature gate for legal teams and agent pipelines. Single-file Node CLI, two runtime deps, deterministic by design, no LLM tier in v1.

Part of the contract-ops CLI suite: template-vault-cli (storage) → draft-cli (fill placeholders) → nda-review-cli (review, redline, negotiate) → docx2pdf-cli (DOCX → PDF) → sign-cli (signing + audit). compare-cli is the pre-signature drift gate. Showcase site.

compare negotiated.docx ready-to-sign.pdf
# exit 0 = safe to sign
# exit 2 = substantive drift, DO NOT sign without review
# exit 3 = cosmetic / typographic drift only (informational)
# exit 4 = clauses moved, content identical

Part of the contract-ops CLI suite. draft-cli (fill placeholders) → nda-review-cli (review, redline, negotiate) → docx2pdf-cli (DOCX → PDF) → sign-cli (signing + audit). Storage: template-vault-cli. Drift detection: compare-cli (this CLI). Showcase site.

Agent pipelines: see mcp/README.md for compare-cli-mcp, the MCP server wrapping this CLI. Three tools (compare_files, compare_with_negotiation, compare_demo), stdio transport, JSON-first responses. Design contract: docs/mcp.md.


Why

You negotiated a contract over several rounds with counterparty's counsel. A few days later their paralegal sends you a ready-to-sign.pdf. Is the PDF the same text you agreed to, or did something quietly shift between "final version" and "version we put in the signing envelope"?

compare-cli answers that question with an exit code your CI can gate on:

  • Exit 0: every clause matches. Safe to sign.
  • Exit 2: substantive drift — a clause's text changed, a clause was added, or a clause was removed. The exact change is in the report. Do not sign without review.
  • Exit 3: cosmetic-only (whitespace, curly quotes, em-dashes) or typographic-only (case, $1,000 vs $1000, Oxford comma) drift. Informational; the agreement didn't change.
  • Exit 4: clauses moved but content is identical. Order shifted; the agreement didn't change.

The CLI works on .docx, .pdf, .md, and plain text — including cross-format comparisons (negotiated .docx vs ready-to-sign .pdf).

Install

npm install -g compare-cli

Or run without installing:

npx -p compare-cli@latest -- compare --demo

(The package is compare-cli; the installed command is compare. The -p … -- compare form tells npx which package to fetch and which bin to run, since the two names differ.)

Requires Node ≥ 20. (Pinned by pdfjs-dist@^5.7.284, which we share with sign-cli.)

Run this

compare --demo

Runs against two bundled fixtures (a negotiated NDA and a candidate where the term silently shifted from "two (2) years" to "three (3) years") and exits 2. You see the headline contract — substantive drift detected, report written, exit code asserted — without authoring a file.

compare --demo --json

Same comparison, structured JSON output to stdout.

Where to go next

| If you are… | Start here | |---|---| | A new user evaluating the gate | Run this above, then the End-to-end transcript | | An LLM agent driving the CLI | AGENTS.mdcompare --catalog jsoncompare <base> <candidate> --json | | Gating in CI | compare --check (exit-code only) or --sarif for code-scanning | | Wiring via MCP | the compare-cli-mcp package — see docs/mcp.md | | Adding a new CLI to the suite | The build-a-CLI playbook — the conventions every suite CLI follows |

End-to-end transcript

# You negotiated this:
cat > negotiated.md <<'EOF'
## 1. Purpose
This agreement governs information exchange between Acme and Globex.

## 2. Term
The term is two (2) years from the Effective Date.

## 3. Notices
All notices shall be delivered to the addresses on the cover page.
EOF

# They sent back this:
cat > ready-to-sign.md <<'EOF'
## 1. Purpose
This agreement governs information exchange between Acme and Globex.

## 2. Term
The term is three (3) years from the Effective Date.

## 3. Notices
All notices shall be delivered to the addresses on the cover page.
EOF

# Gate on it:
compare negotiated.md ready-to-sign.md
# → substantive drift, exit 2
echo "exit: $?"

# Or feed the base from nda-review-cli's negotiation.json:
compare --from-negotiation negotiation.json ready-to-sign.pdf

# Strict mode: treat typographic drift ($1,000 vs $1000) as substantive too
compare negotiated.md ready-to-sign.md --strict

In a CI pipeline:

compare negotiated.docx received/$(date +%F).pdf || {
  status=$?
  case $status in
    0) echo "✓ safe to sign" ;;
    2) echo "✗ substantive drift — do not sign" ;;
    3) echo "⚠ cosmetic drift only — informational" ;;
    4) echo "⚠ clauses moved but content identical" ;;
    *) echo "✗ I/O or arg error" ;;
  esac
  exit $status
}

Command reference

USAGE
  compare BASE CANDIDATE [options]
  compare --from-negotiation NEG.json CANDIDATE [options]
  compare --demo [--json]

ARGS
  BASE        what was agreed (.docx | .pdf | .md | .txt | - for stdin)
  CANDIDATE   what is being put forward (same formats, or -)

OPTIONS
  --from-negotiation PATH   read base text from nda-review-cli's negotiation.json
  --require-signoffs        with --from-negotiation, require both parties to have signed off
  --only-clauses PATTERNS   comma-separated; only include matching clause titles in the report + exit code
  --ignore-clauses PATTERNS comma-separated; exclude matching clause titles from the report + exit code
  --strict                  treat typographic drift as substantive (exit 2)
  --strict-cosmetic         treat cosmetic drift as substantive (exit 2)
  --json                    emit structured JSON to stdout
  --sarif                   emit SARIF v2.1.0 to stdout (for code-scanning / CI annotations)
  --no-intra-diff           disable inline word-level diff inside substantive clauses
  --why                     print structured explanation to stderr
  --silent, -q              suppress stderr
  --check                   suppress all output; communicate via exit code only (implies --silent)
  --output, -o PATH         write report to PATH instead of stdout (ignored with --check)
  --completion bash|zsh     emit shell completion script
  --demo                    run a zero-file 30-second demo
  --version, -V             print version
  --help, -h                show this help

Exit codes

| Code | Meaning | |------|-----------------------------------------------------------------| | 0 | No drift detected, safe to sign | | 1 | I/O error — input not found, unreadable, malformed .docx/.pdf | | 2 | Substantive drift (or --strict/--strict-cosmetic was set and tripped) | | 3 | Cosmetic-only or typographic-only drift (informational) | | 4 | Clause(s) moved but content identical |

Stable across minor versions. Documented in AGENTS.md and COMPARE_SCHEMA.md.

What counts as which class?

  • cosmetic — whitespace runs, line wraps, curly vs straight quotes, em-dashes vs hyphens, NBSP vs space, ellipsis vs ...
  • typographic — number formatting ($1,000 vs $1000, 5.0% vs 5%), Oxford comma flips, case-only differences (Acme vs ACME)
  • substantive — any word change, addition, deletion, or clause reorganization (will not vs will, two years vs three years, clauses added or removed)
  • moved — clauses whose text is byte-identical but whose position in the ordered clause sequence changed

The exact rules — including what is deliberately not normalized away (singular/plural, tense, negation, list punctuation) — are locked in COMPARE_SCHEMA.md §5–§6.

--json output shape

Stable across minor versions. Top-level keys: ok, exit_class, exit_code, base, candidate, summary, differences, warnings. See COMPARE_SCHEMA.md §10 for the full shape.

--why output

Structured key=value lines on stderr describing detection tiers, alignment method, class counts, exit decision, and strict-mode state. Same posture as draft-cli's --why.

--from-negotiation

Reads nda-review-cli's negotiation.json and extracts the latest agreed text as BASE. Three-tier resolution (preferred → fallback): top-level status: converged|signed_off|finalized, per-round agreed: true (minimum schema), per-round clause_status all "agreed" (historical fallback). See COMPARE_SCHEMA.md §9.

Pair with --require-signoffs when running unattended: it errors (exit 2) unless both signoffs.a and signoffs.b are non-empty in the state file. nda-review-cli populates these when the negotiate sign-off checkpoint is satisfied — a human-review gate before any agreement is acted on.

Clause filters

--only-clauses Term,Payment,Indemnification keeps only matching clauses in the report and exit-code calculation; --ignore-clauses Acknowledgments,Notices drops matching ones. Patterns are case-insensitive substrings, matched against numbering-stripped clause titles. Both flags can combine (--ignore-clauses runs after --only-clauses). The number of suppressed differences is surfaced in the human report and as summary.suppressed_by_filter in --json / SARIF output, so the suppression is auditable.

--sarif (CI / code-scanning)

--sarif emits a SARIF v2.1.0 document. Each substantive difference is a result with level: error; cosmetic/typographic are warning; added/removed/moved are note. Designed for GitHub Actions code- scanning upload — substantive drift appears as inline annotations on the candidate file in the PR review UI.

compare base.docx contracts/2026/acme.docx --sarif > compare.sarif
# upload via: github/codeql-action/upload-sarif@v3 with sarif_file=compare.sarif

--check (exit-code-only mode)

--check suppresses both stdout and stderr; the exit code is the only output. Use for CI gates and short shell pipelines:

compare base.docx cand.docx --check && echo "safe to sign"

Implies --silent. --output is also skipped under --check (you said you only care about the exit code).

If no agreed round exists, the CLI exits 2 with a clear error.

Working with PDFs

Text extraction from .pdf is layout-lossy. When either side is a PDF, the report surfaces a warning:

warning: candidate was extracted from PDF; layout-sensitive differences
         may surface as false positives

If extraction returns zero characters (a scanned PDF without an OCR layer), compare-cli exits 1 with a clear message rather than silently reporting no drift.

Part of the contract-ops suite

cli.drbaher.com

Pipeline (in order):

  • draft-cli — fills placeholders in templates before negotiation begins.
  • nda-review-cli — owns the negotiation.json hash-chained state file. --from-negotiation reads its output.
  • docx2pdf-cli — the upstream step that turns the agreed .docx into the .pdf you put in the signing envelope.
  • sign-cli — runs the actual signing flow; compare-cli is the gate that runs before it.

Auxiliaries:

Documentation

License

MIT © DrBaher