A personal AI chief of staff that lives on your Mac or Linux box,
listens on Telegram, speaks back by voice,
and remembers everything it learns.
CLAUDE CODE · TELEGRAM · LOCAL VOICE · DURABLE MEMORY
▶ welcome.wav — listen to the intro
An agent you own completely. No subscription beyond Claude. No SaaS reading your conversations. The reasoning model is Claude Code, running in your terminal. The memory is plain text files on your disk. The voice is synthesized locally — on Apple Silicon (macOS) or an NVIDIA GPU (Linux). You control every layer.
The interface is your phone. Send a voice note or a message to your Telegram bot, and your Mac answers — in text, and by voice.
The persona is yours to name and shape. The assistant maintains a durable wiki of what it learns, follows your behavioral rules, and enforces them with hooks. It is, in every sense, yours.
iPhone ──────────────────┐
Apple Watch (TGWatch) ───┼──▶ Telegram Cloud ──▶ Telegram MCP (Bun)
BlackBerry ──────────────┼ │
│ │
Terminal ────────────────┼────────────────────────────────▶ Claude Code
Chrome Remote ───────────┘ direct to Mac │
├──▶ Whisper speech → text
├──▶ Kokoro 82M text → voice (or Voxtral 4B)
├──▶ Knowledge Wiki ~/knowledge/
├──▶ Local Repos ~/code/
├──▶ GitHub Repos gh CLI
└──▶ Gmail · Calendar
TGWatch is a Telegram client for Apple Watch. Once installed, your watch connects to the same bot — send a voice note or message from your wrist, get a reply in text. Voice replies play back on the watch via the iPhone's speaker. No extra configuration needed beyond the standard Telegram setup.
| Layer | Tool | Where it runs |
|---|---|---|
| Agent | Claude Code CLI | Terminal, your Mac |
| Channel | Telegram MCP plugin (Bun / TypeScript) | Spawned by Claude Code |
| Speech → text | openai-whisper | Local CPU / GPU |
| Text → speech | Kokoro-82M (default, fast) or Voxtral-4B-TTS (slower, more personality) via mlx-audio |
Local Apple Silicon GPU |
| Memory | Karpathy-style wiki — plain markdown + git | ~/knowledge/ |
| Observability | Patched MCP server + LaunchAgent watchdog | launchctl, every 5 min |
| Guardrails | Hooks: reply-enforcer + coding-guidelines | Claude Code harness |
| Keep-awake | caffeinate -is wrapped in ct alias |
Lifetime of session |
matt-stack/
│
├── SETUP-PROMPT.md Guided install — paste into Claude, follow along (60–90 min)
├── STACK-GUIDE.md Long-form manual — why everything works the way it does
│
├── assets/
│ ├── welcome.wav Audio introduction — 24-bit, 24 kHz, BF16 Voxtral (the voice you'll hear on first run)
│ ├── aeris-apple-watch.jpeg Photo
│ ├── aeris-blackberry.jpeg Photo
│ ├── doc-launch.svg Terminal diagram — launching Claude
│ └── doc-paste.svg Terminal diagram — pasting the setup prompt
│
├── templates/
│ └── knowledge-CLAUDE.md Schema for your personal Karpathy-style wiki
│
└── files/
├── coding-guidelines.md Copy to ~/.claude/ — read by the enforcer hook
├── hooks/
│ ├── coding-guidelines-enforcer.py Blocks file edits that violate your guidelines
│ └── telegram-reply-enforcer.py Ensures every Telegram message gets a reply
│
├── scripts/
│ ├── kokoro-tts.py TTS helper (Kokoro 82M) — fast default, ~3s wall
│ ├── voxtral-tts.py TTS helper (Voxtral 4B) — slower but more personality
│ └── mcp-health-check.py Pings the Telegram MCP server; restarts if dead
│
├── launchagents/
│ └── mcp-health.plist macOS LaunchAgent — health check every 5 min
│
├── patches/
│ └── server.ts.patch Fixes a silent crash in the Telegram plugin MCP server
│
└── skills/
├── voice-reply/ Generates and sends a voice reply on Telegram
├── voice-filter/ Strips non-TTS characters before synthesis
├── reflect/ Periodic self-reflection and memory sync
├── seven-rules/ Loads the assistant's core behavioral rules
├── firewall-check/ Checks network before long tasks
└── boot/ Session startup sequence
Total time: 60–90 minutes for a first install. The guided path (Step 3) does most of the work interactively — you paste one prompt and follow along.
On Linux? See
LINUX-SETUP.mdfor the deltas:kokoroPyTorch+CUDA TTS instead ofmlx-audio, systemd-user timer instead of LaunchAgent,systemd-inhibitinstead ofcaffeinate, bash instead of zsh. Tested on Arch / Omarchy + NVIDIA RTX (8 GB VRAM). ReadSETUP-PROMPT.mdfirst to understand the seven parts, then apply the Linux deltas.
Everything runs on the same Mac, but in two different places. Commands in this guide are styled to make the split obvious:
| Where | Looks like | What it is |
|---|---|---|
| Terminal / shell | ```bash fenced block |
Run in your shell (Terminal.app, iTerm, etc.) |
| Inside Claude Code | 💬 blockquote | Type at Claude's ❯ prompt during a session |
When in doubt: if the block starts with 💬, it goes inside Claude. Otherwise, shell. SVG screenshots are included at the key transitions.
Before anything else, confirm you have:
- Mac on Apple Silicon (M1 or later) — required for local voice models
- macOS 13 Ventura or later
- Personal Claude account — team and enterprise plans silently disable
--channels, which breaks the Telegram integration. The bot will show "typing…" but never respond. Check at claude.ai → profile → plan. Switch to personal before proceeding. - A Telegram account and a phone number
- Free disk for TTS models: ~200 MB if you pick Kokoro (recommended), ~3 GB if you pick Voxtral, ~3.2 GB if you install both. Downloaded on first voice use.
# Homebrew (if not already installed)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Core packages
brew install anthropic/claude/claude-code openai-whisper ffmpeg jq oven-sh/bun/bunWhy
bun? The Telegram plugin's MCP server runs on Bun, not Node. The official plugin README doesn't list it as a dependency, but without it the server silently fails to start. Install it now.
Then authenticate Claude Code — it opens your browser for OAuth on first launch:
claude
# Follow the browser prompt, then close Claude with /exitgit clone https://github.com/hjbarraza/matt-yuno-agent.git ~/matt-stackOpen ~/matt-stack/SETUP-PROMPT.md and copy the prompt inside it (everything between the >>> markers). Then return to your home folder and launch Claude Code — the install writes to ~/.claude/, ~/knowledge/, and ~/Library/LaunchAgents/, so starting from ~ keeps every path reference working:
cd ~
claudePaste the prompt at the > prompt. Claude will:
- Ask for your name, assistant name, and Telegram bot token
- Install and configure all hooks, skills, and scripts
- Set up the Telegram MCP plugin and apply the stability patch
- Configure the LaunchAgent watchdog
- Run a verification checklist at the end — 19 checks, all must pass
Follow along and approve each shell command as it runs. Don't skip steps.
You'll need a bot token before the guided install reaches Part 4. Do this in parallel:
- Open Telegram and search for @BotFather
- Send
/newbot - Choose a display name (any name — Unicode, emoji OK)
- Choose a handle — must be ASCII only, must end in
bot(e.g.YourNameBot) - Copy the token BotFather gives you — looks like
1234567890:AAF... - Send yourself a message on the new bot so it has your chat ID
- DM @userinfobot to get your Telegram user ID (a number like
8648152515)
Keep both the bot token and your user ID handy. The guided install will ask for them.
At the end of the guided install, Claude runs a 19-point verification checklist automatically. If anything fails, it will tell you what's wrong and how to fix it.
You can also re-run verification at any time:
Relaunch Claude Code in your shell:
ctThen, inside the Claude Code session (at the ❯ prompt, not your terminal), type:
💬 Run the verification checklist.
| Symptom | Cause | Fix |
|---|---|---|
| Bot shows "typing…" but never replies | Team/enterprise account — --channels is disabled, or stdio pipe between Bun and the CLI is ghosted |
See Diagnosing the ghosted stdio pipe below |
| Telegram plugin silently fails to start | Bun not installed | brew install oven-sh/bun/bun |
| Voice reply has no audio / wrong language | Voice preset language mismatch | Use neutral_female for English; fr_female requires French text |
| Plugin dies after a few hours | Upstream MCP server bug (no heartbeat) | Apply files/patches/server.ts.patch — the guided install does this automatically |
| Mac sleeps and bot goes offline | No keep-awake strategy | Use the ct alias — it wraps Claude in caffeinate -is |
The most common post-install failure: you DM the bot, see the typing… indicator, then silence. The bot is receiving — that's why typing appears — but the message isn't reaching Claude. Two distinct causes have the same symptom; diagnose before reaching for fixes.
Step 1 — verify it's not the Claude account. Team/Enterprise plans silently disable --channels notifications. Check at claude.ai → profile → plan. If you're on Team/Enterprise, switch to personal — no amount of restarting will fix it.
Step 2 — verify the bot identity and queue state (use the token from ~/.claude/channels/telegram/.env):
TOKEN=$(grep '^TELEGRAM_BOT_TOKEN=' ~/.claude/channels/telegram/.env | cut -d= -f2)
# Does the token correspond to the bot you're DMing?
curl -s "https://api.telegram.org/bot${TOKEN}/getMe" | jq '.result | {id, username, first_name}'
# Is a stale webhook intercepting messages? (should be empty url)
# Is the bot consuming the queue? (pending = 0 means yes)
curl -s "https://api.telegram.org/bot${TOKEN}/getWebhookInfo" | jq '.result | {url, pending_update_count}'Interpretation:
- Wrong
username→ wrong token in.env. Run/telegram:configure <correct-token>. urlnon-empty → a stale webhook is stealing messages. Delete it:curl -s "https://api.telegram.org/bot${TOKEN}/deleteWebhook".pending_update_count > 0→ Bun isn't polling. Restart the server (Step 4).- All three look right, messages still don't arrive → it's the ghosted stdio pipe (Step 3).
Step 3 — try /mcp reconnect first. In the Claude REPL:
/mcp reconnect plugin:telegram:telegram
If it reports success and a follow-up DM lands, you're done. If it reports success but messages still vanish, the pipe is ghosted — go to Step 4.
Step 4 — hard restart. Forces a fresh Bun server and a fresh stdio:
/exit
Then in the shell:
pkill -f "bun server.ts"
ct # or the macOS/Linux equivalent that relaunches Claude with --channels --continueDM again. This fixes the vast majority of stdio-ghost cases.
Step 5 — if Step 4 didn't help, apply the debug-log patch. Without it, the MCP server's stderr is swallowed and you have no visibility into why delivery is failing:
cd ~/.claude/plugins/cache/claude-plugins-official/telegram/*/
patch -p1 < ~/matt-stack/files/patches/server.ts.patchThen redo Step 4. After the patch, ~/.claude/channels/telegram/server.log and heartbeat.json will give you the actual failure reason on the next occurrence.
STACK-GUIDE.md — the long-form manual. Every architectural decision, every known failure mode, and the reasoning behind each default. Read this when something breaks or before you customize.
files/README.md — standalone install reference for individual components. Useful if you want to install just the hooks, or just the skills, without running the full guided install.

