Skip to content

ItsMalware/rm2notion

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rm2notion

Sync your reMarkable 2 notes directly to Notion — no server, no cloud middleman.

rm2notion runs as a lightweight daemon directly on your reMarkable 2 tablet. Every 15 minutes it scans your whitelisted notebooks, OCRs any handwritten pages, and creates or updates tasks in a Notion database. One page = one Notion task.

Command Capture template portrait


Features

  • Runs on the tablet itself — pure Python, no external server required
  • Per-page sync — each page in a notebook becomes its own Notion task
  • Handwriting OCR via Google Cloud Vision (service account or API key)
  • Typed text support — reads reMarkable's built-in text conversion output
  • Custom page templates — Command Capture templates with TYPE, PRIORITY, and BIZ fields
  • Smart marker detection — circle or check a TYPE/PRI field and it maps to your Notion schema
  • AGENT routing — mark a page AGENT and it lands in your "Agent Inbox" queue automatically
  • Survives firmware updates — installed to /home partition, which is never wiped
  • systemd daemon — starts on boot, restarts on failure

Requirements

  • reMarkable 2 tablet (firmware 3.x tested)
  • SSH access enabled on the tablet (Settings → Help → Copyrights and licenses → Enable SSH at bottom)
  • A Notion account with an internal integration token
  • A Notion database configured with the expected schema (see below)
  • (Optional) Google Cloud Vision API access for handwriting OCR

Quick start

1. Enable SSH on your reMarkable

Go to Settings → Help → Copyrights and licenses, scroll to the bottom, and enable SSH. The password is shown on that screen.

2. Copy the project to your tablet

Connect via USB (or WiFi) and run from your computer:

scp -r rm2notion/ root@10.11.99.1:/tmp/

For WiFi, replace 10.11.99.1 with your tablet's IP (Settings → Help → Copyright and licenses shows it when SSH is enabled via WiFi).

3. SSH into the tablet and run setup

ssh root@10.11.99.1
bash /tmp/rm2notion/setup.sh

The setup script will:

  • Install Python 3 via Entware (stored in /home/opt_new so it survives firmware updates)
  • Copy rm2notion to /opt/rm2notion/
  • Install the systemd service
  • Register the Command Capture page templates
  • Create a starter config at ~/.config/rm2notion/config.json

4. Configure

Edit the config file on the tablet:

vi ~/.config/rm2notion/config.json

Fill in your Notion credentials:

{
  "notion_api_key": "ntn_YOUR_INTEGRATION_TOKEN_HERE",
  "notion_database_id": "YOUR_NOTION_DATABASE_ID",
  "sync_notebooks": ["Your Notebook Name"],
  "ocr_provider": "google_vision",
  "google_vision_service_account": "/home/root/.config/rm2notion/google_vision_sa.json"
}

5. Test the sync

python3 /opt/rm2notion/rm2notion.py sync

6. Enable the daemon

systemctl enable rm2notion
systemctl start rm2notion

Notion setup

Create an integration

  1. Go to https://www.notion.so/my-integrations
  2. Click New integration, name it (e.g. "rm2notion"), select your workspace
  3. Copy the Internal Integration Token — this is your notion_api_key

Set up the database

Create a Notion database (or use an existing one) and share it with your integration. The database must have these properties:

Property name Type Notes
Name Title Page title
Status Select Backlog, In Progress, Done, etc.
Priority Select Low, Medium, High, Urgent, etc.
Queue Select Founder To-Do, Agent Inbox, etc.
Task Type Select General, Dev, Meeting, etc.
Business Rich text Free-text business/project context
Source Select reMarkable (auto-set)
Synced Date Auto-set on sync
Content Rich text Extracted note text

To share your database with the integration: open the database in Notion → click ··· (top right) → Add connections → select your integration.

To find your database ID: open the database in Notion, look at the URL:

https://www.notion.so/yourworkspace/DATABASE_ID_HERE?v=...

Copy the 32-character ID (with hyphens it looks like xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).


Command Capture templates

The included templates give you structured pages for different capture types. Use them in the tablet's Templates menu when creating a new page.

Portrait layout:

TITLE  _______________________________________________

TYPE  □ DAILY  □ IDEA  □ MEETING  □ TASK  ■ AGENT

PRI   ○ LOW  ○ MED  ○ HIGH  ○ URGENT   BIZ ________

════════════════════════════════════════════════════
│ (lined writing area)
│

ACTION ITEMS  □ ____________  □ ____________

Landscape layout: Same fields arranged horizontally for more writing space.

How markers are detected

rm2notion scans OCR text from each page thumbnail for marker words:

  • TYPE: Circle or check DAILY, IDEA, MEETING, TASK → sets Notion "Task Type"
  • PRI: Circle LOW, MED, HIGH, URGENT → sets Notion "Priority"
  • AGENT: Check the AGENT box → routes the task to your "Agent Inbox" queue
  • BIZ: Any text written on the BIZ line → sets the "Business" field

OCR configuration

Google Cloud Vision (recommended)

Supports both a simple API key and a service account JSON (required if your project disables API key auth).

API key:

  1. Enable the Cloud Vision API
  2. Create an API key under APIs & Services → Credentials
  3. Set in config: "ocr_provider": "google_vision", "google_vision_api_key": "YOUR_KEY"

Service account (more secure):

  1. Create a service account in IAM & Admin → Service Accounts
  2. Grant it the Cloud Vision API User role
  3. Create and download a JSON key
  4. Copy the JSON to your tablet: scp your-sa-key.json root@10.11.99.1:/home/root/.config/rm2notion/google_vision_sa.json
  5. Set in config: "ocr_provider": "google_vision", "google_vision_service_account": "/home/root/.config/rm2notion/google_vision_sa.json"

