Roadmap¶
Original goals (plan approved 2026-07-08): (1) iPad interop without leaving reMarkable land, (2) fixed standard page size in landscape, (3) pen strokes that export the way they look on-device, (4) hands-off ~1-2 min sync, (5) notes readable in a normal PDF app, auto-updating.
Phase 0 — XOVI landscape experiment on-device ⏳ WAITING ON DEVICE¶
Time-critical: the Paper Pro ships for warranty repair (ghosting) around
2026-07-12. Kit is ready in device-mods/ — follow its README checklist:
root (dev mode wipes; cloud restores) → remagic installs XOVI → install
disableInfiniteScroll + createPagesPaperProSize qmds → THE pivotal test:
does clamping the canvas make landscape exports uniform? → iterate qmd if
not → rollback.sh BEFORE disabling dev mode → ship.
Also while rooted: grab-corpus.sh (test data), pull
/usr/share/remarkable/templates/*.svg (exact template art — our dot
spacing is approximated), screenshot pen strokes (fidelity references),
test whether ghostbuster's full refresh clears the ghosting (repair-claim
diagnostic). If a replacement unit returns, re-run install.sh.
Phase 1 — Python core ✅ DONE (2026-07-08)¶
Library reader, faithful renderer (see docs/formats/remarkable.md),
incremental mirror to iCloud Drive (34 notebooks: 68s full, <1s
incremental), TOML config, CLI, launchd watch daemon (installed and
running). The maintainer confirmed output "looks really correct".
Known gaps / follow-ups:
- Pencil / mechanical pencil / paintbrush / shader alphas are best-guess —
not exercised by the validation notebook. Calibrate with an ops-diff against
an official export of a notebook using them (method in
docs/formats/remarkable.md).
- Template art approximated (dots ✓, lines/grid rough); replace with real
template SVGs from the device (Phase 0 grab).
- Annotated PDF/EPUB base-page merge not implemented (scope.pdfs/epubs
default false). Plan: pikepdf overlay of rendered annotations onto base.
- normalize = "paginate" option (split tall grown pages into multiple
fixed pages) not implemented; current default scales to fit.
- Typed-text blocks in notebooks render nothing yet (rmscene exposes them;
rmc's text layout is a reasonable starting point).
Phase 1.5 — universal converter (M1) ✅ DONE (2026-07-09)¶
Generalized the reMarkable-only pipeline into a neutral intermediate
representation so any ink format can convert to any other. See
docs/ir.md for the model, docs/reverse-engineering.md +
docs/corpus-protocol.md for how the undocumented formats were (and will
keep being) decoded, docs/validated-writes.md for write-safety policy.
- IR (
core/src/inkterop/ir/): neutral document/stroke model, per-point channels (pressure/tilt/width/alpha/…), three-fidelity model (exact/native/raw), IR-JSON serialization. - Format registry + CLI:
formats/__init__.pyregistry,inkterop convert/inkterop inspect. - Readers: reMarkable (ported onto the IR with zero regression —
golden byte-for-byte drawing-op tests plus a 110/110 whole-library A/B
check against the pre-IR renderer), xopp, IR-JSON, InkML, GoodNotes
(ink + color only, experimental — pen-type field still unlocated, see
docs/formats/goodnotes.md), Supernote (raster-first), Notability legacy (zip+plist), Notability modern .ntb (FlatBuffers op log decoded 2026-07-09, render-validated vs the app's own thumbnail; same encoding as the app's local-persistence note blobs — seedocs/formats/notability.md). - Writers: PDF, SVG, InkML, xopp, IR-JSON — all
validated = Trueperdocs/validated-writes.md(open formats or our own; no native-app writers yet). - Golden fidelity harness:
core/tests/test_golden_remarkable.pypins the validated renderer's drawing ops so the IR refactor can't silently regress fidelity. - RE toolkit:
tools/re/{inventory,pbwire,applelz4,fbwalk}.py. - Docs:
docs/ir.md,docs/formats/{remarkable,xopp,goodnotes, notability,supernote,inkml-mapping}.md,docs/reverse-engineering.md,docs/corpus-protocol.md,docs/validated-writes.md, all with confidence markers on unverified claims. - License: MIT.
M2 — complete in/out push ✅ LARGELY DONE (2026-07-09)¶
Landed on the note-apps workstream (18 readers / 12 writers total):
- Native writers, all five (each
validated = Falsebehind--experimentalperdocs/validated-writes.md, awaiting app-open checks — samples staged incorpus/validate/): Saber, reMarkable.rm/.rmdoc(int-exact device-fixture round-trips), Supernote (raster RATTA_RLE, cross-validated via supernotelib), GoodNotes (protobuf/LZ4/tpl encoders), Notability.ntb(hand-rolled FlatBuffers builder). - New readers: Excalidraw (r/w), generic SVG (re-ingests our own
SVG output — SVG is now two-way) + Stylus Labs Write, Wacom UIM
3.0/3.1 (oracle-validated vs Wacom's Apache library), MS-ISF
(codec-exact vs Microsoft's WPF implementation), OneNote
.one(full classic ONESTORE parse + undocumented ink hierarchy), Samsung.sdocx, Onyx Boox.note, PencilKit.pkdrawing(own novel RE, oracle-validated — the Apple Notes ink core), tldraw.tldr. - Per-format specs in
docs/formats/with confidence markers.
Still open in M2 scope:
- Writer validation session (app-open checks → flip validated);
Notability additionally gated on the red-ink color-byte-order corpus
case; GoodNotes on Mac-import member-set iteration.
- GoodNotes/Notability corpus deepening: pen-type/pressure fields
(cases 05/07/14/16), curvesfractionalwidths (case 16).
- Apple Notes NoteStore plumbing (TCC-gated) on top of the
PencilKit decoder; rnote (needs drawn samples).
- PDF fidelity (/BM /Darken exact blend; filled-outline
variable-width strokes) and annotated-PDF base-page merge —
carried over, unchanged.
Phase 2 — desktop app (sync control center + converter GUI) ✅ DONE (2026-07-10)¶
Shipped bigger than planned: a full Tauri 2 app (app/) instead of a
menu-bar-only shell — one codebase gives the main window AND the tray item,
and Windows/Linux builds fall out of the same code. ALL logic stays in
core/: the app spawns inkterop daemon (stdio JSON-RPC sidecar;
PyInstaller-frozen in release bundles, live uv tree in dev).
- Core sync module (
core/src/inkterop/sync/): multi-source (reMarkable cache, note-file folders, experimental GoodNotes/Notability container scanners), multi-sink (pdf/svg/png/inkz), per-doc rules (allow/block, rename, destination, format) in rules.toml, v2 state with v1 migration, watcher pid-lock.mirror/watchunchanged for launchd. - App: library browser (Finder-style columns / thumbnail grid / details list, first-page previews, folder+note sync toggles, output overrides), drag-and-drop converter over the full registry, activity log, settings, tray with sync controls, legacy-launchd migration.
- Releases:
.github/workflows/release.yml— macOS signed+notarized (once Apple secrets land — seeapp/RELEASING.md), Windows/Linux community builds; Homebrew cask recipe documented. - Website:
website/landing page at the Pages root, docs moved under/docs/.
Phase 3 — Import lane + iPad trial ◻ NOT STARTED¶
inkterop send <pdf> [--folder X]via ddvk/rmapi (mkdir+put), ALWAYS preceded byrmapibackup (official corruption warning).inkterop send --editablevia drawj2d 1.4+ (PDF/SVG → .rmdoc native editable ink, full Paper Pro color).- iPad app trial order (rationale in
docs/research.md): 1. Saber (only open-format iPad app; verify writing feel), 2. Nebo (best feel; no longer one-way — .nebo BINK ink is now decoded,formats/nebo/), - OneNote (best automation: Graph API
?includeinkML=true). GoodNotes/Notability rejected — closed/uncracked (GoodNotes) or format being replaced mid-crack (Notability). - Stretch: Saber
.sbn2↔.rmbidirectional bridge (both formats open).
Phase 4 — Later¶
Windows/Linux shells; app distribution (notarization/updates); OneNote InkML puller; exact template art; publish for other reMarkable users.