Miguel Santa 24 de mayo de 2026 14 min de lectura

Genera imágenes con tu marca desde VS Code

Un cerebro de marca en markdown, tu key en Keychain y un script de Python. La terminal te devuelve imágenes que ya salen con tu paleta, tu tono y tu estilo. Texto a imagen y con foto de referencia.

geminiimagenesmarcakeychainvscodeclaude-code

Video del canal · YouTubeEsta guía va con video en el canalTe muestro el flujo entero: cerebro de marca, key en Keychain y Claude Code invocando el script desde VS Code.Ver en YouTube @Santa_lA

1 · El problema · cada imagen arranca de cero

Generaste tu primera imagen con IA. Quedó linda. La segunda no se parece a la primera. La tercera tampoco. Todas se ven hechas por máquina, ninguna se ve hecha para tu marca.

Lo que falta no es el modelo. El modelo está bien. Lo que falta es contexto. Tu paleta, tu tono, tu público, lo que sí muestras y lo que nunca. Eso no vive en ninguna parte que el modelo pueda leer.

Cada vez tecleas el prompt de cero. Cada vez se te olvida un detalle. Cada vez sale distinta.

Este patrón cierra esa fuga. Tres piezas:

  • Un cerebro de marca en un archivo .md que viaja con cada prompt.
  • Tu API key guardada en el Keychain de macOS, no en un .env.
  • Un script de Python que junta las dos cosas y llama a Gemini.

Lo invocas desde tu terminal. O le pides a Claude Code dentro de VS Code que lo invoque por ti. Al final tienes imágenes consistentes con tu marca, sin repetir tu storytelling cada vez.


2 · La idea · cerebro · key · cliente

Antes del paso a paso, mira el flujo de lejos.

DE TU MARCA A LA IMAGEN · EN UN SOLO COMANDO CAPA 1 · CEREBRO brand_brain.md CAPA 2 · CLIENTE $ pythongenerate_image.py--prompt "..." generate_image.py Keychain CAPA 3 · MODELO Gemini gemini-3-pro-image CAPA 4 · SALIDA imagen.png · con tu marca OPCIONAL · MODO B foto.jpg (referencia)
Tu cerebro de marca viaja con cada prompt. La imagen sale ya con tu paleta, tu tono, tu estilo.

Cuatro piezas, una sola dirección:

  • Cerebro (capa 1). Un .md que tiene tu marca por escrito. Es la fuente.
  • Cliente (capa 2). Un script Python que lee el cerebro, lee tu prompt y lee la key.
  • Modelo (capa 3). Gemini recibe el cerebro como contexto y tu petición como instrucción.
  • Salida (capa 4). Un PNG que ya viene con tu paleta y tu estilo.

La pieza opcional es la referencia visual. Si pasas una foto local (tu producto, tu cara, una textura), Gemini la usa como ancla y te devuelve variaciones que parten desde ahí.

El cerebro no es un prompt largo que copias y pegas cada vez. Vive en un archivo. El script lo concatena solo. Tú nunca te peleas con el contexto.


3 · Tu key de Gemini · 3 líneas

Pídela una sola vez en Google AI Studio.

Guardarla en Keychain

Desde tu terminal (Mac). El -w sin valor te pregunta el token en interactivo, así no queda en .zsh_history:

bash
security add-generic-password \
  -a "santaia" \
  -s "santaia:gemini-key" \
  -l "Gemini API" \
  -w

Cambia santaia por el nombre que uses tú. Ese mismo nombre va en el argumento --project del script.

Verificar que quedó

bash
security find-generic-password -s "santaia:gemini-key" -w | head -c 12 && echo "..."

Si imprime los primeros 12 caracteres seguido de ..., está guardada. Listo.

Ya no la necesitas en ningún archivo. El script la pide al Keychain solo cuando va a llamar al modelo.


4 · La ficha tipo JARVIS de la key

El patrón completo no es solo guardar la key. Es dejar metadata de qué key es, dónde vive y cómo se rota. Yo lo hago con un archivo por servicio en una carpeta llamada 09-CREDENTIALS/.

La regla es simple: metadata en el .md, valor en el Keychain. Nunca al revés.

Esta es la ficha tipo que uso (la versión vacía está en el starter que descargas más abajo):

markdown
---
servicio: Google Gemini API Key
cuenta: [email protected]
proyectos_que_lo_usan:
  - mi-proyecto
keychain_service: mi-proyecto:gemini-key
keychain_account: mi-proyecto
fecha_guardado: 2026-05-24
expira: no expira (revocable manualmente)
console_url: https://aistudio.google.com/app/apikey
---

# Gemini API Key · mi-proyecto

Una línea: para qué se usa en este proyecto.

## Cómo guardarla, leerla, borrarla
[comandos de security]

