The first complete writeup

Full control of the Freewrite Traveler

The Freewrite Traveler is a lovely e-ink typewriter; I bought mine to write offline, with no browser to tempt me. One odd thing: everything you type on it gets mirrored to the Postbox cloud — the maker's servers. You can't add your own fonts or change the layout. Yet inside, if you open it up, it's an ordinary Linux — Debian 10 on an i.MX6. Just locked from the outside. So we climbed in: got persistent root over SSH, took the app apart, rewrote it to suit ourselves. Here's exactly how. Honestly and in full — both what worked and what didn't.

SoC
NXP i.MX6SLL
RAM
512 MiB
Kernel
Linux 4.14.98
Userland
Debian 10
App
Electron 2.0.7
DB
PostgreSQL 11
Bootloader
U-Boot 2018.03
Access
root · SSH · rw

01 — Context

What this is and why

Straight up: I'm not a programmer. At all — I work in communications and had never touched code before this. Everything described here we did together with Claude (Anthropic's language model): I explained what I wanted and what I saw on the Traveler's screen, it wrote the commands and code, I ran them on my end and reported back. So the «we» from here on is the honest word for it: I explained and tested, Claude wrote and prompted. The two of us climbed in together.

The Traveler is sold as a "distraction-free typewriter": e-ink screen, mechanical keyboard, no browser. But the idea comes with a lock. Everything you write is mirrored to the Postbox cloud (Astrohaus servers). Locally the drafts do stay, by the way — but inside a database you can't just copy out as files. You can't add your own fonts. The layout is whatever they gave you. And the day that cloud shuts down, the machine turns into a brick that "searches for a connection." (That exact line, in fact, once greeted me mid-trip — a slightly sad sight.)

I wanted to give the device back what should already belong to its owner: full access to its own Linux. Real root — the kind that survives reboots and writes straight to the root filesystem, not an SDK sandbox and not a "developer mode".

★

About that word, "first" — honestly, no fanfare. We're not the first to look inside. Back in October 2022 a user named machinaut posted a full serial boot log of the Traveler on Pastebin — so people were on the UART console years before us, and it's the very same hardware: i.MX6, Debian 10. In January 2024 Dr Francintosh (blog) opened the machine — but only to fix the keyboard, signing off that he'd "likely try to figure out how to reprogram" it. No root, no code of his own. There may well be a writeup of the root itself, close to ours, somewhere; if a precise link turns up, I'll add it here with respect. But a complete, reproducible account — how to reach persistent root and rebuild the firmware to suit yourself — I never found, however hard I looked. So "first" here is a modest word: it's about the whole recipe, not about us being uniquely clever.

⚠

This voids the warranty and can brick the device. Everything below is about your hardware, at your own risk. We don't flash the bootloader or kernel (see "Anti-brick"), so the risk is manageable — but real. Don't do this to a machine you're not ready to lose.

02 — Hardware & software

Inside the device

Under the pleasant shell sits a perfectly ordinary embedded Linux computer. That is the whole key: once you're inside, it's just Debian from there.

  • SoC: NXP i.MX6SLL rev 1.1 (ARMv7, USB-OTG node 0x02184000), 512 MiB RAM.
  • Bootloader: U-Boot 2018.03 (built Sep 2020). Device-tree model: "Astrohaus Freewrite Traveler."
  • Kernel: Linux 4.14.98 (Buildroot 2019.08).
  • Userland: Debian 10 with systemd, OpenSSH 7.9.
  • Application: "finchley" — Electron 2.0.7 (Node.js + React/Draft.js), running as the unprivileged user finchley.
  • Database: PostgreSQL 11, cluster ast_v1, database freewrite — this is where drafts, folders, the user and sessions live.
  • Screen: e-ink via the mxc_epdc_fb controller, framebuffer /dev/fb0 1024×1536, physically split by a bezel into a large writing canvas (≈600 px in CSS units) and a narrow status strip (≈156 px).
  • Wi-Fi: the eagle_sdio chip, compiled into the kernel (not a module), 2.4 GHz only, staged "eagle" firmware.
  • OTA updates: Mender (A/B partitions). There is no public DFU/USB mode on the Traveler — firmware arrives over Wi-Fi only.

