Files
RMHook/README.md
2026-08-27 16:21:40 +02:00

8.7 KiB

RMHook

A dynamic library injection tool for the reMarkable Desktop macOS application, enabling connection to self-hosted rmfakecloud servers.

Overview

RMHook hooks into the reMarkable Desktop app's network layer to redirect API calls from reMarkable's official cloud services to your own rmfakecloud server. This allows you to maintain full control over your documents and data.

Other platforms

Features

  • Network request interception and redirection
  • WebSocket connection patching
  • MQTT URI modification for screen sharing features
  • mTLS support for external access via Cloudflare Tunnel

Compatibility

Tested and working on:

  • reMarkable Desktop v3.28.1 (released 2026-08-24)

Installation and usage

⚠️ For legal reasons, this repository does not include a pre-patched reMarkable app. However, the latest compiled dylib is available in the Releases section.

Auto installation

Run in a terminal:

bash <(curl -sL https://raw.githubusercontent.com/NohamR/RMHook/refs/heads/main/scripts/auto-install.sh)

Manual installation

Step 1: Prepare the reMarkable app

Uses the reMarkable Desktop app from your Applications folder or download it fresh from the Mac App Store.

Step 2: Inject the dylib

Use the provided injection script:

./scripts/inject.sh reMarkable.dylib reMarkable.app

This script will:

  • Copy the dylib to the app bundle's Resources folder
  • Inject the load command into the executable using optool
  • Remove the code signature and resign with ad-hoc signature
  • Remove the _MASReceipt folder
  • Fix file ownership

Step 3: Handle document storage

Important path changes

The original Mac App Store version stores data in sandboxed locations: Original sandboxed paths:

  • App data: ~/Library/Containers/com.remarkable.desktop/Data
  • Documents: ~/Library/Containers/com.remarkable.desktop/Data/Library/Application Support/remarkable

After re-signing, the app is no longer sandboxed and will use standard paths:

  • Config: ~/Library/Preferences/rmfakecloud.config
  • Documents: ~/Library/Application Support/remarkable
Migration options

Option 1: Create a symbolic link (recommended)

ln -s ~/Library/Containers/com.remarkable.desktop/Data/Library/Application\ Support/remarkable \
      ~/Library/Application\ Support/remarkable

The symbolic link approach allows you to keep using the original App Store version alongside the patched version.

Option 2: Move files

mv ~/Library/Containers/com.remarkable.desktop/Data/Library/Application\ Support/remarkable \
   ~/Library/Application\ Support/remarkable

Step 4: Configure rmfakecloud server

Quickly access the configuration file from the app's Help menu: help-config.png

Edit the configuration file at:

~/Library/Preferences/rmfakecloud.config

Example configuration:

{
  "host": "your-server.example.com",
  "port": 443
}

Step 5: Launch the patched app :p

Configuration

The config file (~/Library/Preferences/rmfakecloud.config) supports the following keys:

Key Type Default Description
host String example.com Your rmfakecloud server host
port Number 443 Your rmfakecloud server port
client_cert String (none) Path to client certificate file (PEM) for mTLS
client_key String (none) Path to client private key file (PEM) for mTLS
key_algorithm String rsa Key algorithm: rsa, ec, dsa, dh, or opaque
ca_cert String (none) Path to custom CA certificate file (PEM)
disable_ssl_verification Boolean false Disable SSL peer verification (not recommended)

If the config file doesn't exist, it will be created automatically with default values on first launch.

External Access (Cloudflare Tunnel with Client Certificate)

If your rmfakecloud instance is exposed via Cloudflare Tunnel with client certificate authentication, configure the additional TLS settings in ~/Library/Preferences/rmfakecloud.config:

{
  "host": "rmfakecloud.example.com",
  "port": 443,
  "client_cert": "/path/to/client.crt",
  "client_key": "/path/to/client.key"
}

If your server uses a self-signed certificate or a certificate signed by a private CA:

{
  "host": "rmfakecloud.example.com",
  "port": 443,
  "client_cert": "/path/to/client.crt",
  "client_key": "/path/to/client.key",
  "ca_cert": "/path/to/ca.crt"
}

See the rmfakecloud external access guide for generating the client certificate.

Building

  1. Clone the repository:
git clone http://github.com/NohamR/RMHook
cd RMHook

Create a Python environment and install aqtinstall:

python3 -m venv aqt_venv
source aqt_venv/bin/activate
pip install aqtinstall
aqt install-qt mac desktop 6.10.3 -m qtwebsockets --outputdir ~/Qt
  1. Compile the dylib:
./scripts/build.sh [mode]

Build modes

The build script supports different modes for various use cases:

Mode Description
rmfakecloud Redirect reMarkable cloud to rmfakecloud server (default)
qmlrebuild Qt resource data registration hooking for QML replacement
dev Development/reverse engineering mode with all hooks
all Enable all modes

Note (qmlrebuild mode): When using the qmlrebuild feature, you must clear the Qt QML cache before launching the app:

rm -rf ~/Library/Caches/remarkable

Qt caches compiled QML files, so changes to QML resources won't take effect until the cache is cleared.

Examples:

./scripts/build.sh              # Build with rmfakecloud mode (default)
./scripts/build.sh rmfakecloud  # Explicitly build rmfakecloud mode
./scripts/build.sh dev          # Build with dev/reverse engineering hooks
./scripts/build.sh all          # Build with all modes enabled

Debugging

You can stream the macOS console logs to see output from the hooks:

log stream --predicate 'process == "reMarkable"' --level debug

How it works

RMHook uses tinyhook to hook into Qt framework functions at runtime:

  1. QNetworkAccessManager::createRequest - Intercepts HTTP/HTTPS requests
  2. QWebSocket::open - Patches WebSocket connections
  3. MQTTAsync_createWithOptions - Modifies MQTT URIs for screen sharing features

When the app attempts to connect to reMarkable's servers (e.g., internal.cloud.remarkable.com), the hooks redirect these requests to your configured host and port.

Troubleshooting

App won't launch

  • Ensure the code signature was properly applied
  • Check that xattr -cr was run to clear quarantine attributes
  • Verify the dylib is in Contents/Resources/ folder

Document sync issues

  • Ensure your rmfakecloud server is running and accessible
  • Verify the storage path migration was completed

Credits

License

This project is licensed under the MIT License. See the LICENSE file for details.

Disclaimer

This project is not affiliated with, endorsed by, or sponsored by reMarkable AS. Use at your own risk. This tool modifies the reMarkable Desktop application and may violate the application's terms of service.

Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.