Librarian
June 22, 2026 · View on GitHub
A xovi extension that provides a programmatic interface to xochitl's document library without the need to restart xochitl.
Dependencies
- xovi - Extension framework
- xovi-message-broker - Required for shell and QML communication
librm_lines is statically linked into the binary to parse .rm (lines) files for getContentPages. It is bundled at build time and requires no separate installation.
Installation
- Ensure dependencies are installed
- Download the
.sofile for your architecture from the latest release and place it in/home/root/xovi/extensions.d/on your reMarkable tablet- reMarkable 1 & 2:
librarian-armv7.so - reMarkable Paper Pro and Paper Pro Move:
librarian-aarch64.so
- reMarkable 1 & 2:
- Restart xovi
Shell Usage
All commands use the xovi-message-broker pipe interface:
echo '>e<signal>:<params>' > /run/xovi-mb; cat /run/xovi-mb-out
Lookup
Resolve a document or folder name to its UUID. Returns all matches (newline-separated) if multiple entries share the same name.
echo '>elookupEntry:My Document' > /run/xovi-mb; cat /run/xovi-mb-out
echo '>elookupEntry:My Folder/My Document' > /run/xovi-mb; cat /run/xovi-mb-out
Import
Import a PDF, EPUB, or .rmdoc file from the local filesystem. For PDF and EPUB, the file extension is stripped from the display name (e.g., report.pdf becomes report). For .rmdoc files, the archive is extracted directly — the embedded UUID, metadata, and page data are preserved as-is. Returns the document's UUID.
# Import to root
echo '>eimportDocument:/path/to/file.pdf' > /run/xovi-mb; cat /run/xovi-mb-out
# Import into a folder (by name or UUID)
echo '>eimportDocument:/path/to/file.pdf,My Folder' > /run/xovi-mb; cat /run/xovi-mb-out
# Import an rmdoc archive
echo '>eimportDocument:/path/to/backup.rmdoc' > /run/xovi-mb; cat /run/xovi-mb-out
echo '>eimportDocument:/path/to/backup.rmdoc,My Folder' > /run/xovi-mb; cat /run/xovi-mb-out
Import Image
Import a PNG or JPEG image, converting it to a single-page PDF for display in xochitl. Returns the new document's UUID.
echo '>eimportImage:/path/to/screenshot.png' > /run/xovi-mb; cat /run/xovi-mb-out
echo '>eimportImage:/path/to/photo.jpg,My Folder' > /run/xovi-mb; cat /run/xovi-mb-out
Rename
echo '>erenameEntry:Old Name,New Name' > /run/xovi-mb; cat /run/xovi-mb-out
Move
# Move to a folder
echo '>emoveEntry:My Document,Destination Folder' > /run/xovi-mb; cat /run/xovi-mb-out
# Move to root (empty parent)
echo '>emoveEntry:My Document,' > /run/xovi-mb; cat /run/xovi-mb-out
Trash and Restore
echo '>etrashEntry:My Document' > /run/xovi-mb; cat /run/xovi-mb-out
echo '>erestoreEntry:My Document' > /run/xovi-mb; cat /run/xovi-mb-out
Delete (Permanent)
echo '>edeleteEntry:My Document' > /run/xovi-mb; cat /run/xovi-mb-out
Clone
# Clone into same location
echo '>ecloneEntry:My Document,' > /run/xovi-mb; cat /run/xovi-mb-out
# Clone into a different folder
echo '>ecloneEntry:My Document,Other Folder' > /run/xovi-mb; cat /run/xovi-mb-out
Create
# Create notebook
echo '>ecreateNotebook:New Notebook' > /run/xovi-mb; cat /run/xovi-mb-out
echo '>ecreateNotebook:New Notebook,My Folder' > /run/xovi-mb; cat /run/xovi-mb-out
# Create folder
echo '>ecreateFolder:New Folder' > /run/xovi-mb; cat /run/xovi-mb-out
echo '>ecreateFolder:Subfolder,Parent Folder' > /run/xovi-mb; cat /run/xovi-mb-out
# Ensure folder exists (creates if missing, returns UUID)
echo '>eensureFolder:My Folder' > /run/xovi-mb; cat /run/xovi-mb-out
echo '>eensureFolder:Projects/2026/March' > /run/xovi-mb; cat /run/xovi-mb-out
Metadata
# Pin/unpin
echo '>esetPinned:My Document,true' > /run/xovi-mb; cat /run/xovi-mb-out
# Set cover page to last visited
echo '>esetCover:My Document,-1' > /run/xovi-mb; cat /run/xovi-mb-out
# Set cover page to first page
echo '>esetCover:My Document,0' > /run/xovi-mb; cat /run/xovi-mb-out
# Set orientation
echo '>esetOrientation:My Document,landscape' > /run/xovi-mb; cat /run/xovi-mb-out
echo '>esetOrientation:My Document,portrait' > /run/xovi-mb; cat /run/xovi-mb-out
# Set tags
echo '>esetTags:My Document,tag1;tag2;tag3' > /run/xovi-mb; cat /run/xovi-mb-out
Rescan
Scan the xochitl data directory and load any documents not yet known to the running library. Returns the number of new entries loaded.
echo '>erescanLibrary:' > /run/xovi-mb; cat /run/xovi-mb-out
Content Pages
List the page UUIDs in a document that contain non-deleted content — strokes, typed text, images, or highlights. Blank pages, and pages whose strokes were fully erased, are excluded even though their .rm files still exist. Returns the matching page UUIDs (newline-separated) in page order, or an empty response if none.
echo '>egetContentPages:My Notebook' > /run/xovi-mb; cat /run/xovi-mb-out
echo '>egetContentPages:<doc-uuid>' > /run/xovi-mb; cat /run/xovi-mb-out
QML Usage
All signals are accessible from QML via the xovi-message-broker:
import net.asivery.XoviMessageBroker 2.0
XoviMessageBroker { id: librarian }
librarian.sendSimpleSignal("lookupEntry", "My Document")
librarian.sendSimpleSignal("importDocument", "/tmp/report.pdf,My Folder")
librarian.sendSimpleSignal("importDocument", "/tmp/backup.rmdoc")
librarian.sendSimpleSignal("importImage", "/tmp/screenshot.png,Screenshots")
librarian.sendSimpleSignal("renameEntry", "My Document,New Name")
librarian.sendSimpleSignal("moveEntry", "My Document,Destination Folder")
librarian.sendSimpleSignal("trashEntry", "My Document")
librarian.sendSimpleSignal("restoreEntry", "My Document")
librarian.sendSimpleSignal("deleteEntry", "My Document")
librarian.sendSimpleSignal("cloneEntry", "My Document,Other Folder")
librarian.sendSimpleSignal("createNotebook", "New Notebook,My Folder")
librarian.sendSimpleSignal("createFolder", "New Folder,Parent Folder")
librarian.sendSimpleSignal("ensureFolder", "Projects/2026/March")
librarian.sendSimpleSignal("rescanLibrary", "")
librarian.sendSimpleSignal("getContentPages", "My Notebook")
librarian.sendSimpleSignal("setPinned", "My Document,true")
librarian.sendSimpleSignal("setCover", "My Document,-1")
librarian.sendSimpleSignal("setOrientation", "My Document,landscape")
librarian.sendSimpleSignal("setTags", "My Document,tag1;tag2;tag3")
Available Signals
| Signal | Parameter | Returns |
|---|---|---|
lookupEntry | name or path | UUID(s), newline-separated |
importDocument | filepath or filepath,parent | UUID |
importImage | filepath or filepath,parent | UUID |
renameEntry | entry,newName | ok |
moveEntry | entry,parent | ok |
trashEntry | entry | ok |
restoreEntry | entry | ok |
deleteEntry | entry | ok |
cloneEntry | entry,parent | ok |
createNotebook | name or name,parent | ok |
createFolder | name or name,parent | ok |
ensureFolder | name or path | UUID |
rescanLibrary | (none) | count of new entries |
getContentPages | entry | page UUIDs with content, newline-separated |
setPinned | entry,true/false | ok |
setCover | entry,pageNumber | ok |
setOrientation | entry,portrait/landscape | ok |
setTags | entry,tag1;tag2;tag3 | ok |
Name Resolution
All commands accept document names, folder paths, or UUIDs:
| Form | Example | Behavior |
|---|---|---|
| UUID | 9155cd95-147f-4bb5-93f1-a1519dac1021 | Direct lookup |
| Name | My Document | Searches root first, then all folders. Errors if ambiguous. |
| Anchored name | /My Document | Searches root only, no fallback. |
| Path | My Folder/My Document | Walks the folder hierarchy from root |
restoreEntry searches specifically within trashed entries.
All commands return ERROR: <message> on failure (not found, ambiguous name, etc.).
Parameter Separator
Commands that take two arguments use , as the separator (e.g., entry,newName), splitting on the last comma. The first argument (entry name) can contain commas freely. Name and path resolution with / is best-effort convenience as reMarkables doesn't prevent / from being used in document or folder names. If a folder name contains , or a name contains /, use UUIDs instead:
# Get UUIDs first
echo '>elookupEntry:My Document' > /run/xovi-mb; cat /run/xovi-mb-out
echo '>elookupEntry:Destination Folder' > /run/xovi-mb; cat /run/xovi-mb-out
# Then use UUIDs directly
echo '>emoveEntry:<doc-uuid>,<folder-uuid>' > /run/xovi-mb; cat /run/xovi-mb-out
Building
This repository vendors librm_lines as a submodule. Clone with submodules, or initialize them in an existing clone:
git clone --recursive https://github.com/rmitchellscott/rm-librarian
# or, in an existing clone:
git submodule update --init
./build.sh
Builds for both architectures using Docker, compiling librm_lines as a static library and linking it into the extension:
librarian-aarch64.so- reMarkable Paper Prolibrarian-armv7.so- reMarkable 2
License
Copyright (C) 2026 Mitchell Scott
Licensed under the GNU General Public License v3.0.
This project statically links librm_lines by RedTTG, also licensed under the GNU General Public License v3.0.