bulhufas

Servidor MCP que ingere documentações de projetos uma vez e permite que o Claude pesquise por significado em vez de ler tudo — economizando tokens em bases de código grandes.

Documentação

bulhufas

Gerenciamento de projetos com RAG que captura o que as ferramentas de PM não capturam.

Build Go Reference Go Report Card License

Começando · Como Funciona · API · Self-Host · Contribuindo


Por que "bulhufas"?

Bulhufas é uma gíria do português brasileiro para "nada", "coisa nenhuma", "bupkis" — absolutamente nada.

Como em: "Quanto o Claude sabe sobre aquela decisão que seu time tomou no WhatsApp na quinta-feira passada?" Bulhufas.

"E aquele bloqueio que alguém mencionou na daily?" Bulhufas.

"E aquela decisão de arquitetura de dois sprints atrás?" Você adivinhou. Bulhufas.

Agora ele sabe.


Times tomam decisões no Slack, WhatsApp e reuniões — e nada disso chega à ferramenta de PM. bulhufas captura conversas brutas, extrai artefatos estruturados de projeto (decisões, itens de ação, bloqueios, mudanças de escopo) e os torna pesquisáveis via embeddings semânticos.

Binário único. Sem dependências externas. Embeddings rodam no processo.

Recursos

  • Conversa para Estrutura — Cole conversas brutas e obtenha blocos estruturados: decisões, itens de ação, bloqueios, requisitos, mudanças de escopo
  • Memória de Agente — Armazene memórias de trabalho, episódicas, semânticas e procedurais em namespaces isolados com proveniência, confiança, importância e janelas de validade
  • Busca Semântica — Encontre contexto pelo significado, não por palavras-chave. "O que decidimos sobre autenticação?" encontra o bloco certo mesmo que "autenticação" não esteja no texto
  • Recall Compacto — Retorne um pacote de contexto limitado com IDs de memória e referências de origem para que qualquer LLM possa recuperar apenas o que precisa
  • CRUD no Conhecimento — Atualize status, adicione contexto, arquive blocos desatualizados. Sua base de conhecimento permanece atualizada
  • Binário Único — Um binário Go com armazenamento vetorial embutido (chromem-go) e modelo de embeddings (hugot/all-MiniLM-L6-v2). Sem Ollama, sem Docker, sem processos externos
  • Self-Hostable — Implante em qualquer lugar: Coolify, Railway, Hetzner, AWS, GCP. Roda em um VPS de 2GB

Como Funciona

Ingestion and retrieval flow

You paste a conversation into your AI assistant
         |
The LLM extracts structured chunks with metadata
         |
bulhufas stores chunks + generates embeddings in-process (hugot)
         |
Later: "what's pending from last week?" -> semantic search returns relevant chunks

O Que É Capturado

Tipo de BlocoExemplo
decision"Escolhemos WebSockets em vez de polling para atualizações em tempo real"
action_item"Hugo criará credenciais de banco somente leitura até sexta-feira"
blocker"Não dá para fazer deploy até o certificado SSL ser renovado"
requirement"O cliente precisa de exportação CSV para o relatório financeiro"
scope_change"Módulo de autenticação expandido para incluir SSO"
context"A API legada retorna XML, não JSON"
research_finding"pgvector supera pinecone para o nosso tamanho de dataset"
status_update"Integração de pagamento está ativa em staging"

Instalação

1. Compile a partir do código-fonte

# Requires Go 1.22+ with CGO enabled
git clone https://github.com/HugoluizMTB/bulhufas.git
cd bulhufas
make build

2. Adicione ao Claude Code

claude mcp add --transport stdio --scope user bulhufas -- /absolute/path/to/bulhufas/bin/bulhufas --mcp

Substitua /absolute/path/to pelo caminho real onde você clonou o repositório. Use --scope user para disponibilizá-lo em todos os seus projetos. Use --scope project para restringi-lo apenas ao projeto atual.

3. Reinicie o Claude Code e verifique

Execute /mcp dentro do Claude Code. Você deve ver bulhufas conectado com 10 ferramentas:

FerramentaDescrição
save_conversationSalvar uma conversa com blocos estruturados extraídos
rememberSalvar um registro de memória com escopo e metadados de proveniência e ciclo de vida
searchBusca semântica em todos os blocos armazenados
recallRecuperar um pacote de contexto isolado por namespace e consciente de tokens
observe_turnAprender automaticamente uma virada significativa como memória episódica
list_chunksListar blocos com filtros opcionais de tipo/status
update_statusAtualizar status de bloco por ID
delete_chunkExcluir um bloco por ID
list_actionsListar todos os itens de ação pendentes
consolidate_memoryVisualizar ou executar consolidação episódica-para-semântica/procedural

Na primeira execução, o modelo de embeddings (all-MiniLM-L6-v2, ~80MB) é baixado automaticamente para ./data/models/.

Executar como Servidor HTTP (opcional)

./bin/bulhufas

Inicia uma API HTTP na porta 8420. Use a flag --mcp para o modo MCP stdio.

Gateway automático para qualquer LLM compatível com OpenAI

Para capturar viradas automaticamente no Claude Code sem depender do modelo chamar observe_turn, registre o hook Stop em integrations/claude-code-hook.mjs. Veja docs/claude-code-sessions.md.

Para provedores que não suportam MCP, execute o proxy de memória sem dependências:

LLM_UPSTREAM_URL=https://api.openai.com \
LLM_UPSTREAM_API_KEY="$OPENAI_API_KEY" \
BULHUFAS_NAMESPACE=project:bulhufas \
make proxy

Aponte o cliente para http://127.0.0.1:8421/v1. O proxy recupera memória com escopo antes de cada conclusão de chat e captura viradas substantivas após a resposta. Funciona com endpoints compatíveis com OpenAI, como Ollama, vLLM e LM Studio; veja integrations/README.md.

Com Docker Compose, use docker compose --profile proxy up -d após definir LLM_UPSTREAM_URL, LLM_UPSTREAM_API_KEY e BULHUFAS_NAMESPACE no ambiente.

Variáveis de Ambiente

VariávelPadrãoDescrição
PORT8420Porta do servidor
DATA_DIR./dataDiretório de armazenamento persistente (banco SQLite, arquivos de modelo, índice vetorial)
MEMORY_LLM_BASE_URLnão definidoEndpoint /v1 compatível com OpenAI usado para consolidação automática
MEMORY_LLM_API_KEYnão definidoChave de API opcional para o provedor de consolidação
MEMORY_LLM_MODELgpt-4o-miniModelo usado pelo gerenciador de memória em segundo plano
MEMORY_CONSOLIDATION_INTERVAL15mIntervalo para promover memórias episódicas quando MEMORY_LLM_BASE_URL está definido
MEMORY_NAMESPACEdefaultNamespace processado pelo consolidador automático
BULHUFAS_API_KEYnão definidoChave de API opcional exigida por clientes da API HTTP
BULHUFAS_ALLOWED_NAMESPACEnão definidoLimite de namespace rígido opcional para esta instância do servidor
BULHUFAS_TLS_CERT_FILEnão definidoCaminho do certificado; habilita HTTPS junto com o arquivo de chave
BULHUFAS_TLS_KEY_FILEnão definidoCaminho da chave privada para HTTPS

API

Salvar uma conversa com blocos

curl -X POST http://localhost:8420/api/conversations \
  -H "Content-Type: application/json" \
  -d '{
    "source": "whatsapp",
    "summary": "Discussion about database access",
    "participants": ["renan", "hugo"],
    "chunks": [
      {
        "content": "Renan needs read-only access to PostgreSQL",
        "type": "decision",
        "tags": ["infra", "postgres"],
        "people": ["renan"],
        "status": "pending",
        "action_item": "Create read-only credentials"
      }
    ]
  }'

Busca semântica

curl -X POST http://localhost:8420/api/search \
  -H "Content-Type: application/json" \
  -d '{"text": "database access", "limit": 5}'

Salvar e recuperar memória de agente

curl -X POST http://localhost:8420/api/memories \
  -H "Content-Type: application/json" \
  -d '{
    "content": "The payments service uses idempotency keys for retries",
    "memory_kind": "procedural",
    "namespace": "project:bulhufas",
    "source": "architecture-review",
    "source_ref": "meeting:2026-08-01",
    "confidence": 0.95,
    "importance": 0.8,
    "tags": ["payments", "reliability"]
  }'

curl -X POST http://localhost:8420/api/recall \
  -H "Content-Type: application/json" \
  -d '{
    "text": "How should payment retries work?",
    "namespace": "project:bulhufas",
    "memory_kinds": ["semantic", "procedural"],
    "limit": 5,
    "max_chars": 3000
  }'

recall retorna tanto results estruturado quanto uma string context limitada. Namespaces, IDs de projeto/tenant/sessão e tipos de memória são filtros rígidos, para que contextos de agentes não relacionados não sejam concatenados acidentalmente.

Quando MEMORY_LLM_BASE_URL está configurado, um gerenciador em segundo plano consolida periodicamente memórias episódicas em registros semânticos/procedurais conservadores. Também pode ser acionado ou visualizado explicitamente:

curl -X POST http://localhost:8420/api/consolidate \
  -H "Content-Type: application/json" \
  -d '{"namespace":"project:bulhufas","limit":32,"dry_run":true}'

Aprendizado ambiente

No uso normal do agente, o cliente pode chamar recall no início da tarefa e observe_turn após viradas substantivas. Estas são chamadas de ferramenta internas: você não precisa digitar "lembre disso" para aprendizado comum. As ferramentas explícitas remember, atualização e exclusão permanecem disponíveis para correções, promoções, esquecimento e controle exato. Para gateways de chat que podem encaminhar cada mensagem automaticamente, POST /api/turns fornece o mesmo caminho de captura sem depender do modelo para iniciar a chamada.

Listar blocos com filtros

curl "http://localhost:8420/api/chunks?type=blocker&status=pending"

Listar itens de ação pendentes

curl http://localhost:8420/api/actions

Atualizar status de bloco

curl -X PATCH http://localhost:8420/api/chunks/{id}/status \
  -H "Content-Type: application/json" \
  -d '{"status": "resolved"}'

Excluir um bloco

curl -X DELETE http://localhost:8420/api/chunks/{id}

Verificação de saúde

curl http://localhost:8420/healthz

Métricas estão disponíveis em GET /metrics no formato de texto Prometheus. Defina BULHUFAS_API_KEY para proteger rotas da API; coloque o serviço atrás de um proxy reverso TLS ou defina ambas as variáveis de arquivo TLS diretamente.

Arquitetura

cmd/server/          -> entrypoint, wires everything together
internal/
  domain/            -> core types: Conversation, Chunk, WorkItem, Relation
  mcp/               -> HTTP server, handlers, request/response logic
  store/             -> persistence interface + SQLite implementation
  vectorstore/       -> embedded vector search via chromem-go
  embedder/          -> in-process embeddings via hugot (all-MiniLM-L6-v2)
scripts/             -> test scripts
macos/BulhufasMac/   -> native macOS app: Dynamic Island + menu bar (GPL-3.0)

Todas as dependências externas estão atrás de interfaces. Troque SQLite por Postgres, ou chromem-go por pgvector — sem tocar na lógica de negócio.

Stack

ComponenteBibliotecaRoda no processo?
Embeddinghugot + all-MiniLM-L6-v2 (384 dim)Sim
Armazenamento vetorialchromem-goSim
Banco de dadosSQLite (mattn/go-sqlite3)Sim
Servidor HTTPGo stdlib net/httpSim
UI macOSSwiftUI + AppKit NSPanelApp nativo

Sem Ollama. Sem Docker. Sem bancos de dados externos. Um binário.

O backend local é deliberadamente o primeiro nível de um design de memória maior. SQLite/chromem é o armazenamento offline padrão; o app macOS nativo conversa com ele pela API HTTP local, enquanto o adaptador Postgres opcional pode usar pgvector HNSW mais busca em texto completo do PostgreSQL. Quantização vetorial como TurboQuant é uma otimização opcional de índice e deve ser validada contra recall antes de ser habilitada.

O adaptador opcional PostgreSQL/pgvector está documentado em docs/pgvector.md. A pesquisa mais profunda sobre LLM e memória está resumida em docs/research-landscape.md.

Self-Hosting

Binário

CGO_ENABLED=1 GOOS=linux go build -o bulhufas ./cmd/server
scp bulhufas your-server:/opt/bulhufas/
ssh your-server '/opt/bulhufas/bulhufas'

Docker

docker build -t bulhufas .
docker run -d --name bulhufas -p 8420:8420 -v bulhufas-data:/data bulhufas

Docker Compose

git clone https://github.com/HugoluizMTB/bulhufas.git
cd bulhufas
docker compose up -d

Funciona com Coolify, Railway, Hetzner, AWS, GCP, Oracle Cloud — qualquer coisa que rode Docker.

App macOS nativo

O app macOS não tem janela regular. Ele vive em dois lugares: uma Dynamic Island que fica pendurada no notch, e um painel na barra de menu.

make macos-open

Dynamic Island. Fechada, ela tem exatamente o tamanho do notch e, portanto, é invisível. Passar o mouse abre; clicar fixa aberta. Quando novas memórias chegam, ela se alarga brevemente em uma prévia. O estado aberto mostra a sessão ativa do Claude Code e memórias recentes ou a lista de sessões. Em telas sem notch, a mesma forma fica pendurada na borda superior.

Barra de menu. Um painel com a contagem de memórias, atividade de captura ao longo do tempo e uma divisão do que foi capturado por tipo de bloco.

Sessões do Claude Code. O app lista sessões lendo metadados de arquivos de $CLAUDE_CONFIG_DIR/projects, ~/.claude/projects e ~/.claude-pessoal/projects — apenas horários de modificação e nomes de arquivos. O conteúdo das transcrições nunca é aberto e nenhuma credencial é lida. A captura de memória em si ainda acontece pelo servidor MCP; veja docs/claude-code-sessions.md.

O app usa por padrão http://127.0.0.1:8420. Defina BULHUFAS_URL antes de iniciá-lo para usar outro endpoint HTTP local ou remoto. A fórmula Homebrew está documentada em docs/homebrew.md.

Nota de licença: o app macOS em macos/ é GPL-3.0, porque contém código derivado de Atoll e, através dele, boring.notch. O servidor Go e todo o resto neste repositório permanecem Apache-2.0 — são programas separados que se comunicam por uma API HTTP local. Veja macos/NOTICE.

Roadmap

  • Tipos de domínio principais e interfaces
  • API HTTP com salvar/buscar/atualizar/excluir
  • Implementação de armazenamento SQLite
  • Embeddings no processo via hugot (all-MiniLM-L6-v2)
  • Armazenamento vetorial chromem-go
  • Busca semântica com enriquecimento SQLite
  • Endpoint de itens de ação
  • Protocolo de servidor MCP (transporte stdio via mcp-go)
  • Imagem Docker
  • App macOS nativo: Dynamic Island + barra de menu
  • Lista de sessões do Claude Code a partir de metadados de transcrições locais
  • Plugin Slack
  • MCP remoto via transporte SSE

Contribuindo

Veja CONTRIBUTING.md para instruções de configuração, estilo de código e processo de PR.

Licença

Apache License 2.0 — use livremente, até comercialmente. Proteção de patente incluída.


Criado por @HugoluizMTB