minipainter
Inventario local de pinturas para miniaturas + coincidencia de colores entre marcas para agentes de IA (Citadel, Army Painter, Vallejo, AK).
Documentación
MINIPAINTER
El banco de pinturas, indexado.
Sitio: arturskowronski.github.io/minipainter
minipainter es un registro de pinturas local-first para flujos de trabajo de pintura de miniaturas. Existe por una razón práctica: las sugerencias de pintura con IA son mucho más útiles cuando entienden las pinturas que realmente posees.
El proyecto te ofrece:
- un catálogo local determinista (1,607 pinturas de Citadel, Army Painter, Vallejo, AK) e inventario
- búsqueda de pinturas priorizando lo que posees y coincidencia de colores entre marcas
- una interfaz de terminal a color (TUI) que muestra el RGB real de cada pintura como muestra
- servidores MCP tanto para Claude Desktop como para ChatGPT
- una superficie CLI diseñada tanto para humanos como para flujos de trabajo de agentes
La TUI a color
La TUI del libro mayor es una aplicación de terminal real a color: un banner MINIPAINTER, marcos de sección dorados, estado verde OWNED / rojo MISSING, y una muestra truecolor del RGB de cada pintura. El color se activa para una TTY y respeta NO_COLOR.
Por Qué Existe
La mayoría de los flujos de consejos de pintura fallan en el mismo punto: recomiendan pinturas que no tienes a mano.
minipainter está construido para resolver exactamente ese problema:
- mantener un registro local de lo que hay en tu estante de pinturas
- buscarlo rápidamente por nombre, rol, familia y color aproximado
- preparar una base de inventario estable para una futura habilidad de IA que pueda inspeccionar enlaces, fotos e imágenes de modelos
La meta a largo plazo no es "la IA elige colores aleatorios para miniaturas". La meta es "la IA razona primero desde tu inventario real, y luego sugiere alternativas más fuertes solo cuando es útil".
Características Destacadas
Owned-first matching: las búsquedas y recomendaciones pueden priorizar pinturas que ya tienes.Catalog in repo, inventory in your home: los registros de pinturas viven endata/catalog/; lo que posees vive en~/.minipainting/inventory.jsony te sigue entre proyectos.RGB-aware search: valores RGB aproximados ayudan con la coincidencia de color más cercano.Colored TUI: libro mayor de terminal con muestras RGB por pintura y estado OWNED/MISSING.Agent-friendly CLI: salida de comandos determinista para integración con IA (Claude + ChatGPT MCP).
Capturas de Pantalla
Pantalla Principal
TUI a pantalla completa con banner, catálogo, panel de detalles y franja de comandos.
See: docs/assets/hero.txt
Vista de Búsqueda
Búsqueda filtrada para una consulta semántica como bone.
See: docs/assets/search.txt
Vista de Propiedad
Presentación solo de inventario enfocada en lo que ya está vinculado a tu colección.
See: docs/assets/owned.txt
Flujo CLI
Uso representativo de línea de comandos para búsqueda, actualizaciones de propiedad y coincidencia de colores.
See: docs/assets/cli.txt
Ejecutar con Docker (Postgres)
Toda la pila — servidor MCP/HTTP más un Postgres que almacena tu inventario — se inicia con un solo comando. El inventario persiste en un volumen con nombre, por lo que sobrevive reinicios de contenedor y docker compose down / recreación (solo down -v lo borra).
docker compose up --build # http://localhost:3000
GET /health— livenessGET /api/inventory— pinturas poseídas (desde Postgres)POST /mcp— MCP para Claude Desktop ·POST /mcp/v3— MCP para ChatGPT (search/fetch)
El almacenamiento se selecciona mediante DATABASE_URL: configúralo (como hace docker-compose.yml) para Postgres, déjalo sin configurar para usar un archivo JSON de inventario local (comportamiento local sin cambios). Ver .env.example.
Desplegar
Cualquier host con Docker + Postgres funciona (Fly.io, Railway, un VPS…). Para un servidor MCP remoto con un clic y una base de datos gestionada, el repositorio incluye un Render Blueprint (render.yaml) que aprovisiona el servicio web y Postgres juntos y configura DATABASE_URL automáticamente:
El despliegue de referencia warpaint-mcp.fly.dev se ejecuta en Fly.io con Fly Managed Postgres — ver docs/deploy-fly.md para los pasos de fly mpg attach + migración.
Instalar
La forma más rápida — ejecútalo directamente desde npm con npx, sin clonar ni instalar:
npx minipainter paint search bone
npx minipainter match color "#d2c29b"
npx minipainter tui
O instálalo globalmente para tener el comando corto mpaint en todas partes:
npm install -g minipainter
mpaint paint search bone
mpaint match color "#d2c29b"
El catálogo está incluido, por lo que la búsqueda y la coincidencia funcionan en la primera ejecución sin nada que configurar. Tu inventario vive en ~/.minipainting/inventory.json, creado automáticamente la primera vez que marcas una pintura como poseída (el ~/.warpaint/ heredado se migra automáticamente).
Requisitos:
- Node.js 18 o más reciente
- shell tipo POSIX (Linux, macOS, WSL)
Desde el código fuente
Para modificarlo, clona y ejecuta contra el árbol de trabajo:
git clone https://github.com/ArturSkowronski/minipainter.git
cd minipainter
npm install
node src/cli.mjs paint search bone
Después de eso tienes cuatro modos de uso:
- CLI / TUI — ver Inicio Rápido abajo
- Servidor HTTP autoalojado — un runtime único compatible con Docker con almacenamiento JSON y endpoints de API
- MCP local para Claude Desktop — ver Configuración MCP de Claude Desktop
- MCP remoto para Claude móvil/web — ver MCP Remoto
Inicio Rápido
Inicializa el inventario local en ~/.minipainting/inventory.json:
node src/cli.mjs catalog sync
Busca pinturas:
node src/cli.mjs paint search black
node src/cli.mjs paint search bone --json
Inspecciona una pintura:
node src/cli.mjs paint show "Abaddon Black" --json
Marca pinturas como poseídas o faltantes:
node src/cli.mjs inventory own "Abaddon Black"
node src/cli.mjs inventory unown "Abaddon Black"
node src/cli.mjs inventory list
Ejecuta coincidencia semántica o de color:
node src/cli.mjs match describe bone
node src/cli.mjs match color "#d2c29b"
Lanza la TUI:
node src/cli.mjs tui
Ejecuta el servidor MCP localmente:
node src/mcp-server.mjs
Ejecuta el servidor HTTP autoalojado localmente:
DATA_DIR=.minipainting-data node src/mcp-http-server.mjs
Flujo de Trabajo de la TUI
La TUI se centra en tres áreas de presentación:
FORGE CATALOG: pinturas visibles en el alcance actualSELECTED PIGMENT: la pintura actualmente resaltada con proveedor, familias, uso y RGBRITUAL COMMANDS: la leyenda de comandos para la sesión activa
Comandos actuales de la TUI:
search <text>ownedcatalogtogglequit
Uso recomendado:
- comienza con
catalog - reduce con
search bone,search blacko consultas similares - inspecciona el panel de pigmento seleccionado
- alterna la propiedad a medida que tu colección cambia
Dirección del Proyecto
Implementado ahora:
- registro JSON local
- catálogos iniciales de proveedores para Citadel y Army Painter
- seguimiento de inventario poseído / faltante
- búsqueda determinista y coincidencia de color
- presentación de terminal a color con muestras por pintura
- servidor MCP local para Claude Desktop
Planeado después:
- una habilidad separada para analizar enlaces de sets de pinturas
- llenado de inventario basado en imágenes desde fotos de botellas de pintura
- análisis de fotos de modelos que recomiende primero pinturas poseídas
- equivalentes entre proveedores más fuertes y sugerencias de coincidencia
Notas Técnicas
- Los datos del catálogo integrado viven en
data/catalog/(Citadel y Army Painter, mantenidos en control de versiones) - Archivo de inventario:
~/.minipainting/inventory.json— almacena solo ids de pinturas poseídas en la forma{ "version": 1, "owned": ["citadel/abaddon-black", ...] } - Directorio de datos del servidor autoalojado:
DATA_DIR(por defecto/dataen Docker); el inventario vive en<DATA_DIR>/inventory.json - El catálogo y el inventario se componen en tiempo de ejecución; guardar nunca reescribe el catálogo
- Los IDs son estables por convención (proveedor + slug de nombre); al cargar, los ids poseídos que faltan en el catálogo se reportan como advertencias en lugar de descartarse silenciosamente
- Un
.minipainting/registry.jsonpreexistente local al proyecto junto a la ruta del inventario se migra automáticamente en la primera ejecución - Los directorios de datos
.warpaint/heredados se renombran automáticamente a.minipainting/en la primera ejecución (tanto variantes de inicio como locales al proyecto) - Sobrescribe la ubicación del inventario en la superficie de API con
{ inventoryPath }o{ cwd }(el último resuelve a<cwd>/.minipainting/inventory.json, que es lo que usa el conjunto de pruebas para aislamiento) - Los valores RGB son colores de referencia aproximados para coincidencia, no una garantía de la apariencia final pintada
- Punto de entrada MCP:
node src/mcp-server.mjs - Script auxiliar MCP:
npm run mcp - Script auxiliar del servidor HTTP:
npm run server - Las capturas de demostración del README son reproducibles mediante:
npm run generate:demo
Configuración MCP de Claude Desktop
minipainter ahora incluye un servidor MCP local para que Claude Desktop pueda usar tu registro de pinturas directamente.
Ejemplo de configuración MCP local:
{
"mcpServers": {
"minipainter": {
"command": "node",
"args": ["/absolute/path/to/minipainter/src/mcp-server.mjs"]
}
}
}
Después de agregar el servidor, Claude Desktop puede llamar herramientas como:
paint_searchpaint_showinventory_listinventory_mark_ownedinventory_mark_unownedmatch_colormatch_describe
Flujo local sugerido:
- inicializa tu registro una vez con
node src/cli.mjs catalog sync - agrega el servidor MCP a Claude Desktop
- pide a Claude que busque pinturas o actualice la propiedad a través de las herramientas expuestas
Habilidad de Agente
Para Claude Code, obtén la habilidad directamente desde el sitio, sin necesidad de clonar. Viene con las salvaguardas correctas integradas: lecturas solo JSON, reglas product_format, manejo de fallos.
# project-scoped
mkdir -p .claude/skills/minipainter
curl -fsSL https://arturskowronski.github.io/minipainter/SKILL.md \
-o .claude/skills/minipainter/SKILL.md
O guárdala en ~/.claude/skills/minipainter/SKILL.md para usarla en todas partes.
Docker Autoalojado
La imagen Docker ejecuta un runtime de servidor HTTP único diseñado para uso autoalojado. Constrúyela desde el repositorio (aún no se publica ninguna imagen en un registro):
docker build -t minipainter .
docker run -p 3000:3000 -v minipainting-data:/data minipainter
O levanta el servidor junto con Postgres en un solo paso con docker compose up -d.
El servidor expone:
GET /healthGET /api/paintsGET /api/paints/:paintGET /api/inventoryPUT /api/inventory/:paintDELETE /api/inventory/:paintPOST /api/match/colorPOST /api/match/describePOST /mcp
Configuración opcional en tiempo de ejecución:
PORT— puerto de escucha, por defecto3000DATA_DIR— directorio de estado persistente, por defecto/dataen DockerAUTH_TOKEN— protege/api/*y/mcpconAuthorization: Bearer ...INVENTORY_SYNC_TOKEN— protege el endpoint de sincronización/inventoryheredado
MCP Remoto (Claude Móvil)
Para Claude móvil o web, el servidor MCP stdio anterior no es accesible. Ejecuta minipainter-mcp-http en su lugar — un transporte MCP HTTP Streamable que expone las mismas herramientas, más GET/POST /inventory para sincronizar el inventario local.
Prueba de humo local
export INVENTORY_SYNC_TOKEN=$(openssl rand -hex 32)
export PORT=3000
export INVENTORY_PATH=$HOME/.minipainting/inventory.json
npm run mcp:http
Luego en otra terminal:
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
Desplegar en Fly.io
El repositorio incluye un Dockerfile y fly.toml. Receta completa en docs/deploy-fly.md. Versión corta:
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
En Claude (móvil o web), agrega un conector personalizado:
- URL:
https://<your-app-name>.fly.dev/mcp
El endpoint /mcp actualmente no tiene autenticación — cualquiera con la URL puede llamar herramientas. Usa la oscuridad de la URL más los controles de red de Fly por ahora; agrega autenticación por usuario antes de compartir la URL.
Variables de entorno
| Variable | Requerida | Propósito |
|---|---|---|
INVENTORY_SYNC_TOKEN | para /inventory | Token Bearer que protege GET/POST /inventory; cuando no está configurado, la sincronización devuelve 503 |
INVENTORY_PATH | no | Ruta a inventory.json; por defecto ~/.minipainting/inventory.json localmente, /data/inventory.json en la imagen Docker |
INVENTORY_JSON | no | JSON de semilla de una sola vez; solo se usa cuando INVENTORY_PATH está ausente en el primer arranque |
WARPAINT_INVENTORY_JSON | no | Alias heredado de INVENTORY_JSON |
MCP_SERVER_NAME | no | Nombre del servidor en el handshake MCP + registro de inicio; por defecto paint-inventory |
PORT | no (por defecto 3000) | Puerto TCP para escuchar |
Limitaciones conocidas
/mcpaún no tiene autenticación. El token bearer solo protege/inventory.- Transporte sin estado: sin flujos SSE de herramientas de larga duración (las herramientas son rápidas, así que esto está bien).
Autoalojar tu propio MCP
El servidor MCP es genérico — solo el CLI (mpaint) está marcado. Para ejecutar tu propia instancia:
-
Haz un fork o clona el repositorio.
-
(Opcional) Renombra tu aplicación Fly en
fly.toml. -
Crea un volumen Fly y configura secretos:
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) Nombra tu servidor MCP (se muestra en el handshake MCP y los registros de inicio):
fly secrets set MCP_SERVER_NAME=my-paints -
Despliega:
fly deploy -
Registra el remoto en tu CLI local y sincroniza:
mpaint sync add default \ --url https://my-app.fly.dev \ --token <token-from-step-3> mpaint sync push
Después de esto, tu inventario local y el MCP desplegado permanecen sincronizados mediante mpaint sync push (subir local → remoto) y mpaint sync pull --force (sobrescribir local desde remoto).
Licencia
MIT © Artur Skowronski