O ZapTerm é um projeto universitário construído sobre o whatscli (MIT), com a conexão ao WhatsApp feita pela biblioteca whatsmeow, que fala o protocolo do WhatsApp Web por websocket. O núcleo em Go é dividido em três pacotes com fronteiras rígidas: `messages` (conexão, eventos, comandos, mídia, bot), `config` (INI e registro de contas) e `main` (só interface). Cada conta tem um `SessionManager` rodando em goroutine própria e consumindo comandos por canal; a UI nunca chama o manager diretamente e recebe eventos pela interface `UiMessageHandler`. A partir da v2.0.0 o mesmo núcleo roda em modo headless (`--ui=json`) e conversa por NDJSON com uma interface em Ink (React para terminal), compilada com Bun em um executável único; a interface tview continua disponível e é a usada no Raspberry Pi.
- Linguagem
- Go 1.26 (go.mod)CGO habilitado
- WhatsApp
- whatsmeow (pseudo-versão de setembro de 2026) + protobuf
- Interface clássica
- tview + tcell v2 + cbind (atalhos)
- Interface padrão
- Ink 5 + @inkjs/ui 2 + React 18compilada com bun --compile
- Armazenamento
- SQLite (go-sqlite3) para a sessão de cada contacache JSON local e config em INI (gopkg.in/ini.v1)
- Sistema
- beeep (notificações)go-qrcodeclipboardxdg
- IA opcional
- API de Chat Completions da OpenAI com streaming (gpt-4o-mini por padrão)
- Build e release
- GitHub Actions com cross-compile para Linux amd64Windows (mingw) e Raspberry Pi (ARM)
Arquitetura
Núcleo Go headless e interface Ink por NDJSON
Com `--ui=json`, o binário Go vira o 'cérebro' (sessão, armazenamento, mídia, áudio) e emite eventos em NDJSON no stdout, recebendo comandos pelo stdin. A interface em Ink só desenha e devolve comandos, então as duas UIs compartilham 100% da lógica de WhatsApp. O launcher Ink, empacotado com Bun, encontra o `zapterm-core` ao lado do executável.
Concorrência
Uma goroutine por conta, comunicação só por canais
O `AccountManager` cria um `SessionManager` para cada conta (até 5) e roteia os comandos para o canal da conta certa; todo evento JSON leva o id da conta. Na UI tview, toda atualização vinda do núcleo passa por `app.QueueUpdateDraw`, e as regras do projeto documentam armadilhas como chamar `GetFocus()` durante o draw, que causaria deadlock.
Arquitetura
Várias contas sem quebrar quem já usava
A migração para múltiplas contas foi planejada em fases (doc/multi-conta.md): cada conta ganhou sua pasta com sessão SQLite, cache e QR, e na primeira execução a sessão antiga é movida para `accounts/default/` automaticamente, sem pedir para ler o QR Code de novo.
Performance
Estado em memória com locks separados e cache enxuto
Mensagens, conversas e contatos ficam em memória com `RWMutex` independentes para cada coleção. Para abrir rápido, um cache JSON versionado guarda a lista de conversas e só as últimas 100 mensagens de cada uma, descartando os protobufs brutos; o histórico completo vem da sincronização do próprio WhatsApp.
Integração
Bot de IA com streaming e cancelamento
O bot opcional consome a API da OpenAI via server-sent events e vai editando a resposta no WhatsApp conforme o texto chega, com um intervalo mínimo entre edições para não sobrecarregar. A requisição usa `context`, então uma mensagem nova interrompe a resposta em andamento. A chave vem só de `OPENAI_API_KEY` (ambiente ou .env), nunca do arquivo de configuração.
DevOps
Release automática com cross-compile e CGO
Ao entrar código no master, o workflow lê a `VERSION` do main.go e, se a tag ainda não existe, publica a release sozinho. Num único runner Ubuntu ele compila o núcleo com CGO para Linux, Windows (mingw) e Raspberry Pi (gcc ARM), gera os executáveis Ink com Bun e monta os .zip com os scripts de instalação e as notas geradas do git log.