A tiny macOS menu-bar character that reacts to how hard you type.
KeyMood turns local MacBook motion-sensor energy into a live companion state.
No typed text. No key logging. No cloud model. No Python backend.
| Usual menu-bar pet | KeyMood |
|---|---|
| Changes by timer, CPU load, or manual mode | Changes by physical typing force |
| Reads keyboard events or app activity | Reads local MacBook motion energy |
| Shows a status label first | Uses the character itself as the menu-bar signal |
| Jumps directly between states | Uses dwell and relaxation so motion feels alive |
| Needs cloud AI or a background service | Runs locally as a small Swift menu-bar app |
KeyMood is not a keylogger and not a chat-based mood app. It treats typing force as a chassis-motion signal: the MacBook body moves slightly when you type, the local accelerometer reports that motion, and app-owned Swift logic maps the signal into deterministic companion regimes.
Apple does not publish a full public AppleSPU accelerometer compatibility matrix for third-party apps. This target list is based on Apple's current motion-sensor feature boundary for Mac laptops and teardown evidence for the M2 MacBook Air.
| Support | MacBook models |
|---|---|
| Possible | MacBook Air 13-inch (M2, 2022) |
| Possible | MacBook Air 13-inch/15-inch (M2, 2022-2023) |
| Possible | MacBook Air 13-inch/15-inch (M3, 2024) |
| Possible | MacBook Air 13-inch/15-inch (M4, 2025) |
| Possible | MacBook Pro 13-inch (M2, 2022) |
| Possible | MacBook Pro 14-inch/16-inch (M1 Pro/M1 Max, 2021) |
| Possible | MacBook Pro 14-inch/16-inch (M2 Pro/M2 Max, 2023) |
| Possible | MacBook Pro 14-inch/16-inch (M3/M3 Pro/M3 Max, 2023-2024) |
| Possible | MacBook Pro 14-inch/16-inch (M4/M4 Pro/M4 Max, 2024-2025) |
| Not possible | Desktop Macs: iMac, Mac mini, Mac Studio, Mac Pro |
| Not possible | MacBook Air (M1, 2020), 13-inch MacBook Pro (M1, 2020), MacBook Neo, and earlier Mac laptops |
References:
- Apple says Vehicle Motion Cues are available on Mac laptop computers, but not on MacBook Neo, MacBook Air (M1), 13-inch MacBook Pro (M1), or earlier models: Apple Support.
- iFixit identified a Bosch Sensortec 6-axis accelerometer/gyroscope in the M2 MacBook Air logic board: iFixit teardown.
If a MacBook does not expose usable raw sensor reports, KeyMood still launches and shows No Sensor.
- Typing-force driven: stronger physical typing produces stronger character regimes.
- Motion-only input: KeyMood uses accelerometer deltas, not typed content.
- Menu-bar native: the selected character is the status item; controls live in a standard macOS menu.
- Stateful motion: thresholds, dwell, sensitivity, and relaxation prevent one-frame noise from becoming a fake intense state.
- Small local runtime: the current app bundle is about 380 KB, and the zip artifact is about 104 KB.
| Layer | Value |
|---|---|
| App type | Swift macOS menu-bar app |
| Minimum macOS | macOS 14 |
| Sensor path | Local AppleSPU / HID motion reports |
| Input signal | Accelerometer vector deltas |
| Primary metric | impact_g |
| Smoothed metric | energy |
| User tuning | Sensitivity slider, 0-100 |
| State control | Thresholds + dwell gate + relaxation path |
| Menu-bar output | Animated companion regime |
| Privacy boundary | No typed text, key names, key codes, prompts, or cloud calls |
KeyMood models typing force as a local vibration proxy, not as semantic input.
Let a_t = (x_t, y_t, z_t) be the local accelerometer vector reported at time t. A keystroke produces a small impulse through the keyboard deck and chassis, so KeyMood estimates instantaneous typing impact from the frame-to-frame acceleration delta:
impact_g(t) = || a_t - a_{t-1} ||_2
Because a single spike may come from desk movement, hand repositioning, or sensor noise, the app does not map impact_g directly to a character state. It first computes a smoothed energy estimate:
energy(t) = alpha * energy_{t-1} + (1 - alpha) * normalize(impact_g(t), sensitivity)
The visible regime is then selected by a finite-state controller:
regime(t) = FSM(energy(t), thresholds, dwell_time, relaxation_decay)
In practice, this means Full Ahead requires sustained high energy rather than one accidental bump, and falling energy enters Standby before returning to Dead Slow. The character therefore behaves like a physical companion responding to force over time, while the privacy boundary stays narrow: only motion deltas are observed.
| Internal state | User-facing regime | Character behavior |
|---|---|---|
calm |
Dead Slow |
Barely moving |
focused |
Slow Ahead |
Steady and calm |
charged |
Half Ahead |
Faster, more energetic |
intense |
Full Ahead |
Maximum shake and motion |
relaxing |
Standby |
Cooling down |
Sensitivity controls how easily the same physical typing force reaches each regime. Lower sensitivity requires firmer typing before KeyMood climbs into Half Ahead or Full Ahead; higher sensitivity lets lighter keyboard impact produce stronger motion. The slider scales the local energy estimate before threshold and dwell logic, so it changes responsiveness without reading typed text or key events.
The first companion direction is a tiny white submarine/engine pet. Stronger regimes increase propeller speed, body motion, smoke, splash, and eye intensity. Character assets live in docs/assets/character/.
KeyMood is distributed as a source-first GitHub project. Clone the repository and run it locally.
Run from source:
git clone https://github.com/Everyseok/keymood.git
cd keymood
swift run keymood-menubarBuild and open the local app bundle:
git clone https://github.com/Everyseok/keymood.git
cd keymood
./scripts/build_app_bundle.sh
open output/KeyMood.appBasic checks:
swift testRelease bundle smoke check:
./scripts/build_app_bundle.sh
./scripts/smoke_app_bundle.sh| Requirement | Version / Note |
|---|---|
| macOS | >= 14 |
| Swift | Swift 6 toolchain / Xcode Command Line Tools |
| Hardware | Supported MacBook with usable AppleSPU motion reports |
| Network | Required only for git clone |
| App size | About 380 KB for KeyMood.app; about 104 KB for KeyMood.zip |
| Symptom | Fix |
|---|---|
No Sensor |
This Mac may not expose usable AppleSPU motion reports. Try a supported MacBook model. |
| Character feels too quiet | Increase Sensitivity from the menu. |
| Character feels too intense | Lower Sensitivity from the menu. |
| App bundle does not open | Rebuild with ./scripts/build_app_bundle.sh, then open output/KeyMood.app. |
The default bundle script creates output/KeyMood.app and output/KeyMood.zip, then ad-hoc signs the app for local testing.
Public macOS distribution should use Developer ID signing and Apple notarization. AppleSPU raw sensor access is not a public App Store API, so KeyMood is designed first as a local GitHub/Developer ID MacBook app.
KeyMood treats sensor input as local physical telemetry, not user content.
The runtime reads accelerometer motion deltas only. It does not read typed text, key names, key codes, prompts, focused app content, URLs, screenshots, or clipboard data. Swift-owned logic maps motion energy into fixed regimes, then the renderer updates only the known menu-bar character states.
KeyMood is released under the Apache License 2.0.
Commercial use is permitted, but redistributions must retain the license terms and the attribution notice:
Copyright 2026 junseokism
See LICENSE and NOTICE for the full terms and attribution notice.
Jun Seok Kim
GitHub: @Everyseok
Typing force. Local motion. Menu-bar life.
