Automatic Remarkable2 backup on Mac

This script backs up the data and its config from your Remarkable2 tablet to the repository once it is connected via USB, commits it and pushes to origin.

Install

Create a git repository with origin and with this script:

#!/bin/bash

BACKUP_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
LOG_FILE="$BACKUP_DIR/backup.log"
REMARKABLE_IP="10.11.99.1"
REMARKABLE_USER="root"
REMARKABLE_DATA="/home/root/.local/share/remarkable/xochitl/"
REMARKABLE_CONFIG="/home/root/.config/remarkable/xochitl.conf"

log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
    echo "$1"
}

mkdir -p "$BACKUP_DIR/data"
mkdir -p "$(dirname "$LOG_FILE")"

if ! ping -c 1 -W 2 "$REMARKABLE_IP" >/dev/null 2>&1; then
    log "reMarkable not accessible at $REMARKABLE_IP - ensure USB web interface is enabled"
    exit 1
fi

log "Starting backup to $BACKUP_DIR"
cd "$BACKUP_DIR"

log "Backing up xochitl data..."
scp -r "$REMARKABLE_USER@$REMARKABLE_IP:$REMARKABLE_DATA"* "$BACKUP_DIR/data/" >> "$LOG_FILE" 2>&1

log "Backing up xochitl.conf..."
scp "$REMARKABLE_USER@$REMARKABLE_IP:$REMARKABLE_CONFIG" "$BACKUP_DIR/" >> "$LOG_FILE" 2>&1

CHANGES=$(git status --porcelain | wc -l)

if [ $CHANGES -gt 0 ]; then
    git add -A
    git commit --no-gpg-sign -m 'update changes'
    git push origin main

    log "Backup committed to git - $CHANGES files changed"
    log "Total backup size: $(du -h -d 0 "$BACKUP_DIR/data" | cut -f1)"
    log "Total files: $(find "$BACKUP_DIR/data" -type f | wc -l)"
else
    log "No changes detected since last backup"
fi

Commit everything. Then create launchd agent:

vim ~/Library/LaunchAgents/com.user.remarkable.connect.plist

With these contents:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.user.remarkable.connect</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Users/YOUR_USERNAME/remarkable/backup.sh</string>
    </array>
    <key>LaunchEvents</key>
    <dict>
        <key>com.apple.iokit.matching</key>
        <dict>
            <key>com.apple.device-attach</key>
            <dict>
                <key>idVendor</key>
                <integer>1203</integer>
                <key>idProduct</key>
                <integer>16400</integer>
                <key>IOProviderClass</key>
                <string>IOUSBDevice</string>
            </dict>
        </dict>
    </dict>
    <key>ThrottleInterval</key>
    <integer>7200</integer>
</dict>
</plist>

Modify the agent, at least change ProgramArguments to where the backup script repo is located, use absolute path. Modification via sed:

sed -i '' 's#/Users/YOUR_USERNAME/remarkable/backup.sh#/this/repo/backup.sh#' \
    ~/Library/LaunchAgents/com.user.remarkable.connect.plist

Or simply just do it manually:

- <string>/Users/YOUR_USERNAME/remarkable/backup.sh</string>
+ <string>/this/repo/backup.sh</string>

Note: You can also modify ThrottleInterval which is currently set to two hours (7200 seconds), so the backup does not happen too often when the device is connected and not sleeping. Default value is 10 seconds which is far too often for my taste.

Then re-load the agent:

launchctl unload ~/Library/LaunchAgents/com.user.remarkable.connect.plist
launchctl load ~/Library/LaunchAgents/com.user.remarkable.connect.plist

Make sure you have ssh access to RM2:

ssh [email protected]

Plug RM2 in a observe cat backup.log and git log.

Debug

If there are problems in the plist file, they can be pinpointed more precisely via:

plutil -lint ~/Library/LaunchAgents/com.user.remarkable.connect.plist

Fix and re-load the plist file agent again. If it still does not work, check the system log:

log show --predicate 'subsystem contains "remarkable"' --last 5m

Which could help you identify errors such as wrong script path:

2025-02-23 11:13:22.942298+0100 0x2b86f63  Default     0x0                  1      0    launchd: [gui/501/com.user.remarkable.connect [83113]:] Could not find and/or execute program specified by service: 2: No such file or directory: /this/path/does/not/exist/backup.sh
2025-02-23 11:13:22.942321+0100 0x2b86f63  Error       0x0                  1      0    launchd: [gui/501/com.user.remarkable.connect [83113]:] Service could not initialize: access(/this/path/does/not/exist/backup.sh, X_OK) failed with errno 2 - No such file or directory, error 0x6f - Invalid or missing Program/ProgramArguments

This should be helpful enough.

Finding idVendor and idProduct

To find your connected device's vendor and product IDs on macOS, you can use:

system_profiler SPUSBDataType

Results in something like this:

Product ID: 0x4010
Vendor ID: 0x04b3  (IBM Corporation)
Version: 5.04
Serial Number: 0
Speed: Up to 480 Mb/s
Manufacturer: reMarkable
Location ID: 0x01100000 / 1
Current Available (mA): 500
Current Required (mA): 2
Extra Operating Current (mA): 0

Then convert the hexadecimal values from your output to decimal:

  • Vendor ID: 0x04b3 (hex) = 1203 (decimal)
  • Product ID: 0x4010 (hex) = 16400 (decimal)

For vendor/product IDs in the plist file, macOS expects decimal values rather than hexadecimal. We took the hex values from your system_profiler output:

0x04b3 = (4 × 16²) + (11 × 16¹) + (3 × 16⁰) = 1203
0x4010 = (4 × 16³) + (0 × 16²) + (1 × 16¹) + (0 × 16⁰) = 16400

This leads to values in the agent com.user.remarkable.connect.plist':

<key>idVendor</key>
<integer>1203</integer>
<key>idProduct</key>
<integer>16400</integer>

Enjoy!