') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); GitHub - Jayy001/codexctl: Automated update managment for the ReMarkable tablet · GitHub
Skip to content

Repository files navigation

Codexctl

A utility program that helps to manage the remarkable device version utilizing ddvks update server

Caveat for downgrading from 3.11.2.5 or greater to a version less than 3.11.2.5

If your reMarkable device is at or above 3.11.2.5 and you want to downgrade to a version below 3.11.2.5, codexctl cannot do this currently. Please refer to #95 (comment) for manual instructions.

Paper Pro bootloader updates

When downgrading a Paper Pro device across the 3.20/3.22 firmware boundary, codexctl automatically handles bootloader updates. It will download the current version's firmware if needed and extract the necessary bootloader files (update-bootloader.sh and imx-boot) to ensure a safe downgrade.

Installation

You can find pre-compiled binaries on the releases page. This includes a build for the reMarkable itself, as well as well as builds for linux, macOS, and Windows. Alternatively, you can install directly from pypi with pip install codexctl. Codexctl currently only has support for a command line interfaces but a graphical interface is soon to come.

Finally, if you want to build it yourself, you can run make executable which requires python 3.11 or newer, python-venv and pip. Linux also requires libfuse-dev.

General useage

❯ codexctl --help
usage: Codexctl [-h] [--verbose] [--address ADDRESS] [--password PASSWORD]
{install,download,backup,cat,ls,extract,mount,upload,status,restore,list} ...
positional arguments:
{install,download,backup,cat,ls,extract,mount,upload,status,restore,list}
install Install the specified version (will download if not available on the device)
download Download the specified version firmware file
backup Download remote files to local directory
cat Cat the contents of a file inside a firmwareimage
ls List files inside a firmware image
extract Extract the specified version update file
mount Mount the specified version firmware filesystem
upload Upload folder/files to device (pdf only)
status Get the current version of the device and other information
restore Restores to previous version installed on device
list List all available versions
options:
-h, --help show this help message and exit
--verbose, -v Enable verbose logging
--address ADDRESS, -a ADDRESS
Specify the address of the device
--password PASSWORD, -p PASSWORD
Specify password or path to SSH key for remote access

Examples

  • Installing the latest for device (will automatically figure out the version)
codexctl install latest
  • Downloading rmpp version 3.15.4.2 to a folder named out and then installing it
codexctl download 3.15.4.2 --hardware rmpp -o out
codexctl install ./out/remarkable-ct-prototype-image-3.15.4.2-ferrari-public.swu
  • Downloading rmppm version 3.23.0.64 to a folder named out and then installing it
codexctl download 3.23.0.64 --hardware rmppm -o out
codexctl install ./out/remarkable-production-image-3.23.0.64-chiappa-public.swu
  • Backing up all documents to the cwd
codexctl backup 
  • Backing up modified/newer documents only, overwrites out-of-date files on disk
codexctl backup --incremental
  • Backing up only documents in a folder named "FM" to cwd, without overwriting any current files
codexctl backup -l root -r FM --no-recursion --no-overwrite
  • Getting the version of the device and then switching to previous version
codexctl status
codexctl restore
  • Download 3.8.0.1944 for rm2, then cat the /etc/version file from it
codexctl download 3.8.0.1944 --hardware rm2
codexctl cat 3.8.0.1944_reMarkable2-7eGpAv7sYB.signed /etc/version
  • Extract the filesystem image of an upgrade file as a file named extracted
codexctl extract remarkable-production-image-3.22.0.64-ferrari-public.swu -o extracted

About

Automated update managment for the ReMarkable tablet

Resources

Stars

186 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages