npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

remarkable-cli

v0.3.1

Published

Command line over rmscene-ts and rmcommunication-ts for reMarkable tablets

Downloads

1,191

Readme

remarkable-cli

The rmcli command line over rmscene-ts and rmcommunication-ts for reMarkable tablets in developer mode. It is a thin mapping of those libraries: every capability lives in them, and rmcli only parses arguments, calls one library function, and prints the result.

Install

npm install -g remarkable-cli
rmcli --help

The package is named remarkable-cli on npm because the shorter name is taken; the command it installs is rmcli.

To work on it from a checkout instead:

npm install
npm run build
node dist/cli.js --help

Node 22 or newer, the floor rmindex-ts sets through better-sqlite3.

SKILL.md in this package is the agent-facing guide: what to run for a given request, and what not to do. Point an AI assistant at it rather than at this README.

Configure

export RMCLI_HOST=<tablet-wifi-address>
export RMCLI_PASSWORD='...'
rmcli device fingerprint      # prints the tablet's host key and trusts nothing
export RMCLI_FINGERPRINT=SHA256:...

device fingerprint is the only command that runs before a host key is pinned. Check what it prints against the tablet before exporting it; every other command then refuses to connect if the key changes.

The SSH password is never a command argument. Set RMCLI_PASSWORD for a one-off run, or leave it unset and set RMCLI_PASSWORD_COMMAND to a command whose stdout is the password, which is how a password manager or a secret store supplies it:

export RMCLI_PASSWORD_COMMAND='pass show remarkable/root'

The command runs through the platform shell, cmd.exe on Windows and /bin/sh elsewhere, and only its stdout is read.

Either way the value reaches the connection through a provider function and is never printed, not even inside an error.

RMCLI_TIMEOUT_MS sets the Web Interface request timeout, default 180000.

Commands that leave the tablet running

These go through a pinned WiFi SSH tunnel to the tablet's internal Web Interface. Xochitl keeps running and the user is not interrupted.

rmcli device status [--json]
rmcli device identity [--json]
rmcli device capabilities [--json]
rmcli device enable-wifi-ssh
rmcli documents current [--json]
rmcli documents list [--json]
rmcli documents get <documentId> [--json]
rmcli documents download <documentId> --backup-dir <dir> [--json]
rmcli documents upload <file.pdf|file.epub|image> --name <name> --backup-dir <dir> [--folder <folderId>] [--json]
rmcli pages list <documentId|current> --backup-dir <dir> | --archive <file.rmdoc> [--raw] [--json]
rmcli pages render <documentId|current> <page|current|pageId> --output <file.svg|file.png>
                   --backup-dir <dir> | --archive <file.rmdoc>
                   [--template <name>] [--background white|transparent] [--width <px>] [--json]
rmcli templates read <name> --output <file.json> [--json]

documents current reads LastOpen from the tablet's configuration and the open page from the document's own content file. Both are plain reads and neither stops the tablet UI. It reports documentId: null when the user is in the library list.

pageSource says where the page number came from: content is the live pointer the tablet rewrites on every page flip, metadata is the page of the last save, and only-page means the document has a single page and can be showing nothing else. A one-page notebook usually needs the second or third of those, because the firmware leaves its live pointer empty. When no source answers, pageId, pageNumber and pageIndex are null together and pageCount still reports the real count.

pages render downloads the document as a verified rmdoc backup and renders from that archive, which is the only page source that does not stop the tablet UI. Pass --archive instead of --backup-dir to reuse a download you already have. Pass --template to draw the ruled background; the template itself is read over SFTP, which does not interrupt anything either.

Page numbers

A document positional accepts current, meaning whatever the tablet has open. A page positional accepts current, a page ID, or the page number the tablet shows, counting from 1.

current is resolved by the command itself, on the connection it has already opened, so pages render current current is the whole "render the page I am looking at" flow in one run. Calling documents current first and passing its documentId on costs a second process and a second SSH handshake for an answer the command already has.

pages list and pages render report the document name, and pages list reports the page a current document token resolved to: pageId, pageNumber, pageIndex and pageSource, the fields documents current prints. The four are null together when the document was named outright, and when the tablet named no page. A caller that holds a snapshot of the open document therefore fills it from pages list current alone.

pages list prints both PAGE and INDEX. INDEX is the raw position inside the document file and a deleted page leaves a gap in it, so only PAGE is the number a person sees. pages render --json reports svg and png sizes separately, because SVG user units and raster pixels are unrelated numbers.

Commands that interrupt the tablet

These run inside a guarded offline session: the library stops Xochitl, works, and starts it again. Each one refuses to run until --service is added.

rmcli service documents list --service [--json]
rmcli service page read <documentId> <pageId> --output <file.rm> --service
rmcli service page write <documentId> <pageId> --input <file.rm> --expected-revision <rev> --backup-dir <dir> --service
rmcli service snapshot <documentId> --backup-dir <dir> --service
rmcli service mirror --mirror-dir <dir> --service

Output

--json writes stable JSON to stdout; without it the same data is printed as a table. Errors go to stderr and the exit code is 1. Binary output always goes to the file named by --output, never to stdout, so an image never lands in the context of the tool that invoked the command.

There is no delete

The tablet's Web Interface exposes exactly three endpoints, GET /documents/{folder}, POST /upload and GET /download/{id}/{format}. Deleting a document is a tablet-UI action.

One run at a time

Upload targets the container listed most recently, and that selection is global tablet state rather than per-connection. rmcli therefore takes a lock file per host for the whole invocation, so two runs on this machine cannot interleave a folder selection with someone else's upload. Runs from different machines are not covered; a single owning service is the real answer to that.

The four packages

| Package | What it does | | --- | --- | | rmscene-ts (npm) | Reads, writes and renders .rm version 6 scene files. No filesystem, no network, browser-safe. | | rmcommunication-ts (npm) | Talks to the tablet over pinned SSH: listings, verified rmdoc backups, page rendering, templates, PNG, PDF and EPUB import. | | rmindex-ts (npm) | Turns a local mirror into a catalog: SQLite index, FTS5 full-text search and a page-image cache. Reads the mirror only. | | remarkable-cli (npm) | The rmcli command line over these libraries. |

None of them implements the reMarkable Cloud protocol.

License and credits

MIT.

rmcli is a thin command line over rmcommunication-ts and rmscene-ts. The .rm scene format itself was worked out by rmscene, the Python library that rmscene-ts was rewritten from.