Skip to main content

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

Project description

mrsf — Markdown Review Sidecar Format (Python)

Python CLI and SDK for the MRSF (Sidemark) specification. A 1:1 port of the Node.js @mrsf/cli package.

Installation

pip install mrsf

CLI Usage

# Validate sidecar files
mrsf validate docs/*.review.yaml
mrsf validate --strict README.md

# Add a comment
mrsf add README.md --author "Alice" --text "Fix this" --line 10

# Re-anchor after edits
mrsf reanchor docs/
mrsf reanchor --staged --force
mrsf reanchor --dry-run --threshold 0.8

# List comments
mrsf list docs/
mrsf list --open --severity high --json

# Resolve/unresolve
mrsf resolve doc.md.review.yaml abc123
mrsf resolve doc.md.review.yaml abc123 --undo

# Check anchor health
mrsf status docs/
mrsf status --json

# Create empty sidecar
mrsf init README.md

# Rename document + sidecar
mrsf rename old.md new.md

# Watch for changes
mrsf watch docs/ --reanchor --force

Global Options

Option Description
--cwd <dir> Working directory
--config <path> Path to .mrsf.yaml config
-q, --quiet Suppress non-essential output
-v, --verbose Detailed diagnostic output
--no-color Disable color output

SDK Usage

import mrsf

# Parse a sidecar file
doc = mrsf.parse_sidecar("README.md.review.yaml")

# Iterate comments
for comment in doc.comments:
    print(f"{comment.author}: {comment.text} (line {comment.line})")

# Add a comment
opts = mrsf.AddCommentOptions(
    author="Alice",
    text="Consider rephrasing this section",
    line=42,
    selected_text="The quick brown fox",
    type="suggestion",
    severity="medium",
)
new_comment = mrsf.add_comment(doc, opts)

# Add a comment with tool-specific x_* metadata
bot_opts = mrsf.AddCommentOptions(
    author="review-bot",
    text="Needs a second pass",
    line=12,
    extensions={
        "x_source": "review-bot",
        "x_score": 0.91,
        "x_labels": ["needs-review", "docs"],
    },
)
mrsf.add_comment(doc, bot_opts)

# Write back (preserves YAML formatting)
mrsf.write_sidecar("README.md.review.yaml", doc)

# Validate
result = mrsf.validate(doc)
if not result.valid:
    for err in result.errors:
        print(f"Error: {err.message}")

# Re-anchor after edits
results = mrsf.reanchor_document(doc, document_lines)
for r in results:
    print(f"{r.comment_id}: {r.status} ({r.reason})")

# Discover sidecar for a document
sidecar_path = mrsf.discover_sidecar("docs/guide.md")

# Fuzzy text matching
score = mrsf.combined_score("original text", "edited text")
matches = mrsf.fuzzy_search("search text", ["line 1", "line 2", "line 3"])

API Reference

Parsing

Function Description
parse_sidecar(path) Parse a .review.yaml or .review.json file
parse_sidecar_content(content, format) Parse sidecar from string content
read_document_lines(path) Read document lines for anchoring

Writing

Function Description
write_sidecar(path, doc) Write with round-trip YAML preservation
to_yaml(doc) Serialize to YAML string
to_json(doc) Serialize to JSON string
compute_hash(text) SHA-256 hash for selected_text_hash
sync_hash(comment) Sync hash with current selected_text

Comments

Function Description
add_comment(doc, opts) Add a new comment
resolve_comment(doc, id) Mark comment as resolved
unresolve_comment(doc, id) Mark comment as unresolved
remove_comment(doc, id, opts) Remove with reply promotion (§9.1)
filter_comments(comments, filter) Filter by status/author/type/severity
get_threads(comments) Group into reply threads
summarize(comments) Aggregate statistics

AddCommentOptions accepts an optional extensions map. Keys must start with x_, and entries are written back to the sidecar as flat x_* fields on the comment.

Validation

Function Description
validate(doc) Validate an MrsfDocument in memory
validate_file(path) Validate a sidecar file on disk

Re-anchoring

Function Description
reanchor_comment(comment, lines, opts) Re-anchor a single comment
reanchor_document(doc, lines, opts) Re-anchor all comments in a document
reanchor_file(path, opts) High-level file-based re-anchor

Discovery

Function Description
discover_sidecar(doc_path) Find sidecar for a document
discover_all_sidecars(root) Find all sidecars in a directory
find_workspace_root(cwd) Find workspace root (.mrsf.yaml or .git)
load_config(root) Load .mrsf.yaml configuration

Fuzzy Matching

Function Description
exact_match(needle, haystack) Find exact substring matches
normalized_match(needle, haystack) Whitespace-normalized matching
fuzzy_search(needle, lines) Multi-line fuzzy search with scoring
combined_score(a, b) Combined similarity score (0.0–1.0)

Git Integration

Function Description
is_git_available() Check if git is on PATH
find_repo_root(cwd) Find .git root directory
get_current_commit(root) Get HEAD commit SHA
get_diff(commit, path, root) Get unified diff output
get_line_shift(commit, path, line, root) Compute line shift from diff

Data Types

@dataclass
class MrsfDocument:
    mrsf_version: str
    document: str
    comments: list[Comment]

@dataclass
class Comment:
    id: str
    author: str
    timestamp: str
    text: str
    resolved: bool = False
    line: int | None = None
    end_line: int | None = None
    selected_text: str | None = None
    selected_text_hash: str | None = None
    type: str | None = None
    severity: str | None = None  # "low" | "medium" | "high"
    reply_to: str | None = None
    commit: str | None = None
    # ... plus start_column, end_column, anchored_text

Requirements

  • Python ≥ 3.10
  • Dependencies: click, jsonschema, ruamel.yaml, rapidfuzz, rich, watchdog

Development

cd python
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

# Run tests
pytest -v

# Lint
ruff check src/ tests/

# Type check
mypy src/mrsf/

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mrsf-0.4.1.tar.gz (66.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mrsf-0.4.1-py3-none-any.whl (42.5 kB view details)

Uploaded Python 3

File details

Details for the file mrsf-0.4.1.tar.gz.

File metadata

  • Download URL: mrsf-0.4.1.tar.gz
  • Upload date:
  • Size: 66.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for mrsf-0.4.1.tar.gz
Algorithm Hash digest
SHA256 28e77ba4863429e000e1fd9410438af6b9731b762576c9d2a1c05891fc6a295e
MD5 a74858c44dd0385e1b2782401e358107
BLAKE2b-256 4fb0206e00e3d2857ba602882ef086f85b4e056cd9dae851d2764e6c535e8f45

See more details on using hashes here.

File details

Details for the file mrsf-0.4.1-py3-none-any.whl.

File metadata

  • Download URL: mrsf-0.4.1-py3-none-any.whl
  • Upload date:
  • Size: 42.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for mrsf-0.4.1-py3-none-any.whl
Algorithm Hash digest
SHA256 696dc7b7bc111a5996855fa8038d474b35e15428f703549221cbdfb320f80925
MD5 ae3762a548c0ae09c0e74201ecf4aa87
BLAKE2b-256 362b9086830db3bf9feea122aeabbab219d879a8613bbfb3b3565f7645ab784e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page