A local-first AI digital pet that lives on your desktop.
Mochi moves on her own, remembers what matters, and chats briefly through an optional local LLM. Works fully offline. No accounts. No cloud. No telemetry.
idle |
walk |
jump |
sit |
look |
sleep |
eat |
yawn |
roll |
blush |
hide |
celebrate |
14 hand-drawn poses + per-mood color tint + 4 distinguishing glyphs
(π‘ hungry Β· β¦ bored Β· β‘ lonely Β· ? curious)
Most AI companions are chatbots wearing a mascot. Most virtual pets are cute shells with no memory. Mochi is a deliberate middle path:
- Alive without the LLM. A deterministic local simulation drives mood, needs, movement, sleep, and idle behavior β every 3 seconds, all day, no network calls.
- LLM only at salience moments. Short greetings, daily reflections, and memory extraction. Hard cooldowns prevent spam and bills.
- Memory you can read and delete. SQLite + FTS5, ranked by importance Γ recency Γ confidence. Export to Markdown anytime.
- Sandbox by default. Mochi can read files you drop into her inbox only after explicit per-file consent β never your filesystem at large.
"The pet must feel alive even when the LLM is off." β Project North Star
git clone https://github.com/cskwork/pet-mochi.git
cd pet-mochi
npm install
npm run tauri:dev # launches the desktop petRequirements
- Node β₯ 20 Β· Rust β₯ 1.77
- Windows / macOS / Linux (Tauri 2 supported platforms)
- Optional: Ollama for chat replies
That's it. Mochi happily runs in silent mode β no setup needed for the core experience.
- Lives as a transparent always-on-top overlay β drag her anywhere on the desktop, click-through hit-testing keeps the rest of your screen usable.
- Animates 22 sprite states β idle / walk / run / sleep / jump / sit / look-cursor / hide / celebrate / eat / yawn / roll / blush plus the expressive set (stretch / peek / tilt-head / shake / nuzzle / wiggle / dizzy / surprise), each with its own CSS motion.
- Feels alive between interactions β mood-weighted idle micro-quirks, squash-and-stretch juice on every press, and particle bursts (hearts, crumbs, confetti, z's) on care moments.
- Mood you can read at a glance β color tints + glyphs (π‘ hungry, β¦ bored, β‘ lonely, ? curious) so similar mood tones stay distinguishable.
- Tamagotchi-style actions β Feed (with a 3-snack tray, snack-specific eating sprites, and a hidden favorite snack to discover) Β· Play Β· Pat Β· Rest Β· Report.
- Tiny sound effects (optional) β synthesized chirps acknowledge your actions (pat boop, nom-nom, play bounce); Mochi never beeps on her own, and a settings toggle silences everything.
- Loves you back β tiered welcome-back rituals after an absence (never guilt, always joy), keepsake gifts after good care days (collected on a shelf in Settings), hatch-day anniversaries, morning/evening rituals.
- Pick-up physics β drag her and she dangles in surprise; drop her and she lands with a squash-bounce (and a dizzy wobble after long flights).
- Behavior choreography (Β§9.11) β at salient moments the optional LLM picks a named animation preset from a closed catalog; a deterministic fallback reacts even fully offline. Closed-vocabulary bubbles only.
- Pick your stage β fully transparent desktop overlay by default, or a soft themed card (cream / blossom / mint / night) from Settings, applied live.
- Settings, two ways in β a small β in the opened status panel, or right-click β Settingsβ¦ (the same menu also has Close Mochi, since the overlay window is frameless).
- Persistent memories β durable preferences and recurring context survive restarts. Review, export, or delete from Settings.
- 12h idle-triggered status reports β fires autonomously when β₯12h has elapsed and Mochi finds a quiet minute; missed windows are dropped (no catch-up). Browse them in Settings β Sandbox.
- File summaries with consent β drop a
.txt/.md/.jsoninto the inbox; Mochi notices with a curious peek and asks before reading it. - Optional Ollama chat β short, mood-aware in-character replies. Hard cooldown, graceful fallback when the model is offline.
Further out: Voice (opt-in) Β· Custom skins Β· Live2D / VRM Β· Git/test-runner
watcher Β· Local embedding memory search Β· Multiple pets Β· Wardrobe & growth
stages. See PRD.md Β§24 and Β§27.8.
Pet Mochi is happy in silent mode. To enable chat, install Ollama and pull a small lightweight model:
ollama pull gemma4:e2bOpen Settings β set provider to ollama, point endpoint at
http://localhost:11434 and choose a model (defaults to gemma4:e2b).
Mochi retrieves relevant memories, sends a compressed prompt, and stores
the interaction. A best-effort memory extraction job runs in the
background after each LLM-backed reply.
| Layer | Tech | Notes |
|---|---|---|
| Desktop shell | Tauri 2 | Transparent, always-on-top, draggable overlay. |
| UI | Svelte 5 + TypeScript | PNG sprite + CSS animation, no extra renderer. |
| Simulation engine | TypeScript pure functions | Mood/decay/movement; testable, no LLM required. |
| Memory engine | Rust + rusqlite + FTS5 | Durable memories, prefix search, weighted ranking. |
| LLM adapter | Rust + reqwest | Pluggable LlmProvider trait. Ollama is the first impl. |
| Sandbox | Rust | Inbox watcher (notify), path-jail safe IO, declarative skills. |
src/ Svelte + TypeScript frontend
ββ App.svelte Routes pet (default) and settings (#/settings)
ββ lib/
β ββ sim/ Pure simulation engine (testable)
β ββ events/bus.ts In-process event bus + salience-driven LLM gating
β ββ bridge/ Tauri invoke wrapper + typed API
β ββ components/ Pet, MochiSprite, ChatBubble, PetActions, Settings
src-tauri/ Rust backend
ββ src/
β ββ db.rs SQLite schema, FTS5 search, CRUD
β ββ llm/ Provider trait, Ollama, prompts, cooldowns
β ββ sandbox.rs Pet home, safe file IO, skill manifests
β ββ watcher.rs notify-based inbox watcher
β ββ commands.rs Every #[tauri::command]
β ββ state.rs Shared AppState (Arc<Db>, LLM, cooldowns)
β ββ lib.rs Tauri builder, plugin wiring, setup
- Simulation first. A
runTick(state, ctx, elapsed)pure function decides the pet's behavior every 3s. The LLM is consulted only when an event's salience clears 70 and a 90-second autonomous cooldown has passed. - Memory ranking. FTS5 prefix search retrieves candidates; we re-rank by
0.4 Γ importance + 0.3 Γ recency + 0.3 Γ confidenceso old-but-important memories beat fresh trivia. - Failure first. The pet keeps animating when the DB is unavailable, when Ollama is offline, when memory extraction returns garbage JSON. Failures log warnings instead of bubbling up to the UI.
- Safety. No
eval, no shell, no remote skill loading. File paths are canonicalized and verified to live under the sandbox before any read/write.
Mochi's home folder lives at:
| OS | Path |
|---|---|
| Windows | %LOCALAPPDATA%\pet-mochi\ |
| macOS | ~/Library/Application Support/pet-mochi/ |
| Linux | ~/.local/share/pet-mochi/ |
Override with the MOCHI_HOME env var.
pet-mochi/
ββ inbox/ β drop .txt / .md / .json files here
ββ notes/ β Mochi writes summaries
ββ dreams/ β daily reflections
ββ exports/ β memory exports (Markdown / JSON)
ββ mochi.db β SQLite memory + state
Mochi never reads files outside inbox/, never writes outside notes/,
dreams/, or exports/, never executes shell commands, and refuses paths
containing .., absolute escapes, or symlinks that resolve outside the
sandbox.
npm test # 213 frontend simulation tests (vitest)
cd src-tauri && cargo test --lib # 79 backend tests (db, sandbox, llm, prompts)npm run check # svelte-check
npm run build # vite frontend bundle
npm run tauri:build # full desktop installer (icons already generated)See DECISIONS.md for the rationale behind recent UX/a11y
improvements, and BACKLOG.md for deferred items.
Every numbered requirement (REQ-001 β¦ REQ-113) from PRD.md is
either implemented or explicitly out-of-scope. Highlights:
- β Transparent always-on-top draggable overlay (REQ-001β¦005)
- β Idle / walk / sleep / jump / sit / look_cursor / celebrate / hide / run animations (REQ-010)
- β Deterministic simulation, LLM-free movement (REQ-011β¦013)
- β Hidden stats with decay & recovery (REQ-020β¦024)
- β Event bus with salience scoring & LLM cooldown (REQ-030β¦033, Β§14.1)
- β
Provider trait (
LlmProvider) β Ollama default, swappable (REQ-040β¦044) - β Short, mood-aware chat replies with graceful fallback (REQ-050β¦054)
- β SQLite + FTS5 memory store, recency Γ importance Γ confidence ranking (REQ-060β¦066)
- β
Idle-triggered 12h status report, autonomous + deterministic fallback β
dreams/(REQ-070β¦076) - β
Pet home folder with
inbox/,notes/,dreams/,exports/(REQ-080β¦084) - β Declarative skill manifests, no remote skill installation (REQ-090β¦093)
- β Behavior choreography with closed presets + closed bubble vocabulary (REQ-094β¦099)
- β v0.2 The Adorable Update β juice, quirks, snacks & favorite, greetings, keepsakes, hatch-day, rituals, drag physics, stage backgrounds, sound toggle, settings access, snack sprites, intensity guardrails (REQ-100β¦117, PRD Β§27)
Out of scope for MVP (per PRD Β§4.2): voice, 3D/Live2D, browser automation, shell execution, cloud sync, marketplace plugins.
Issues and PRs welcome. Before opening a PR:
- Run
npm testandcd src-tauri && cargo test --libβ both must pass. - Run
npm run checkβ must be 0 errors / 0 warnings. - For UI changes, smoke-test in
npm run tauri:devand describe what you saw in the PR description. - Match the existing simulation-first principle: the pet must feel alive even when the LLM is off.
MIT β do whatever you want, no warranty.
If Pet Mochi made your day a little nicer, β the repo. That's all.