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.

CI npm

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.

MINIPAINTER terminal UI — catalog

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 en data/catalog/; lo que posees vive en ~/.minipainting/inventory.json y 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

Hero Screen

Vista de Búsqueda

Búsqueda filtrada para una consulta semántica como bone.

See: docs/assets/search.txt

Search View

Vista de Propiedad

Presentación solo de inventario enfocada en lo que ya está vinculado a tu colección.

See: docs/assets/owned.txt

Owned View

Flujo CLI

Uso representativo de línea de comandos para búsqueda, actualizaciones de propiedad y coincidencia de colores.

See: docs/assets/cli.txt

CLI Flow

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 — liveness
  • GET /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:

Deploy to Render

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 actual
  • SELECTED PIGMENT: la pintura actualmente resaltada con proveedor, familias, uso y RGB
  • RITUAL COMMANDS: la leyenda de comandos para la sesión activa

Comandos actuales de la TUI:

  • search <text>
  • owned
  • catalog
  • toggle
  • quit

Uso recomendado:

  1. comienza con catalog
  2. reduce con search bone, search black o consultas similares
  3. inspecciona el panel de pigmento seleccionado
  4. 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 /data en 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.json preexistente 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_search
  • paint_show
  • inventory_list
  • inventory_mark_owned
  • inventory_mark_unowned
  • match_color
  • match_describe

Flujo local sugerido:

  1. inicializa tu registro una vez con node src/cli.mjs catalog sync
  2. agrega el servidor MCP a Claude Desktop
  3. 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 /health
  • GET /api/paints
  • GET /api/paints/:paint
  • GET /api/inventory
  • PUT /api/inventory/:paint
  • DELETE /api/inventory/:paint
  • POST /api/match/color
  • POST /api/match/describe
  • POST /mcp

Configuración opcional en tiempo de ejecución:

  • PORT — puerto de escucha, por defecto 3000
  • DATA_DIR — directorio de estado persistente, por defecto /data en Docker
  • AUTH_TOKEN — protege /api/* y /mcp con Authorization: Bearer ...
  • INVENTORY_SYNC_TOKEN — protege el endpoint de sincronización /inventory heredado

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

VariableRequeridaPropósito
INVENTORY_SYNC_TOKENpara /inventoryToken Bearer que protege GET/POST /inventory; cuando no está configurado, la sincronización devuelve 503
INVENTORY_PATHnoRuta a inventory.json; por defecto ~/.minipainting/inventory.json localmente, /data/inventory.json en la imagen Docker
INVENTORY_JSONnoJSON de semilla de una sola vez; solo se usa cuando INVENTORY_PATH está ausente en el primer arranque
WARPAINT_INVENTORY_JSONnoAlias heredado de INVENTORY_JSON
MCP_SERVER_NAMEnoNombre del servidor en el handshake MCP + registro de inicio; por defecto paint-inventory
PORTno (por defecto 3000)Puerto TCP para escuchar

Limitaciones conocidas

  • /mcp aú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:

  1. Haz un fork o clona el repositorio.

  2. (Opcional) Renombra tu aplicación Fly en fly.toml.

  3. 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)"
    
  4. (Opcional) Nombra tu servidor MCP (se muestra en el handshake MCP y los registros de inicio):

    fly secrets set MCP_SERVER_NAME=my-paints
    
  5. Despliega:

    fly deploy
    
  6. 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