Assistente de voz desktop, em background, que transcreve sua fala localmente (sem enviar áudio para a nuvem) e injeta o texto no campo que estiver focado em qualquer aplicativo — VSCode, terminal, navegador, editores, etc. Também pode conversar diretamente com o Claude Code CLI por voz, com as respostas lidas em voz alta por um motor de TTS local.
Status: v2 funcional (dictado + modo Claude Code). Testado em Windows. Veja
prompt-jarvis-voice-assistant.mdpara o histórico da v1 eplanejamento-v2-integracao-claude-code.mdpara as decisões de arquitetura da v2.
v1 — Ditado por voz
- Escuta contínua e leve em background com wake word "Hey Jarvis".
- Ao detectar o wake word, grava o áudio, detecta o fim da fala automaticamente (VAD) e transcreve localmente.
- Injeta o texto transcrito no campo focado via clipboard + paste simulado (não precisa clicar em lugar nenhum antes de falar).
- Overlay flutuante (animação Strands, WebGL) que reage ao estado (parado / ouvindo / gravando / transcrevendo), arrastável com o mouse para qualquer posição da tela.
- Painel de configuração (Electric Border) para ajustar a posição do overlay.
- Tudo roda localmente: wake word e transcrição não saem da máquina.
v2 — Modo Claude Code por voz
- Segundo modo de operação (alternável pela bandeja do sistema): em vez de ditar texto, o áudio transcrito vira um prompt enviado ao Claude Code CLI (
claude -p, modo headless), e a resposta volta para o Jarvis. - Respostas lidas em voz alta por um motor de TTS 100% local (Piper) — nenhum texto sai da máquina para virar áudio.
- Token do Claude Code (
ANTHROPIC_API_KEY) armazenado com criptografia viasafeStoragedo Electron (Credential Vault/Keychain do SO), nunca em texto plano. - Gerenciamento de projetos: registra pastas de trabalho, escolhe o projeto ativo (usado como diretório do
claude -p) e mantém a sessão/contexto de conversa por projeto entre reinícios do app. - Histórico de conversa (pergunta transcrita → resposta do Claude Code), com painel próprio acessível pela bandeja.
- Suporte alternativo a um servidor LLM local compatível com a API da OpenAI (Ollama, LM Studio, text-generation-webui, ...), como opção ao Claude Code.
| Camada | Tecnologia |
|---|---|
| Shell desktop | Electron 33 + electron-vite (build) + electron-builder (empacotamento) |
| Frontend | React 18 + TypeScript + Vite |
| Animação do overlay | Strands (React Bits, WebGL via ogl) |
| Moldura das janelas (Customizar/Histórico) | Electric Border (React Bits, Canvas 2D) |
| Injeção de texto no SO | @nut-tree-fork/nut-js (Windows/macOS, clipboard + paste simulado, Enter opcional); xdotool via subprocess (Linux/X11) |
| Sidecar local | Python 3.13 + FastAPI + Uvicorn (WebSocket + REST) |
| Wake word | openWakeWord — modelo pré-treinado hey_jarvis (ONNX runtime), reaproveitado também como comando de saída da conversa fluida |
| Transcrição (STT) | faster-whisper — modelo small, CPU, int8 |
| VAD (detecção de fim de fala) | webrtcvad (via webrtcvad-wheels), com gate de energia (RMS) pra não confundir ruído de fundo com fala |
| Captura de áudio | Web Audio API (getUserMedia + AudioWorklet) direto no renderer, downsample para PCM16 16kHz mono |
| Claude Code (v2) | @anthropic-ai/claude-code — CLI instalado separadamente via npm, chamado em modo headless (claude -p), prompt enviado via stdin |
| TTS (v2) | Piper (piper-tts) — voz pt_BR-faber-medium, síntese local, playback via winsound (Windows) |
| Armazenamento de credenciais (v2) | safeStorage do Electron (Credential Vault/Keychain do SO) — token nunca em texto plano |
| LLM local alternativo (v2) | Qualquer servidor compatível com a API da OpenAI (Ollama, LM Studio, text-generation-webui, ...) |
┌────────────────────────────────────────────────┐
│ Electron — processo principal (Node.js) │
│ - Tray, overlay, Customizar, Histórico │
│ - Injeção de texto no SO (clipboard + paste) │
│ - safeStorage (token), projetos/sessões/config │
│ - Sobe/gerencia o sidecar Python (subprocess) │
└───────────────────┬──────────────────────────────┘
│ IPC (contextBridge)
┌───────────────────▼──────────────────────────────┐
│ Renderer (React) — janela overlay │
│ - Captura de áudio (getUserMedia+AudioWorklet) │
│ - Conecta direto no sidecar via WebSocket │
│ - Renderiza Strands (cor muda por modo ativo) │
│ - Chama /claude-code/query e /tts (modo v2) │
└───────────────────┬──────────────────────────────┘
│ WebSocket (áudio PCM16 16kHz + eventos JSON + controle)
│ REST (/claude-code/query, /tts)
┌───────────────────▼──────────────────────────────┐
│ Sidecar Python (FastAPI, subprocess local) │
│ - openWakeWord + webrtcvad + faster-whisper │
│ (wake word, fim de fala, transcrição — v1) │
│ - /claude-code/query → subprocess `claude -p` │
│ (prompt via stdin, --resume por sessão — v2) │
│ - /tts → Piper (síntese + playback local — v2) │
└────────────────────────────────────────────────────┘
A captura de áudio roda direto no processo de renderer (Chromium) via getUserMedia/AudioWorklet, conectando via WebSocket diretamente no sidecar — o processo principal do Electron não fica no caminho crítico do áudio, só cuida de tray, janelas, credenciais e da injeção de texto no SO.
Fluxo do modo Claude Code (v2): wake word → grava até detectar silêncio (VAD) → transcreve → renderer chama POST /claude-code/query (sidecar roda claude -p com o texto via stdin, --resume se houver sessão salva pro projeto ativo) → resposta é injetada no campo focado e, se ativado, enviada a POST /tts pra ser falada. Depois de a fala terminar de tocar (nunca antes, pra não se auto-ouvir), o sidecar volta a escutar sem exigir o wake word — só encerra a conversa fluida se o wake word for dito de novo ou após um timeout de inatividade.
- Node.js 20+ e npm
- Python 3.11+ (testado com 3.13)
- Windows ou macOS para o MVP (Linux é stretch goal — veja limitações abaixo)
- Claude Code CLI instalado e no PATH (
npm install -g @anthropic-ai/claude-code), comANTHROPIC_API_KEYcadastrado pelo app — só necessário se for usar o modo "Claude Code" (o modo Ditado funciona sem isso)
# 1. Dependências do Electron/React
npm install
# 2. Ambiente virtual do sidecar Python
cd sidecar
python -m venv .venv
.venv\Scripts\activate # Windows
# source .venv/bin/activate # macOS/Linux
pip install -r requirements.txt
cd ..
# 3. Rodar tudo (Electron sobe o sidecar automaticamente)
npm run devNa primeira execução, o sidecar baixa os modelos do openWakeWord e do faster-whisper (precisa de internet nesse primeiro run; depois funciona 100% offline).
npm run build:win # ou build:mac / build:linux- Electron pinado em 33.x: a versão 43.2.0 apresentou um crash de inicialização (falha ao carregar o snapshot do V8) neste ambiente de desenvolvimento. Se for atualizar o Electron, valide antes que
electron.exesobe sem crashar. - Linux/Wayland: a injeção de texto via
xdotoolnão funciona em Wayland (só X11). Suporte a Linux é stretch goal. - Wake word único: por enquanto só "Hey Jarvis" (modelo pronto do openWakeWord). Treinar frases customizadas em português exige um passo de treino adicional — veja o roadmap no
.mdde especificação. - Um único idioma de transcrição por vez: o modelo Whisper detecta o idioma automaticamente por padrão; pode ser fixado via variável de ambiente do sidecar.
jarvis-two/
├── src/
│ ├── main/ # processo principal do Electron
│ │ ├── claude-cli.ts # integração com o Claude Code CLI
│ │ ├── claude-token-store.ts # token criptografado (safeStorage)
│ │ ├── projects-store.ts # projetos registrados + sessão ativa
│ │ ├── chat-history-store.ts # histórico de pergunta/resposta
│ │ ├── llm-settings-store.ts # configurações de LLM/TTS
│ │ ├── local-llm-client.ts # cliente p/ servidor LLM local (Ollama etc.)
│ │ └── history-window.ts # janela do painel de histórico
│ ├── preload/ # bridge contextBridge/ipcRenderer
│ ├── renderer/ # app React (overlay, Customizar, Histórico)
│ └── shared/ # tipos compartilhados entre main e renderer
├── sidecar/ # app FastAPI (wakeword, VAD, transcrição)
│ ├── claude_code/ # subprocess `claude -p` (modo headless)
│ └── tts/ # síntese e reprodução de voz (Piper)
├── electron.vite.config.ts
├── electron-builder.yml
├── prompt-jarvis-voice-assistant.md # spec v1 + histórico de decisões
└── planejamento-v2-integracao-claude-code.md # planejamento v2 (Claude Code + TTS)
Veja a seção "Próximos Passos" em prompt-jarvis-voice-assistant.md.
MIT.