A desktop AI companion that lives with you — she remembers, perceives, acts, and speaks.
An LLM brain with layered memory and dreams, proactive agency, action-integrity rails, and a code-agent capability — embodied as a Live2D avatar with lip-synced custom voice.
English · 简体中文
This repository is the engineering, published as a reference — not a distributed product.
There are no installers: Luna is one person's companion, and the instance that matters lives on one
machine. Read the code, clone it, take the parts you want.
- 🧠 Three-layer memory + dreams — a rolling working window, salience-scored durable turns, and structured long-lived facts over one SQLite file; an offline dream cycle consolidates the day into facts, diary, and distilled skills. Hybrid recall blends embeddings, keywords, recency, and a relevance floor so a decisively relevant old memory is never buried.
- 🌱 Proactive agency — she can open a conversation herself: silence-aware timing ladders, weather-shift and reconnect hooks, follow-up thoughts — all behind deterministic, tunable rails (quiet hours, outreach intensity) instead of a "message me every N minutes" loop.
- ⚡ Streaming everything — one WebSocket, one Zod-typed event contract shared by server and web. Reply tokens, tool starts/progress, memory updates all stream live; tool turns never block.
- 🛠 Real capabilities — web search + SSRF-guarded page reading, weather (QWeather / Open-Meteo), time perception, a gated code-agent (repo map, symbol search, edits), and a skills shelf she distills herself.
- 🎭 Embodied — a Live2D avatar with emotion-driven expressions, gaze follow, idle animation profiles, phoneme lip-sync, and a transparent always-on-top desktop pet mode.
- 🗣 Her voice — a GPT-SoVITS cloned voice, set up with no terminal anywhere: the wizard downloads & deploys the runtime in one click, you drag a voice pack in, and Luna starts + supervises the voice server herself. Drop a new pack onto the running app to swap voices.
- 🧙 Guided onboarding — a bilingual (中文/English) wizard that opens by asking which Luna you
want: the complete companion (Live2D + voice, seven steps) or just the agent core (chat box
only, five steps, nothing to download). Either way you get live key validation against the real
vendors, drag-and-drop avatar/voice installs, and escape hatches everywhere (status-bar button,
native
⌘,menu, failure dialogs) so a bad config can never strand you. - 🔒 Local-first — memory is a local SQLite file, keys live in a local config only, the server binds loopback by default. Nothing about her leaves your machine.
There is no installer to download — you build her from source, which is also the honest way to read what she is.
git clone https://github.com/Alan-Yu-2077/Luna-ts.git
cd Luna-ts
bun run app # installs deps → builds → packages → puts Luna.app on your Desktop → launchesThe only required thing is a chat API key (Anthropic, or any compatible gateway) — every other step is optional and re-runnable from Settings.
Prefer the browser, or not on macOS?
bun install
cp .env.example .env # set ANTHROPIC_API_KEY
bun run dev # server + web at http://localhost:5173![]() Voice step — one-click GPT-SoVITS deploy, drag a voice pack in, live health badge |
![]() First run — she ships with no body; you bring the avatar and the voice |
graph LR
D[desktop shell<br/><sub>pet mode · wizard · supervision</sub>] -.hosts.-> W
W[web<br/><sub>Live2D · lip-sync · chat UI</sub>] <-- "one WS, Zod-typed events" --> S[server<br/><sub>turns · tools · proactive rails</sub>]
S --- M[(SQLite<br/><sub>3-layer memory · dreams · skills</sub>)]
S -- provider seam --> L[Anthropic / OpenAI-compatible]
Five Bun workspace packages with a one-way dependency arrow: protocol (the
shared wire contract — a wire change that isn't reflected on both sides is a compile error),
server (the brain; owns all state and model calls),
web (a thin reactive view), music-cli (a vendored
macOS Now-Playing observer), and desktop (an optional
Electron shell). The deep dive lives in ARCHITECTURE.md.
Real conversations — she jokes, she looks things up, she reads her own codebase, she remembers.
Reading this as a reference? Start with ARCHITECTURE.md for the shape, then
docs/history/DEVELOPMENT.md — 140+ per-version entries, each split
into Fact (what changed) and Inference (why it mattered), including the versions that were wrong
and the gaps that were never closed. That log, not this README, is the honest account of how she got
built.
| Doc | What it covers |
|---|---|
docs/SETUP.md |
Bring-your-own model & voice, step by step (the wizard does this for you) |
ARCHITECTURE.md |
The structural map: packages, wire contract, memory, tools, proactive rails |
ROADMAP.md |
Where things are heading, by theme |
docs/history/DEVELOPMENT.md |
The full per-version engineering log (130+ entries) |
.env.example |
Every configuration knob, documented |
CONTRIBUTING.md |
Dev workflow, tests, conventions |
bun test # the whole suite, all packages
bun run --cwd packages/server tsc --noEmit # per-package typecheck (server/web/desktop/protocol)Tests live next to the code (*.test.ts), the wire contract is as-free, and every risky feature
lands behind a default-off env flag before its default flips. The server binds
loopback (127.0.0.1) by default; set LUNA_BIND_HOST=0.0.0.0 only on a trusted network.
This is a personal project published as a reference, not a supported product — no promises about
issues, PRs, or platform support. That's the deal, and it's meant generously: the code is MIT, the
per-version reasoning is all in docs/history/DEVELOPMENT.md, and
CONTRIBUTING.md documents the conventions if you're forking or reading closely.
Take what's useful; you don't owe anything back.
MIT, with one carve-out: the vendored Live2D Cubism Core runtime
(packages/web/public/live2dcubismcore.min.js) is proprietary to Live2D Inc. and governed by its
own license. See THIRD_PARTY_LICENSES.
GPT-SoVITS · pixi-live2d-display · Live2D Cubism · Bun · Electron · weather by QWeather & Open-Meteo · search by Tavily





