{"id":51671531,"url":"https://github.com/MaximeRivest/riddle","last_synced_at":"2026-08-03T05:00:54.884Z","repository":{"id":369535132,"uuid":"1290120400","full_name":"MaximeRivest/riddle","owner":"MaximeRivest","description":"The diary of Tom Riddle for the reMarkable Paper Pro — write with your pen, the page drinks your ink and answers in a flowing hand","archived":false,"fork":false,"pushed_at":"2026-07-12T23:53:42.000Z","size":7518,"stargazers_count":1750,"open_issues_count":18,"forks_count":160,"subscribers_count":7,"default_branch":"main","last_synced_at":"2026-07-29T15:34:02.554Z","etag":null,"topics":["appload","eink","quill","remagic-app","remarkable-customization","remarkable-paper-pro"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MaximeRivest.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null,"disclosure":null}},"created_at":"2026-07-05T15:48:08.000Z","updated_at":"2026-07-29T10:47:37.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/MaximeRivest/riddle","commit_stats":null,"previous_names":["maximerivest/riddle"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/MaximeRivest/riddle","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaximeRivest%2Friddle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaximeRivest%2Friddle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaximeRivest%2Friddle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaximeRivest%2Friddle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MaximeRivest","download_url":"https://codeload.github.com/MaximeRivest/riddle/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaximeRivest%2Friddle/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":36218648,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-08-03T02:00:06.975Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["appload","eink","quill","remagic-app","remarkable-customization","remarkable-paper-pro"],"created_at":"2026-07-15T01:00:33.687Z","updated_at":"2026-08-03T05:00:54.879Z","avatar_url":"https://github.com/MaximeRivest.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"# riddle — the diary of Tom Riddle, for the reMarkable Paper Pro\n\nWrite on the page with your pen. After a pause, the diary **drinks your ink** —\nyour words fade into the paper — the page thinks for a moment, and an answer\nwrites itself back in a flowing hand, stroke by stroke, then fades away.\n\nNo screen glow, no keyboard, no chat UI. Just ink appearing on paper.\n\n_This is the diary from [the demo](https://x.com/MaximeRivest)._\n\n### 🪄 New to this? Start here\n\nYou need a **reMarkable Paper Pro** in developer mode with a launcher installed.\nIf that sounds like a lot, it isn't — **[remagic](https://github.com/maximerivest/remagic)**\nwalks you through turning on developer mode and sets up everything with one\ncommand. Come back here, drop riddle in, and start writing to Tom.\n\nAlready have xovi + AppLoad? Install from the [remagic](https://github.com/maximerivest/remagic)\ncatalog, [grab the prebuilt bundle](#install-the-prebuilt-bundle), or\n[build from source](#building).\n\n### Install with remagic (easiest)\n\n```sh\nremagic install riddle     # checksum-verified download → AppLoad\nremagic config riddle      # settings form in your browser (+ QR for phone)\n```\n\nThen in **AppLoad**: tap **Reload**, then **The Diary**. Write, and rest your\npen. (Or install it from the **Store** app right on the tablet.)\n\n### Install the prebuilt bundle\n\n1. Grab `riddle-\u003cversion\u003e.zip` from the [latest release](https://github.com/MaximeRivest/riddle/releases/latest)\n   and unzip it into a folder: `unzip riddle-*.zip -d riddle`\n2. Copy the folder to your tablet:\n   `scp -O -r riddle root@10.11.99.1:/home/root/xovi/exthome/appload/`\n3. Add an API key: `cp oracle.env.example oracle.env` in that folder and put your `RIDDLE_OPENAI_KEY` in it (any OpenAI-compatible key). Or skip it to use [pi](#option-b--pi-the-power-path).\n4. In **AppLoad**: tap **Reload**, then **The Diary**. Write, and rest your pen.\n\n\u003e ⚠️ **This modifies your device.** The prebuilt bundle and the catalog build\n\u003e run in **takeover mode**: tapping The Diary stops the whole reMarkable UI\n\u003e and takes the screen. Leave with a **5-finger tap** — xochitl restarts\n\u003e automatically. It runs as root and drives the e-ink engine directly. It has\n\u003e only been tested on a **reMarkable Paper Pro** (ferrari, aarch64,\n\u003e OS 3.26–3.27). It may not work on other models or OS versions, and you use\n\u003e it entirely at your own risk. Not affiliated with reMarkable AS. Keep SSH\n\u003e access working before you install anything — if anything ever wedges:\n\u003e `ssh root@10.11.99.1 'systemctl start xochitl'`.\n\n## How it works\n\n```\n pen (raw evdev, full 4096-level pressure, hardware event rate)\n   │ strokes\n   ▼\n riddle ── idle 2.8s → commit page → PNG ──► oracle (resident LLM process,\n   │                                          streams reply sentence-by-sentence)\n   ▼ strokes (Dancing Script → skeletonized to single-pixel pen paths)\n display backend\n   ├── qtfb        — windowed, inside xochitl (build-from-source flavour)\n   └── quill       — full takeover: xochitl stopped, vendor e-ink engine\n                     driven directly for instant ink (lowest latency there\n                     is; what the prebuilt bundle runs)\n```\n\n- **This repository** — the app (Rust). Pen input, ink surface, handwriting\n  synthesis (rasterize → Zhang-Suen thinning → stroke tracing → animated\n  replay), the oracle process manager, and both display backends.\n- **[Quill](https://github.com/MaximeRivest/quill)** — the sibling takeover display host (C/C++). A\n  clean-room, MIT-licensed adapter over the vendor `libqsgepaper.so` waveform\n  engine, exposed as a small C ABI (`quill_init` / `quill_buffer` / `quill_swap`)\n  that riddle links against with `--features takeover`. Also carries a small\n  family of demos (`scribble`, a pen-to-glass latency test, plus map, image,\n  and GIF renderers).\n\n## Gestures\n\n| Do this | And |\n|---------|-----|\n| Write, then rest the pen | The diary drinks your ink and Tom replies |\n| Write *\"show me what I wrote about…\"* | The remembered page **rises through the paper**: the date, your own handwriting rewriting itself stroke by stroke, Tom's old reply — all in faded ink. Touch the pen anywhere and today's page returns |\n| Write *\"what do you remember?\"* | Tom answers with a handwritten list of remembered moments |\n| Flip the marker | Erase |\n| Draw a large **?** | Summon the built-in guide |\n| Tap five fingers at once | Leave the diary *(takeover mode)* |\n| Power button | The page turns to *\"The diary sleeps.\"*, then the tablet suspends; press again to wake exactly where you were *(takeover mode)* |\n\nIn the windowed (qtfb) flavour, xochitl keeps the touchscreen and the power\nbutton: close the diary from AppLoad instead.\n\n## The diary remembers\n\nEvery finished page is kept — your actual pen strokes, a transcription, and\nTom's reply — so the diary can do three things:\n\n- **Follow the conversation.** Recent pages ride along with each request, so\n  Tom remembers what you wrote yesterday (both backends, same behavior).\n- **Conjure the past.** Ask in ink — *\"show me the page about the garden\"*,\n  *\"find what I wrote on Tuesday\"* — and the diary rewrites that page in\n  front of you, in your own hand, dated, in faded ink. No buttons, no lists,\n  no chrome: the pen is the only interface.\n- **Answer from memory.** *\"What do you remember?\"* gets a handwritten index.\n\nMemories live only on the tablet, in plain files under\n`/home/root/riddle-data/memories` (delete the folder and the diary forgets;\nthe last ~400 pages are kept). `RIDDLE_MEMORY=off` in `oracle.env` turns all\nof it off — no storage, and nothing extra sent with requests. Set\n`RIDDLE_TZ_OFFSET` (hours from UTC) so memory dates read right.\n\n## The oracle (the \"spirit\" in the diary)\n\nThe diary's replies come from a vision LLM that reads your handwriting from the\ncommitted page (sent as an inline PNG). There are **two backends**, chosen at\nstartup — pick whichever you have:\n\n### Option A — any OpenAI-compatible API (easiest, zero setup)\n\nSet an API key and riddle talks straight to an OpenAI-compatible\n`/chat/completions` endpoint. Works with OpenAI, OpenRouter, Groq, a local\nserver — anything that speaks the format. No extra software on the tablet.\n\n```sh\nexport RIDDLE_OPENAI_KEY=\"sk-...\"                       # required\nexport RIDDLE_OPENAI_BASE=\"https://api.openai.com/v1\"   # optional (default)\nexport RIDDLE_OPENAI_MODEL=\"gpt-4o-mini\"                # optional; must see images\nexport RIDDLE_OPENAI_REASONING=\"low\"                    # thinking models only\nexport RIDDLE_OPENAI_MAX_TOKENS=\"2000\"                  # runaway guard\n```\n\nAny vision-capable model works. On the tablet these live in `oracle.env`\nnext to the binary (see `oracle.env.example`, or just run\n`remagic config riddle` — it has one-tap presets for OpenAI, OpenRouter,\nand Gemini). Example with OpenRouter:\n\n```sh\nexport RIDDLE_OPENAI_KEY=\"$OPENROUTER_API_KEY\"\nexport RIDDLE_OPENAI_BASE=\"https://openrouter.ai/api/v1\"\nexport RIDDLE_OPENAI_MODEL=\"openai/gpt-4o-mini\"\n```\n\nTwo gotchas with thinking models (Gemini 3.x, o-series): set\n`RIDDLE_OPENAI_REASONING=low` for faster first ink (some providers reject\nthe field on non-thinking models — leave it unset there), and keep\n`RIDDLE_OPENAI_MAX_TOKENS` roomy — hidden reasoning tokens count against it,\nand a tight cap starves the visible reply.\n\nVerify your setup before launching the diary:\n\n```sh\nriddle --oracle-test path/to/handwriting.png   # prints the streamed reply\n```\n\nMeasured ~0.9–1.1 s to first ink on-device. The HTTPS is built into riddle\n(pure-Rust, no extra libraries).\n\n### Option B — pi (the power path)\n\nIf you already run [`pi`](https://github.com/badlogic/pi-mono), riddle will use\na resident `pi --mode rpc` process kept warm (Node + your subscription auth\nloaded once), so each turn pays only model latency. Used automatically when\n`RIDDLE_OPENAI_KEY` is **not** set. Defaults (override in `oracle.env`):\npi at `/home/root/node/bin` (`RIDDLE_PI_BIN_DIR`), provider `openai-codex`\n(`RIDDLE_PI_PROVIDER`), model `gpt-5.4-mini` (`RIDDLE_PI_MODEL`).\n\nBoth stream the reply sentence-by-sentence, so the quill starts writing seconds\nbefore the model finishes. The persona prompt lives in `src/oracle.rs`.\n\nA note on Tom's memory: with the HTTP backend every page is a fresh\nconversation — Tom does not remember your previous page. With pi, the warm\nsession remembers everything since the diary was opened (and pi persists\nthat session in its own data dir on the tablet).\n\nIf the oracle can't answer — missing key, refused key, no Wi-Fi — Tom writes\nthe reason on the page instead of a reply, and the full error goes to the\njournal (`journalctl -u riddle-takeover`).\n\n## Building\n\nCross-compiled from x86_64. Two flavours:\n\n### Windowed (AppLoad/qtfb) — build from source\n\nThe bundles above are the takeover flavour; the windowed flavour must be\nbuilt. Requires [xovi + AppLoad](https://github.com/asivery/rm-appload) on\nthe device.\n\n```sh\ngit clone https://github.com/MaximeRivest/riddle\ncd riddle\ncargo build --release --target aarch64-unknown-linux-gnu\n```\n\nInstall the binary to `/home/root/xovi/exthome/appload/riddle/` with an\n`external.manifest.json` that sets `\"qtfb\": true` and points `\"application\"`\nat the binary itself (the manifest in this repo is the takeover one — AppLoad\nonly hands riddle a window, via `QTFB_KEY`, when `qtfb` is true).\n\n### Takeover (instant ink) — the one from the demo\n\nRequires the reMarkable SDK toolchain (`~/rm-sdk-3.26`) because the linked\nvendor Qt libs need its glibc, **and** `libqsgepaper.so` pulled from *your own\ndevice* (it is proprietary and not distributed here):\n\n```sh\n# Keep the quill and riddle repositories beside each other.\ncd quill \u0026\u0026 ./build.sh              # pulls libqsgepaper.so from the device over\n                                    # ssh, builds libquill.so + the demos\ncd ../riddle \u0026\u0026 ./build-takeover.sh\n./scripts/make-bundle.sh            # stages the AppLoad bundle in dist/riddle/\n```\n\nThe staged `dist/riddle/` is self-contained (binary, `libquill.so`, launch\nscripts, manifest) — copy it to\n`/home/root/xovi/exthome/appload/riddle/`, or publish it to the catalog with\n`remagic publish dist/riddle`. Launching via AppLoad (`appload-launch.sh`)\ndetaches into a transient systemd unit, stops xochitl, runs the diary, and\n**always restores xochitl on exit** — leave with a 5-finger tap or SIGTERM\n(`systemctl stop riddle-takeover`); the power button sleeps and wakes the\ndiary without leaving it. The unit's stop hook restarts xochitl even if\nriddle dies uncleanly. If anything wedges:\n`ssh root@10.11.99.1 'systemctl start xochitl'`.\n\n## What leaves the device\n\n- Each committed page is rasterized to a small grayscale PNG and sent to the\n  oracle **you** configured — nothing else ever leaves the tablet, and there\n  is no telemetry.\n- The PNG (`/tmp/riddle-page.png`) is deleted as soon as the oracle has read\n  it; set `RIDDLE_KEEP_PAGE=1` to keep the last page around for debugging.\n- riddle never writes replies to disk. The pi backend, however, keeps its own\n  session history in its data dir — the HTTP backend keeps nothing.\n- Tom stays in character by design: the persona prompt (see\n  `src/oracle.rs`) tells the model it is the diary and nothing else.\n\n## Fonts\n\nThe reply hand is [Dancing Script](https://github.com/googlefonts/DancingScript)\n(SIL OFL 1.1 — see `fonts/OFL.txt`).\n\n## License\n\nMIT for everything in this repository (see `LICENSE`). The vendor libraries it\ninterposes (`libqsgepaper.so`, Qt) are **not** included and must come from\nyour own device/SDK.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMaximeRivest%2Friddle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FMaximeRivest%2Friddle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMaximeRivest%2Friddle/lists"}