Skip to content

dimakis/mitzo

Repository files navigation

Mitzo

Claude Code on your phone. A self-hosted web UI built on the Agent SDK, designed for mobile over Tailscale.

Features

  • Streaming chat with thinking blocks, tool pills, and markdown
  • Three modes — Ask (read-only), Agent (file edits allowed), Auto (shell too). Switch mid-chat.
  • Slash-command skills/simplify, /risk-scan, /pr-review, plus repo-local and user skills. Type / to browse.
  • Voice — push-to-talk input (STT) and auto-speak output (TTS) via Yapper. Graceful degradation when offline.
  • MCP tools — reads ~/.cursor/mcp.json, passes servers to every session
  • File browser — view and edit repo files, switch between worktree roots
  • Worktree sandbox — opt-in git worktree isolation per session
  • Session resilience — phone sleeps, WS drops, session survives. Reattach on reconnect. Message snapshot recovery for iOS silent drops.
  • Auto-rename sessions — sessions get meaningful names via LLM summarization after every few prompts
  • Quick actions — one-tap commands via .mitzo.json
  • Push notifications — ntfy + Pushover (Apple Watch) when Claude needs approval
  • Image attachments — send photos/screenshots from your camera
  • Session history — resume past conversations, swipe to dismiss

Quick start

git clone https://github.com/dimakis/mitzo.git && cd mitzo
npm install && cd frontend && npm install && cd ..
cp .env.example .env  # set AUTH_PASSPHRASE, AUTH_SECRET, REPO_PATH
npm run build && npm start
# http://localhost:3100

Access from your phone: install Tailscale on server and phone, then open http://<tailscale-ip>:3100. No HTTPS needed — Tailscale encrypts via WireGuard.

Architecture

Phone (Tailscale) ──┬── HTTP: REST API
                    └── WebSocket: v2 streaming protocol
                        │
                    Server (Node + TypeScript)
                        │
                        ├── query-loop: SDK events → v2 protocol
                        ├── session-registry: detach/reattach/snapshot
                        ├── MCP servers from Cursor config
                        ├── git worktrees (opt-in)
                        └── passphrase + JWT auth

The server translates raw SDK stream events into a v2 block lifecycle protocol (block_startblock_deltablock_end). Explicit turn boundaries (message_start/message_end), deferred finalization, and message snapshots for reconnect recovery. See docs/design/message-protocol-v2.md.

Backend (server/) — 33 modules

Core Purpose
query-loop.ts SDK → v2 event translator. Deferred message_end, snapshot state, block lifecycle.
chat.ts Agent SDK query(), prompt assembly, streaming-input queue, session restore API
session-registry.ts Session state: detach, reattach, rekey, TTL abort, snapshot storage
permission-handler.ts canUseTool callback — auto-allow by tier, prompt via WS + push notifications
async-queue.ts AsyncIterable queue for follow-up messages and interrupt
Skills Purpose
skills.ts Skill registry — scoped discovery, precedence, collisions
slash-commands.ts Slash-command parsing and prompt expansion
skill-policy.ts Per-turn tool restriction from skill frontmatter
native-commands.ts Built-in native commands (/skills)
Supporting Purpose
tool-tiers.ts Risk classification + mode/tier auto-allow matrix
tool-summary.ts Summarizes tool inputs for pill display
permissions.ts Request/response registry
content-blocks.ts SDK content block parsing
event-store.ts Persistent event store for session replay
auto-rename.ts LLM-based session auto-renaming
hook-bridge.ts Project hooks → Agent SDK bridge
api-schemas.ts / ws-schemas.ts Zod validation schemas
mcp-config.ts Loads Cursor MCP config
worktree.ts Git worktree lifecycle
repo-config.ts .mitzo.json reader
auth.ts Passphrase + JWT
notify.ts / pushover.ts Push notifications
logger.ts / constants.ts / git-version.ts / port-check.ts / index.ts Infrastructure

Frontend (frontend/) — React 19 + Vite

Five pages (Login, SessionList, ChatView, FileViewer, InboxView), a useReducer-based message state machine (useChatMessages), module-level WebSocket pool with 500-message buffer, and components for thinking blocks, tool pills, tool groups, permission banners, and a slash-command picker.

Environment

Variable Description Required
AUTH_PASSPHRASE Login passphrase Yes
AUTH_SECRET JWT signing key (min 32 chars) Yes
REPO_PATH Default repo for sessions Yes
PORT Server port (default: 3100) No
WORKTREE_ENABLED Allow worktrees (default: true) No
MCP_CONFIG_PATH MCP config path (default: ~/.cursor/mcp.json) No

See .env.example for the full list.

.mitzo.json

Drop this in your repo root for quick actions and Python venv support:

{
  "quickActions": [
    {
      "label": "Run Tests",
      "desc": "Full suite",
      "prompt": "Run tests and report.",
      "extraTools": "Bash"
    }
  ],
  "venvPaths": [".venv/bin"]
}

Development

npm run dev          # backend + frontend concurrently
npm test             # vitest (525 tests, 48 files)
npm run lint         # eslint
npm run format:check # prettier

Pre-commit: husky + lint-staged + commitlint (conventional commits).

Tech

Node.js, Express, React 19, Vite, TypeScript, Claude Agent SDK, Vitest, ESLint, Prettier.

Attribution

Evolved from claude-command-center by Afstkla. The original used tmux; Mitzo uses the Agent SDK directly.

License

MIT

About

Mobile-first AI command center for managing Claude Code sessions

Resources

License

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors