+250 skills, dinamita para tu productividad 🧨Explorar →

Mercadona CLI: accede a la tienda de Mercadona con IA

Hacer la compra del súper desde la terminal. O mejor: dejar que un agente de IA te la haga, mientras tú miras qué le falta a la nevera.

Eso es lo que hace el CLI de Mercadona: un binario que habla con tienda.mercadona.es por debajo, busca productos, llena el carrito y prepara el checkout. Suena a juguete. No lo es. Por dentro hay decisiones de ingeniería que merecen un repaso pausado, porque resuelven problemas que te vas a encontrar tú el día que quieras automatizar cualquier web que no quiere ser automatizada.

Aquí no vamos a hacer un tutorial de uso. Vamos a abrir el capó.

Esto es lo que cubre el artículo:

  • Cómo instalarlo en un minuto para empezar a trastear.
  • Quién está detrás y qué problema resuelve exactamente.
  • La receta para crear un CLI de cualquier web, con las pistas que deja Mercadona CLI.
  • Dónde está la magia: el disfraz de Chrome y las credenciales que se curan solas.
  • Dónde están las dificultades feas: el captcha, la consistencia eventual del carrito y gastar dinero real.

Cómo se instala mercadona-cli

Se instala en un solo comando y tienes tres caminos según tu entorno. El proyecto distribuye un binario precompilado de Go, así que no hay que compilar nada para empezar.

Método Comando Cuándo usarlo
npm npm install -g @ivorpad/mercadona Lo más cómodo si ya tienes Node
curl curl -fsSL https://raw.githubusercontent.com/ivorpad/mercadona-cli/main/install.sh | sh macOS o Linux sin Node
Manual Descargar el tarball de la página de releases Cuando quieres fijar una versión a mano

Hay binarios para macOS, Linux y Windows en arquitecturas x64 y arm64. El instalador por curl verifica el checksum antes de dejarte nada en el PATH, y el paquete de npm descarga el binario que toca según tu sistema.

Una vez instalado, dos pasos para ponerte a trastear ya mismo. Primero fija tu almacén con tu código postal, porque los precios y los identificadores de producto cambian según el centro que te sirve:

# Resuelve el almacén que reparte en tu código postal y lo guarda por defecto
mercadona set-postal 28022

Y ahora tu primera búsqueda, que no necesita login porque las lecturas son anónimas:

# Búsqueda de catálogo en texto completo (sin login)
mercadona search queso
mercadona search --limit 5 --json mayonesa   # salida estructurada para agentes

Con eso ya estás dentro. El carrito y el checkout sí piden autenticación, y de cómo se resuelve eso hablamos más abajo, porque tiene su miga.

Quién hay detrás del proyecto

El autor es Ivor Padilla, que en GitHub firma como @ivorpad. Es un ingeniero de software venezolano afincado en España, con muchos años de oficio en frontend y full stack, y con una vena clara de “vamos a probar esta herramienta nueva a ver hasta dónde llega”.

Conviene decirlo antes de entrar en el código, porque el carácter del proyecto es suyo: pragmático, bien documentado y con un README que da gusto leer. No es un scraper escupido a las tres de la mañana. Es un proyecto con tests, con CI endurecido y con una skill de Claude empaquetada dentro. Eso marca el tono de todo lo que viene.

Vamos a por el cómo.

Qué problema resuelve mercadona-cli

Mercadona no tiene API pública. Punto. mercadona-cli resuelve justo eso: te da una interfaz programable sobre una tienda que no la ofrece, imitando lo que hace el navegador cuando entras a la web. Por debajo, la tienda habla con unos endpoints HTTP y con un buscador de Algolia, y el CLI replica esa misma conversación.

La gracia está en la intención con la que está escrito. No busca ser una app bonita con menús. Busca ser conducido por otro programa, normalmente uno de esos agentes de IA que viven en la terminal. Por eso casi todo tiene un flag --json, los datos salen por stdout, los logs por stderr, y el código de salida es 1 cuando algo falla. Eso lo hace fácil de encadenar en un script o de pilotar desde un LLM.

Y todo ello en un único binario de Go, estático, sin dependencias en tiempo de ejecución. Lo descargas, lo pones en el PATH y funciona.

🔑 La idea de fondo: este proyecto no automatiza “una web”, automatiza la conversación HTTP que el navegador ya tiene con esa web. Esa distinción cambia todas las decisiones de diseño que vienen a continuación.

Curso gratis · paso a paso

Que tu agente siga un plan en vez de improvisar

Igual que este CLI le pone barreras a la IA, el Spec Driven Development le pone método. Te llevas el ciclo completo con OpenSpec sobre un proyecto real y en modo asistido: lo ves funcionar entero antes de coger tú el volante.

Entra en el curso gratis →

Cómo puedes crear un CLI de cualquier web

La receta para convertir una web sin API pública en un CLI es casi siempre la misma, y mercadona-cli la recorre de principio a fin. Si alguna vez quieres hacer lo propio con otra tienda, otro panel o cualquier servicio que no te da API, estos son los pasos, con la pista de cómo los resolvió este proyecto:

  1. Espía la conversación, no la pantalla. Abre las DevTools, pestaña Network, y mira qué peticiones HTTP lanza la web. Replicar esas peticiones es mucho más robusto que pelearte con el DOM. Mercadona CLI no renderiza nada: habla directo con los endpoints. Cuando la web sí exige ejecutar JavaScript y renderizar de verdad, el enfoque cambia y ahí entra otra familia de herramientas, como Crawl4AI para scraping con IA.
  2. Reprodúcele al servidor lo que espera de un navegador. Cabeceras realistas y, si hay un antibots delante, también la huella TLS. Aquí está uno de los trucos estrella del proyecto, que vemos en detalle más abajo.
  3. Localiza de dónde salen las credenciales y asume que caducan. Suelen estar en el bundle de JavaScript o en tokens de sesión, y rotan. Diseña para descubrirlas en vivo en vez de fijarlas a fuego.
  4. Resuelve el login una vez y renueva sin fricción. Si hay captcha, el primer acceso será en navegador; a partir de ahí, un token de refresco mantiene la sesión sin intervención.
  5. Modela las formas reales de leer y escribir. No te fíes: a menudo el GET y el PUT de un mismo recurso tienen estructuras distintas.
  6. Sé educado con la API. Reintentos con backoff ante un 429 o un 503. Te ahorra bloqueos y caídas.
  7. Si hay dinero o acciones irreversibles, pon topes y falla en cerrado. Que ante la duda el programa pare en vez de tirar para adelante.
  8. Empaqueta un binario fácil de instalar. Cuanto menor sea la fricción de instalación, más se usará.

El resto del artículo es exactamente eso: cada uno de estos pasos, visto en el código real de Mercadona CLI, con sus aciertos y sus partes feas. Empecemos por el mapa que lo organiza todo.

La idea que lo organiza todo: tres capas según el riesgo

El proyecto se entiende mejor si lo partes en tres capas, ordenadas por una variable muy concreta: cuánto te van a vigilar en cada una. Ivor estructura todo el cliente alrededor de esa distinción.

  1. Búsqueda (Algolia). No está detrás del muro antibots de Mercadona. Funciona desde cualquier IP. Es la capa “barata” y la más permisiva.
  2. Lecturas de catálogo (/api/...). Sí pasan por Akamai, pero a peticiones anónimas y a ritmo humano se sirven sin problema. Hay que parecer un navegador, sin más.
  3. Auth, carrito y checkout. La parte sensible. Aquí Akamai mira con lupa y conviene salir desde una IP residencial, no desde un datacenter marcado.

Esta separación no es decorativa. Cada capa recibe un trato técnico diferente, y entender por qué te ahorra muchos quebraderos de cabeza si algún día montas algo parecido. La capa 1 puede ir a saco; la capa 3 va de puntillas.

Con el mapa claro, vamos a las dos piezas donde está la magia.

Abrir un proyecto y ver por dentro sus decisiones de ingeniería es justo lo que más disfruto compartiendo cada domingo con +6.700 developers: lo que vamos aprendiendo metiendo IA en el trabajo real.

Suscríbete gratis →

La magia número uno: el CLI se hace pasar por Chrome

El truco más bonito del repositorio es que el cliente presenta la misma huella TLS que Chrome, y vive en internal/client/transport.go. Sin eso, el antibots de Akamai lo cazaría en el handshake, antes incluso de mirar una sola cabecera.

El problema: Akamai Bot Manager no solo mira tus cabeceras. Mira tu huella TLS, lo que se conoce como JA3. Es el patrón de cómo tu cliente saluda al servidor durante el handshake de cifrado: qué versiones soporta, qué extensiones manda y en qué orden. Un cliente HTTP normal de Go tiene una huella JA3 que grita “soy un bot” desde lejos.

La solución de Ivor: usar uTLS para presentar el saludo de Chrome. En cada conexión, el cliente construye un ClientHello calcado al del navegador.

// Construye un saludo TLS idéntico al de Chrome para que Akamai no lo marque
func chromeSpecHTTP1() (utls.ClientHelloSpec, error) {
	spec, err := utls.UTLSIdToSpec(utls.HelloChrome_Auto)
	if err != nil {
		return spec, err
	}
	// Fijamos ALPN a http/1.1: así un http.Transport estándar puede usar
	// la conexión sin montar la fontanería de HTTP/2
	for _, ext := range spec.Extensions {
		if a, ok := ext.(*utls.ALPNExtension); ok {
			a.AlpnProtocols = []string{"http/1.1"}
		}
	}
	return spec, nil
}

Hay dos detalles finos que delatan a alguien que sabe lo que hace.

El primero: fija el ALPN a http/1.1. ¿Por qué? Porque así puede seguir usando el http.Transport normal de Go sin tener que implementar HTTP/2 a mano. Y aquí está el matiz brillante: el JA3 clásico hashea los tipos de extensión, no la lista de protocolos ALPN. O sea, puede cambiar el protocolo a su conveniencia y la huella sigue pareciendo la de Chrome.

El segundo: construye un spec nuevo en cada conexión, porque aplicar el preset puede mutar la configuración (el GREASE de Chrome introduce aleatoriedad). Y si uTLS no arranca por lo que sea, cae al transporte estándar de Go. Degrada con elegancia en vez de romperse.

💡 Si algún día te bloquean y juras que tus cabeceras son perfectas, mira la huella TLS antes de volverte loco. Es el detalle que casi nadie revisa y el que más te delata.

La magia número dos: las credenciales de Algolia que se reparan solas

La segunda pieza lista es que el CLI redescubre solo las credenciales de búsqueda cuando caducan. La búsqueda usa Algolia con unas claves públicas incrustadas en el bundle de JavaScript de la web, y ese app-id rota cada cierto tiempo: en el propio README se documenta el salto de 7UZJKL1GNI a 7UZJKL1DJ0. Si lo dejas a fuego en el código, el día que cambie tu CLI deja de buscar.

La respuesta está en internal/client/algolia.go y es de manual. El cliente lleva un valor por defecto de “última versión conocida que funcionaba”, para que el caso normal no gaste ni una petición extra. Pero cuando detecta una señal de credenciales caducadas (un fallo de DNS, un 401, un 403 o un 404), se pone a trabajar:

  1. Descarga el HTML de la web.
  2. Localiza con una expresión regular el bundle de JavaScript principal (algo como /v9200/index-DdAHguc-.js).
  3. Dentro de ese JavaScript, extrae con otra regex el app-id, la clave de búsqueda de 32 caracteres hexadecimales y el nombre del índice.
  4. Cachea lo nuevo y reintenta la búsqueda.
// shouldRefresh detecta credenciales caducadas: un estado de auth/no-encontrado
// de Algolia, o un fallo de DNS por un app-id rotado (host ya muerto)
func shouldRefresh(err error) bool {
	var apiErr *APIError
	if errors.As(err, &apiErr) {
		switch apiErr.Status {
		case http.StatusUnauthorized, http.StatusForbidden, http.StatusNotFound:
			return true
		}
	}
	return strings.Contains(err.Error(), "no such host")
}

Es elegante porque resuelve un problema que casi todos los scrapers ignoran hasta que les explota: las credenciales “públicas” de terceros no son eternas. Aquí el CLI se cura solo y tú ni te enteras.

Estas dos piezas, el disfraz TLS y la rediscovery de Algolia, son la parte “lista”. Ahora vienen las dificultades, que es donde un proyecto se diferencia de un prototipo.

El muro del captcha y cómo lo rodea

El primer gran obstáculo es que el login no se puede automatizar, y el proyecto lo rodea apoyándose en el token de refresco. El login por usuario y contraseña de Mercadona exige un token de reCAPTCHA Enterprise de Google, y eso no se puede generar desde un proceso sin navegador. Headless, mueres.

¿Cómo se sortea algo que por diseño no se puede automatizar? Con una observación afilada: el token que renueva la sesión, el refresh token, no necesita captcha y además rota en cada uso. Así que la jugada es un login en navegador una sola vez y, a partir de ahí, sesión sin atención humana para siempre.

El flujo cómodo es importar un HAR. Te logueas en el navegador (da igual con email o con “Entrar con Google”), exportas el HAR desde las DevTools, y el CLI saca de ahí lo que necesita. Y lo hace con cuidado quirúrgico:

  • Lee el refresh_token de las respuestas de /api/auth/ (soporta los dos endpoints, el de email y el de Google).
  • Coge el Bearer y la cookie más recientes de las cabeceras de las peticiones autenticadas.
  • Detecta de paso el almacén y el idioma desde los parámetros de la URL.
  • Nunca toca el cuerpo de las peticiones, que es donde viaja la contraseña.

Hay otro detalle que me gusta: el customer_id no se lo inventa ni te lo pide. Lo decodifica del propio JWT, leyendo la claim customer_uuid sin verificar la firma, porque solo necesita el dato que el servidor ya da por bueno. El token de acceso dura unas seis semanas, según el README; cuando caduca, el refresh token vuelve a entrar en juego sin que tú hagas nada.

🛡️ Regla de oro que el código cumple a rajatabla: los secretos entran por stdin o por variable de entorno, jamás como argumento de línea de comandos, y nunca se imprimen de vuelta. Cuando reporta algo, dice “token de 412 caracteres”, no el token. Cópiate esa costumbre.

El carrito: dos formas distintas del mismo objeto

La segunda dificultad es sutil: el carrito se lee de una forma y se escribe de otra. Es una trampa clásica de las APIs internas, y si mandas de vuelta lo que recibiste, la rompes.

Cuando lo lees con un GET, cada línea trae el producto anidado dentro, con su nombre y su precio. Cuando lo escribes con un PUT, la API quiere un product_id plano y nada más.

La solución en internal/client/cart.go es definir un UnmarshalJSON y un MarshalJSON a medida para la línea del carrito. Al leer, levanta el nombre y el precio para poder mostrártelos y calcular totales. Al escribir, los descarta y manda solo la forma plana que la API espera. Y hay un test específico que comprueba que esos campos de solo-lectura nunca se filtran en el PUT.

// MarshalJSON escribe la forma del PUT: product_id plano, sin nombre ni precio
func (l CartLine) MarshalJSON() ([]byte, error) {
	sources := l.Sources
	if sources == nil {
		sources = []any{}
	}
	return json.Marshal(map[string]any{
		"quantity":   l.Quantity,
		"product_id": l.ProductID,
		"sources":    sources,
	})
}

Es el tipo de asimetría que no ves en la documentación (porque no hay) y que solo descubres mirando peticiones reales. Tenerla resuelta y testeada es lo que separa un experimento de algo en lo que confías.

La consistencia eventual, el bug que no era un bug

La tercera dificultad es para enmarcar: el backend del carrito es consistente de forma eventual, así que las lecturas pueden ir un poco por detrás de las escrituras. Esa única característica produce dos efectos traicioneros:

  • Dos escrituras seguidas por separado pueden pisarse. La segunda lee el carrito de antes del primer cambio y lo sobrescribe.
  • Incluso una sola escritura puede parecer que “no ha cuajado” si lees demasiado pronto.

¿Cómo lo resuelve? Con el comando set-many: una sola lectura, todos los cambios aplicados en memoria, y una sola escritura. Sin carrera entre peticiones. Y de forma deliberada no usa control de concurrencia optimista (ni versión ni If-Match), porque como el backend va con retraso, un GET suele devolver una versión vieja y un chequeo estricto daría un 409 falso.

El comentario del código es oro puro, porque cuenta una historia que muchos hemos vivido: hubo un supuesto bug de “no me borra el producto del carrito”. Lo persiguieron. Y resultó que no era un bug del parser ni del flag --max. Era el retraso de lectura. El arreglo no fue añadir un workaround para un fallo inexistente, sino reordenar el flujo para no exponerse a la carrera.

⚠️ Cuando algo “no se guarda” en un sistema distribuido, sospecha de la consistencia eventual antes de acusar a tu código. Reescribir mil veces el parser no arregla un retraso de propagación. Aquí casi caen en esa trampa, la documentaron y la esquivaron.

Cazar trampas como esta, un fallo que no era un fallo, se hace más fácil en compañía. Cada domingo, +6.700 developers cambiamos notas sobre IA en el desarrollo. Gratis desde 2018.

Quiero esa dinamita 🧨

Dinero de verdad: el guardarraíl de gasto

La cuarta dificultad es la más seria, porque ya no hablamos de datos sino de una tarjeta real y una compra real. El diseño de seguridad alrededor del dinero es, para mí, lo mejor pensado del proyecto.

El flag --max <eur> pone un techo al gasto, y lo hace con dos capas. La primera es preventiva: antes de escribir el carrito, calcula el total del cesto resultante (reutilizando los precios que ya tiene de la lectura y pidiendo solo los de los productos nuevos) y se niega a escribir si se pasa del tope. La segunda es un respaldo con autoridad: tras la escritura, vuelve a comprobar el total real y, si aun así se ha pasado, revierte el carrito.

Y el checkout submit, el comando que de verdad gasta, falla en cerrado: si con un tope puesto no consigue leer el total, se niega a pagar en vez de arriesgarse. Prefiere parar a equivocarse con tu dinero.

Hay tres cifras en euros que el código se cuida mucho de no confundir:

  • El mínimo de pedido (~60 €), un suelo que el cesto debe superar o el checkout te rechaza.
  • El --max del carrito, un techo sobre el precio de los productos.
  • El --max del checkout, que además debe cubrir la tarifa de reparto (~8,20 €).

Y un detalle de oficio que me encanta: los totales se suman en céntimos enteros, no en coma flotante, para que no haya desviaciones al acumular muchas líneas.

// priceCents convierte un precio "1.20" a céntimos enteros, así los totales
// suman exacto sin la deriva de la coma flotante
func priceCents(s string) (int64, error) {
	s = strings.TrimSpace(s)
	if s == "" {
		return 0, fmt.Errorf("empty price")
	}
	v, err := strconv.ParseFloat(s, 64)
	if err != nil {
		return 0, fmt.Errorf("unparseable price %q", s)
	}
	return int64(math.Round(v * 100)), nil
}

🔑 Cuando tu programa puede gastar dinero, el comportamiento por defecto ante la duda no es “tira para adelante”, es “para y reporta”. Ese principio está cosido en cada decisión de esta capa.

Los detalles pequeños que evitan errores grandes

Hay tres piezas que parecen menores y que sostienen toda la fiabilidad del proyecto. Vale la pena nombrarlas porque son justo el tipo de cosa que se olvida en un prototipo.

Reordenar los flags para que no se pierda --max. El parser de flags estándar de Go se detiene en el primer argumento posicional. Eso significa que en cart add 123 5 --max 50, el --max se ignoraría sin avisar. Para un flag de seguridad eso es una bomba. Por eso hay una función reorderArgs que coloca los flags por delante antes de parsear, y está testeada con varios casos raros.

Leer el total con tolerancia. Un checkout en vivo trae el total a pagar en summary.total, pero también un price que es solo el subtotal y que viene como cadena de texto. Si intentas decodificar todo el JSON de golpe en una struct, ese campo te revienta el parseo y perderías el summary.total. Por eso ExtractTotal examina campo por campo, con cuidado, y la forma exacta está verificada contra un checkout real.

Resolver el almacén desde el código postal. Los identificadores de producto y los precios son por almacén, y el checkout exige que el almacén del carrito coincida con tu dirección. El comando set-postal hace un POST y lee la cabecera x-customer-wh de la respuesta, sin necesidad de login. Así todo el flujo trabaja sobre el catálogo que de verdad te van a servir a casa.

A esto se suma el reintento automático con backoff ante un 429 o un 503, respetando la cabecera Retry-After, con espera exponencial y un poco de aleatoriedad. Una ráfaga de peticiones se degrada en una pausa breve en vez de en un fallo. Educación con la API, que además es la mejor forma de que no te bloqueen.

Guardarraíles desde el diseño

Diseñar agentes que no se descontrolan: arquitectura y guardarraíles

Te llevas los seis niveles de arquitectura de un agente — tools, guardarraíles, memoria, skills, MCP y orquestación — para que el tuyo no haga un destrozo en producción, justo el tipo de diseño que hace seguro este CLI.

Ver el método entero →

Masterclass en directo · 6 niveles de arquitectura

Pensado para que lo pilote una IA, con dos puertas de seguridad

El círculo del enfoque “agent-first” se cierra con una skill de Claude empaquetada en el repo (mercadona-shop) que es la que convierte una lista de la compra en una compra de verdad. Si quieres entender el formato de estas skills, lo desgranamos en la guía de Agent Skills.

La skill no deja al agente campar a sus anchas. Le impone dos puertas que son innegociables:

  1. Confirmar antes de tocar el carrito. Buscar y calcular precios es gratis y reversible, así que se hace a discreción. Pero antes de la primera escritura, el agente tiene que enseñarte el plan (cada producto resuelto, con id, nombre, tamaño y precio) y esperar tu visto bueno. Es donde cazas un producto equivocado.
  2. Consentimiento explícito antes de pagar. El checkout submit es irreversible. Solo se lanza cuando has dicho que sí, para ese pedido concreto, tras ver el total completo. Y como red de seguridad final, el propio CLI exige el flag --yes que el agente no debe poner por su cuenta.

Encima de las dos puertas va el --max como defensa en profundidad. Búsqueda libre, escritura confirmada, pago con doble llave y un techo de gasto por si acaso. Es un manual de cómo dejar que una IA actúe sin que pueda hacer un destrozo.

Cómo se reparte el binario por el mundo

La distribución también está cuidada y enseña buenas prácticas de cadena de suministro. Se apoya en GoReleaser para compilar binarios estáticos para varias plataformas y publicarlos como release de GitHub.

Encima hay un paquete de npm que es un envoltorio fino: al instalarlo, descarga el binario que corresponde a tu sistema. Y el instalador por curl verifica el checksum antes de dejarte nada en el PATH.

El CI tiene su propio mimo: las actions están fijadas por SHA de commit (no por etiqueta movible), los permisos son mínimos por trabajo, y la publicación en npm va por OIDC con Trusted Publishing, sin tokens de larga duración. Son detalles que muchos proyectos grandes todavía no aplican.

Preguntas frecuentes

¿Puedo hacer la compra de Mercadona con IA?

Sí. mercadona-cli incluye una skill para Claude que convierte tu lista de la compra en productos reales, llena el carrito y prepara el reparto. El agente busca cada producto, te enseña el plan con precios y solo paga si das tu consentimiento explícito. La IA hace el trabajo pesado; tú confirmas las decisiones que importan.

¿Cómo accedo a la tienda de Mercadona desde la terminal?

Instalas mercadona-cli (con npm, con un script de curl o descargando el binario), fijas tu código postal con mercadona set-postal y ya puedes buscar productos con mercadona search. Las búsquedas y la consulta de catálogo no necesitan login; el carrito y el checkout sí piden autenticarte una vez.

¿Mercadona tiene una API oficial para esto?

No. Mercadona no ofrece una API pública. Este CLI habla con los mismos endpoints HTTP y con el buscador de Algolia que usa la propia web, imitando lo que hace el navegador. Por eso el README insiste en usarlo a un ritmo razonable de peticiones.

¿Funciona con Claude, ChatGPT u otros agentes?

El proyecto trae una skill lista para Claude, pero como el CLI expone salida en --json y códigos de salida claros, cualquier agente capaz de ejecutar comandos puede pilotarlo. La pieza clave no es el modelo concreto, sino que la herramienta esté pensada para ser conducida por un programa.

¿Por qué está escrito en Go y no en Python o JavaScript?

Go permite compilar un único binario estático sin dependencias en tiempo de ejecución, fácil de distribuir y de ejecutar en cualquier máquina o servidor. Para una herramienta de línea de comandos pensada para encadenarse en scripts y agentes, ese rasgo es una ventaja enorme.

¿Qué es la huella TLS (JA3) y por qué importa aquí?

Es el patrón de cómo tu cliente inicia el handshake de cifrado: versiones, extensiones y su orden. Los sistemas antibots como Akamai la usan para distinguir navegadores de bots. El CLI presenta la huella de Chrome con uTLS para no destacar como cliente automatizado.

¿Cómo evita el captcha del login?

No lo evita: lo rodea. El login con contraseña sí exige un reCAPTCHA que solo se genera en un navegador. Pero el refresh token renueva la sesión sin captcha y rota en cada uso, así que basta con un login en navegador una vez e importar el HAR para tener sesión headless después.

¿Es seguro darle mis credenciales?

El diseño está pensado para minimizar el riesgo: los secretos se leen por stdin o por variable de entorno, nunca como argumento visible, y no se imprimen de vuelta. El refresh token se guarda con permisos 0600. Aun así, son tus credenciales reales de Mercadona, así que trátalas con el mismo cuidado que cualquier otra contraseña.

¿Puede un agente de IA gastar dinero sin que yo lo apruebe?

No debería. La skill que acompaña al CLI impone dos puertas: confirmar el plan antes de tocar el carrito y dar consentimiento explícito antes de pagar. Además, el flag --max pone un techo de gasto y el comando de compra exige --yes como red de seguridad final.

¿Por qué a veces un cambio en el carrito parece no guardarse?

Porque el backend del carrito es consistente de forma eventual: las lecturas pueden ir por detrás de las escrituras durante uno o dos segundos. La solución del proyecto es agrupar todos los cambios en una sola escritura con set-many y volver a leer si hace falta, en lugar de disparar varias escrituras seguidas.

Fuentes

🧨 Última oprtunidad para recibir la dinamita que mereces sobre programación con IA el próximo domingo: Suscríbete gratis a Web Reactiva en https://webreactiva.com/newsletter

Imagen de Daniel Primo
Claude, IA de Anthropic

Escrito con la ayuda de la IA generativa de Claude, fuentes fidedignas y con un human in the loop:
Dani Primo.

CEO en pantuflas de Web Reactiva. Programador y formador en tecnologías que cambian el mundo y a las personas. Activo en linkedin, en substack y canal @webreactiva en telegram

12 recursos para developers cada domingo en tu bandeja de entrada

Además de una skill práctica bien explicada, trucos para mejorar tu futuro profesional y una pizquita de humor útil para el resto de la semana. Gratis.