Compare Cli — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Compare Cli (Agent Skill) and scored it 96/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 1 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
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 identicalPart 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: seemcp/README.mdforcompare-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.
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:
added, or a clause was removed. The exact change is in the report. Do not sign without review.
typographic-only (case, $1,000 vs $1000, Oxford comma) drift. Informational; the agreement didn't change.
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).
npm install -g compare-cliOr 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.)
compare --demoRuns 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 --jsonSame comparison, structured JSON output to stdout.
| 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.md → compare --catalog json → compare <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 |
# 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 --strictIn 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
}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| 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.
em-dashes vs hyphens, NBSP vs space, ellipsis vs ...
$1,000 vs $1000,5.0% vs 5%), Oxford comma flips, case-only differences (Acme vs ACME)
reorganization (will not vs will, two years vs three years, clauses added or removed)
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 shapeStable 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 outputStructured 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-negotiationReads 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.
--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.
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 positivesIf 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.
Pipeline (in order):
placeholders in templates before negotiation begins.
the negotiation.json hash-chained state file. --from-negotiation reads its output.
upstream step that turns the agreed .docx into the .pdf you put in the signing envelope.
signing flow; compare-cli is the gate that runs before it.
Auxiliaries:
— clause-aware template storage; produces info --json payloads that downstream tools consume. Implements the same clause-detection rule (docs/clause-detection.md) compare-cli does; divergences tracked in template-vault-cli/docs/clause-detection-divergence.md.
source of truth for what the CLI does. Implementation and tests are written against this file.
Stable output shapes, exit codes, failure diagnosis.
MIT © DrBaher
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.