{"id":13771752,"url":"https://github.com/cherti/remarkable-cli-tooling","last_synced_at":"2026-01-12T13:28:15.280Z","repository":{"id":78373710,"uuid":"408981550","full_name":"cherti/remarkable-cli-tooling","owner":"cherti","description":"Tooling for the reMarkable paper tablet.","archived":false,"fork":false,"pushed_at":"2024-02-19T05:45:17.000Z","size":109,"stargazers_count":81,"open_issues_count":1,"forks_count":7,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-05-11T04:31:59.658Z","etag":null,"topics":["remarkable-tablet"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cherti.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-21T21:39:53.000Z","updated_at":"2025-05-10T17:44:25.000Z","dependencies_parsed_at":"2024-02-23T02:45:43.478Z","dependency_job_id":null,"html_url":"https://github.com/cherti/remarkable-cli-tooling","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/cherti/remarkable-cli-tooling","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cherti%2Fremarkable-cli-tooling","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cherti%2Fremarkable-cli-tooling/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cherti%2Fremarkable-cli-tooling/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cherti%2Fremarkable-cli-tooling/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cherti","download_url":"https://codeload.github.com/cherti/remarkable-cli-tooling/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cherti%2Fremarkable-cli-tooling/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28339079,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T12:22:26.515Z","status":"ssl_error","status_checked_at":"2026-01-12T12:22:10.856Z","response_time":98,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["remarkable-tablet"],"created_at":"2024-08-03T17:00:55.114Z","updated_at":"2026-01-12T13:28:15.247Z","avatar_url":"https://github.com/cherti.png","language":"Python","funding_links":[],"categories":["Other"],"sub_categories":["Template Builders"],"readme":"# remarkable CLI tooling\n\nThis repository provides a couple of tools that provide easy direct interaction with a [reMarkable paper tablet](https://remarkable.com) via the shell.\nIt doesn't require internet, the cloud or a remarkable account, it just works over ssh via a USB-cable connection (or local Wifi, if configured and enabled, although [additional steps may be necessary](https://www.reddit.com/r/RemarkableTablet/comments/edozpq/howto_access_the_web_interface_via_ssh/)).\n\n*This software is not endorsed by reMarkable AS nor are any guarantees provided regarding suitability and correct functionality, use at your own risk.*\n\nAll scripts are currently tested with software versions:\n\n  * 2.9.1.217\n  * 2.10.3.379\n  * 2.11.0.442\n  * 2.12.1.527\n  * 2.12.2.573\n  * 2.12.3.606\n  * 2.14.3.1005\n\nand should work under any unixoid operating system, such as Linux, BSD or MacOS/OSX. If you want to use these scripts under Windows, you likely need to resort to the Windows Subsystem for Linux to do so.\nWhere reMarkable-specific internals have changed, supported version numbers are tagged to specific commits, to make sure to mark version-specific verified software versions.\nThe latest version of this repository is typically tailored to the latest version of the reMarkable software.\n\n## Summary\n\n  * `resync.py`: push documents to or pull documents from the reMarkable, or to pull everything for backup purposes\n  * `reclean.py`: cleanup deleted documents on the reMarkable (necessary if the cloud is not used)\n  * `resign.py`: temporarily transfer documents to the reMarkable to put a signature, and pull them again once it's done\n\n## resync.py\n\n`resync.py` provides easy direct transfer of documents and folders of documents to a reMarkable and pull documents from it again.\nIt includes the possibility to synchronize entire filesystem trees between devices (with the limitation of, if desired, skipping or replacing either all files or none).\nBy default, files will, however, simply be added to the document tree, even if they exist.\n\n### Usage\n\nBasic usage:\nTo push documents to the remarkable, use one of\n\n    resync.py push document1.pdf another_document.epub folder_with_documents ...\n    resync.py + document1.pdf another_document.epub folder_with_documents ...\n\nTo retrieve documents from the remarkable, use one of\n\n    resync.py pull document1.pdf some_folder/another_document folder_with_documents ...\n    resync.py - document1.pdf some_folder/another_document folder_with_documents ...\n\nTo pull all documents (exclude patterns still apply), use\n\n    resync.py backup\n\nTo pull documents or folders, the full path from the top level has to be provided; entire folders can also be pulled.\n\n`resync.py` also provides a number of flags to select the destination folder, to skip already existing files or to overwrite them.\nIf in doubt, especially when pushing, use `--dry-run` to see what's going to happen beforehand.\n\nFiles are identified by their visible name and their parent folder, if this is not unambiguously possible, resync.py will error out.\nBy default all files will be copied anew to the remarkable, if you copy a file that is already there, you'll have it twice. See for example `-s` below for alternative behaviors.\nFolders are never recreated, they are only created if they don't already exist.\n\nFor the full set of options, refer to `resync.py --help`:\n\n\tusage: resync.py [-h] [--dry-run] [-o \u003cfolder\u003e] [-s | --overwrite | --overwrite_doc_only] [-e EXCLUDE_PATTERNS [EXCLUDE_PATTERNS ...]] [-r \u003cIP or hostname\u003e]\n\t\t\t\t\t [--transfer-dir \u003cdirectory name\u003e] [--debug]\n\t\t\t\t\t mode [documents ...]\n\n\tPush and pull files to and from your reMarkable\n\n\tpositional arguments:\n\t  mode                  push/+, pull/- or backup\n\t  documents             Documents and folders to be pushed to the reMarkable\n\n\toptional arguments:\n\t  -h, --help            show this help message and exit\n\t  --dry-run             Don't actually copy files, just show what would be copied (currently push only)\n\t  -o \u003cfolder\u003e, --output \u003cfolder\u003e\n\t\t\t\t\t\t\tDestination for copied files, either on or off device\n\t  -v                    verbosity level\n\t  --if-exists {skip,new,replace,replace-pdf-only}\n                        if the destination file already exists: *skip* pushing document (default); create a\n                        separate *new* separate document under the same name; *replace* document; *replace-\n                        pdf-only*: replace underlying pdf only on reMarkable, keep notes etc.\n\t  -e EXCLUDE_PATTERNS [EXCLUDE_PATTERNS ...], --exclude EXCLUDE_PATTERNS [EXCLUDE_PATTERNS ...]\n\t\t\t\t\t\t\texclude a pattern from transfer (must be Python-regex)\n\t  -r \u003cIP or hostname\u003e, --remote-address \u003cIP or hostname\u003e\n\t\t\t\t\t\t\tremote address of the reMarkable\n\t  --transfer-dir \u003cdirectory name\u003e\n\t\t\t\t\t\t\tcustom directory to render files to-be-upload\n\t  --debug               Render documents, but don't copy to remarkable.\n\nIf you want to test this script without the risk of messing up your documents, you can make a backup of the folder `~/.local/share/remarkable/xochitl` on the remarkable to restore if anything goes wrong.\n\n\n### Prequisites\n\n  * Python 3.6+\n  * Functioning [ssh-access](https://remarkablewiki.com/tech/ssh#passwordless_login_with_ssh_keys) to the device (practically speaking passwordless via SSH keys)\n  * for pull: the web-interface must be enabled (Settings \u003e Storage \u003e USB web interface)\n  * optional: Python's `termcolor`-module to add color to the dry-run output\n\n## reclean.py (deprecated)\n\n~`reclean.py` will clean up deleted files on your remarkable, i.e. files that are gone from trash by emptying it. Due to the reMarkable typically needing to sync this action with the reMarkable cloud, these files only actually get deleted after their deletion has been synced to the cloud. If no reMarkable account is configured, this is never, hence they indefinitely stay on the device. `reclean.py` takes that place, cleaning up those leftovers to free the space on the remarkable again.~\n\nThe above is no longer accurate, in software versions of at least 3.9.4.2018 (that's the one I could verify this for, it might have been introduced in earlier versions even) reMarkable will delete all of the data and only leave a `*.tombstone` file of negligible size (4K), which only contains a timestamp of deletion (which is probably used for reporting to the remarkable cloud on next sync).\nGiven that this size is negligible in size, `reclean.py` is deprecated for all use cases except the one below (which should however never happen in the first place unless something is buggy or things were manually fiddled with).\n\n`reclean.py` can still search for orphaned documents, i.e. documents that are missing their metadata and are, as a consequence never picked up by the reMarkable UI (and they don't have a deleted flag either, as this would be noted in said metadata). Those files are cleaned up as well, if the user desires.\n\nThis includes tombstones, as they are also files without associated metadata.\nThat being said, ssh-ing into the device and running `rm ~/.local/share/remarkable/xochitl/*.tombstone` executes unconditionally faster than `reclean.py`.\n\n### Usage\n\nBasic usage:\n\n    reclean.py\n\nFor the full set of options, refer to `reclean.py --help`:\n\n\tusage: reclean.py [-h] [-r \u003cIP or hostname\u003e] [--dry-run]\n\t\n\tClean deleted files from your reMarkable\n\t\n\toptional arguments:\n\t  -h, --help            show this help message and exit\n\t  -r \u003cIP or hostname\u003e, --remote-address \u003cIP or hostname\u003e\n\t                        remote address of the reMarkable\n\t  --dry-run             Don't actually clean files, just show what would be done\n\n### Prequisites\n  * Python 3.6+\n  * Functioning [ssh-access](https://remarkablewiki.com/tech/ssh#passwordless_login_with_ssh_keys) to the device (practically speaking passwordless via SSH keys)\n\nNothing needs to be installed on the remarkable.\n\n\n## resign.py\n\n`resign.py` will transfer documents onto the reMarkable, so you can sign them, and then pulls them again with the signature on it and deletes the document from the reMarkable again.\nIt requires `resync.py` to be available, so if you name `resync.py` or put it into a location that is not in `PATH`, you need to adjust the variable at the very top in `resign.py`.\n\n### Usage\n\nBasic usage:\n\n    resign.py document1.pdf [document2.pdf ...]\n\nFor the full set of options, refer to `resign.py --help`:\n\n\tusage: resign.py [-h] [-r \u003cIP or hostname\u003e] [documents ...]\n\t\n\tRelay documents over your reMarkable for signing\n\t\n\tpositional arguments:\n\t  documents             Documents and folders to be signed\n\t\n\toptional arguments:\n\t  -h, --help            show this help message and exit\n\t  -r \u003cIP or hostname\u003e, --remote-address \u003cIP or hostname\u003e\n                        remote address of the reMarkable\n\n### Prequisites\n  * Python 3.6+\n  * Functioning [ssh-access](https://remarkablewiki.com/tech/ssh#passwordless_login_with_ssh_keys) to the device (practically speaking passwordless via SSH keys)\n\nNothing needs to be installed on the remarkable.\n\n## Limitations\n\nAt this time, this set of tools imposes two limitations on file names in your reMarkable:\n\n  * No `/` in file names, as this is the filesystem separator, messing with the proper mapping of directory trees within your remarkable onto your filesystem\n  * No `'` in file names, as it messes with the remote ssh command construction.\n\n`resync` will check for these and ignore paths that contain such characters.\n\n## Credits\n\nThese scripts are inspired by [reHackable/scripts](https://github.com/reHackable/scripts).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcherti%2Fremarkable-cli-tooling","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcherti%2Fremarkable-cli-tooling","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcherti%2Fremarkable-cli-tooling/lists"}