The friend who notices when you can’t ask

pip runs quietly on a night out. When it looks like you can’t ask for help, it asks you first. Your friends hear only if you don’t answer, and your location stays encrypted until then.

1Night mode

It switches itself on

Leave your saved home places during your evening window and night mode starts by itself. There is nothing to set up each night, and your home places never leave the phone.

2Detection

It notices what you can’t say

A hit above 3 g, a tilt, then no steps and no touch for 15 s. A Rust engine on the phone opens a “down after fall” incident and turns the microphone on for a short listening window.

3Check-in

It asks you first

A full-screen “You okay?” on the lock screen. Prove it’s you with your fingerprint, then type three random words. Nobody else has been told anything yet.

4Heads-up

Then it tells your friends

Two minutes and no answer. Your friends get “Sam might not be okay” and one sentence about what happened. They get no location yet.

5Location unlock

Your location unlocks only now

Four minutes after the check-in, your phone seals two hours of location keys to each friend. Before this, nobody could read it: not one friend, and not the server.

6Friends decide

Your friends decide what to do

Ring the phone loudly, call, say “I’m going”, mark you found. They can also call campus safety in one tap. The app never calls anyone on its own.

19:58
pip Home · off Night mode · on

You’re home. Have a good night.

Out with Ava, Jo and Kai. Everyone’s okay.

Hold for help
I’m okay
Motion · |a| in g50 Hz
Possible fall Down after fall Listening · 10 min

pip · check-in

You okay?

A possible fall, then no movement.

2:00

Type these words

mapleorbittulip

I’m OK I need help

Your friends were told

Tap if you’re OK

Ava found you

Your friends know you’re safe.

23:46

pip · now

Sam might not be okay

A possible fall, then down for 2 min, then no answer to a check-in.

S

Sam

Heads-up · just nowLocation shared · loggedFound safe

S
Location sealed 9f3a·c41e·77b0·e2d9

A possible fall, then down for 2 min, then no answer to a check-in.

Ring Call I’m going Found safe
Sam is safe

Why pip

Most safety apps wait for you to ask. pip notices when you can’t.

A hard fall, unsteady walking, a snatched phone. These are the moments you can’t reach for a button, so pip doesn’t wait for one.

Nothing to press

Other safety apps need the person in danger to act: press a button, set a timer, share a location. pip watches how you move, so it works when you can’t.

You hear first

Before anyone is told, your phone asks “You okay?”. If the cause clears, for example you get up and walk, the check-in withdraws and nobody ever knows.

Sealed until it matters

Your location uploads as ciphertext. Nobody can read it alone: not one friend, and not the company. It unlocks only when a check-in goes unanswered.

Friends decide

Your friends choose what to do: ring you, call, come and find you. pip never calls the police or anyone else by itself.

Detection

It knows your walk. It notices when that changes.

A foreground service samples motion all night, with the screen off and the phone in your pocket. A Rust engine on the phone turns it into gait, impact, grab and stillness signals and compares them with your own normal range. Pick a situation to see what opens.

Walking home

Every measure sits inside your normal range. Nothing opens, and nobody is told anything.

The motion here is synthesized in your browser. The thresholds are the engine’s own, sped up so each situation fits in a few seconds.

Sam’s phone · live 50 Hz · gyro on
3 g 1 g
|a| motionrotationyour normal

Cadence

0 steps/min

Regularity

0

Sway

0 m/s²

Wobble

0 rad/s

