Adopt rmscene For .rm Read/Write (0005-rmscene-dependency)

Context

Writing modern reMarkable .rm files (v6) involves a block-based format with CRDT sequences and tagged blocks (TreeNode, SceneGroupItem, SceneLineItem, RootText, etc.). Implementing a correct writer is non-trivial and requires a robust encoder and stable schema knowledge. A prior exploration of a Go codebase (rm2pdf) showed that while it parses v5, its v6 parsing and any writing are not implemented, making it impractical to base a writer on it.

Decision

Use the Python rmscene library as the canonical mechanism for reading and writing .rm v6 files in this project.

  • For generating notebooks/pages, rmfiles.notebook will build in-memory structures and call rmscene.write_blocks to produce .rm files.

  • For inspection and future read flows, prefer rmscene.read_blocks and higher-level helpers.

  • Keep local, minimal helpers only for convenience or data modeling; avoid re-implementing block encoders.

Consequences

Positive

  • Leverages a maintained, specialized implementation for the v6 format.

  • Reduces risk of subtle encoding bugs; faster path to working features.

  • Aligns with existing tests and abstractions already using rmscene.

Trade-offs

  • Introduces a runtime dependency, fetched from GitHub (network access needed).

  • Upstream API or behavior changes can affect us if unpinned.

  • Developers need a Python environment (already true for this repo).

Guidance For Development

  • Installation - Editable install: pip install -e . (installs rmscene from GitHub). - Network-restricted environments: pre-install rmscene from a wheel or

    pin a specific commit/tag in setup.py/requirements.txt as needed.

  • Usage patterns - Write

    • Build blocks from our in-memory notebook and call rmscene.write_blocks(binary_io, blocks).

    • Read - Use rmscene.read_blocks(binary_io) to iterate blocks, or

      higher-level tree helpers if needed.

  • Testing - Prefer golden tests using known-good .rm fixtures. - For generation tests, verify file presence, header bytes (reMarkable

    string), and basic structure via rmscene.read_blocks when available.

Follow-ups

  • We have pinned rmscene==0.7.0 in setup.py and requirements.txt to ensure reproducible CI/local installs. Revisit the pin periodically to incorporate upstream fixes (consider pinning to a tag/commit if needed).

  • Extend CLI with richer inspect commands powered by rmscene.

  • Document offline workflows (prebuilt wheels, internal mirrors) if needed.