Skip to main content

rmcl: reMarkable Cloud Library

rmcl is a Python library for interacting with the reMarkable cloud. It supports a file-tree view onto your files, exposes metadata, and gives access to the original PDF or EPUB documents. If rmrl is installed, it can also produce PDF versions of any type of document with your annotations included. rmcl can create, update, and delete items from the reMarkable cloud.

Quick Demo

As a taste, this code will list all of the files and their types in the root directory of your reMarkable cloud.

from rmcl import Item, Document, Folder
import trio

async def list_files():
    root = await Item.get_by_id('')  # The root folder has ID of empty string
    for child in root.children:
        if isinstance(child, Folder):
            print(f"{child.name}: folder")
        elif isinstance(child, Document):  # The only other possibility
            print(f"{child.name}: {await child.type()}")

trio.run(list_files)

Installation

rmcl requires Python 3.7 or later. If that's installed, the easiest installation is to do a

pip install rmcl

Alternatively, you may clone this repository. Poetry is used for development, so once that is installed you can run

poetry install

to get a virtual environment all set up.

rmcl is asynchronous, and must be used with the trio async library.

Features

Asynchronous

rmcl is asynchronous at its core. This keeps it from blocking during the many HTTP transactions it uses. Most methods are async, and therefore must be called with the await keyword. rmcl is designed to work with the trio async library.

Synchronous Option

Asynchronous code can be overkill for simple scripts, so rmcl offers synchronous versions of all of its async functions. These functions have a suffix of '_s' in their names. This means that the above example could be written

def list_files_sync():
    root = Item.get_by_id_s('')
    for child in root.children:
        if isinstance(child, Folder):
            print(f"{child.name}: folder")
        elif isinstance(child, Document):
            print(f"{child.name}: {child.type_s()}")

Note that these synchronous functions are still calling the asynchronous low-level code. They may fail if called within another asynchronous framework.

Object Oriented

The main interface to rmcl is the Item class and its two subclasses, Folder and Document. The reMarkable cloud gives each item an ID. If the ID of an Item is known, it can be retrieved with the Item.get_by_id() static method. New Folders and Documents can be made with the .new() class method, which expects as arguments the item's name and parent ID.

While the cloud API presents a flat directory structure, rmcl assembles these objects into a file tree. Every Folder has a .children attribute, a list of the Items within it. Each Item has a .parent property, which gives the ID of its parent. (The ID is given instead of the parent to avoid circular references.) The parent object of item may be looked up with await Item.get_by_id(item.parent).

Two "virtual" folders are provided. The root folder (ID = '') contains all Items with no explicit parent. The trash folder (ID = 'trash') contains all Items marked as trashed.

Various metadata are exposed as properties: .name, .id, .version, .parent, and .mtime, for modification time. The .name and .parent properties can be modified, which updates the underlying metadata. Such changes can be sent to the cloud with the .update_metadata() method.

The contents of Documents can be retrieved in several ways. The .raw() method gets the zip file that the reMarkable cloud API uses to transfer documents. The .contents() method gets the original PDF or EPUB file associated with a Document. If rmrl is installed, the .annotated() method yields a PDF file with the user's annotations. All three methods return a file-like object, but the exact type is not guaranteed and may vary in the future. The same object may be returned from multiple calls to a given method; the user is responsible for coordinating reads and seeks to avoid contention.

New Items or existing Documents with new contents may be uploaded to the cloud with .upload() method.

Smart Updates

rmcl keeps a list of all documents in the reMarkable cloud, so that it doesn't need to query the API for each bit of information. To ensure this list is up to date, it automatically refreshes itself when you use Item.get_by_id() more than five minutes after the last refresh. You can also trigger this behavior by calling rmcl.invalidate_cache() before Item.get_by_id().

rmcl only updates objects that have a new version, so existing objects remain valid. Nonetheless, it is better to call Item.get_by_id() often, instead of keeping your own list of Items.

Caching Expensive Operations

