Encuentra funciones de Cineplanet con buenos asientos, sin revisar sede por sede.
La interfaz principal es un CLI determinista para agentes: Codex, Claude Code,
Cursor, OpenCode o cualquier otro harness puede ejecutar recommend, leer un
JSON estable y decidir qué opción mostrarte. También incluye una TUI para uso
humano directo en la terminal.
Agente / harness ── recommend ──► JSON v1 ──► comparación y recomendación
│
└── checkout --yes ──► Chrome visible /entradas
Persona ─────────── tui ─────────► selección interactiva con flechas
┌ CineplanetCLI ───────────────────────────────────────────┐
│ Película: Spider-Man │
│ Grupo: 2 personas │
├ Funciones disponibles ──────────────────────────────────┤
│ > 20:30 55 asientos CP La Molina │
│ 21:00 18 asientos CP Salaverry │
└ ↑↓ elegir Enter ver o modificar Esc volver Q salir ─┘
CineplanetCLI resuelve la parte tediosa de buscar entradas: compara muchas funciones y sedes en una sola consulta y te dice dónde hay asientos que sí valen la pena, no solo cuántos quedan.
- Consulta cartelera y mapas públicos en vivo, sin login.
- Filtra por ciudad, película, fechas publicadas, sedes, idioma, formato y tipo de sala.
- Compara hasta las mejores opciones y muestra hora, sede, modalidad y asientos disponibles.
- Busca bloques contiguos para grupos de 1 a 5; si solo existe una separación por pasillo, la explica.
- Puntúa la visión según centro horizontal y zona media/media-trasera, evitando extremos, primeras filas y accesibilidad.
- Devuelve mapas completos y legibles, con cada asiento recomendado identificado.
- Puede revalidar una opción, seleccionar las butacas en Chrome y dejarte en
/entradascomo invitado; tú eliges tarifa, promociones y pago.
Este proyecto también dio lugar a una interfaz web y una API reutilizable para consultar Cineplanet sin instalar el CLI:
| Proyecto | Repositorio | Demo |
|---|---|---|
| cineplanet-api, de gersonsebastianx: experiencia web conversacional con IA para consultar funciones y encontrar entradas de Cineplanet. | GitHub | cineplanet-api.vercel.app |
Ciudad → película → fecha(s) → sede(s) → grupo (1-5) → funciones → mapa
La TUI permite escribir para filtrar ciudades, películas, fechas, sedes y funciones al instante. También funciona con flechas, Enter, Escape y selectores múltiples; no requiere memorizar comandos.
recommend es la interfaz recomendada para automatización. No abre una
interfaz ni depende de un LLM: escribe exactamente un documento JSON v1 en
stdout. Los errores también tienen un sobre JSON versionado y salen por stderr,
por lo que un harness puede separar datos y errores de forma determinista.
Desde el repositorio:
cargo run --quiet -- recommend \
--movie-title "La Odisea" --city "Lima" --party-size 2 \
--date 2026-08-15 \
--venue "CP La Molina" --venue "Salaverry" \
--language Subtitulada --format 2D --room-type Regular \
--limit 3 > cineplanet-result.jsonCon una instalación global es equivalente:
cineplanet-cli recommend --movie-title "La Odisea" --city Lima \
--party-size 2 --date 2026-08-15 --venue "La Molina" --limit 3El contrato está pensado para que otro programa lo consuma directamente:
cineplanet-cli recommend \
--movie-title "La Odisea" --city Lima --party-size 3 \
--date 2026-08-15 --venue "San Miguel" --venue "Salaverry" \
--limit 3 \
| jq '.recommendations[] | {rank, venue, starts_at, seats: .checkout_handoff.selected_seat_labels, score: .viewing.score}'Un harness puede seguir este ciclo:
- Convertir la petición humana en
--movie-title/--movie-id,--city,--party-size, fechas, sedes y--limit. - Ejecutar
recommenduna sola vez y parsear el JSONv1. - Presentar hora, sede, modalidad, asientos explícitos, visión y el mapa
seat_previewde cada opción. - Conservar el
recommendations[].idde la opción que el usuario elija. - Solo si el usuario pide reservar, ejecutar
checkoutcon ese ID y--yes.
En Codex, la skill repo-scoped $cineplanet-recommend se descubre desde
.agents/skills/cineplanet-recommend y traduce peticiones como «busca las tres
mejores funciones de La Odisea esta noche en San Miguel para tres personas» a
este flujo. En Claude Code, OpenCode, Cursor u otro harness, basta con darle el
comando anterior como herramienta local y pedirle que trate stdout como JSON;
no necesita conocer la TUI ni usar un navegador para consultar disponibilidad.
recommend es de solo lectura. El checkout es una acción separada y solo debe
ejecutarse después de una instrucción explícita como reservar opción 2 o
continuar con 2:
cineplanet-cli checkout \
--movie-title "La Odisea" --city Lima --party-size 3 \
--date 2026-08-15 --venue "San Miguel" --venue "Salaverry" \
--recommendation-id "<id-devuelto-por-recommend>" --yesEl comando vuelve a validar el ID y los asientos, abre Chrome visible, elige
Seguir como invitado y deja la sesión en /entradas. El usuario escoge la
tarifa, promociones y pago. La retención dura aproximadamente cinco minutos y
vive en esa sesión de Chrome. Un número solo (2) selecciona una opción pero
no crea ninguna retención.
El selector de película es exactamente uno de --movie-id o --movie-title; ciudad y grupo (1 a 5) son obligatorios. Repite --date, --venue, --language, --format, --room-type y --favorite-venue para varios valores. Las fechas usan YYYY-MM-DD en America/Lima. La respuesta v1 contiene observed_at (RFC 3339 en UTC, momento en que la CLI observó la disponibilidad), query, recomendaciones ordenadas con venue, starts_at, modality, viewing (score, calidad, zona y razones), selected_block, seat_preview y diagnostics (candidate_count, hydrated_count, map_failures). seat_preview es compacto y determinista: PANTALLA queda arriba, las filas se ordenan como el mapa observado y su layout usa . disponible, # ocupado, A accesibilidad, * asiento recomendado y espacios para pasillos o huecos. No expone IDs remotos de los demás asientos. Cuando la fuente live entrega los IDs oficiales, cada recomendación añade checkout_handoff con slug, sede, sesión, huella session_fingerprint, URL oficial efímera de selección, etiquetas recomendadas y requisito de sesión de navegador. observed_at no aparece en sobres de error.
cineplanet-cli sin argumentos, o cineplanet-cli tui, abre la interfaz
interactiva. Es útil cuando quieres explorar visualmente la cartelera y moverte
por las opciones con el teclado; no es la interfaz que deben automatizar los
agentes.
cineplanet-cli tuiCantidad de opciones vs tamaño de grupo. El agente trata estas dos dimensiones como ejes independientes y las pasa como flags separadas:
- Cantidad de opciones — frases como
los 3 mejores,dame 3 opciones,muéstrame 5,los primeros 4,top N,N alternativas,N funcionesyN horariosse mapean a--limit Ny nunca a--party-size. Interpretartop 3como grupo de tres es exactamente el bug que estamos corrigiendo. - Tamaño de grupo = 1 —
para mí,voy solo,voy sola,individual,una persona,yo nada másse mapean a--party-size 1. No se asume 1 en su ausencia. - Tamaño de grupo inequívoco —
somos tres,somos 4,para 3 personas,para cuatro,vamos 3,tres asientos juntos,4 amigos,mi familia de 5,en pareja,con mi novia,con mi esposo,N espacios,N lugares,N asientos,N butacas,N entradas,espacio para N,lugares para Nyasientos para Nse mapean a--party-sizecon el conteo nombrado (2 para las frases en parejaen pareja/con mi novia/con mi esposo, porque implican dos personas). En este dominio, un número con semántica de asientos/personas es suficiente:3 espacios buenos,4 entradasypara 3significan grupos de 3, 4 y 3. Solo preguntar una vez cuando no exista ninguna señal de tamaño de grupo; nunca heredar el tamaño de grupo de un turno previo.
{
"version": "v1",
"observed_at": "2026-08-15T12:34:56.789012+00:00",
"recommendations": [{
"rank": 1,
"viewing": { "score": 99.7, "zone": { "id": "central_middle_rear" } },
"selected_block": { "seats": [{ "row": "G", "number": 6 }, { "row": "G", "number": 7 }] },
"seat_preview": {
"screen": "PANTALLA",
"symbols": { "available": ".", "occupied": "#", "accessible": "A", "recommended": "*", "aisle": " " },
"rows": [{ "label": "G", "layout": ".. ..**#" }]
},
"checkout_handoff": {
"movie_slug": "la-odisea", "cinema_id": "0000000007", "session_id": "66776",
"seat_selection_url": "https://www.cineplanet.com.pe/compra/la-odisea/0000000007/66776/asientos",
"selected_seat_labels": ["G6", "G7"],
"session_fingerprint": "cineplanet:0000000007:66776", "browser_session_required": true
}
}],
"diagnostics": { "map_failures": [] }
}El sobre JSON v1 se conserva verbatim — la transformación visual se aplica solo a la respuesta humana. La paleta humana es de ancho 2: . → ◻ disponible, # → ◼ ocupado, A → ♿, * → ♟︎ recomendado y espacio → dos espacios. El recomendado usa la presentación de texto monocromática de una pequeña figura, por lo que no depende del soporte de colores y sigue diferenciándose de disponibles y ocupados. No se usa el emoji 🟧, porque macOS lo dibuja más grande y con degradado. No se mezclan celdas ASCII con el mapa humano ni se usan cajas cerradas o bordes derechos. Las opciones se separan mediante una regla horizontal fuera del mapa.
| Celda JSON | Glifo | Significado |
|---|---|---|
. |
◻ | disponible |
# |
◼ | ocupado |
A |
♿ | accesibilidad |
* |
♟︎ | recomendado |
|
(dos espacios) |
pasillo / hueco |
La respuesta comienza con tres líneas compactas y cada opción usa una sección abierta ┌─ N / └─ Elegir: N. Si la petición dice «en San Miguel o Salaverry», ambas sedes son filtros estrictos (--venue) y jamás aparecerá una sede distinta; solo palabras explícitas como «prefiere» o «prioriza» activan --favorite-venue. Por defecto #1, #2 y #3 muestran cada una su seat_preview completo en un bloque text, con todas las filas y columnas. Se preservan las filas vacías estructurales que expresan la geometría de la sala, sin añadir padding decorativo ajeno al mapa. Los mapas conservan la paleta documentada y no usan bordes, incluido el derecho; mapa N puede repetir la sala completa almacenada como detalle, sin revelar contenido oculto. En cualquier opción se muestran hora/sede, libres/modalidad, visión en español y los asientos explícitos, sin rangos. Ejemplo documental:
🎬 LA ODISEA · HOY · NOCHE · 2 PERSONAS
📍 SOLO LA MOLINA + SALAVERRY · 3 OPCIONES
🕒 Actualizado 14:34 (Lima) · 12/12 mapas · 0 fallas
┌─ ⭐ 1 · 20:30 · CP LA MOLINA
55 libres · 2D · SUB · Regular
♟︎ G6, G7 · Visión 97/100 Excelente · juntos · zona central media-trasera
PANTALLA
```text
E ◻ ◼ ◻ ◻ ◻ ◻ ◻ ◻ ◻
F ◻ ◼ ◻ ◻ ◻ ◻ ◻ ◻ ◻
G ◻ ◻ ◻ ◼ ◻ ♟︎ ♟︎ ◻ ◻
H ◼ ◻ ◻ ◻ ◻ ◻ ◻ ◻ ◼
I ◻ ◻ ◻ ◻ ◻ ◻ ◻ ◻ ◻
```
└─ Elegir: 1
────────────────────────────────────────────────────────────
┌─ 2 · 21:00 · CP SALAVERRY
18 libres · 2D · SUB · PRIME
♟︎ G6, G7 · Visión 95/100 Excelente · juntos · zona central media-trasera
PANTALLA
```text
E ◻ ◼ ◻ ◻ ◻ ◻ ◻ ◻ ◻
F ◻ ◻ ◼ ◻ ◻ ◻ ◻ ◻ ◻
G ◻ ◻ ◻ ◻ ◼ ♟︎ ♟︎ ◻ ◻
H ◻ ◼ ◻ ◻ ◻ ◻ ◻ ◼ ◻
I ◻ ◻ ◻ ◻ ◻ ◻ ◻ ◻ ◻
```
└─ Elegir: 2
────────────────────────────────────────────────────────────
┌─ 3 · 21:30 · CP LA MOLINA
27 libres · 2D · DOB · Regular
♟︎ H7, H8 · Visión 88/100 Buena · juntos · zona media
PANTALLA
```text
F ◻ ◻ ◻ ◻ ◻ ◻ ◻ ◻ ◻
G ◻ ◼ ◻ ◻ ◻ ◻ ◻ ◻ ◼
H ◻ ◻ ◻ ◼ ◻ ♟︎ ♟︎ ◻ ◻
I ◻ ◻ ◼ ◻ ◻ ◻ ◻ ◻ ◻
J ◻ ◻ ◻ ◻ ◻ ◻ ◻ ◻ ◻
```
└─ Elegir: 3
◻ disponible · ◼ ocupado · ♿ accesibilidad · ♟︎ recomendado · dos espacios = pasillo / hueco
Disponibilidad observada a 2026-08-15T19:34:56+00:00; puede cambiar.
El contrato es deliberadamente pequeño: recommend y la TUI son de solo
lectura; solo checkout --yes crea una retención. Una función agotada se
reporta como tal y una falla parcial de mapa nunca se convierte en datos
inventados. La disponibilidad siempre incluye observed_at porque puede
cambiar antes de comprar.
- Rust: CLI, dominio, ranking, parsing y concurrencia asíncrona.
- Tokio + Reqwest: consultas HTTP en vivo y reutilización de sesión.
- Ratatui + Crossterm: TUI multiplataforma para exploración humana.
- Node.js + Playwright Core: checkout visible y controlado en Chrome; no descarga otro navegador ni depende de Agent Browser.
- JSON v1: contrato estable para Codex, Claude Code y cualquier harness.
- Cargo + npm: distribución del binario y dependencia mínima del checkout.
- Modos de decisión: Mejor vista, Más pronto y Todos juntos.
- Filtros por horario y modalidad.
- Agrupación de estrenos.
- Monitoreo técnico del contrato público de Cineplanet.
El runtime es determinista: no usa LLM. Las consultas normales son HTTP; el checkout explícito usa un Chrome visible y persistente mediante Playwright.
Al iniciar crea una sesión anónima efímera y la reutiliza durante esa ejecución. Si el contrato público cambia, la aplicación falla de forma explícita y nunca sustituye datos reales por demo. El demo solo se habilita explícitamente con CINEPLANET_DEMO=1.
Instala las Herramientas de línea de comandos de Xcode, Rust estable, Node.js 20+ y Google Chrome. Luego, desde un clon del repositorio:
xcode-select --install
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
git clone https://github.com/asther0/cineplanet-cli.git
cd cineplanet-cli
npm install
cargo install --path .npm install instala playwright-core; no descarga otro navegador porque el checkout reutiliza Google Chrome. La TUI y recommend funcionan sin Playwright, pero checkout lo requiere.
Si cargo no está disponible tras instalar Rust, cierra y vuelve a abrir la terminal.
Luego inicia la aplicación con:
cineplanet-cliControles de la TUI:
- Flechas: moverte entre opciones.
- Escribir: filtrar al instante la lista visible.
- Backspace: borrar caracteres del filtro.
- Enter: seleccionar o continuar.
- Space: alternar selección en los selectores múltiples.
- Esc: volver al paso anterior.
- Q: salir.
macOS es la plataforma actualmente verificada.
