Modules
The Handler
The module that asks β daily reflection, check-in surveys, mantras, affirmations, headspace sessions, proof on demand, and the audit that notices a missed day. Rule-based today, a local AI persona later, same module.
On this page
πΎ The Handler is the voice of the game. It sets the day's prompt, asks how your head is on a cadence, hands you a mantra, sits with you through a headspace session, and notices when you skipped the one thing it required. Everything it does is an entry in your journal and an event in the log, so the stats see it.
You name it (What you call them β the default is "Handler"). The name is in every line it
says. You also set how strict it is; every rule below is a field on /settings.
The daily rhythm
The Handler card on the dashboard shows one line at a time β the most important thing it wants β and lights the πΎ button with due or overdue:
- Not locked β "The kennel is quiet. When you're ready, cage up."
- A challenge is open β "Proof. Now. Write OTTER 47 where the camera can see itβ¦" β see Challenges. It outranks everything below: it has minutes on it.
- Check-in overdue β "You've gone quiet. Check in. Now."
- No reflection today β "Write today's reflection before the day ends."
- Check-in due β "Good boy. Now check in."
- Mantra not yet recited β "Recite today's mantra and mean it."
- Everything logged β "Stay in your headspace."
What matters now
Each of those lines has a reason code, the one machine word for what the Handler wants
right now. /api/v1/handler/today returns it as reason, so a Shortcut or a bot can decide
whether to nag without re-deriving the order above:
| Code | When |
|---|---|
unlocked / unlocked_slacking |
not locked (the second when a habit is slacking) |
challenge |
a challenge is open β answer it now |
recovery_checkin Β· recovery_reflect Β· recovery_rest |
a recovery day β the Handler eases off |
checkin_overdue |
check-in overdue |
reflect_due |
no reflection today |
checkin_due |
check-in due |
recite_due |
mantra not yet recited |
habits |
duties done; the Handler talks about your habits |
all_done |
everything logged |
The three recovery_* codes come from your health readings, so they stay on your box:
anything that leaves it is told the reason as if no health module existed.
Reflection (required)
One per local day while locked. The prompt is chosen from the library deterministically per day, so reloading never changes the question. Two ways to answer:
- Typed β at least Minimum reflection length characters (default 120). Shorter is refused, and the refusal tells you how many you wrote.
- Spoken β press the microphone, talk for at least Minimum spoken reflection seconds (default 30), stop, save. The recording is stored as a voice memo; an optional note goes with it. A recording with no measurable length is refused β a rule you can pass by sending less is not a rule. (Ogg/Opus recordings are measured exactly; other formats use the browser's reported length, cross-checked against the file's size.)
Either way: +15 XP, Good boy. Reflection logged. The due by hour (default 22:00) only changes the nag text; the day is the unit.
The microphone needs HTTPS
Browsers refuse the recorder on an insecure origin. Use your https:// address through the
reverse proxy, never the raw port. See Install.
Check-in survey
While locked, every Check-in every N hours (default 4; 0 turns it off). Five scores from 1 to 10 β headspace Β· obedience Β· mood Β· denial Β· energy β plus a prompt ("What does your Handler need to know right now?") and a free line. At twice the interval it becomes overdue and jumps to the top of the Handler's list. +5 XP.
On a short leash (Mischief) the interval is halved β 4 hours becomes 2, never under an hour β and the card says so. Going overdue earns a π Went quiet mark, once per stretch of silence, never overnight.
The scores are the raw material for headspace-over-time charts (on the roadmap) and are exported as their own CSV columns. They are prose-adjacent: they never appear on a share card or on the API's event feed (Privacy).
Mantras and affirmations
A mantra of the day (deterministic per day, like the prompt), meant to be said out loud before you log it β +3 XP. The whole mantra list is one fold away. Affirmations are the Handler's lines to you, one tap each, +2 XP. Both are journal entries.
Headspace sessions
A timed sit β meditation now, hypno scripts later. Pick minutes (at least one), optionally a script from the library, add a note after. XP = minutes, capped at 20. The duration is logged as part of the entry.
The audit: a missed reflection costs
Once per local day, at the first tick after midnight, the Handler looks at yesterday:
- If you were locked at 20:00 yesterday, and
- no reflection was logged for that day (voided ones do not count),
then it emits a reflection missed event and adds Penalty for a missed daily reflection (default 30 minutes) to the active clock. If there is no active lock at audit time, the event is recorded with the penalty marked not applied.
It looks exactly one day back, once. It never stacks, and the very first run only starts the clock β there is no retroactive penalty for days before you installed it. A missed-reflection penalty is undoable within the undo window if it was wrong.
Catching up
A day the audit marked blank stays open for seven days, and while any is open a π Catch up card sits at the top of the Handler page (the home card says Blank pages Β· N to catch up). It lists the days and asks one question; one entry answers every page on it, however many β at least Minimum reflection length.
It is cheaper than staying silent, and never free:
- each π Blank page mark (2) becomes a π Late page (1) for the rest of its week (Mischief);
- it earns no XP, and the penalty the audit added stays added;
- the days stay blank β on the calendar, in the heatmap and in your streaks. The entry is filed on the day you wrote it, as a catch-up, and the log says which days it answered.
What it buys is the Handler letting go of those pages: it stops asking for them. A reflection cannot be backdated into a day that is already marked blank β the catch-up is the one way back. Undo a catch-up (within the undo window) and its pages are open again.
Challenges: proof on demand
Off until you switch it on. Then, while you are locked, your Handler asks for proof at a moment you did not choose: a word and a number β say OTTER 47 β and a few minutes to send a photo with it in frame and your cage in the shot. Write it on paper, on another screen, on your skin; anywhere the camera can read it.
- It arrives as the Handler's top line on the dashboard and the Handler page (with the answer
form right there), as
reason: challengeon/api/v1/handler/todaywith the word and the deadline, and β if you use the chat bot with reminders on β as a message that makes your phone ring. - Answer with π― Here it is: a verification photo, captioned with the word, +10 XP. The word rides onto the photo's stamped export as proof Β· OTTER 47, so the picture carries the question it answered.
- Miss it and it costs what a missed reflection costs (Penalty for a missed daily reflection or challenge, default 30 minutes), stamped at the deadline, undoable within the undo window if it was wrong. With Mischief on, silence is a π» Ghosted mark.
- Can't right now? Say so (π I can't right now). The same minutes go on β but it is a π Owned up mark, not Ghosted. Honesty is the cheaper move, never a free one.
When none is asked: outside your asking hours, while you are not locked, while one is already open, while you are paused (the safeword) or out for hygiene, on a recovery day, and past twice your daily number. A moment that falls on any of these is skipped, not saved for later.
When a miss costs nothing: if you said the safeword, or opened a hygiene window, while the challenge stood β the miss is still written, saying why it was held back (no penalty β paused). Out for hygiene is no mark at all; a pause is a mark with no weight. Nothing passes silently.
π΄ Latch does not read the word in your photo. It records that you answered in time and keeps the word beside the picture, for you β and anyone you show it to β to check. A model on your own box that looks for it is on the roadmap (local vision verification).
Why it works this way
These are choices, and each has a reason:
- The word is the proof, not the camera. A page can ask the browser for the camera, but any browser may ignore it and every desktop does, so "camera only" would be a rule you could pass by picking a file β a ritual, not a control. A photo taken before the challenge cannot show a word minted for it. So the answer form takes a photo from anywhere (on a phone, the camera is the first thing it offers), and there is no "did it earlier" time field: an answer is stamped when it arrives.
- A word and two digits (from a list of 64 words, digits 2β9): fast to write by hand, easy to read in a dim photo, no 0/O or 1/I to argue about, 4,096 possibilities. A photo's own timestamp is not used: photos lose it on purpose when they are re-saved.
- Off by default. A new way to lose time on the clock should never arrive with an upgrade.
- Truly random timing. The wait to the next challenge is drawn fresh every time, averaging your number per day across your asking hours. Any other spacing would let a challenge you just answered tell you how long you are safe. The price: some days bring fewer than your number, some more β never more than twice it.
- Ten minutes to answer by default: enough to find a pen in another room, short enough that it is a test of now.
- The missed-reflection penalty, not a new one. A challenge is the same kind of duty β asked, not optional β so it costs the same through the same setting. One number to tune.
- No time off for answering. Proof is the price of the lock, not a bargain; time off would make you want to be asked. You get XP.
- The same marks as training. Ghosted and Owned up already mean "left to run out" and "said you couldn't"; a challenge is weighed the way training is, so the ledger stays one idea.
- None on a recovery day. The Handler's own line on those days is "Nothing more is being asked of you today." A surprise demand would make it a liar.
- Ringing in the chat room, not a quiet notice. A notice does not notify, and an ask with
minutes on it that reaches nobody is not an ask. It follows your
!remindswitch, because it is a reminder in all but name.
| Setting | Meaning | Default |
|---|---|---|
handler.challenges_per_day |
About how many a day while locked (0 = off, at most 12) | 0 |
handler.challenge_minutes |
Minutes to answer one (2β120) | 10 |
handler.challenge_from_hour |
Asked from this hour⦠| 9 |
handler.challenge_until_hour |
β¦until this hour (wraps midnight: 14 β 2 is fine; the same hour = all day) | 21 |
The journal
The Handler page ends with the journal: the last forty entries of every kind, with prompt, body, scores, duration and the voice player where there is a memo. The Log page shows the same things as events with an excerpt.
The library: your Handler's voice
Settings β πΎ Handler holds the prompt library, one table, five kinds:
| Kind | Used for | Seeded with |
|---|---|---|
reflection |
the daily prompt | 12 |
checkin |
the check-in question | 4 |
mantra |
mantra of the day | 8 |
affirmation |
the affirmation buttons | 8 |
meditation |
headspace scripts | 3 |
Each line has a weight (probability in the daily draw; 0 never draws) and an enabled
switch. A line tagged lapse:<mark> (lapse:zoomies, lapse:blank_page, β¦ or lapse:any) is a
lapse question: it is never drawn on an ordinary day, only asked about a lapse
(Mischief). A set of them is seeded once; edit them like the rest. Add your own; rewrite the seeded ones; disable what does not land. The register is
yours: firm, gentle, explicit, clinical β the mechanics do not care.
A prompt written for one day
Somebody you have allowed to write a prompt (Consent) writes it for one later day, never today β a reflection, a check-in or a mantra. On that day it goes first β ahead of the library and ahead of a running event's lines β but only while their permission is still live, they are still the one holding it (a pack's next Handler does not inherit the last one's prompts), and you are not paused. That is checked every time the page is drawn, so a revoke or the safeword takes it off the page at once and a resume brings it back; the prompt itself is never edited or deleted. It is not part of your library, and you cannot rewrite it β to take it away, revoke their permission or pause. While a hidden lock is running, a prompt somebody else wrote is not shown at all (they may be able to see the clock you chose not to), and it is back the moment the lock ends.
Settings
| Key | Meaning | Default |
|---|---|---|
handler.name |
What you call them | Handler |
handler.strictness |
How strict they are: warm, firm or strict β what Mischief weighs and asks, and your AI Handler's voice | firm |
handler.reflection_min_chars |
Minimum typed reflection | 120 |
handler.reflection_due_hour |
Due-by hour for the nag text β and the chat bot's reflection reminder comes four hours before it | 22 |
handler.checkin_hours |
Check-in cadence while locked (0 = off) | 4 |
handler.missed_penalty_minutes |
Cost of a missed daily reflection β and of a missed challenge | 30 |
handler.voice_min_seconds |
Minimum spoken reflection (0 = no minimum) | 30 |
handler.challenge* |
The four challenge settings | off |
What the Handler never does
It never leaves the box, never reads anything that is not in your log, never posts, and only
ever acts by writing events through the same doors you use. Your AI Handler inherits
exactly those limits: a model on your own computer, acting as ai only under what you grant on
Consent, capped per day, every action an event β and this page's rule-based line
always stands beside whatever it says.
Lines from others
The card under the Handler's own line shows what somebody else said to you today: your AI Handler (π€ Your AI Handler said) and, with packs, a Handler (π£ Sir (Handler) said, or π€ Byte (AI Handler) said when the one who signed says it is an AI). Each is today's latest, and each stands only while its voice may speak β the grant to say a line still live, and nothing paused: revoke it, or say the safeword, and the line leaves this page (it stays in your log).
π While your lock is hidden, a line that talks about time shows as a line about time β hidden with your timer. It is theirs and is kept word for word; tap to reveal shows it on this page only. Your AI never gets that far: a line of its own about a hidden clock is dropped before it is kept β and a line it wrote knowing your hidden clock (you granted it) shows as a line written knowing your hidden clock, whatever it says, until the lock is no longer hidden.
The Handler and your habits
Since 0.11.0 the Handler reads the habits board. Once the day's duties are done β reflection written, check-in made, mantra said β its line turns to the work: praise for a habit on a run, a stern word for one you are slacking on. When you are not locked it still speaks: Not locked β but you're still my pup. The Handler page carries an On your habits card with every verdict, and the same sentence it says is the one written into your log as a Consistency rewarded or A word from your Handler event. See Habits β Praise and a talking-to for how it judges.
This page also ships inside the app, at /guide β so your own instance always serves the guide for the version you are running, with the internet unplugged. Get Latch Β· Something wrong here? Tell me.