Mic off
    01

    Two sensor speeds

    10 samples a second by day. 50 a second plus the gyroscope at night, and for 30 min after any incident.

    02

    Your own normal

    Each walking measure is compared with your range for where the phone is carried: pocket, hand or bag. It is learned on ordinary walks and trusted after 7 different days.

    03

    Microphone in short windows

    Off by default. After a fall, a grab, a missed check-in or unsteady walking it listens for 10 min. YAMNet on the phone turns each second into scream, shout and snoring scores. Audio is never stored or uploaded.

    04

    Everything else

    Activity (still, walking, running, vehicle), speed, screen and unlock events, time since you last touched the phone, battery, distance to home, and whether you are with your friends.

    Incidents, not a score

    Clear rules you can read, not a black box

    There is no machine-learned danger score. Each signal opens and closes a named incident with a rule for when it clears. That way the phone can always tell you, and your friends, why it asked.

    Context
    Logged only.
    Watch
    Turns on full sensing and counts toward a check-in.
    Danger
    Asks “You okay?” on its own.
    • watch Fall

      Possible fall

      An impact above 3 g, a tilt, then little movement. Or a free fall and a hard landing.

      Clears: Steps resume

    • danger Fall

      Down after fall

      After a fall or hard impact: no steps and no touch for 15 s.

      Clears: Steps resume

    • context Fall

      Fall, recovered

      Walking again after a possible fall.

      Clears: A moment, kept in the log

    • watch Fall

      Hard impact

      A hit with a tilt that was neither a fall nor a dropped phone.

      Clears: Walking resumes

    • watch Fall

      High-g impact

      The first reading above 3 g, shown at once. Mid-walk, a bump is held 10 s and dropped if you keep walking.

      Clears: Reclassified ~2.4 s later

    • watch Walking

      Unsteady walking

      Regularity, sway or wobble outside your own normal range for 35 s of walking.

      Clears: 2 min of in-range walking

    • watch Walking

      Slowed walking

      Pace 20 % below your normal for a minute of walking.

      Clears: 30 s at your normal pace

    • context Walking

      Stumble

      One step far off rhythm with a sideways jolt, while walking continues.

      Clears: Pruned after 30 min

    • watch Walking

      Repeated stumbles

      Three stumbles within 5 min.

      Clears: 10 min without one

    • danger Phone

      Grab

      Phone in hand, a yank with a twist, then running away.

      Clears: The owner unlocks the phone

    • watch Phone

      Phone drop

      A long free fall, lands flat, dead still, not picked up within 60 s.

      Clears: Picked up

    • watch Phone

      Phone left behind

      Set down and untouched for 20 min while out late.

      Clears: Picked up or touched

    • watch Location

      Separated

      Over 150 m from every friend for 10 min, and not heading home.

      Clears: Back with someone

    • watch Location

      Stopped on the way home

      Was heading home, then stopped for 10 min somewhere that isn’t home.

      Clears: Moving again, or home

    • context Location

      In a vehicle

      The phone reports a vehicle.

      Clears: Out of the vehicle

    • danger Check-in

      Check-in missed

      “You okay?” unanswered for 2 min.

      Clears: Answered

    • watch Check-in

      Check-in typing off

      The check-in was typed far off your normal rhythm.

      Clears: A normal check-in

    • watch Sound

      Scream or shout

      Two frames within 2 min of a fall or grab, in a venue that isn’t loud.

      Clears: 10 min

    • danger Sound

      Snoring while down

      Snoring while down after a fall, with a check-in missed.

      Clears: Answered, or steps resume

    • context Device

      Battery critical

      10 % or less, not charging, while out late. Uploads a last encrypted location.

      Clears: Charging, or 15 %

    • watch Device

      Phone offline

      The server misses heartbeats for 10 min at night. Friends can start a fallback unlock.

      Clears: Heartbeat returns

    Entries in the on-device log expire after 8 hours. The rules ship as a TOML file served by the backend and merged over the copy built into the app, so a bad file can’t break the engine.

    When it asks

    One clue is a maybe. Two kinds of clue is a question.

    A single odd signal is usually nothing. pip asks “You okay?” only when the evidence adds up.

    1. 1A danger incident is open, such as being down after a fall.
    2. 2A possible fall, hard impact or scream has stayed open for 5 s. The wait lets the engine check whether it was only a dropped phone.
    3. 3Watch incidents from two different families are open together. Two from the same family never ask.

    Answering covers everything that’s open. After that, only a new incident can ask again, after a 5-minute pause.

    Open incidents. Tap to add evidence.

    Fall

    Walking

    Phone

    Location

    Sound

    Nothing open

    The phone samples at the low rate and logs nothing.

    Alerts

    Four steps, and you can stop it at any one of them

    Each step waits for the one before it, and the evidence must still hold. If you get up and walk, or rejoin your friends, the episode resolves by itself and friends are never told.

    1. 0:00

      Check-in

      A full-screen “You okay?” on the lock screen, with what was detected and a countdown. Nobody else is told.

    2. 2:00

      Heads-up

      No answer. Friends get “might not be okay” and a one-line summary. No location.

    3. 4:00

      Location unlock

      Your phone seals the current and next hour’s location keys to each friend and uploads a fresh fix.

    4. 10:00

      Call option

      Friends get one tap to campus safety or 911, with text ready to read out.

    Answering “I’m OK”

    First you prove it’s you: face unlock where the phone allows it, fingerprint, or PIN. A thief can’t pass this step. Then you type three random words while the phone checks your typing rhythm. If it’s far off your normal rhythm, friends hear “answered, but may be impaired”.

    “I need help”

    Anyone holding the phone can tap it. It counts as consent and unlocks your location at once.

    Other ways in

    Grab or snatch

    Skips the check-in. Friends are told at once, with the snatch-moment location and a warning not to chase. Only your biometric dismisses it.

    Manual SOS

    Hold the button in the app, the Quick Settings tile or the home-screen widget. Try holding this one.

    Phone offline or dying

    The server notices 10 min without a heartbeat, or a battery at 3 %, and tells friends. A dying phone uploads one last encrypted location first.

    What friends can do

    • Ring the phone loudly
    • Call
    • Alert the whole group
    • Ask for the location now
    • I’m going
    • Found and safe
    • Campus safety or 911

    Try a check-in

    Three words, typed like you

    A thief can’t answer for you, and a friend can’t answer while you’re slumped in a corner. First the phone checks it’s you. Then it gives you three random words and listens to how you type them: the gaps between keys, how steady they are, how often you go back.

    • The first time is your practice round, like onboarding. It sets your rhythm.
    • Then try again, slowly, or with one thumb. See what your friends would hear.

    Everything runs in this page. Nothing you type is sent anywhere.

    pip · check-in

    You okay?

    A possible fall, then no movement.

    Hold to prove it’s you

    Type these words

    Check-in dismissed

    Privacy

    Nobody can read your location. Not one friend, and not us.

    Every day your phone makes a fresh key and splits it among your friends. Any one share is useless. It takes several friends together, and every time they combine shares, everyone sees.

    Friends it takes to unlock

    Sam’s day key
    Combined shares

    Approve shares as Sam’s friends to try to rebuild the key.

    This is real Shamir secret sharing over GF(256), running in your browser. With fewer shares than it takes, the combined bytes are noise. Fallback unlock works only while Sam’s phone is offline or dying, and only in groups of three or more.

    Hour keys, two at a time

    Each hour’s key comes from the day key with HKDF. An alert releases the current hour and the next, so friends can read two hours at most, never the whole day. Keys are wiped when the day ends.

    Ciphertext on the server

    Each location fix is sealed with XChaCha20-Poly1305 under the hour key. The server keeps only the last 6 hours of it, and has no way to decrypt it. A database test checks that no decrypt path exists.

    Together or separated

    Every 2 minutes each phone uploads keyed hashes of its map cell and the 8 around it, about 150 m. The server compares hashes and learns only “together” or “separated”. It never sees a coordinate.

    What leaves the phone, and who can read it

    Encrypted location
    Nobody until an unlock, then your group
    Night mode, battery, alert level
    Your group and the server
    Together or separated
    Your group. The server sees only yes or no
    That an incident happened, in one sentence
    Your group and the server
    Live motion stream (never location)
    You and your group, on a private channel
    Every unlock
    You and your whole group

    Never leaves the phone

    • Home places
    • Walking baselines
    • Typing baselines
    • Private keys
    • Audio

    Friends are added in person

    You scan each other’s QR code and check that the fingerprints match on both screens. That way the server can’t swap in a key of its own. Both sides have to accept.

    For friends

    Your friends see what they need, and nothing more

    Friends follow along in the app, or on a laptop with the web monitor. It is the same code built for the browser, with the Rust crypto compiled to WebAssembly, so a released location decrypts on the friend’s own device.

    pip · monitor · Sam live
    S

    Sam

    Out tonight · with Ava

    Cadence104
    Sway2.4
    Battery61 %
    Round trip84 ms

    Incident log

      AI read advisory

      0

      Calm

      Nothing to read yet

        Engine level: idle

        Heads-up open RingCallI’m goingFound safe

        Live sensor view

        Motion and rotation at 10 frames a second over one Realtime connection. Nothing is stored, and it never carries location.

        An incident log made for scanning

        Plain names, “2 min ago”, a status like “Active · 3 min so far”, severity as a coloured edge, and one box per episode.

        An escalation dock

        It appears while an alert is open, turns red and beeps when a step is overdue, and holds every friend action and the map.

        An AI read that shows its working

        The incident timeline (names, order, gaps; never measurements, location or audio) goes to Claude Haiku from the friend’s browser. It is advisory only: the engine’s own alert level sets a floor.

        Under the hood

        Detection on the phone. Ciphertext on the server.

        All detection runs in Rust and Kotlin on the phone, never in JavaScript, so it keeps running when the app’s UI is asleep. The server only ever receives ciphertext, hashed tokens and a coarse status.

        Sam’s phone

        • Kotlin service · 50 Hz
        • Rust engine
        • Rust crypto

        Supabase

        • Postgres + RLS
        • Realtime
        • Edge functions

        can’t decrypt

        Friends

        • Android app
        • Web monitor
        • Crypto in WASM
        1

        On the phone

        Kotlin sensing service

        A foreground service that survives the screen going off, the charger coming out and a reboot. Motion at 10 or 50 Hz, activity, screen and unlock events, battery, and the mic in listening windows only.

        2

        On the phone

        Rust safety-core

        Pure Rust with no I/O: signals, personal baselines, incident rules, the on-device log and the escalation state machine. Bound to Kotlin with uniffi.

        3

        On the phone

        Rust safety-crypto

        Device identity (X25519, Ed25519), Shamir over GF(256), HPKE sealing, XChaCha20-Poly1305 location blobs and proximity tokens. Also compiled to WebAssembly for the monitor.

        4

        In the cloud

        Supabase

        Postgres with row-level security on every table, Realtime, and Deno edge functions: push, watchdog, proximity, unlock, purge and config. pg_cron runs the watchdog every minute.

        5

        For friends

        Expo app and web monitor

        One Expo / React Native code base: the Android UI, and the friends’ console in the browser. No detection logic lives in JavaScript.

        6

        Tooling

        sim and the trace gate

        A Rust CLI replays recorded and synthetic traces through the real engine. CI fails a change that adds false alarms or slows detection.

        92
        Rust testsengine stories, recorded walks, crypto
        48
        database checkspgTAP, row-level security
        25
        edge-function testsDeno
        22
        TypeScript testsmonitor, recorder, OK log

        Try the demo

        Run a night out on your desk

        One phone or emulator plays Sam. A browser plays a friend. Recorded traces stand in for the night, so you don’t have to fall over.

        1. checkin-dismissA check-in appears. Type the three words and it’s dismissed. The friend sees nothing.
        2. heads-upIgnore the check-in. The friend gets “might not be okay” with no location.
        3. unlock-mapStill down 2 min later, and the friend’s map appears. The database holds only ciphertext.
        4. snatchAn immediate “don’t chase” alert with the snatch-moment pin. Only a biometric dismisses it.
        5. manual-sosHold the SOS button. Friends are told and the location unlocks at once.

        Settings → Demo sensitivity swaps in easier thresholds for trying it out in a room: shorter timers, unsteady walking after 12 s, a grab after 2 s of jogging, and a 30 s check-in.

        Terminal
        # the engine, the crypto and the trace gate
        $ cargo test --manifest-path core/Cargo.toml
        $ cargo run --manifest-path core/Cargo.toml -p sim -- batch core/traces
        
        # the backend
        $ cd supabase && supabase start && supabase db reset
        $ supabase functions serve
        
        # a friend in the browser, Sam on Android
        $ pnpm --filter mobile web      # ?mock=friend
        $ core/build-mobile.sh && pnpm --filter mobile android
        $ adb shell am start -a android.intent.action.VIEW \
            -d 'safe://debug/inject?trace=heads-up'

        Not an emergency service

        Detection is heuristic. It can miss events and raise false alarms. If you are in danger, call your local emergency number. pip is for adults (18+).