A Mac screen recorder
you can audit before
you switch it on.

A look at your display every two seconds, the text read on your own machine, filed to your own disk. The engine is written; the screen half is switched off. What still runs is a two-second look at which window is in front and, in a browser, which tab — none of it written down. Below is every mechanism, and its limit.

Apple silicon · built for macOS 11+, tested on none · nothing published · screen capture switched off

Top Secret — disclosure sheet build state: pre-beta
Claim In source Settles it
No microphone entitlement, no audio capture code entitlements.mac.plist codesign -d --entitlements -
Whole display, every 2.0s, when something qualifies main.swift:112 the .mp4s under chunks/
The screen half is switched off main.swift:100 temp/ stays empty
Switched off

Not a screenshot. The sheet is the page — the third column only settles anything once there is a build to run it against.

3entitlements ship in the app. None is the microphone.
140secret patterns on by default, of the 142 that load.
1 in 9pixels sampled, roughly, to decide if anything changed.
0frames on disk. Nothing has ever been recorded.

File 00 · Why

The last local-first one was switched off from the inside.

The tab with the right price on it. There were four, and you closed four. Rewind kept a record of things like that on your own Mac — the recording and the indexing happened there. It still phoned home: an account, and a remote flag service that could change how the app behaved. That was the half that mattered.

Rewind’s maker had renamed itself Limitless. Meta’s acquisition of it was announced on 5 December 2025, and the same day an update shipped with 19 December compiled into it. Fourteen days later, screen and audio capture stopped inside copies people had already installed. Nothing was downloaded on the day it died — the switch was already in the building. A teardown found seven cutoff-date messages wired through the recording lifecycle: start, resume, toggle, audio, meeting detection.

Too bad about the reWind Mac app, which they’ve kneecapped with the latest update starting on Dec 19th even though it could probably have continued to function as a local-only thing.

joisig, Hacker News

Local-first was never the property that mattered. Checkable was.

So: nothing here should be able to stop it recording except you, and your archive should open without this app. Neither is true today. Both are on the queue, and the rest of this page is what is true instead.

File 01 · The recorder

What the recorder does, and where each claim stops.

Mechanisms, because the adjectives are already taken. The source is not public, so the marks on the right are provenance, not proof. Three of the rows below describe code written against Rewind’s database rather than this one — the secret scanner, the purge and Backup Data quit Rewind, copy its folder, and work on the copy. None of them has ever run against a file this app wrote, because it has not written one.

  • Every 2.0 seconds, the whole display — when there is something to take. A polling interval with 100ms leeway, not a frame rate. It grabs the entire display holding your frontmost window, uncropped and unscaled, one display per tick — so a second monitor only while it has focus. A tick with nothing qualifying takes nothing: the bare desktop, the login window, the Dock, this app itself, any window transparent or under 50px in both dimensions. main.swift:71 · 88 · 112 · activeapp.swift:132
  • Text is read by Apple’s Vision, in the same process. No cloud OCR, no bundled model, no second service. First the frame is compared against a cached one on a sampled grid, roughly one pixel in nine, skipping the top 46 rows where the menu bar sits: nothing moved and the cached text is reused, Vision never invoked. With no cached frame for that exact window title, it diffs against the last one from the same app. ocr.swift:84 · 89 · 164 · 298 · 328
  • Every 150 frames become about five seconds of video. At one frame a tick that is roughly five minutes of screen, less if you switch between displays of different sizes — frames are bucketed by pixel size and each bucket fills on its own. HEVC at 30fps, full resolution, filed under chunks/YYYYMM/DD/, each frame indexed back to its position so a scrub seeks straight to it. No chunk has been written yet. screencapture.swift:49 · 125 · 155 · 343
  • Browsers hand over the URL, not just the pixels. Tab URL, title and private-mode flag by AppleScript for about twenty Chromium builds plus Safari, Arc and Orion; Firefox from its session file; every other app gives up its window title. Safari’s script reports normal unconditionally, so its private windows are not detected at all. activeapp.swift:167 · 317 · 334
  • Delete is written to take the files, and today takes the row. 147 gitleaks patterns ship inside the app, plus credit card, Social Security, Bitcoin WIF and email rules. Every match is shown with its timestamp first. Approve, and the database row goes — the frame and the video chunk stay: the purge builds their paths by deleting the space out of Application Support, and looks for them in a folder that does not exist. Found writing this page. It is on the queue. db.ts:337 · worker.js:167 · 1173
  • No microphone, no keyboard, no clicks. No audio capture code, no keystroke, click or scroll hook. One exception, because this is what gets found later: cursor position is polled every 17ms while a desktop character follows the mouse. It is never written down. entitlements.mac.plist · ipc.ts:407
$ ls ~/Library/Application\ Support/com.memoryvault.MemoryVault
db-enc-topsecret.sqlite3   chunks/   temp/

$ ls ~/Library/Application\ Support/com.memoryvault.MemoryVault/temp
$

Not a transcript — no build has made this folder yet. It is what the source says goes in it; a live listing would also show the -wal and -shm sidecars, because the database opens in WAL mode. com.memoryvault.MemoryVault is Rewind’s own bundle identifier: this app files into the folder Rewind used, because it was built against it. And there are two directories, not one — the capture helper writes frames to a dozy/ folder of its own while the app reads from this one. The second command is the honest one.