## Si se filtra
1. Revoca en console_url
2. Genera nueva
3. delete del Keychain
4. add de nuevo
5. Actualiza fecha_guardado

¿Por qué este patrón importa? Porque dentro de 6 meses, cuando rotes la key o entre alguien nuevo a tu equipo, este archivo es el que responde "dónde está esa cosa". El Keychain guarda el valor, la ficha guarda la historia.


5 · El cerebro de marca · qué va dentro

El cerebro es un .md con frontmatter. Lo que escribas ahí viaja con cada prompt. Mientras más concreto, más consistente sale la imagen.

Para el starter inventé una marca demo, una academia ficticia de panadería casera llamada Levadura Lenta:

yaml
---
marca: Levadura Lenta
mision: enseñar panadería casera a gente que nunca ha amasado
voz: cálida, paciente, sin tecnicismos
paleta:
  primario: "#C97B4A"
  secundario: "#F4E4C1"
  acento: "#3D2817"
publico: principiantes 25-45 años, viven en ciudad
estilo_visual: fotografía cálida con grano, luz dorada, manos visibles, ingredientes humildes
do:
  - mostrar el proceso, no solo el resultado
  - personas reales, manos sucias de harina
dont:
  - planos perfectos de revistas
  - tipografía cursiva exagerada
---

Las 3 reglas para escribir un buen cerebro

Sé específico, no decorativo

"Fondo neutro" no le dice nada al modelo. "Mesa de madera oscura con luz lateral suave" sí. Si una palabra del cerebro la podrías reemplazar por su opuesto sin que cambie nada, sobra.

Hex codes, no nombres de colores

"Naranja terracota" lo interpreta cada modelo distinto. #C97B4A no. Nombra los colores por su hex en el frontmatter. El modelo los respeta.

Lista 2 o 3 dont claros

Las prohibiciones son lo que más diferencia tu marca de la imagen genérica. "Sin tipografía cursiva exagerada" te ahorra 30 iteraciones contra el default romántico de stock.


6 · El wrapper · keychain.py y generate_image.py

Dos piezas de código. La primera lee la key. La segunda llama a Gemini.

shared/secrets/keychain.py · wrapper de Keychain

Lee, guarda y borra secretos del Keychain de macOS. Lo importas desde el script principal. Si la key no existe, te dice exactamente qué comando correr para guardarla.

python
from __future__ import annotations
import subprocess

DEFAULT_PROJECT = "santaia"

def _service_name(key: str, project: str) -> str:
    if ":" in key:
        return key
    return f"{project}:{key}"

def get_secret(key: str, project: str = DEFAULT_PROJECT) -> str | None:
    try:
        result = subprocess.run(
            ["security", "find-generic-password",
             "-s", _service_name(key, project), "-w"],
            capture_output=True, text=True, check=False,
        )
    except FileNotFoundError:
        return None
    return result.stdout.strip() if result.returncode == 0 else None

def require_secret(key: str, project: str = DEFAULT_PROJECT) -> str:
    value = get_secret(key, project=project)
    if value is None:
        service = _service_name(key, project)
        raise RuntimeError(
            f"Secret '{service}' no encontrado en Keychain.\n"
            f"Guárdalo con: security add-generic-password "
            f"-s {service} -a {project} -w '<valor>' -U"
        )
    return value

(En el starter va completo con set_secret y delete_secret también.)

generate_image.py · el script CLI

Argumentos:

  • --prompt "texto": qué quieres ver (obligatorio).
  • --ref foto.jpg: imagen local de referencia (opcional, activa modo B).
  • --brain brand_brain.md: cerebro de marca (default ./brand_brain.md).
  • --out salida.png: ruta del PNG (default: out_<timestamp>.png).
  • --project santaia: prefijo de tu proyecto en Keychain.

El flujo es directo:

python
from google import genai
from google.genai import types
from PIL import Image
from shared.secrets.keychain import require_secret

MODEL = "gemini-3-pro-image-preview"

api_key = require_secret("gemini-key", project=args.project)
client = genai.Client(api_key=api_key)

brain_text = Path(args.brain).read_text(encoding="utf-8")
full_prompt = (
    "Generate an image following the brand brain below as visual + tone "
    "context. The brand brain defines colors (use the hex codes exactly), "
    "visual style, do/don't and audience.\n\n"
    f"=== BRAND BRAIN ===\n{brain_text}\n=== END BRAND BRAIN ===\n\n"
    f"User request: {args.prompt}"
)

contents = []
if args.ref:
    contents.append(types.Part.from_bytes(
        data=Path(args.ref).read_bytes(),
        mime_type="image/jpeg",
    ))
contents.append(full_prompt)

resp = client.models.generate_content(
    model=MODEL,
    contents=contents,
    config=types.GenerateContentConfig(response_modalities=["IMAGE"]),
)

raw = resp.candidates[0].content.parts[0].inline_data.data
Image.open(io.BytesIO(raw)).save(out_path, format="PNG")

7 · Modo A · texto a imagen

Una vez instalas dependencias (pip install google-genai pillow), la primera invocación es esta:

bash
python generate_image.py \
  --prompt "una hogaza de pan recién horneada sobre una mesa de madera oscura, luz lateral, vapor saliendo"

Output:

text
[modelo] gemini-3-pro-image-preview
[cerebro] brand_brain.md
[gemini] generando ...
[ok] guardada -> out_20260524-181830.png  (1024x1024)

La imagen sale con la paleta y el mood del cerebro. Sin que tuvieras que repetir "estilo cálido, grano, manos visibles" en el prompt. Eso ya viajó adentro.

Cuando el resultado no es lo que querías

Dos caminos, en este orden:

Ajusta el prompt si fue un error de petición

Pediste "pan" y querías "croissant". Cambias el prompt y vuelves a correr.

Ajusta el cerebro si el problema se repite

Pediste "pan" y siempre te sale en un plano cenital perfecto de revista. El problema no es el prompt: es que tu cerebro no tiene dont: planos cenitales todavía. Edítalo. La siguiente vez sale distinto.


8 · Modo B · imagen a imagen con foto local

Aquí es donde la mayoría de APIs te dejan colgado. Kie.ai, por ejemplo, solo recibe URLs públicas. No puedes pasarle una foto que vive en tu disco.

Gemini sí. Le pasas la ruta local con --ref y la usa como ancla visual:

bash
python generate_image.py \
  --prompt "el mismo pan pero cortado a la mitad, mostrando la miga" \
  --ref ./mi-hogaza.jpg

Output:

text
[ref] cargada mi-hogaza.jpg
[modelo] gemini-3-pro-image-preview
[cerebro] brand_brain.md
[gemini] generando ...
[ok] guardada -> out_20260524-182112.png  (1024x1024)

El modelo recibe tres cosas en orden: la imagen de referencia, el cerebro de marca, tu petición. Gemini usa la foto como composición base y la regenera siguiendo el cerebro.


9 · Que Claude Code lo invoque por ti

Hasta acá invocas el script tú, desde tu terminal. El siguiente paso es no escribir el comando.

Abres VS Code en la carpeta del starter. Tienes Claude Code corriendo (si no, mira Claude Code recién instalado). Le dices en lenguaje natural:

text
genera 3 variaciones de una foto cenital de masa madre sobre mesa de madera,
con la luz de la tarde, siguiendo el brand brain. Guárdalas en ./posts/

Claude lee tu petición. Sabe que tiene un script generate_image.py. Construye el comando con --prompt y --out, lo corre 3 veces variando levemente el prompt, te entrega las 3 imágenes en la carpeta posts/.

Tú nunca tocas la terminal. La diferencia es de minutos a segundos.


10 · Descarga el starter

Te dejo el cerebro de marca demo, el wrapper de Keychain, el script con los dos modos, el inventario base de credenciales y un README con los 3 pasos para arrancar. Lo descomprimes en tu carpeta de proyectos y lo adaptas:


11 · Lo que tienes que recordar

  • El cerebro de marca vive en un .md con frontmatter. Hex codes explícitos, lista de dont. Eso es lo que hace consistente cada imagen.
  • La key vive en Keychain. La metadata vive en una ficha en 09-CREDENTIALS/. Nunca al revés.
  • El wrapper de Python lee la key solo cuando va a llamar al modelo. El valor no toca disco en ningún archivo del repo.
  • Modo A para texto a imagen. Modo B para foto local de referencia. Cuando la referencia es local, el camino es Gemini.
  • Itera el cerebro, no el prompt. Cuando un resultado no te guste, agrega una regla al cerebro y la próxima imagen ya sale distinto.
  • Claude Code dentro de VS Code llama el script por ti en lenguaje natural. Tú nunca escribes el comando.

Qué viene después

Este patrón está atado a Gemini, que es lo que uso hoy. Pero la lógica (cerebro + key + wrapper + cliente) no depende del proveedor.


Video del canal · YouTubeMira el flujo entero en videoCerebro, Keychain, script, Claude Code en VS Code, todo en una sola sentada. Suscríbete y la próxima sale ahí primero.Ver en YouTube @Santa_lA

¿El cerebro te quedó pegado pero no logras que el script corra? ¿Tu primera imagen salió rara? Escríbeme por DM en @santaia.lab con el prompt y el resultado. Las dudas reales son material de la próxima guía.

hecho con mucho amor

espero les sea útil

santa-ia · 2026 · @santaia.lab