The service account auth uses openssl (already on the tablet) to sign JWTs — no additional Python packages required.

reMarkable built-in text conversion

If you use the tablet's built-in Convert → Text feature on a page, rm2notion will read that output first (before falling back to Vision OCR). Note: the built-in conversion only sees your handwritten ink layer, not the template background, so checkboxes and template labels won't appear in the output.

No OCR

Set "ocr_provider": "none" to skip OCR entirely. Only typed text (Type Folio keyboard input) will be extracted.


Config reference

Full list of ~/.config/rm2notion/config.json options:

{
  "notion_api_key": "ntn_...",
  "notion_database_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",

  "sync_notebooks": ["Sync to notion"],
  "sync_mode": "per_page",
  "sync_interval_minutes": 15,

  "ocr_provider": "google_vision",
  "google_vision_api_key": "",
  "google_vision_service_account": "/home/root/.config/rm2notion/google_vision_sa.json",
  "myscript_app_key": "",
  "myscript_hmac_key": "",

  "default_status": "Backlog",
  "default_priority": "Normal",
  "default_queue_label": "Founder To-Do",
  "default_task_type": "General",

  "folder_task_type_map": {
    "dev": "Dev",
    "security": "Secure Coding",
    "marketing": "Marketing",
    "content": "Content",
    "finance": "Finance"
  },

  "sync_folders": [],
  "ignored_notebooks": [],
  "log_level": "INFO"
}
Key Description
notion_api_key Internal integration token from notion.so/my-integrations
notion_database_id ID of your target Notion database
sync_notebooks List of notebook names to sync (case-sensitive). Empty = all notebooks
sync_mode "per_page" (one task per page, recommended) or "per_notebook"
sync_interval_minutes How often the daemon syncs (default: 15)
ocr_provider "google_vision", "myscript", or "none"
google_vision_service_account Path to service account JSON (preferred over API key)
default_status Notion Status value for new tasks
default_priority Notion Priority value when no PRI marker is detected
default_queue_label Notion Queue value — use "Agent Inbox" for AGENT-marked pages
folder_task_type_map Map reMarkable folder name keywords → Notion Task Type values
ignored_notebooks Notebook names to always skip
log_level "DEBUG", "INFO", "WARNING", or "ERROR"

Commands

Run these on the tablet after SSHing in:

# One-time sync
python3 /opt/rm2notion/rm2notion.py sync

# Run as daemon (loops every sync_interval_minutes)
python3 /opt/rm2notion/rm2notion.py daemon

# List all notebooks on the device
python3 /opt/rm2notion/rm2notion.py list

# Show sync state (which pages have been synced)
python3 /opt/rm2notion/rm2notion.py status

# Show current config
python3 /opt/rm2notion/rm2notion.py config

# View live logs
journalctl -u rm2notion -f

# Restart the daemon after config changes
systemctl restart rm2notion

After a firmware update

reMarkable firmware updates wipe the root filesystem but leave /home untouched. rm2notion is installed to /home/opt_new/ (symlinked as /opt), so the Python environment and scripts survive. However, the symlink and systemd service need to be re-registered.

Run this once after any firmware update:

sh /home/root/reenable_rm2notion.sh

This script rebuilds the /opt symlink, reinstalls the systemd service, and re-registers the page templates. It lives in /home/root/ so it also survives updates.


Troubleshooting

"No notebooks found matching sync_notebooks" Check that the notebook name in config exactly matches the name shown on the tablet (case-sensitive). Run python3 /opt/rm2notion/rm2notion.py list to see exact names.

Handwriting not appearing in Notion

  • Check that OCR is configured: python3 /opt/rm2notion/rm2notion.py config
  • Check logs: journalctl -u rm2notion -n 50
  • Make sure the page thumbnail exists at ~/.local/share/remarkable/xochitl/{notebook_uuid}.thumbnails/{page_uuid}.png
  • Verify your Google Vision credentials have the Vision API enabled

SSH "REMOTE HOST IDENTIFICATION HAS CHANGED" This appears after a firmware update (the tablet generates a new host key). Fix it:

ssh-keygen -R 10.11.99.1
ssh-keygen -R 192.168.X.X   # your tablet's WiFi IP

Templates not appearing on tablet After deploying new templates, restart xochitl:

systemctl restart xochitl

Service not starting

systemctl status rm2notion
journalctl -u rm2notion -n 100

Project structure

rm2notion/
├── rm2notion.py              # Main sync script (runs on tablet)
├── setup.sh                  # Installer script (run on tablet via SSH)
├── reenable_rm2notion.sh     # Post-firmware-update restore script
├── templates/
│   ├── command_capture_portrait.png    # Template for portrait orientation
│   ├── command_capture_landscape.png   # Template for landscape orientation
│   ├── command_capture_portrait.svg    # Source SVG (editable)
│   └── command_capture_landscape.svg   # Source SVG (editable)
└── .gitignore

License

MIT — do whatever you want with it.


Contributing

Issues and PRs welcome. The main areas that could use improvement:

  • Support for reMarkable's .rm v6 stroke format for direct vector OCR (currently uses thumbnail PNG)
  • MyScript Nebo integration (API key auth already wired, needs testing)
  • Multi-database routing (different notebooks → different Notion databases)
  • reMarkable Cloud API as an alternative sync path (no SSH needed)

About

Sync reMarkable 2 notes to Notion — runs directly on the tablet, no server needed

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors