minipainter
Inventário local de tintas para miniaturas + correspondência de cores entre marcas para agentes de IA (Citadel, Army Painter, Vallejo, AK).
Documentação
MINIPAINTEER
A bancada de tintas, indexada.
Site: arturskowronski.github.io/minipainter
minipainter é um registro de tintas local-first para fluxos de trabalho de pintura de miniaturas. Ele existe por um motivo prático: sugestões de tintas por IA são muito mais úteis quando entendem as tintas que você realmente possui.
O projeto oferece:
- um catálogo local determinístico (1.607 tintas entre Citadel, Army Painter, Vallejo, AK) e inventário
- busca de tintas priorizando as que você possui e correspondência de cores entre marcas
- uma interface de terminal colorida (TUI) que mostra o RGB real de cada tinta como uma amostra
- servidores MCP para Claude Desktop e ChatGPT
- uma superfície de CLI projetada para humanos e fluxos de trabalho de agentes
A TUI colorida
A TUI do livro-razão é um aplicativo de terminal realmente colorido: um banner MINIPAINTER, molduras de seção douradas, status verde OWNED / vermelho MISSING, e uma amostra truecolor do RGB de cada tinta. A cor é ativada para um TTY e respeita NO_COLOR.
Por que isso existe
A maioria dos fluxos de aconselhamento sobre tintas quebra no mesmo ponto: eles recomendam tintas que você não tem em mãos.
minipainter foi construído para resolver exatamente esse problema:
- manter um registro local do que está na sua estante de tintas
- pesquisar rapidamente por nome, função, família e cor aproximada
- preparar uma base de inventário estável para uma futura habilidade de IA que possa inspecionar links, fotos e imagens de modelos
O objetivo de longo prazo não é "a IA escolhe cores aleatórias para miniaturas". O objetivo é "a IA raciocina a partir do seu inventário real primeiro, e então sugere alternativas mais fortes apenas quando útil."
Destaques de recursos
Owned-first matching: buscas e recomendações podem priorizar tintas que você já possui.Catalog in repo, inventory in your home: os registros de tintas vivem emdata/catalog/; o que você possui vive em~/.minipainting/inventory.jsone acompanha você entre projetos.RGB-aware search: valores RGB aproximados ajudam na correspondência de cores mais próximas.Colored TUI: livro-razão de terminal com amostras RGB por tinta e status OWNED/MISSING.Agent-friendly CLI: saída de comando determinística para integração com IA (Claude + ChatGPT MCP).
Capturas de tela
Tela principal
TUI em tela cheia com banner, catálogo, painel de detalhes e faixa de comandos.
See: docs/assets/hero.txt
Visualização de busca
Busca filtrada para uma pesquisa semântica como bone.
See: docs/assets/search.txt
Visualização de possuídos
Apresentação apenas do inventário, focada no que já está vinculado à sua coleção.
See: docs/assets/owned.txt
Fluxo de CLI
Uso representativo de linha de comando para busca, atualizações de propriedade e correspondência de cores.
See: docs/assets/cli.txt
Executar com Docker (Postgres)
Toda a pilha — servidor MCP/HTTP mais um Postgres que armazena seu inventário — inicia com um único comando. O inventário persiste em um volume nomeado, então ele sobrevive a reinicializações de contêiner e docker compose down / recriação (apenas down -v o apaga).
docker compose up --build # http://localhost:3000
GET /health— livenessGET /api/inventory— tintas possuídas (do Postgres)POST /mcp— MCP para Claude Desktop ·POST /mcp/v3— MCP para ChatGPT (search/fetch)
O armazenamento é selecionado por DATABASE_URL: defina-o (como docker-compose.yml faz) para Postgres, deixe-o não definido para usar um arquivo de inventário JSON local (comportamento local inalterado). Veja .env.example.
Implantação
Qualquer host Docker + Postgres funciona (Fly.io, Railway, um VPS…). Para um servidor MCP remoto com um clique e banco de dados gerenciado, o repositório inclui um Render Blueprint (render.yaml) que provisiona o serviço web e o Postgres juntos e configura DATABASE_URL automaticamente:
A implantação de referência warpaint-mcp.fly.dev roda no Fly.io com Fly Managed Postgres — veja docs/deploy-fly.md para os passos de fly mpg attach + migração.
Instalação
A maneira mais rápida — execute direto do npm com npx, sem clonar, sem instalar:
npx minipainter paint search bone
npx minipainter match color "#d2c29b"
npx minipainter tui
Ou instale globalmente para obter o comando curto mpaint em qualquer lugar:
npm install -g minipainter
mpaint paint search bone
mpaint match color "#d2c29b"
O catálogo é incluído, então busca e correspondência funcionam na primeira execução sem nada para configurar. Seu inventário fica em ~/.minipainting/inventory.json, criado automaticamente na primeira vez que você marca uma tinta como possuída (o legado ~/.warpaint/ é migrado automaticamente).
Requisitos:
- Node.js 18 ou mais recente
- shell POSIX-ish (Linux, macOS, WSL)
A partir do código-fonte
Para hackear, clone e execute contra a árvore de trabalho:
git clone https://github.com/ArturSkowronski/minipainter.git
cd minipainter
npm install
node src/cli.mjs paint search bone
Depois disso, você tem quatro modos de uso:
- CLI / TUI — veja o Quickstart abaixo
- Servidor HTTP auto-hospedado — um runtime único amigável ao Docker com armazenamento JSON e endpoints de API
- MCP local para Claude Desktop — veja Configuração do MCP para Claude Desktop
- MCP remoto para Claude mobile/web — veja MCP remoto
Quickstart
Inicialize o inventário local em ~/.minipainting/inventory.json:
node src/cli.mjs catalog sync
Pesquise tintas:
node src/cli.mjs paint search black
node src/cli.mjs paint search bone --json
Inspecione uma tinta:
node src/cli.mjs paint show "Abaddon Black" --json
Marque tintas como possuídas ou ausentes:
node src/cli.mjs inventory own "Abaddon Black"
node src/cli.mjs inventory unown "Abaddon Black"
node src/cli.mjs inventory list
Execute correspondência semântica ou de cores:
node src/cli.mjs match describe bone
node src/cli.mjs match color "#d2c29b"
Inicie a TUI:
node src/cli.mjs tui
Execute o servidor MCP localmente:
node src/mcp-server.mjs
Execute o servidor HTTP auto-hospedado localmente:
DATA_DIR=.minipainting-data node src/mcp-http-server.mjs
Fluxo de trabalho da TUI
A TUI é centrada em três áreas de apresentação:
FORGE CATALOG: tintas visíveis no escopo atualSELECTED PIGMENT: a tinta atualmente destacada com fornecedor, famílias, uso e RGBRITUAL COMMANDS: a legenda de comandos para a sessão ativa
Comandos atuais da TUI:
search <text>ownedcatalogtogglequit
Uso recomendado:
- comece com
catalog - restrinja com
search bone,search blackou consultas semelhantes - inspecione o painel de pigmento selecionado
- alterne a propriedade conforme sua coleção muda
Direção do projeto
Implementado agora:
- registro JSON local
- catálogos iniciais de fornecedores para Citadel e Army Painter
- rastreamento de inventário possuído / ausente
- busca determinística e correspondência de cores
- apresentação de terminal colorida com amostras por tinta
- servidor MCP local para Claude Desktop
Planejado depois:
- uma habilidade separada para analisar links de conjuntos de tintas
- preenchimento de inventário orientado por imagens a partir de fotos de frascos de tinta
- análise de fotos de modelos que recomenda tintas possuídas primeiro
- equivalentes entre fornecedores mais fortes e dicas de correspondência
Notas técnicas
- Os dados do catálogo embutido vivem em
data/catalog/(Citadel e Army Painter, mantidos no controle de versão) - Arquivo de inventário:
~/.minipainting/inventory.json— armazena apenas IDs de tintas possuídas na forma{ "version": 1, "owned": ["citadel/abaddon-black", ...] } - Diretório de dados do servidor auto-hospedado:
DATA_DIR(padrão/datano Docker); o inventário fica em<DATA_DIR>/inventory.json - O catálogo e o inventário são compostos em tempo de execução; salvar nunca reescreve o catálogo
- IDs são estáveis por convenção (fornecedor + slug do nome); ao carregar, IDs possuídos ausentes do catálogo são relatados como avisos em vez de serem descartados silenciosamente
- Um
.minipainting/registry.jsonpré-existente local ao projeto, ao lado do caminho do inventário, é migrado automaticamente na primeira execução - Diretórios de dados legados
.warpaint/são renomeados automaticamente para.minipainting/na primeira execução (variantes de home e local ao projeto) - Substitua a localização do inventário na superfície da API com
{ inventoryPath }ou{ cwd }(o último resolve para<cwd>/.minipainting/inventory.json, que é o que a suíte de testes usa para isolamento) - Valores RGB são cores de referência aproximadas para correspondência, não uma garantia da aparência final pintada
- Ponto de entrada do MCP:
node src/mcp-server.mjs - Script auxiliar do MCP:
npm run mcp - Script auxiliar do servidor HTTP:
npm run server - As capturas de demonstração do README são reproduzíveis via:
npm run generate:demo
Configuração do MCP para Claude Desktop
minipainter agora inclui um servidor MCP local para que o Claude Desktop possa usar seu registro de tintas diretamente.
Exemplo de configuração local do MCP:
{
"mcpServers": {
"minipainter": {
"command": "node",
"args": ["/absolute/path/to/minipainter/src/mcp-server.mjs"]
}
}
}
Após adicionar o servidor, o Claude Desktop pode chamar ferramentas como:
paint_searchpaint_showinventory_listinventory_mark_ownedinventory_mark_unownedmatch_colormatch_describe
Fluxo local sugerido:
- inicialize seu registro uma vez com
node src/cli.mjs catalog sync - adicione o servidor MCP ao Claude Desktop
- peça ao Claude para pesquisar tintas ou atualizar a propriedade através das ferramentas expostas
Habilidade de agente
Para Claude Code, busque a habilidade direto do site, sem clonar. Ela vem com as proteções certas embutidas: leituras somente JSON, regras product_format, tratamento de falhas.
# project-scoped
mkdir -p .claude/skills/minipainter
curl -fsSL https://arturskowronski.github.io/minipainter/SKILL.md \
-o .claude/skills/minipainter/SKILL.md
Ou salve-a em ~/.claude/skills/minipainter/SKILL.md para usá-la em qualquer lugar.
Docker auto-hospedado
A imagem Docker executa um runtime de servidor HTTP único projetado para uso auto-hospedado. Construa-a a partir do repositório (nenhuma imagem é publicada em um registro ainda):
docker build -t minipainter .
docker run -p 3000:3000 -v minipainting-data:/data minipainter
Ou suba o servidor junto com Postgres em um único passo com docker compose up -d.
O servidor expõe:
GET /healthGET /api/paintsGET /api/paints/:paintGET /api/inventoryPUT /api/inventory/:paintDELETE /api/inventory/:paintPOST /api/match/colorPOST /api/match/describePOST /mcp
Configuração opcional em tempo de execução:
PORT— porta de escuta, padrão3000DATA_DIR— diretório de estado persistente, padrão/datano DockerAUTH_TOKEN— protege/api/*e/mcpcomAuthorization: Bearer ...INVENTORY_SYNC_TOKEN— protege o endpoint de sincronização legado/inventory
MCP remoto (Claude Mobile)
Para Claude mobile ou web, o servidor MCP stdio acima não é alcançável. Execute minipainter-mcp-http em vez disso — um transporte MCP HTTP Streamable expondo as mesmas ferramentas, além de GET/POST /inventory para sincronizar o inventário local.
Teste de fumaça local
export INVENTORY_SYNC_TOKEN=$(openssl rand -hex 32)
export PORT=3000
export INVENTORY_PATH=$HOME/.minipainting/inventory.json
npm run mcp:http
Então, em outro shell:
curl -s http://localhost:3000/health
curl -s -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
# Sync endpoint (bearer-token protected)
curl -s -H "Authorization: Bearer $INVENTORY_SYNC_TOKEN" \
http://localhost:3000/inventory
Implantar no Fly.io
O repositório inclui um Dockerfile e fly.toml. Receita completa em docs/deploy-fly.md. Versão curta:
fly launch --no-deploy --copy-config --name <your-app-name>
fly volumes create inventory_data --region <your-region> --size 1
fly secrets set INVENTORY_SYNC_TOKEN="$(openssl rand -hex 32)"
fly deploy
Conectar Claude
No Claude (mobile ou web), adicione um conector personalizado:
- URL:
https://<your-app-name>.fly.dev/mcp
O endpoint /mcp atualmente não tem autenticação — qualquer pessoa com a URL pode chamar ferramentas. Use a obscuridade da URL mais os controles de rede do Fly por enquanto; adicione autenticação por usuário antes de compartilhar a URL.
Variáveis de ambiente
| Variável | Obrigatório | Propósito |
|---|---|---|
INVENTORY_SYNC_TOKEN | para /inventory | Token Bearer protegendo GET/POST /inventory; quando não definido, a sincronização retorna 503 |
INVENTORY_PATH | não | Caminho para inventory.json; padrão ~/.minipainting/inventory.json localmente, /data/inventory.json na imagem Docker |
INVENTORY_JSON | não | JSON de semente único; usado apenas quando INVENTORY_PATH está ausente no primeiro boot |
WARPAINT_INVENTORY_JSON | não | Alias legado de INVENTORY_JSON |
MCP_SERVER_NAME | não | Nome do servidor no handshake do MCP + log de inicialização; padrão paint-inventory |
PORT | não (padrão 3000) | Porta TCP para escutar |
Limitações conhecidas
/mcpainda não tem autenticação. O token Bearer protege apenas/inventory.- Transporte sem estado: sem streams de ferramentas SSE de longa duração (as ferramentas são rápidas, então isso é aceitável).
Auto-hospedando seu próprio MCP
O servidor MCP é genérico — apenas a CLI (mpaint) é marcada. Para executar sua própria instância:
-
Faça um fork ou clone do repositório.
-
(Opcional) renomeie seu app Fly em
fly.toml. -
Crie um volume Fly e defina segredos:
fly volumes create inventory_data --size 1 --region <your-region> fly secrets set INVENTORY_SYNC_TOKEN=$(openssl rand -hex 24) # Optional one-time seed: fly secrets set INVENTORY_JSON="$(cat ~/.minipainting/inventory.json)" -
(Opcional) nomeie seu servidor MCP (mostrado no handshake do MCP e nos logs de inicialização):
fly secrets set MCP_SERVER_NAME=my-paints -
Implante:
fly deploy -
Registre o remoto em sua CLI local e sincronize:
mpaint sync add default \ --url https://my-app.fly.dev \ --token <token-from-step-3> mpaint sync push
Depois disso, seu inventário local e o MCP implantado permanecem sincronizados via mpaint sync push (upload local → remoto) e mpaint sync pull --force (sobrescrever local a partir do remoto).
Licença
MIT © Artur Skowronski