Get Bananas
Una lista de compras manuscrita para iPhone, iPad, Mac y Apple Watch — que Claude puede editar mientras tienes las manos ocupadas.
Lanzado en abril de 2026. SwiftUI en todos los dispositivos. Una extensión de Claude Desktop incluida dentro de la app de Mac. Veintinueve idiomas, cada uno con datos iniciales de compras curados a mano para que la primera lista que vea el usuario se sienta nativa, no traducida. Sin servidor, sin cuenta, sin API key. Un archivo JSON en tu contenedor de iCloud es todo el backend.
Claude puede modificar tu lista de compras.
Get Bananas incluye una extensión de Claude Desktop dentro de la propia app de Mac. Abre los Ajustes en el Mac, haz clic en Instalar extensión y Claude Desktop muestra un aviso de instalación. Acepta, abre un nuevo chat y Claude tendrá cinco herramientas que pueden leer y editar tu lista de compras real. Pregúntale "¿qué hay en mi lista?" y te lo dice. Pídele "agrega huevos y leche" y aparecerán en tu iPhone la próxima vez que iCloud sincronice.
No hay registro, ni API key, ni un servidor nuestro. La extensión es un paquete .mcpb que se comunica con un servidor MCP en Node.js, que lee y escribe en un único archivo JSON dentro de tu propio contenedor de iCloud Drive.
Cinco herramientas, una tarea cada una.
La superficie de herramientas es deliberadamente pequeña. Claude puede leer la lista, agregar un elemento, eliminar uno, actualizar uno o reemplazarla por completo. No hay atajos ingeniosos ni envoltorios de tipo leer-modificar-escribir; la superficie sigue lo que pedirías de forma natural en una conversación.
- get_shopping_listLeer la lista actual
- add_itemAgregar un elemento nuevo
- remove_itemEliminar un único elemento
- update_itemMarcar, desmarcar, renombrar o cambiar la cantidad
- update_shopping_listReemplazo total (p. ej. "comienza una lista para Acción de Gracias")
Se instala desde dentro de la app.
Los Ajustes de la app de Mac tienen un botón Instalar extensión. Al pulsarlo se abre con NSWorkspace un archivo get-bananas.mcpb incluido en el paquete, que Claude Desktop registra como extensión y le pide al usuario que confirme. Toda la instalación es una sola llamada a NSWorkspace.shared.open() sobre un archivo que viene dentro del bundle de la app — porque la plataforma nos entregó la primitiva correcta: un formato de archivo que significa "regístrame con Claude".
private func installExtension() { guard let extensionURL = Bundle.main.url( forResource: "get-bananas", withExtension: "mcpb" ) else { extensionMessage = "Error: Extension not found in app bundle." return } let opened = NSWorkspace.shared.open(extensionURL) if opened { extensionMessage = "Check Claude Desktop for the install prompt..." } else { extensionMessage = "Couldn't open the extension. Make sure Claude Desktop is installed." } }
Este patrón va a ser importante para muchas apps nativas. La extensión vive dentro del bundle de tu app, se distribuye cuando se distribuye la app y se actualiza cuando la app se actualiza — sin un registro aparte, sin configuración por usuario, sin "copia esta URL en un archivo de configuración". Si quieres que Claude pueda hacer algo dentro de tu app, pones ese algo dentro de la app y dejas que el OS los presente.
Pluma sobre papel, con persistencia.
Las listas de compras se escriben a mano, en papel, con un bolígrafo. La app se siente así. Tipografía manuscrita estilo Caveat para los encabezados de sección, líneas finas como de pluma para los divisores, círculos huecos para los elementos sin marcar. Cuando tocas para marcar algo, la app dibuja una línea hecha a mano sobre el texto — y cada línea es ligeramente distinta.




El tachado es un <code>Shape</code>, y cada palomita es única.
La línea dibujada a mano es un Shape personalizado de SwiftUI con veinte segmentos de trazado. Cada extremo de segmento recibe un pequeño desplazamiento vertical aleatorio entre -1.5 y +1.5 puntos. El resultado: cada tachado dibujado en tiempo de ejecución es ligeramente distinto del anterior. A lo largo de una lista de veinte elementos, no hay dos líneas idénticas — igual que no hay dos trazos de bolígrafo iguales.
struct HandDrawnStrikethrough: Shape { func path(in rect: CGRect) -> Path { var path = Path() let startY = rect.midY let segments = 20 let segmentWidth = rect.width / CGFloat(segments) path.move(to: CGPoint(x: 0, y: startY)) for i in 1...segments { let x = CGFloat(i) * segmentWidth let randomOffset = CGFloat.random(in: -1.5...1.5) let y = startY + randomOffset path.addLine(to: CGPoint(x: x, y: y)) } return path } }
Son doce líneas de código. También es la diferencia entre una app que parece manuscrita y una que se siente manuscrita. Un tachado SVG estático se habría podido lanzar el mismo día, con el mismo conteo de píxeles, y se habría leído como decoración.
Mira de cerca los dos elementos marcados de arriba. Las líneas sobre 'Claras de huevo' y 'Requesón 2%' tienen formas diferentes — distinto temblor, distinto ángulo. Se generaron con 200 milisegundos de diferencia mediante el mismo Shape, dibujando aleatoriedad nueva cada vez. Esa es toda la identidad de la app: variación pequeña y honesta, integrada en el diseño.
Veintinueve idiomas, con datos de compras nativos.
La primera lista que abre un usuario japonés no es una compra estadounidense traducida. Es tamagiro en una sección tanpaku-shitsu — claras de huevo, en una sección de Proteínas que usa el término que realmente encontrarías en un anaquel en Tokio. Veintinueve localizaciones en el App Store, y cada locale que no sea inglés trae su propio SeedData-{locale}.json curado a mano con elementos de muestra y nombres de sección culturalmente apropiados. El árabe trae biyad al-bayd en al-burutinat. El hebreo trae helbonei beitza en helbonim. Veintinueve archivos de datos iniciales, escritos a mano, no pasados por un traductor de cadenas.





RTL es una victoria gratis si dejas de pelear con ello.
SwiftUI trata .leading y .trailing como direcciones semánticas, no como .left y .right fijas. Maqueta la pantalla semánticamente una vez, y el árabe y el hebreo invierten toda la disposición de forma gratuita — el encabezado de sección se mueve a la derecha, el círculo de marcación se mueve a la izquierda del texto, los botones Reset y More rotan a la esquina opuesta. No escribimos una sola línea de código específica para RTL para esto.
El tachado dibujado a mano vive sobre todo esto y nunca tiene que conocer el locale. El Shape se sitúa dentro de un ZStack sobre el Text con el nombre del elemento y dibuja a través de ese rectángulo delimitador; la fila circundante es lo que SwiftUI espeja para la disposición RTL. La línea termina donde debe — sobre el texto — sin un solo condicional de idioma en el código del Shape.
Un archivo JSON en tu contenedor de iCloud.
El intercambio entre dispositivos es un solo archivo en tu propio iCloud Drive: BananaList.json, en el contenedor de Get Bananas. El servidor MCP lee y escribe ese archivo exacto. Las apps de iOS, iPad, Mac y Watch leen y escriben ese archivo exacto. iCloud se encarga de la sincronización — la infraestructura de Apple, gratuita, cifrada en reposo y end-to-end privada cuando la Protección Avanzada de Datos está activada. La nuestra no existe.
// iCloud path for Banana List data const ICLOUD_FILE_PATH = path.join( os.homedir(), "Library/Mobile Documents/iCloud~com~941apps~Banana-List/Documents/BananaList.json" ); // Lock file for atomic operations const LOCK_FILE_PATH = ICLOUD_FILE_PATH + ".lock"; const LOCK_TIMEOUT_MS = 5000;
Cada ruta que toca el servidor MCP es hermana de ese archivo JSON. El archivo de bloqueo vive junto a él (.lock, escrituras atómicas, tiempo de espera de cinco segundos que se autolimpia si queda obsoleto). Las escrituras van a un archivo temporal etiquetado con el proceso (.tmp.{pid}) y luego se renombran atómicamente a la ruta real. Todo el modelo de concurrencia — Claude contra la app en ejecución — cabe en una única función de adquirir/liberar.
En cada dispositivo, SwiftData es el almacén local. El JSON en iCloud es el formato de transferencia. SwiftData se mantiene rápido y consultable en el dispositivo; el JSON se mantiene simple y legible por humanos para la sincronización y para que Claude lo manipule. Dos almacenes con una tarea cada uno — ninguno intenta ser ambos.
Lo que esto nos permite prometer.
Sin servidor de 941 Apps. Sin analíticas. Sin inicio de sesión. Sin API key para Claude — ya te autenticaste con Claude Desktop. Sin suscripción. La extensión es de código abierto, así que cualquier curioso puede leer toda la ruta de los datos: es el archivo JSON, y eso es todo lo que toca. Tu lista de compras nunca sale de tu contenedor de iCloud a través de ninguna infraestructura nuestra.
El trabajo es la lista.
Una lista de compras es un solo trabajo. Capturar un elemento en el momento en que piensas en él, marcarlo cuando lo encuentras, y hacer que la lista se quite de en medio el resto del tiempo. El producto es ese trabajo. No es una app de recetas, ni un planificador de comidas, ni un escáner de códigos de barras, ni un rastreador de precios, ni un gestor de inventario. La lista es el entregable.
La integración con Claude se gana su lugar específicamente porque acelera la captura y edición en los casos en que escribir en el teléfono es la herramienta equivocada: parado frente a la estufa con las manos oliendo a ajo, conversando en voz alta sobre las comidas de la semana, copiando doce ingredientes de una receta sin tener que retipear cada uno. Delegar esos momentos a Claude mantiene pequeño al resto de la app.
Todo lo que no sea lista, captura, marcado o esa delegación es un producto distinto. Productos distintos pertenecen a apps distintas.
Lo que no está en Get Bananas.
La mayoría de las apps de listas de compras tienen una hoja de ruta que termina en "convertirse en Instacart". Esta no. Get Bananas se niega a crecer hasta convertirse en una plataforma de supermercado, a propósito. Aquí está la lista explícita de lo que no hace:
- Sin escaneo de códigos de barras
- Sin precios, totales ni presupuestos
- Sin importación de recetas ni planificación de comidas
- Sin navegación por pasillos ni mapas de tiendas
- Sin app web
- Sin cuenta, sin inicio de sesión, sin recolección de correo
- Sin listas compartidas con otros usuarios (solo tu propio iCloud, entre tus propios dispositivos)
- Sin analíticas, jamás
- Sin anuncios, sin suscripción, sin nivel Pro
- Sin pantallas insistentes ni promociones dentro de la app
Get Bananas cuesta $0.99. Pagas una vez y es tuya. El servidor MCP es de código abierto. Los datos son tuyos y viven en tu iCloud Drive. El trabajo es la captura rápida, el marcado rápido y delegarle ediciones a Claude cuando tienes las manos llenas de cilantro. Todo lo demás es la app de alguien más.
Get Bananas.
Disponible ahora en el App Store para iPhone, iPad, Mac y Apple Watch. Instala la extensión de Claude Desktop desde dentro de la app de Mac.