Disk partitions

Partition Mount FS Note
mmcblk1p4/ext4 rwroot, 2 GB — edits persist
mmcblk1p5/dataext4data, 1 GB (sync/journal)
boot1/memristorroboot hooks
mmc0 p0—FATtestjig, first files

03 — Why it's hard

The locks on the door

Astrohaus closed the obvious doors. Understanding these locks saves hours — you immediately know what will not work.

  1. Zero boot delay. bootdelay=0 — "Hit any key: 0." The window to interrupt U-Boot is nearly nonexistent; the key must already be held at power-on.
  2. Secure Boot (HAB) is closed. HAB Config 0xcc / State 0x99. You cannot load your own U-Boot or kernel over serial-download (SDP) — the signature check will reject it.
  3. No login on UART. The serial console prints boot logs, but no getty/login is running there — it won't just hand you a shell.
  4. No public recovery. The key combo for the Traveler's fastboot/recovery is undocumented — we later worked it out ourselves (E + X + L, see below); the factory reset wipes data.
✓

The loophole that unlocks everything: HAB most likely covers only the bootloader and kernel, not the root filesystem. That means the kernel will boot with whatever arguments we hand it at runtime — including init=/bin/sh. Nothing needs flashing — for a single boot we just swap init and write our own key into the rootfs.

04 — Disassembly

Opening the case

The teardown is simple and non-destructive.

  1. Peel off the rubber feet.Six screws hide underneath, on the base.
  2. Remove the six screws.Standard Phillips; keep them apart.
  3. Disconnect the USB-C ribbon.The two halves then separate freely.

The board (barcode 202102251688 ≈ 2021-02-25, marking 7221A) is black, littered with labelled test points TP1–TP113+. The blue FFC connector J3 is the screen and keyboard, not UART.

Where UART lives

The prime candidate is a row of six through-hole pads in a line near the barcode (with resistors R58/R60/R62, R82, R111–114 nearby). There are no TX/RX/GND labels — you work out the pinout yourself. In practice it turned out to be:

  • GND — the rightmost pad (the square pad = "pin 1").
  • Board TX — second from the left.
  • Board RX — adjacent to TX.

How to find it if your revision differs: GND — continuity-test each pad against bare metal (the USB-C shell or a screw). TX — listen with your adapter at 115200, tie the grounds together, and rotate the adapter's RX across the pads while powering the device on: wherever the boot log appears is TX. RX — the neighbour.

What you'll need

  • a small Phillips screwdriver and a thin plastic spudger
  • a 3.3 V USB-UART adapter (we used an FT232RL; the level jumper on 3.3 V, not 5 V, or you can damage the SoC)
  • a multimeter in continuity mode — to find GND
  • a soldering iron optional: the pads are through-hole, you can also just press pins in

A map of the board

The revision we opened: barcode 202102251688 (≈ 25 Feb 2021), marking 7221A. The board is black and literally littered with labelled test points TP1–TP113+. Don't be fooled: the blue FFC connector J3 is the screen-and-keyboard ribbon, nothing to do with UART. The row of six through-hole pads you want stands on its own line by the barcode, ringed by resistors R58/R60/R62, R82, R111–R114. It has no silkscreen labels — re-check the pinout from the UART section against your own board with a multimeter: revisions can differ.

⚠

Don't look for a reflash path here. With the board in front of you it's tempting to load your own image over SDP. It won't work: Secure Boot is closed (see "What didn't work"). The one working gate is UART → U-Boot — that's where we head.

05 — Serial console

The UART console

You need a 3.3 V USB-UART adapter (we used an FT232RL with the jumper set to 3.3 V). Speed 115200 8N1. Wire GND↔GND, board-TX→adapter-RX, board-RX→adapter-TX.

A logger on the Mac that survives the whole process:

