📋 Pré-requisitos
OpenHuman é um monorepo híbrido: TypeScript no workspace app/ e crate Rust openhuman-core na raiz. Antes de qualquer pnpm install, você precisa de três toolchains funcionando em paralelo.
🎯 Stack mínima
- •Node 20+ (LTS recomendado) — runtime do Vite, ESLint, Vitest
- •pnpm via
corepack enable— versão fixada pelo campopackageManagerdopackage.jsonraiz - •Rust stable via
rustup— compilaopenhuman-coree o Tauri shell - •Git — fork-based workflow exige remotes
origineupstreamdistintos
🍎 macOS
Xcode Command Line Tools (xcode-select --install). Brew opcional para utilities.
🐧 Linux
Pacotes de WebKit/GTK + build-essential. CEF runtime exige libs gráficas adicionais.
🪟 Windows
Visual Studio Build Tools + WebView2 runtime (já vem no Windows 11).
💡 Dica prática
Habilite Corepack antes de clonar: corepack enable. Assim o pnpm é instalado automaticamente na versão correta na primeira vez que você roda qualquer comando no repo. Sem isso, você pode acabar com uma versão divergente que quebra o lockfile.
Versão do Node
Use nvm ou fnm para fixar 20.x. Mais novo costuma funcionar mas não é garantido.
Toolchain Rust
Estável (não nightly). rustup component add rustfmt clippy para format e lint.
Espaço em disco
Reserve ~10 GB. target/ Rust e node_modules/ crescem rápido.
RAM
8 GB compila mas sofre. 16 GB+ é confortável para rodar dev:app + cargo check em paralelo.
🍴 Fork e clone do repositório
O fluxo é fork-based: origin aponta para o SEU fork (pra onde você empurra branches), e upstream aponta para tinyhumansai/openhuman (fetch-only). Esse layout é regra dura no CONTRIBUTING.md.
⌨️ Comandos exatos
# 1. Forkar tinyhumansai/openhuman no GitHub (UI)
# 2. Clonar o SEU fork:
git clone git@github.com:<your-username>/openhuman.git
cd openhuman
# 3. Adicionar upstream
git remote add upstream git@github.com:tinyhumansai/openhuman.git
git fetch upstream
# 4. Verificar
git remote -v
# origin git@github.com:<your-username>/openhuman.git (fetch/push)
# upstream git@github.com:tinyhumansai/openhuman.git (fetch/push)
🔄 Já clonou upstream direto? Conserte uma vez:
git remote rename origin upstream
git remote add origin git@github.com:<your-username>/openhuman.git
git fetch upstream
✓ O que FAZER
- ✓Branchar de
upstream/main:git checkout -b feat/x upstream/main - ✓Push para
origin(seu fork) - ✓PR contra
tinyhumansai/openhuman:main - ✓Manter
mainlocal limpo, atualizado por fast-forward
✗ O que NÃO fazer
- ✗Push direto em
upstream(polui branches do repo oficial) - ✗Commitar em
main(CLAUDE.md proíbe explicitamente) - ✗Trocar a URL de
originpara upstream - ✗Usar
git push --forceemmain
SSH vs HTTPS
SSH evita prompts de credencial. Gere chave com ssh-keygen -t ed25519 e adicione no GitHub.
Sync com upstream
git fetch upstream && git rebase upstream/main antes de abrir PR para evitar conflitos.
📦 pnpm install: instalando dependências
Da raiz, pnpm install resolve o workspace inteiro de uma vez — TypeScript, ESLint, Vite, Vitest, Tauri JS APIs e tudo no workspace app/. Use pnpm: npm e yarn quebram a resolução.
⌨️ Comando
# Da raiz do repo
pnpm install
# Verificar workspace foi reconhecido
pnpm -r ls --depth -1
📊 Anatomia do workspace
- openhuman-repo — pacote raiz privado, define scripts agregados e
packageManager - openhuman-app — workspace
app/, React + Vite + Tauri (v0.53.45) - packages/tauri-plugin-ptt — Push-to-Talk plugin (Swift + Rust, iOS-only)
Resolução de lockfile
pnpm lê pnpm-lock.yaml e pnpm-workspace.yaml.
Workspace packages são symlinkados — alterações em um pacote são vistas pelos outros sem reinstall.
Husky hooks
Setup automático pós-install.
Pre-push roda pnpm rust:check — falha se o Tauri shell não compila.
tauri:ensure invocado
Postinstall garante CLI correta.
Roda scripts/ensure-tauri-cli.sh — instala a CLI vendorizada se não estiver presente.
Comandos da raiz
Sempre rode da raiz — pnpm dev delega para app automaticamente.
Limpando estado
Em problemas: pnpm store prune + rm -rf node_modules && pnpm install.
Cache do pnpm
Reuso global do .pnpm-store torna reinstalls quase instantâneos.
Workspaces aninhados
pnpm --filter openhuman-app <cmd> direciona comando para subworkspace.
🧱 A CLI vendorizada do Tauri (e por que ela existe)
O runtime do OpenHuman é CEF (Chromium Embedded Framework), não o WebView nativo padrão do Tauri. Só a CLI vendorizada em app/src-tauri/vendor/tauri-cef/crates/tauri-cli sabe empacotar Chromium em Contents/Frameworks/ do bundle final.
⚠️ Atenção: stock CLI quebra
Usar @tauri-apps/cli oficial produz um bundle quebrado que crasha no boot com:
panic: cef::library_loader::LibraryLoader::new
O panic acontece porque o loader procura Chromium em Contents/Frameworks/ e não encontra — a CLI stock não copia para lá.
⌨️ Como a vendored CLI entra automaticamente
# pnpm dev:app e qualquer cargo tauri script chamam:
pnpm tauri:ensure
# Que executa:
scripts/ensure-tauri-cli.sh
# Se sobrescrita, reinstalar manualmente:
cargo install --locked \
--path app/src-tauri/vendor/tauri-cef/crates/tauri-cli
💡 Dica prática
Se algum colega instalou cargo install tauri-cli ou usou cargo install --force em outro projeto, ele pode ter sobrescrito a vendored. O sintoma é pnpm dev:app abrir uma janela em branco que crasha em alguns segundos. Solução: rodar o comando de install --path acima.
✓ Sinais de CLI correta
- ✓Janela abre e renderiza UI
- ✓
cargo tauri --versionreporta versão CEF-aware - ✓Bundle
.apptemFrameworks/populado
✗ Sinais de CLI errada
- ✗Panic em
LibraryLoader::new - ✗Bundle sem
Contents/Frameworks/ - ✗Janela abre em branco e fecha
iOS é diferente
pnpm tauri:ios:dev usa @tauri-apps/cli@^2 stock via npx — iOS não usa CEF.
Localização vendor
app/src-tauri/vendor/tauri-cef/ é um fork interno do Tauri com patches CEF.
Por que CEF?
Embedded providers (WhatsApp, Slack, etc.) precisam de Chromium consistente cross-platform.
Lock file
--locked é importante — sem ele cargo install pode pegar versões diferentes de deps.
🦀 cargo check do core
Antes de subir a UI, valide que o crate Rust compila. São dois Cargo.toml: o da raiz (core) e o do shell Tauri em app/src-tauri/. Cada um precisa do seu check.
⌨️ Comandos
# Core lib + binário openhuman-core
cargo check --manifest-path Cargo.toml
cargo build --manifest-path Cargo.toml --bin openhuman-core
# Tauri shell
cargo check --manifest-path app/src-tauri/Cargo.toml
# Atalho equivalente:
pnpm rust:check
📦 Binários auxiliares
O Cargo.toml raiz também define helpers em src/bin/:
slack-backfill— script para popular histórico Slackgmail-backfill-3d— backfill de 3 dias de email
⏱️ Primeira compilação demora
A primeira cargo build pode levar 5-15 minutos porque baixa e compila ~400 crates. Builds incrementais subsequentes são na casa de segundos. Não cancele achando que travou.
check vs build
check só verifica tipos (rápido). build gera o binário linkado.
target/ compartilhado
Core e shell compartilham deps. Limpar target/ recompila tudo.
Release vs debug
Dev usa debug. --release é ~10× mais lento para compilar mas roda muito mais rápido.
Falhas comuns
Faltam libs de sistema (libssl, libwebkit) — instale pelo gerenciador da sua distro.
✅ Verificação final do setup
Quatro comandos confirmam que tudo está pronto. São os mesmos checks do CI — passar localmente significa que seu PR não vai vermelhar por gosto.
⌨️ Check final
# Da raiz
pnpm typecheck # tsc --noEmit (alias: pnpm compile)
pnpm lint # ESLint --cache
pnpm format:check # Prettier check + cargo fmt --check
pnpm rust:check # cargo check do Tauri shell
✓ Tudo verde significa
- ✓TS compila sem erro de tipo
- ✓ESLint não tem violações
- ✓Código formatado (Prettier + rustfmt)
- ✓Tauri shell Rust compila
✗ Não force push se
- ✗Algum check acima falha
- ✗Você não rodou format antes
- ✗Husky pre-push reporta erro
💡 Auto-format antes de commit
Rode pnpm format (sem o :check) periodicamente — ele escreve as correções. Não precisa pensar em estilo de código no review.
typecheck = compile
São aliases no package.json do workspace app. Mesmo comando, dois nomes históricos.
ESLint --cache
Cache em .eslintcache torna runs subsequentes quase instantâneos.
--no-verify
Só use quando o hook falha em código que você NÃO tocou (breakage pré-existente).
Coverage gate
CI exige ≥80% de cobertura nas linhas alteradas — testes desde já.
📚 Resumo do módulo
origin = seu fork, upstream = tinyhumansai/openhuman fetch-onlypnpm tauri:ensure mantém certaapp/src-tauri/)Próximo módulo:
2.2 - Variáveis e configuração: .env raiz, app/.env.local e o TOML do core