📦 pnpm workspaces: o "porquê" de monorepo
O Understand Anything roda em três runtimes diferentes (Claude Code, Cursor, Copilot) e compartilha código entre
duas superfícies (skill TypeScript + dashboard React). Repositórios separados significariam publicar versões alinhadas
manualmente o tempo todo. pnpm workspaces resolve isso: um workspace:*
no package.json e o link entre pacotes vira simbólico, instantâneo.
🎯 O contrato do workspace
A raiz declara três coisas que definem tudo:
- •
pnpm-workspace.yaml— lista os pacotes (understand-anything-plugin/packages/*) - •
package.jsonraiz — campopackageManagerpina a versão do pnpm - •Scripts
--filter— rodam tarefas só onde importa
pnpm-workspace.yaml
packages:
- "understand-anything-plugin"
- "understand-anything-plugin/packages/*"
workspace protocol
Link simbólico entre pacotes locais
Hoisting
Deps comuns sobem para a raiz
--filter
Roda script só num pacote
packageManager
Pin do gerenciador para reprodutibilidade
🧩 packages/core: a engine de análise compartilhada
O @understand-anything/core é o cérebro neutro. Não sabe se está num terminal, num navegador ou
dentro de um agente — só sabe trabalhar com o grafo. Esse isolamento é o que permite o dashboard rodar a mesma lógica de busca que o skill TS roda no scan.
✓ O que vive no core
- ✓types — definição canônica de Node, Edge, Graph
- ✓schema — validação Zod do grafo persistido
- ✓persistence — read/write atômico de
knowledge-graph.json - ✓tree-sitter (WASM) — parser determinístico
- ✓search — fuzzy + semantic indices
- ✓tours — gerador de walkthroughs
✗ O que NÃO pertence ao core
- ✗Componentes React (vão pro dashboard)
- ✗Lógica de slash-command (vai pro plugin/src)
- ✗Chamadas para LLM (são responsabilidade dos agents)
- ✗Configs de Vite/Tailwind/PostCSS
- ✗I/O específico de Claude Code, Cursor, etc.
💡 Dica prática
Antes de criar uma feature nova, pergunte: "isso é sobre o grafo em si, ou sobre como o grafo é usado?" Se for sobre o grafo, vai pro core. Se for sobre uso, vai pro dashboard ou plugin. Esse teste evita 80% das discussões de arquitetura.
Pure TS
Sem deps de framework
SSOT
Schema canônico
Subpaths
Browser-safe exports
Vitest
Testes rápidos com filter
🌐 Subpath exports browser-safe
O core importa node:fs e node:path na camada de persistência. Se o dashboard importasse o entry default,
o Vite tentaria empacotar isso pro navegador e o build morreria. A solução: conditional exports que expõem
só fatias seguras.
packages/core/package.json (trecho)
{
"exports": {
".": "./dist/index.js", // Node-only (skill, scan)
"./types": "./dist/types/index.js", // Browser-safe
"./schema": "./dist/schema/index.js", // Browser-safe
"./search": "./dist/search/index.js" // Browser-safe
}
}
🚨 Atenção
Importar from '@understand-anything/core' dentro de packages/dashboard/ é proibido.
Use from '@understand-anything/core/search', /types, ou /schema. Esse é um dos erros que mais aparecem em PR de contribuidor novo.
✓ FAZER (dashboard)
- ✓import {'{ Graph }'} from '@ua/core/types'
- ✓import {'{ validate }'} from '@ua/core/schema'
- ✓import {'{ fuzzySearch }'} from '@ua/core/search'
✗ NÃO fazer (dashboard)
- ✗import {'{ ... }'} from '@ua/core'
- ✗import {'{ readGraph }'} from '@ua/core/persistence'
- ✗import fs from 'node:fs' (browser!)
Conditional exports
Múltiplos entrypoints
Boundary
Browser ↔ Node
Vite-friendly
Build não quebra
TS strict
.d.ts por subpath
🎨 packages/dashboard: o frontend que o usuário vê
Aqui mora o app React. Stack escolhida pra ser leve e moderna: Vite como bundler, React Flow para o canvas do grafo, Zustand para estado global e Tailwind v4 com tokens centralizados. Sem Redux, sem Monaco, sem ChatPanel — o foco é o grafo.
Layout: 75% grafo + sidebar 360px
Decisão de UX
O grafo é a estrela. A sidebar à direita é um painel auxiliar que reage à seleção. Nada de painel inferior cheio de abas — isso vira ruído.
Schema validation no boot
Falha cedo, falha alto
Ao carregar o JSON, o dashboard valida contra o schema do core. Falha = banner vermelho explicando qual campo está errado. Nunca tela em branco.
Tema dark luxury
Identidade visual
Preto profundo #0a0a0a, acento gold/amber #d4a574, tipografia DM Serif Display nos títulos. Tailwind v4 tokens centralizam tudo.
React Flow
Canvas de grafo
Zustand
Estado global enxuto
Tailwind v4
Tokens centralizados
prism-react-renderer
Code viewer leve
🔌 understand-anything-plugin/: skills, agents, hooks, src
A pasta understand-anything-plugin/ é o "embrulho" Claude-Code. Ela junta TypeScript dos slash-commands em src/,
definições de skills/, agentes em agents/ e hooks de auto-update. É o ponto de integração com o runtime.
Estrutura
understand-anything-plugin/
├── packages/
│ ├── core/ # @understand-anything/core
│ └── dashboard/ # @understand-anything/dashboard
├── src/ # TypeScript dos slash-commands
│ ├── understand-chat.ts
│ ├── understand-diff.ts
│ ├── understand-explain.ts
│ └── understand-onboard.ts
├── skills/ # Skill definitions (.md frontmatter)
├── agents/ # Agentes do pipeline
│ ├── project-scanner.md
│ ├── file-analyzer.md
│ ├── architecture-analyzer.md
│ ├── tour-builder.md
│ └── graph-reviewer.md
└── .claude-plugin/
└── plugin.json # Manifest Claude Code
📊 Como nasce um comando novo
- 1. Escreve a lógica TS em
src/understand-novo.ts - 2. Cria a skill em
skills/understand-novo/SKILL.mdcom frontmatter - 3. Se precisar de pipeline, adiciona agente em
agents/ - 4. Builda com
pnpm --filter @understand-anything/skill build
💡 Dica prática
Agentes omitem o campo model no frontmatter. Era model: inherit antes — mas opencode
e outras ferramentas tratam isso como literal e quebram com ProviderModelNotFoundError. Sem campo, cada plataforma usa o default dela. Veja a issue #167.
src/
TS dos comandos
skills/
Definições .md
agents/
Pipeline workers
hooks/
post-commit, etc.
🛒 Três manifests: Claude, Cursor, Copilot
Cada runtime quer um manifesto diferente — e cada um valida coisas diferentes. O Understand Anything mantém três pastas:
.claude-plugin/, .cursor-plugin/, .copilot-plugin/. Cada uma com seu plugin.json. Mas o número da versão tem que bater.
🚨 Cinco arquivos, uma versão
Quando empurra pra remote, atualize a versão em todos os cinco:
- • understand-anything-plugin/package.json
- • understand-anything-plugin/.claude-plugin/plugin.json
- • .claude-plugin/plugin.json
- • .cursor-plugin/plugin.json
- • .copilot-plugin/plugin.json
Cuidado: .claude-plugin/marketplace.json NÃO tem campo version. Adicionar quebra a validação do marketplace.
✓ Auto-discovery
- ✓Cursor: detecta
.cursor-plugin/plugin.jsonao abrir o repo - ✓VS Code + Copilot (v1.108+): mesma ideia via
.copilot-plugin/ - ✓Sem instalação manual no fluxo padrão
📦 Instalação explícita
- Claude Code:
/plugin install understand-anything - Codex/OpenCode/etc:
install.sh codex - Copilot CLI:
copilot plugin install ...
3 manifests
Mesmo plugin, runtimes diferentes
5 versões
Sincronizadas em cada release
marketplace.json
Sem version (schema strict)
install.sh
12 plataformas suportadas
📋 Resumo do Módulo
/types, /schema, /search.Próximo Módulo:
2.2 — O pipeline de agentes e o knowledge graph