macOS · screen
# log everything to a file so the boot log can be grepped
screen -L -d -m /dev/cu.usbserial-XXXXXXXX 115200
# watch: tail -f screenlog.0  (binary junk at the start, use grep -a)
⚠

Reliable boot capture. A cold start yields the full U-Boot log and Reset cause: POR: first power off (new+Power ≈3 s), then power on (Power). A "15 s Power hold" doesn't always give POR.

From the log you'll see what we saw: U-Boot 2018.03, i.MX6SLL, 512 MiB, model "Astrohaus Freewrite Traveler," then the kernel and systemd, the PostgreSQL cluster ast_v1, a Vector service, the "Smart Typewriter frontend." U-Boot also prints the scan code of any key held at power-on — "Detected N keys for recovery: Key XX."

What the boot log tells you

The first full boot log already tells you most of what you need to know about the system. Here are the lines worth capturing it for, and what each one means:

Line in the logWhat it means
U-Boot 2018.03 (Sep 2020)the bootloader; also where bootdelay=0 lives
i.MX6SLL rev1.1 · 512 MiBthe SoC and RAM
Model: Astrohaus Freewrite Travelerthe device-tree name
HAB Config 0xcc / State 0x99Secure Boot closed — no custom image
env ... bad CRCthe MMC environment is corrupt → the default is used
Reset cause: PORa cold boot was captured (what you want)
Detected N keys for recovery: Key XXthe scan code of a key held at power-on
Linux 4.14.98 (Buildroot 2019.08)the kernel
PostgreSQL cluster ast_v1where your text lives
Vector · Smart Typewriter frontendthe app's system services

Note env ... bad CRC: the on-disk U-Boot environment is corrupt, so the loader falls back to its compiled-in default — another reason you can't rely on saveenv, and why the init= override is done "live" only.

06 — The core of it

Getting root

The idea — "Path B": flash nothing; for a single boot, make the kernel launch a plain shell instead of the system (init=/bin/sh), get it as root, remount the root read-write, and plant a permanent way in. HAB permits this: it doesn't validate kernel arguments, and the rootfs is unsigned.

First: how to interrupt the bootloader at all

The crux is bootdelay=0. U-Boot doesn't wait: the "Hit any key to stop autoboot: 0" line flies past in microseconds, faster than a human can press. The trick is to not "press at the right moment," but to have a keystroke already sitting in the UART receive buffer when U-Boot reaches that check. In practice: start holding a key (or streaming characters) in your terminal a heartbeat before you apply power. One of them lands in the micro-window — autoboot stops and the => prompt appears. The trick isn't reaction speed but a buffer that's already loaded.

The exact moment of access

Now the most important — and simplest — part, the one that usually gets lost in explanations. We don't exploit anything and don't crack a password. We tell the bootloader one thing: "run this program instead of the system" — and hand it init=/bin/sh. The kernel boots as usual, but its first and only process (PID 1) is not systemd (which would have brought up the password login) but a bare /bin/sh. And PID 1 runs as root (uid 0) by definition, and a bare shell has no password prompt.

→

Where root actually appears. The instant a # prompt appears on the UART after boot — you are already root, with full read/write over the entire disk. No password, no exploit: you simply told the bootloader to skip the login system and hand you a root shell. Everything after that (the key, the password) is only cementing the access you already have, so it comes up by itself after a normal reboot.

✓

Why Secure Boot (HAB) doesn't stop this. HAB signs images — the bootloader and the kernel. But it checks neither the arguments you pass the kernel (init=…) nor the filesystem it mounts. We changed not a single byte of the signed images — we only changed how the signed kernel is invoked, for one boot. That is exactly why "you can't flash your own U-Boot, yet you can still get root."

Step by step

  1. Interrupt U-Boot.Because of bootdelay=0, spam a key in the terminal exactly as power is applied, until the => prompt appears.
  2. Override init at runtime — without saving.Critically: do not run saveenv. We change the environment for this boot only.
  3. Boot into a single-user root shell.The kernel hands you /bin/sh as root, no password.
  4. Remount rw and plant your way in.Your ssh key into /root/.ssh/authorized_keys, set a root password, unlock root in /etc/shadow.
  5. Sync and reboot normally.After a normal boot, key-based login comes up on its own.
