Md. Asif Uddin

    Projects09 of 15

    Lucy

    An AI desktop companion that runs entirely on the Mac

    A 3D anime-style companion who lives on the Mac's screen, talks in a natural voice and listens when you say her name, with no account and no network needed. Speech recognition, voice and model all run on the machine, and Rust owns every network call.

    Source code

    Who she is

    Lucy is a 3D anime-style companion who lives on the screen, talks in a natural voice, and listens when called by name. She needs neither an account nor a network to do any of it.

    A character animated in code

    • She is a VRM model animated wholly in code: breathing, blinking, walking and floating, with hair and clothes on spring-bone physics.
    • She turns towards where she is going.
    • On a long break she sits on a bar stool with a coffee. The stool and mug are generated in three.js and follow her bones every frame.
    • Six moods, driven by the time of day and how she is treated, change her face, posture, outfit and voice.

    Voice and listening

    • Wake word. Say “Hey Lucy” and keep talking. The always-on listener is Apple’s on-device speech recogniser, so no audio leaves the machine.
    • Her voice. A local Kokoro-82M neural model, not the system voices.
    • Expression. The language model can mark a sentence [happy], [soft] or [surprised] to set her expression and pace. The tag is never shown or spoken.

    Private by architecture

    The architecture is drawn around what should not happen.

    • Rust owns every native capability and all network access, with keys kept in the Keychain.
    • The webview’s Content Security Policy permits no network at all.
    • The voice server binds to 127.0.0.1 and never logs what she says.
    • The model behind her is any OpenAI-compatible endpoint or Anthropic, free and local by default through Ollama.

    The problems a desktop pet actually has

    • Clicks. A transparent, always-on-top window has to let clicks through everywhere except her body. A background hit-test thread decides.
    • Petting. An unfocused webview receives no mouse movement, so petting is detected by a Rust cursor watcher counting quick back-and-forth strokes.
    • Lost questions. macOS speech recognition sometimes finalises on an empty transcript, so the last non-empty one is kept.
    • Arithmetic. A 3B model cannot do it, so arithmetic goes to a deterministic calculator with its own expression parser: precedence, powers, functions, percentages and Bangla digits.
    • Gaps in speech. The next sentence is synthesised while the current one plays.

    Cheap to keep running

    A companion that is always running has to be cheap. Rendering stops while she is hidden and drops to 12–30 fps when she is idle. The voice server sits at about 190 MB and speaks faster than real time.

    Built with

    Tauri 2, Rust, TypeScript, three.js with VRM, Apple Speech, Ollama, and Kokoro TTS on ONNX. 146 TypeScript tests and 48 Rust tests, clippy with warnings as errors, strict types, and CI on Linux and macOS on every push.