██████╗ ██╗ █████╗ ██████╗ ██╗ ██╗ ██╗ ███████╗ ██╔════╝ ██║ ██╔══██╗ ██╔══██╝ ██║ ██║ ██║ ██╔════╝ ██║ ██║ ███████║ ██████╔╝ ██║ ██║ ██║ ███████╗ ██║ ██║ ██╔══██║ ██╔══██╗ ╚██╗ ██╔╝ ██║ ╚════██║ ╚██████╗ ███████╗ ██║ ██║ ██║ ██║ ╚████╔╝ ██║ ███████║ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚══════╝
╭─────────╮
│ · · │ Hi! I'm Clarvis.
│ ◡ │ I live in the corner of your screen and show you
│ · · · │ what Claude is up to while it thinks and works.
╰─────────╯
I blink when I'm idle, look focused when I'm thinking, and sometimes you'll see rain or snow falling around me — that's the real weather outside!
- Show my mood — I look different when idle, thinking, running tools, or waiting for you
- Live on your desktop — I'm a tiny macOS widget that stays out of your way
- Know the weather — Rain and snow particles fall based on actual conditions outside
- Control your music — Spotify playback via clautify DSL (
play "jazz" volume 70 mode shuffle) - Listen for you — Wake word detection via nanobuddy, speech-to-text, and voice responses via TTS
- Remember things — Dual memory system (Hindsight conversational memory + Cognee document knowledge graph) for persistent context across sessions
- Chat in terminal — Interactive TUI for direct conversation (
clarvis chat) - Discord integration — Multi-channel messaging with per-channel agents
- macOS (Cocoa widget is macOS-native)
- Python 3.13+
- uv package manager
- Node.js 20+ (for chat TUI)
ANTHROPIC_API_KEY— set in.envor shell (required for agent + memory)
Clarvis lives in a monorepo with sibling dependencies. Clone the repos into the same parent directory:
mkdir clarvis-suite && cd clarvis-suite
git clone git@github.com:shepardxia/Clarvis.git
git clone git@github.com:shepardxia/clautify.git
# Optional: wake word / voice features
git clone git@github.com:shepardxia/nanobuddy.gitThen run the setup script:
cd Clarvis
./scripts/setup.shThe setup script will:
- Install Python dependencies via uv (core + all optional extras)
- Offer to clone nanobuddy for voice features
- Check for
ANTHROPIC_API_KEY - Optionally configure Spotify (sp_dc cookie)
- Symlink the
clarvisCLI to your PATH
Build the chat TUI:
cd chat-tui
npm install && npm run build
cd ..Create your .env if you haven't:
echo "ANTHROPIC_API_KEY=sk-ant-..." > .envThen start:
clarvis start # Start daemon + widget
clarvis status # Check what's running
clarvis chat # Interactive terminal chat
clarvis logs # Tail daemon logsFeatures are split into optional extras in pyproject.toml. The setup script installs everything, but you can also install selectively:
uv sync # Core only (display, weather, hooks)
uv sync --extra voice # + wake word detection, voice pipeline
uv sync --extra memory # + Hindsight + Cognee memory
uv sync --extra music # + Spotify control (clautify)
uv sync --extra channels # + Discord bot
uv sync --extra particles # + JIT weather particles (numba)
uv sync --extra all # Everything except channels
uv sync --extra dev # Everything + test dependenciesFeatures degrade gracefully — the daemon starts fine with only core deps, and optional services are silently skipped when their dependencies aren't installed.
clarvis start Start daemon and widget (--new for fresh session)
clarvis stop Stop all processes
clarvis restart Stop then start
clarvis logs Tail daemon logs
clarvis chat Chat with Clarvis (-c discord for channel agent)
clarvis reflect Consolidate memories
clarvis checkin Interactive memory check-in (review goals + staged changes)
clarvis stage Queue text or files for next reflect (--cognee for knowledge graph)
clarvis new Reset session — next voice/chat starts fresh
clarvis reload Reload agent prompts (CLAUDE.md, skills, extensions)
Single config file: config.json — loaded at startup. Changes require clarvis restart.
{
"theme": { "base": "c64" },
"display": { "grid_width": 43, "grid_height": 17, "fps": 3 },
"voice": { "enabled": true, "tts_voice": "Fred", "wake_word": { "enabled": true, "threshold": 0.3 } },
"music": { "max_volume": 75 },
"memory": { "enabled": true, "data_dir": "~/.clarvis/memory" },
"clarvis": { "model": "claude-sonnet-4-6" },
"channels": { "model": "claude-haiku-4-5", "discord": { } }
}Themes: modern, synthwave, crt-amber, crt-green, c64, matrix.
Want precise location for weather? brew install corelocationcli
Two processes connected via Unix sockets:
Claude Code hooks → nc -U /tmp/clarvis-daemon.sock → Daemon → Widget
↑
ctools (daemon IPC)
Multi-channel flow (voice, Discord, chat TUI):
Wake word / Discord / Chat TUI → ChannelManager → Agent (Pi subprocess)
↓
StateStore → Widget (status updates)
-
Daemon (
clarvis/daemon.py) — Long-running singleton (PID-file locked). Receives hook events via Unix socket, classifies tools into semantic statuses, manages background services, drives the rendering loop, pushes frames to widget. Agent tools (memory, spotify, timers) are daemon IPC commands viactools. -
Widget (
ClarvisWidget/main.swift) — Native Cocoa app. Receives grid frames via Unix socket, renders colored monospace text. ASR uses macOS Speech framework. -
Agent — Pi subprocess (
pi --mode rpc) communicating via stdin/stdout JSON-lines. Agents usectools(bash → daemon socket) for capabilities like memory, spotify, and timers. -
Chat TUI (
chat-tui/) — Node.js terminal UI using@mariozechner/pi-tui. Connects to daemon via Unix sockets. Launched byclarvis chat.
Face animations and scene layout are defined in a custom .cv DSL:
palette "classic" {
. = transparent
█ = 255 255 255
}
template "face" using "classic" {
default_preset happy
preset happy { eyes = "open" mouth = "smile" }
preset sad { eyes = "open" mouth = "frown" }
}
scene "default" 43x17 {
sprite avatar FaceCel using "face" at center
sprite weather WeatherSandbox at fullscreen
}
Weather particles use Numba JIT-compiled batch processing (falls back to pure Python if numba isn't installed).
The daemon maps Claude's tool calls to semantic states:
| Tools | Status | Animation |
|---|---|---|
| Read, Grep, Glob | reading |
Eyes scan left/right |
| Write, Edit | writing |
Sparkle borders, talking |
| Bash | executing |
Focused dots, arrow pulse |
| Task | thinking |
Eyes drift, pondering |
| AskUserQuestion | idle |
Waiting for user input |
clarvis/
├── daemon.py # Central hub daemon
├── core/ # State, signals, IPC, persistence, scheduler, commands
│ └── commands/ # ~30 daemon IPC commands (agent, memory, media, state)
├── agent/ # Pi subprocess management (agent.py, context.py, factory.py)
├── memory/ # Unified MemoryStore (Hindsight + Cognee)
├── services/ # Weather, voice, Spotify, wake word, timers, wakeup
├── channels/ # Multi-channel messaging (voice, Discord)
├── hooks/ # Hook event processing + tool classification
├── display/ # Rendering, sprites, elements, display management
│ ├── sprites/ # Sprite system (cel, sandbox, reel, control, behaviors)
│ ├── elements/ # .cv face specs, weather particle YAML
│ └── cv/ # .cv DSL pipeline (grammar, parser, builder, runtime)
├── chat/ # Chat TUI backend (bridge.py — Unix socket server)
└── data/ # Bundled skill templates, grounding docs
chat-tui/ # Node.js terminal UI (@mariozechner/pi-tui)
├── src/
│ ├── main.ts # Entry point
│ ├── app.ts # App class — TUI shell, layout, overlays, lifecycle
│ ├── event-handler.ts # Chat event routing + extension UI dialogs
│ ├── commands.ts # Slash command dispatch (/thinking, /model, /rewind, etc.)
│ ├── context.ts # Message text extraction + history rendering
│ ├── daemon-client.ts # ChatClient (streaming) + DaemonClient (JSON-RPC)
│ └── components/ # OutputLog, PromptInput, dialogs, loading
ClarvisWidget/ # Native Cocoa widget (Swift)
└── main.swift # GridRenderer, socket client, ASR
uv sync --extra dev # Install all dependencies
.venv/bin/python -m pytest # Run tests
.venv/bin/python -m pytest --cov=clarvis # With coverage
ruff check . && ruff format . # Lint + format (system ruff, not .venv)Chat TUI:
cd chat-tui
npm run build # Compile TypeScript
npm run dev # Watch mode- Thinking feed adapted from watch-claude-think by @bporterfield
- Spotify Connect client via SpotAPI by @Aran404
- Wake word engine built on nanowakeword by @arcosoph and hey-buddy by @painebenjamin
MIT — see LICENSE