Some of this information, like document type and size, require several round trips to calculate. rmcl stores these values locally, so they do not need to be recalculated every time. They are stored in a persistent database, so this information is not lost when the process stops. The database stores this information by version, so it knows when it must be recalculated.

rmcl does some simple caching of document contents after it is downloaded. It currently only keeps the most recent contents, but we hope to build a more sophisticated caching system soon.

Handles Authentication

The reMarkable cloud requires two tokens: The device token identifies your device and needs only to be set once. The user token is used on most requests, and should be updated occasionally. rmcl automatically renews the user token each time it is run.

Getting the device token requires user interaction the first time a program is run. If rmcl detects that it is being run interactively, it will print instructions and prompt to user to input a new device token. Otherwise, it will throw a rmcl.exceptions.AuthError. You must call register_device(code) with the code provided obtained from https://my.remarkable.com/connect/desktop. Once obtained, the device token is stored for future use.

Comparison with rMapy

rmcl started as a fork of rMapy. As we started moving in a rather different direction, we decided it would be better to make it into its own project. At this point, only some of the low-level API code from rMapy remains.

To help users decide which library best fits their needs, here are the major differences:

  • rmcl is asynchronous, while rMapy is synchonous. This means that rmcl will not block while making HTTP requests to the reMarkable API. rmcl's synchronous functions will block, much like rMapy.
  • rmcl has a simpler object structure, mostly focused around Item and its subclasses Document and Folder. rMapy has similar objects (Meta, Document, and Folder), but it also has a Client and Collection singleton objects, and operations like getting documents or listing directories are provided by these singletons.
  • rmcl abstracts away some details of the reMarkable cloud API, while rMapy provides a more direct mapping of the API into Python. For instance, rMapy items have a .VissibleName [sic] property, because that's what the API provides. rmcl turns this into a .name property. In rmcl, Folders have a list of children, but in rMapy, the children must be looked up via the Collection singleton. (The API provides a flat file list.)
  • rMapy is more complete than rmcl. rMapy exposes all metadata as properties, while rmcl only exposes some metadata items. rMapy provides an object model for the zip files provided by the API, while rmcl just exposes the zip files themselves.
  • rMapy has better documentation than rmcl. (But we're working on it!)

Trademarks

reMarkable(R) is a registered trademark of reMarkable AS. rmrl is not affiliated with, or endorsed by, reMarkable AS. The use of "reMarkable" in this work refers to the company’s e-paper tablet product(s).

Copyright 2019 Stijn Van Campenhout

Copyright 2020-2021 Robert Schroll

rmcl is released under the MIT license. See LICENSE.txt for details.

Metadata

Release files for rmcl 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for rmcl 0.3.0
File Size Uploaded
rmcl-0.3.0.tar.gz 18.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for rmcl 0.3.0
File Interpreter ABI Platform
rmcl-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 34.8 kB

Release files / rmcl-0.3.0.tar.gz

Download URL rmcl-0.3.0.tar.gz
Size 18.0 kB
Tags Source
SHA-256 checksum
How to use checksums
df5c38176309cb119c29bf9bca9d8f2f6427280241a882106b939db17ef48f3d
BLAKE2b-256 checksum
How to use checksums
2d54b0a3e1984320019e93c24e8a41719b6d68e88192162677faa52c178f566c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.1.4 CPython/3.7.3 Linux/5.4.51-v7+

Release files / rmcl-0.3.0-py3-none-any.whl

Download URL rmcl-0.3.0-py3-none-any.whl
Size 16.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cc9cfbfd904164bada7d6680695b54defd066c31a36935410a53c53351d0e6aa
BLAKE2b-256 checksum
How to use checksums
db255137327f075d933f58bc880c6eeafac020bc7ab85d2d11633a24b0648d66
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.1.4 CPython/3.7.3 Linux/5.4.51-v7+

Release history Release notifications | RSS feed

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.1

2 release files

This release

0.3.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page