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!