01
The loophole
Every focus app can be ignored. You pick the phone up anyway — the timer keeps running, your focus doesn't. The app has no idea. Your hand is the loophole, so the phone had to become the commitment instead of the thing measuring it.
com.abiola.anchor · v1.1.2 · SIGNED RELEASE
Your phone stays still, or the session dies.
A focus timer that cannot be ignored, because the phone itself is the commitment. Start a session and put it down. Pick it up, or leave the app, and your anchor breaks.
Try it
That ring is filling right now because you're holding still. Move the cursor quickly and you'll get the same five-second warning the app gives you. Come back to stillness and you keep the session. Let it run out and the streak resets to zero.
It is a slightly unfair thing to do to a visitor, which is the point. Reading that a focus app is strict tells you nothing. Losing a session to a twitch tells you everything.
Package
com.abiola.anchor
Version
1.1.2 · build 14
Platform
Android · minSdk 24
Source
~3,900 lines · 31 files

Your hand is the loophole. So the phone had to become the commitment instead of the thing measuring it.
01
Every focus app can be ignored. You pick the phone up anyway — the timer keeps running, your focus doesn't. The app has no idea. Your hand is the loophole, so the phone had to become the commitment instead of the thing measuring it.
02
Anchor reads the device motion sensors and smooths them exponentially so a passing truck doesn't end your session. Deviate more than the threshold from the established baseline and you've moved. It re-baselines only after a full run of consecutive still readings, so setting the phone down somewhere new is allowed — while lifting it is not. Switching apps is caught separately through visibility, because leaving is the same as moving.
Smoothing factor α0.18rejects jitter, keeps real movement
Violation threshold0.55deviation from the established baseline
Re-baseline after60consecutive still readings
Grace period5sRETURN TO ANCHOR — none in Strict Mode
Every one of these is a number I had to guess wrong first. 0.18 was 0.5, and a bus going past ended a session.
03
Breaking focus doesn't end the session instantly. The screen goes red — RETURN TO ANCHOR — and a countdown starts. Put it back and you keep your streak with a warning against your score. Let the countdown run out and the session is gone. Strict Mode removes the mercy entirely: any movement, instant failure. That toggle exists for the days you don't trust yourself.
04
Six ranks climb from Novice to Iron Anchor at a sixty-day streak. Sessions pay credits, credits can be wagered on the next session double-or-nothing, and a broken streak gives you ten seconds to spend credits saving it. Squads take it further: a four-character join code, live member status, and a flag that tells everyone when one of you breaks. Focus stops being private.
05
The Android build shipped as a black screen for a while. The Capacitor WebView silently refuses module script tags carrying a crossorigin attribute, so I wrote a Vite plugin that strips it at build time. The second was Firebase Analytics throwing at module load and blanking the whole app before React mounted — fixed by deferring initialization past first paint. Neither is in any tutorial. Both are written down in the config next to the reason.
<script type=module crossorigin>blackCapacitor WebView refuses it, silently → stripCrossorigin() Vite plugin
getAnalytics() at module loadblackthrows before React mounts → deferred past first paint
A black screen tells you nothing about which of the two you are looking at. That is why they are both written down in the config, next to the reason.
Built with
Next
Ghost