File 02 · What leaves

Everything that leaves this Mac.

No frame, no video, no analytics SDK. One qualification: crash reports carry the log lines that came before them, and those lines include window titles, browser URLs and file paths. Nothing strips them today. Rather than write never, here is everywhere it can reach.

  • Crash reports, to Sentry — and more than crashes. Production builds, no opt-out, no scrubbing step. The SDK’s defaults also attach a minidump — a snapshot of the crashed process’s memory, not a stack trace — and open a session at launch that is sent when you quit, so Sentry hears from the app on an ordinary run with no crash in it. Every event carries the Mac’s hostname, CPU, memory, screen size and locale, and up to a hundred recent console lines. main.ts:83 · @sentry/electron main/sdk.js:22
  • Update checks, to GitHub. At launch and every two hours, then downloaded and installed without asking. An update channel that can change how the app behaves is the same class of mechanism that killed Rewind. main.ts:292
  • Favicons, to Google. Dormant. A helper would send the origin of every site you visit to t3.gstatic.com, and keep a PNG named after each hostname in your data folder. Neither of its two call sites is on the live path: one sits inside an eight-line commented block, the other in a superseded capture path. activeapp.ts:282 · 376 · swiftmanager.ts:201
  • Three links, on click. The tray menu hands discord.gg, twitter.com and dozy.ai to your browser, which is your browser going, not the app. Three more tray items open something local the same way — the log file twice, and macOS’s Privacy pane — and reach no host at all. Listed because all of them has to mean all of them. tray.ts:469 · 476 · 899

Put a network monitor in front of it. On the day there is a build you should see three names and no others: sentry.io, github.com, and objects.githubusercontent.com when an update actually downloads. Sentry will appear on runs with no crash in them, for the reason in the first row.

Anything more and this page is wrong.

File 03 · Encryption

Where the word encrypted stops.

The database of window metadata and recognised text is SQLCipher, legacy 4. Read that as narrowly as it is written: the key is a build constant compiled into the app, identical in every install. Not derived from a password, not held in your Keychain, not rotatable. Anyone holding the app and the file can open the file.

Settings are a partial exception, and smaller than it sounds: the file is wrapped by a second build constant — the same weakness again — and each value inside is encrypted again with a key macOS holds in the Keychain. The Keychain holds the key, not your settings; those sit in a JSON file next to the database.

The frames and the video chunks are not encrypted at all, and neither is anything else in that folder: the app icons, the per-site favicons, the names of your settings keys, or the log written to ~/Library/Logs. The folder is created asking for world-writable permissions; only your umask narrows that.

A key every install shares is a bad lock and a permanent export path, out of the same fact. The lock has to get better, and the export has to survive the fix: a way to read your own archive with off-the-shelf tools. Not stock sqlite3 — it cannot open a SQLCipher file at any key — so sqlcipher, or an export that comes out plain.

File 04 · Build state

Written, hidden, missing.

Written, never run joined up

  • Capture, OCR, change detection
  • Browser URLs and window titles
  • The encrypted database, behind one worker thread
  • HEVC chunking and the crash-safe re-encode — both read frame rows the app does not yet write, so neither has ever produced a file

Built, marked invisible

  • Open Screen History
  • Pause and Start Capture
  • The privacy window
  • Delete recent data, two minutes to a day
  • Backup Data, Open Rewind Folder

Not written

  • Search — text lands in full-text tables and nothing searches them. Their only reader is the secret scanner, which walks them row by row with regexes
  • The global shortcut — registered; its handler prints one line to a console
  • Settings — the menu item logs UNIMPLEMENTED
  • Retention limit, size cap, editable blocklist — none, so nothing expires
  • Any AI — no model, no embeddings, no summaries, no chat
  • Any battery or disk figure — nothing measured here, so nothing published
Not measured

File 05 · The queue

In order, and without dates.

  1. Join the recorder up. Startup asks the helper for a mode that returns before it takes a frame, and the handler that would file the row is commented out. The encoder then gives up when the database hands back fewer frames than it holds. Two edits, not one.
  2. Point the writer and the reader at the same folder. The capture helper writes under dozy/; everything that reads looks one level up.
  3. Make delete take the files. One string replacement in a path is the whole bug.
  4. Unhide the menu. Everything in the middle column above, made reachable. This is where it stalled.
  5. Make encrypted mean something. A key you hold, and a way to read your own archive without this app.
  6. Put a switch and a scrubbing step in front of the crash reporter, and delete the favicon helper.
  7. Take the teeth out of the updater. Ask first, or it goes.
  8. Then the search box, and the limits: a retention cap and an editable blocklist.

One email, and a standing correction.

One message when capture is switched back on and the timeline is reachable. Not a newsletter, nothing to buy, no build to download today.

When a claim here stops being true it gets a bar through it, and the new wording underneath. The old one stays visible.

nineteen days later → Fourteen days later

the engine is written end to end → written in every stage, never run joined up

Apple silicon, macOS 11 or later — the capture helper is compiled arm64-only. One-click unsubscribe.