U-Boot → single-user root
# at the U-Boot => prompt (do NOT save the environment!)
=> setenv bootargs ${bootargs} init=/bin/sh rw
=> boot

# we're in a root shell. remount the root read-write:
# mount -o remount,rw /

# your public key (one line, no wrapping):
# mkdir -p /root/.ssh
# echo "ssh-ed25519 AAAA...your_key..." > /root/.ssh/authorized_keys
# chmod 700 /root/.ssh; chmod 600 /root/.ssh/authorized_keys

# backup root password + unlock the account:
# passwd root
# sync
# reboot -f
⚠

UART mangles pastes. This serial console drops multi-line pastes and lines with quotes (it will eat a ' and hang on >, or wedge junk into the password). The rule: send one short line at a time, and verify by reading the actual file (cat/grep), never by the terminal echo. Do all the setup in the live shell before the reboot — there a typo is one command to fix; after the reboot it isn't.

✓

Persistence confirmed. The root /dev/mmcblk1p4 is ext4 rw, so the key, the password and every later edit survive reboots (verified: fresh boot, key in place, login came up by itself). This is FULL root, not an SDK sandbox.

07 — Dead ends

What we tried that didn't work

The road to root was not straight. Here are the dead ends — honestly, in order. Each one saves you time: don't go there.

✗ The single SDK login over SSH

The first thing you try on a plugged-in device is SSH. It brings up a USB gadget, but only tcp/22 is open, and the documented sdk:sdk over IPv6 link-local answers Permission denied. Guessing passwords is pointless and harmful — the device has a classifier that kills brute force; only single documented logins get through.

✗ The sanctioned SDK & extensions

Freewrite has an official developer path (the garnet SDK): a static IPv4 (192.168.99.44 → .190), sFTP sdk:sdk, an extensions/ folder, and "Preflight" JS hooks that run before a document is uploaded to Postbox. It's useful (you can intercept/encrypt/route a draft), but it's a sandbox: a different user, not root, no access to the filesystem or the system. For full control, that isn't enough.

✗ Flashing our own bootloader/kernel (SDP)

The i.MX6 supports serial-download (SDP) — so, seemingly, flash your own U-Boot and do as you please. No: Secure Boot HAB is closed (HAB Config 0xcc / State 0x99), and an unsigned image is rejected. That is exactly why we don't flash — we go around it through kernel arguments (see "Getting root").

The recovery combo: guessing failed, so we reverse-engineered it

At boot U-Boot prints the scan code of a held key: "Detected N keys for recovery: Key XX." We tried single keys — 35 (;), 39, 42, 61 — all "Fastboot: Normal." Dead end: the entry turned out to be a multi-key combo, and nobody had published which one. So we came at it from the other side — pulled U-Boot straight off the device (/dev/mmcblk1boot0), worked out the load address from the IVT header (0x877ff000), disassembled it in radare2, and found the function. It builds a three-bit tally: one key from each of three groups — and if all three are held, it boots the recovery kernel (a fourth key, by contrast, throws it into panic). The scan codes spelled E + X + L — the same chord as the factory reset on the sibling Freewrite Alpha. So the Traveler's recovery is E + X + L, held at power-on. We already had root by then, so we didn't need recovery — we just wanted to close the question.

✗ Small false trails

  • "Hold Power 15 s" to restart — does not always give a clean POR log. Only a full power-off (new+Power ≈3 s) then power-on is reliable.
  • "The device doesn't serve DHCP." At first the Mac took an APIPA 169.254.x and we assumed there was none. In fact the device does bring up DHCP itself (the Mac gets .44, the device .190). A false alarm.

08 — Permanent way in

Access over USB-C

Plugged into a computer, the Traveler brings up a USB-C network gadget. The Mac gets an interface (ours: en8), and the device serves DHCP itself: the Mac takes 192.168.99.44, the device is 192.168.99.190, with SSH open on tcp/22. The address lives as long as the cable is in.

~/.ssh/config
Host freewrite
    HostName 192.168.99.190
    User root
    IdentityFile ~/.ssh/freewrite_ed25519
    StrictHostKeyChecking accept-new
now simply
$ ssh freewrite
root@59a291782d3941d7:~# # full root — from here on it is just Debian.
⚠

The device sleeps aggressively. The baker-powerd daemon drops the USB bridge after about two minutes of idle — SSH disconnects. systemctl stop powerd keeps it awake (reversible with a reboot); or simply work fast and wake it with a keypress. After a drop, wake the device and en8/.190 return by themselves.

09 — How it fits together

System map

The application is called finchley and lives in /astrohaus/finchley/. Understanding its two halves saves enormous time.

  • Main process — core/ and main.js. Plain Node.js, required at runtime. Edit core/*.js + restart finchley and the change is live, no rebuild.
  • Renderer — sdk/ui/ (React), compiled into dist/bundle.js by webpack. Any UI change requires a rebuild (see §09).
  • Launch: the systemd unit finchley.service (restart with systemctl restart finchley.service). Power and sleep are handled by powerd.service (the baker-powerd daemon).

Where the text lives

Drafts live in PostgreSQL (database freewrite, 127.0.0.1:5432). The key table is document (uuid, title, body, uploaded, uploadedAt, folder_id, createdAt…). There's also folder, user, session, printjob, device_shred_jobs. Access is via the postgres system user:

psql
# su - postgres -c 'psql -d freewrite -tA -c "SELECT uuid,title,uploaded FROM document;"'
☁

Your text stays on the device — in this very database. The stock sync daemon /astrohaus/highgate/ (compiled to .so via Cython) mirrors drafts to postbox.getfreewrite.com and sets an uploaded flag. But it doesn't wipe them locally: a document row disappears only when you yourself shred or archive a draft — that's when a device_shred_jobs entry shows up. So there is somewhere to pull your writing from, which is exactly what we did (see §10).

The table schema

TableKey columns
documentuuid · id · title(≤50) · body · uploaded · uploadedAt · folder_id · bookmarked · createdAt
folderfolders A/B/C (folder_id 1/2/3)
userfont_size · languages[] · is_tooltip_shown · ...
sessionsession / user
printjobprint jobs
device_shred_jobsshred/archive queue — only on your explicit action

✓ The text is stored here, in document, and survives reboots. It's mirrored to Postbox (uploaded/uploadedAt), but stays locally — gone only on your own shred or archive. So there is something to pull off the device: our sync reads the .md straight from here.

The sync daemon — "highgate"

The upload logic lives in /astrohaus/highgate/ and is compiled to .so via Cython (highgate.so, fota_*.so, setup.so) — hard to read or patch directly. Endpoints: postbox.getfreewrite.com (drafts) and repo(-traveler).astrohaus.com (FOTA). Takeaway: rewriting sync is easier not inside the .so but by intercepting at the hosts/DNS level, disabling daemons, or via an SDK extension — which is what we did (see "What we changed").

Inside finchley

  • main.js + core/ — the main process: Sequelize models, dbus, daemons. Edit + restart = live, no rebuild.
  • sdk/ui/ — the renderer (React); webpacked into dist/bundle.js. Fonts live here too as dist/*.ttf.
  • preload.js — the Electron bridge; core/extensions — built-in hooks; /data/freewrite/extensions — user (SDK) ones.
  • Device settings: /data/freewrite/config/settings.json.

10 — Your own UI changes

Rebuilding the app

The renderer is a webpack bundle, so "change a button" means rebuild. It's convenient to build right on the device, from a copy of the source. On the weak i.MX6 a build takes ≈8 minutes.

rebuild recipe
# 1. a working copy of the source
# cp -r /astrohaus/finchley /data/fbuild
# cd /data/fbuild

# 2. babel/webpack environment (once)
# printf '{ "presets": ["react","env"] }' > .babelrc
# npm install --ignore-scripts

# 3. edit sdk/ui/... then build (~8 min)
# NODE_ENV=production ./node_modules/.bin/webpack \
      --config webpack/webpack.config.prod.js

# 4. deploy the bundle and restart
# cp -r /data/fbuild/dist/* /astrohaus/finchley/dist/
# chown -R finchley:astrohaus /astrohaus/finchley/dist/
# systemctl restart finchley.service
⚠

File ownership. The app runs as the finchley user (not root). Files are owned by finchley:astrohaus. If you copy from a Mac over scp (as root), you must chown finchley:astrohaus afterward — otherwise the app can't read its own bundle. Keep a bundle.js.bak before each deploy.

11 — In practice

What we changed

With root, the device becomes yours. Here's what we've already done — a map of what's possible.

→ Our own sync instead of a dead cloud

We disabled the cloud daemons (commented out document_uploader, settings_downloader, sync_shredded in core/daemons/index.js) and wrote our own sync on the Mac side: once a minute a launchd agent reads the document table over SSH, turns each draft into a .md file, and drops it into a working folder + Obsidian. The text no longer goes to someone else's cloud; it stays on your own Mac.

→ A Russian keyboard

The ru layout already existed in the keyboard engine but was disabled: the user's languages field in the DB was empty. One SQL line, and Ctrl+Shift cycles languages, with the built-in indicator.

SQL
=> UPDATE "user" SET languages = ARRAY['en','ru'];

→ A road mode without the cloud

To collect drafts on the road, the device brings up its own access point (hostapd + dnsmasq) and serves the drafts as a web page at http://10.42.0.1. The phone joins the "Freewrite" network and sees everything written. The firmware shipped without dnsmasq/hostapd/iptables — we had to sideload them (verified .debs from archive.debian.org over HTTPS+SHA256, since apt has no sources).

→ A clock that doesn't lie

The Traveler's RTC has no battery — powered off, it loses time. We keep it in sync three ways: a launchd agent on the Mac sets the time every 60 s over USB; NTP when online; and a nudge from the phone on the road (the export page posts /settime?ts=…).

→ The interface, made ours

  • Removed all "Freewrite/Astrohaus" branding from visible surfaces.
  • A permanent status panel on the lower screen (folder · words · time · battery · sync · language) instead of paged widgets.
  • A font-size switcher right in settings (keys 1/2/3), persisting to the DB through a core service.
  • Killed the LED that shone through the case (an RGB lamp under /sys/class/leds).

→ Deep-writing modes

Since it's an offline instrument for depth, we added two modes for the act of writing itself. Fade: old text on the e-ink dissolves into fog, only the last lines at the cursor stay sharp — forward only, the Freewrite philosophy taken to its limit. Immersion: instead of a word count, a metric of the longest unbroken flow (how long you wrote without ever pausing more than 90 seconds).

Under the hood: moves worth stealing

Three mechanisms from our changes that generalise to anything on this device.

1. Writing to the DB as the app, not as root. The renderer runs as finchley and can't su postgres. A live change goes through Redux + a core service (persist), not straight to psql:

renderer → core → DB
// live: Redux -> re-render Paper
this.props.actions.updateUser({...user, font_size: size});
// persist: core service via remote
require('electron').remote
  .require('./core/service/user')
  .setFontSize(user.id, size);   // models.User.update(...)

2. Testing connectivity without ping. There's no ping binary — do all diagnostics through bash's built-in /dev/tcp (or you'll get a false "no network," as we once did):

/dev/tcp
# timeout 4 bash -c 'exec 3<>/dev/tcp/1.1.1.1/443' && echo UP || echo down

3. "Deep writing" — a mask on the textarea. Fading old text is a CSS gradient mask on the <textarea>: transparent at the top edge, sharp at the cursor. No editor-engine changes:

Paper/index.js
maskImage: 'linear-gradient(to bottom,'
  'transparent 0%, #000 14%, #000 100%)'

Immersion (the longest unbroken flow) is measured from keystroke timing in a global keydown: a pause over 90 s breaks the flow, over 20 min starts a new session. All ordinary React in the renderer, available after a rebuild (§10).

12 — Map of the rakes

Reference & gotchas

Small things, each of which cost us an hour. Take them for free.

Rake What to do
pingit does NOT exist → test connectivity with bash /dev/tcp/host/port, not ping
curlalso absent → fetch .debs from a host and dpkg -i
baker-powerddrops USB after ~2 min → systemctl stop powerd or work fast
/tmpclears on sleep — don't keep anything you need there
UART pastemangles quotes & multi-line → one line at a time, verify by reading the file
sudostock binary lacks setuid ("broken") → chmod 4755 /usr/bin/sudo
rendererruns as finchley (non-root): no su postgres → write to the DB via a core service/sudoers

13 — Safety net

Anti-brick

The main reason this path is relatively safe: we never flash the bootloader or kernel. All edits are in the rootfs, which is reversible. Broke a file — restore it from backup through the same root access.

  • Always back up a file before editing it (cp x x.bak).
  • Don't touch saveenv in U-Boot — change the environment for one boot only.
  • Last resort: the i.MX6 supports serial-download (SDP). Recovery via imx_usb_loader / uuu (mfgtools). ⚠️ but HAB is closed — you can't load your own unsigned image this way, so protect the rootfs rather than counting on a reflash.

14 — The human side

What we found along the way

When you climb inside a locked device, you meet not just its locks but the people who built it. Here are three finds about them.

Codenames — London Underground stations

The system's components are named after London Underground stations — a quiet signature of the team, visible only to someone who climbed inside.

ComponentRoleTube
finchleythe app (Electron)Finchley
highgatePostbox sync daemonHighgate
baker-powerd / -paperdpower & screenBaker Street
brixtonapp serviceBrixton

The writer screensavers — the ones we turned off

On boot the device cycled portraits of writers — ink-and-watercolour, each captioned "set your story free." They are genuinely beautiful. We turned them off (on our panel they got in the way and flipped), but they're too lovely to lose — so here they are, published. In their place we put a Chronolith: at rest, the screen shows a literary quote that names the current hour. You glance at the sleeping machine, and there's a line from a book about exactly this time.

What we put in their place — and the idea behind it

We didn't just "switch things off." There was a single idea: turn a cloud-tethered gadget into a personal, offline deep-writing instrument that belongs to you. The writer screensavers are lovely, but on our re-oriented panel they flickered and flipped — so in their place we put something else:

  • One permanent status line instead of switchable widgets: folder · words · time · battery · "Synced to your Mac" · language — always visible, always honest.
  • A fade — old text dissolves at the top edge so you look forward, not back; and "immersion" — a meter of your longest unbroken flow of writing.
  • Our own Mac-side sync instead of the dead Postbox cloud, a Russian keyboard, a font-size control, and an honest interface with nobody else's brand.

The through-line is simple: the machine serves the writing, and the writing belongs to you. The details of each move are in "What we changed."

Easter egg: a developer among the classics

In that same screensaver folder, among Poe, Dumas and Austen, sits a file called ginger.jpg — and it is not a writer. It's a candid photo of one of the developers: a ginger fellow with an enormous mug in a café, in a "TIDES" fleece. A quiet joke left inside the firmware — a wave from the people who wrote it.

ginger.jpg — a developer
ginger.jpg

We deliberately keep this easter egg in the document: it's part of the device's character. Taking control needn't be hostile to the people who built it. We took our typewriter back — but the fellow with the mug, we respect.

15 — Finally

Disclaimer & ethics

All of this is with your own device — the one you bought and own. Repairing, studying, changing what's yours is fine; it's your right. We don't hand out anyone's firmware, don't bypass DRM for anyone's content, and don't poke around in anyone else's hardware.

And still: rooting voids the warranty, turns off the vendor's cloud sync, and can cost you your data or the machine itself. No promises. Do it thoughtfully, with backups, on a device you wouldn't mind losing. Everything above is how we did it. If you repeat it, you do so at your own risk.

✍

Why any of this. A good typewriter serves the person writing on it, not a cloud that will one day shut down. We gave the Traveler that simple thing back — you can do the same for yours.