Compartir
Portada de DragoTerminal: 34 herramientas y 59 juegos en una terminal Matrix
Logo de DragoTerminal: 34 herramientas y 59 juegos en una terminal MatrixProyecto flutter · androidssh

DragoTerminal: 34 herramientas y 59 juegos en una terminal Matrix

Una terminal en el bolsillo: 34 herramientas de desarrollador y un arcade de 59 juegos offline, con estética Matrix.

16 mar 20268 minde lectura
Herramientas
34
Juegos
59
Versión
2.1.4
Descargas
100+
año
2026
estado
Online

Qué es DragoTerminal

DragoTerminal es una app Flutter para Android que reúne 34 herramientas técnicas —SSH, bases de datos, red, ficheros, IA, multimedia y utilidades de desarrollo— junto a un arcade de 59 juegos que funcionan sin conexión, todo bajo una misma interfaz con estética de terminal: fondo negro, FiraCode, lluvia Matrix y transiciones de CRT.

La filosofía es local-first: todo lo esencial funciona sin cuenta y sin servidor, y las credenciales sensibles se guardan cifradas en el propio dispositivo. La cuenta es opcional; sirve para sincronizar con la web y para las funciones que de verdad necesitan servidor, como Encuestas y Biblioteca.

Inicio de DragoTerminal, el menú de herramientas por categorías y el de juegos

SSH y túneles reales

Cliente SSH completo con SFTP, monitor de servidor y port-forwarding local de verdad, con verificación de host-key.

Gestor de bases de datos

MySQL y PostgreSQL en directo o a través del túnel, más explorador de Firebase: tablas, datos y edición desde el móvil.

IA con tu propia clave

Chat multi-proveedor (Anthropic, OpenAI, Gemini, Groq) con tu API key, y ejecución de modelos locales vía Ollama.

Caja de red

Escáner de hosts y puertos con Wake-on-LAN, test de velocidad, cliente REST tipo Postman y geolocalización de IP.

Arcade de 59 juegos

De snake a ajedrez con minimax, todos offline y con récord y hoja de ayuda en cada uno; siete tienen modo contra la CPU.

Dev tools

Autenticador 2FA offline, hashes y AES, regex lab, cron builder, formateador JSON/YAML/XML y calculadora de bases y subredes.

Nació como un túnel SSH

El proyecto empezó en enero de 2026 con otro nombre, SSH Tunnel DB Manager, para resolver algo que yo necesitaba: conectarme desde el móvil a bases de datos MySQL o PostgreSQL remotas a través de un túnel SSH y poder ver y editar los datos, algo que en Android no tenía una solución cómoda.

Aquel primer README admitía que el túnel era «una implementación simplificada». Hoy es port-forwarding local de verdad: la app abre un socket local, multiplexa cada conexión hacia el servidor y apunta la huella de su clave la primera vez; si un día cambia, corta la conexión. El gestor de bases de datos trabaja encima con naturalidad. A partir de ahí, la app fue creciendo herramienta a herramienta hasta convertirse en una navaja suiza.

Perfil SSH, terminal SSH y gestor de bases de datos de DragoTerminal

34 herramientas, un mismo lenguaje

Las herramientas viven en un registro declarativo con 9 categorías —conexiones, IA, nube personal, multimedia, archivos, red, ubicación, dispositivo y dev tools— y el menú se adapta a cada uno: se pueden reordenar por arrastre, ocultar las que no uses y buscarlas todas desde un buscador global que ignora acentos.

Hay de todo: editor de documentos PDF y Excel, editor de fotos y EXIF, creador de stickers para WhatsApp, sonómetro y afinador por FFT, escáner y generador de QR, GPS simulado con rutas y joystick, recordatorios programados, arte ASCII y un generador de tonos de 20 Hz a 20 kHz. El chat de IA también sabe hablar con un servidor Ollama de tu red, el mismo motor que uso en DRAGO Model Runner.

Herramientas de DragoTerminal agrupadas por categorías, con Multimedia desplegada

Un arcade con esqueleto común

Los 59 juegos se reparten en cuatro categorías —11 arcade, 6 de puzle, 6 de mesa y 36 minijuegos rápidos— y comparten un mismo armazón: un shell que aporta el marcador, el récord persistente, los estados de pausa y fin de partida y la hoja de cómo se juega. Cada juego solo implementa su bucle; añadir uno nuevo es crear su pantalla y una línea en el registro.

El historial lo demuestra: el arcade entró en la app el 11 de junio con 12 juegos y once días después ya tenía 59. Así es como una sola persona mantiene desde un snake hasta un ajedrez completo, cuyo minimax corre en un isolate —igual que el de las damas y el reversi— para no congelar la interfaz. Los seis juegos de mesa y el Pong tienen modo contra la CPU, con marcador de victorias, derrotas y empates.

Ajedrez contra la CPU, Tetris y Reversi en el arcade de DragoTerminal

El game-over fantasma

El esqueleto compartido corta en los dos sentidos: un bug en el shell afecta a los 59 juegos a la vez. El mejor ejemplo fue una condición de carrera al reiniciar partida: el final de la partida anterior podía pintar su pantalla de game-over encima de la nueva. La solución fue un token de partida que se comprueba antes de mostrar nada: un arreglo mínimo en un solo sitio que corrigió los 59 juegos de golpe.

Donde Flutter no llega, Kotlin

Varias piezas necesitaron código nativo Android: el GPS simulado corre como servicio en primer plano con su gestor de ubicaciones simuladas, el generador de tonos sintetiza el audio en Kotlin, los packs de stickers se exponen a WhatsApp mediante un content provider propio, y hay un widget de pantalla de inicio con la frase del día. Existe incluso un módulo independiente para Wear OS: una Tile que muestra la misma frase en el reloj.

Subir a Google Play también obligó a bajar al build. El escáner de QR arrastraba librerías nativas alineadas a páginas de 4 KB, y Play exige que funcionen con páginas de 16 KB. La solución fue forzar en Gradle las versiones de cámara y ML Kit que Google ya había recompilado, y empaquetar las librerías nativas sin comprimir.

GPS simulado de DragoTerminal: mapa, rutas predefinidas y joystick

La misma frase, tres superficies, cero red

La frase del día se calcula indexando una lista por los días transcurridos desde el año 2000, módulo el número de frases. Como el cálculo es determinista, la app, el widget del escritorio y la Tile del reloj —que ni siquiera embebe Flutter— muestran la misma frase el mismo día sin hablar entre ellos ni con ningún servidor. La solución más simple resultó ser también la más robusta.

Local-first, con cuenta opcional

Nada del arranque depende de la red: las sincronizaciones se lanzan en segundo plano y el menú se pinta sin esperar a ningún servidor. Las credenciales sensibles —perfiles SSH, conexiones guardadas, claves de API, secretos 2FA— viven cifradas en el almacén seguro del sistema, y una migración única sacó de las preferencias en texto plano las que habían guardado versiones antiguas.

Con la sesión iniciada, la cuenta suma sincronización: el orden y las herramientas ocultas del menú, los récords de los juegos, el portapapeles si lo activas y los perfiles de conexión. Encuestas —formularios con enlace público que cualquiera puede responder— y Biblioteca —un chat personal de notas y archivos— forman la sección Nube personal y viven directamente de esa cuenta: lo que creas en la app aparece en la web, y al revés.

Un backend para la app y para la web

Al principio DragoTerminal tuvo su propio servidor: un FastAPI con PostgreSQL y Redis en Docker, con 15 routers y 86 endpoints. En junio de 2026 decidí no mantener dos backends y consolidarlo todo en el de esta web: un único FastAPI bajo /api/v1, con los mismos usuarios y contraseñas en la app y en el navegador. Los endpoints que usaba la app se portaron a 13 routers dentro de ese backend, y el servidor original quedó congelado como referencia.

La pieza que hace posible la simbiosis es la autenticación. En el backend, una sola función resuelve el usuario a partir de la cookie de sesión de la web, de un token Bearer o de una cabecera X-API-Key, cuya clave se guarda solo como hash; cualquier endpoint que la use sirve igual a los dos clientes. En la app, la forma de autenticarse es una estrategia intercambiable —token o clave API— y la clave vive en el almacén seguro, así que el cambio de backend no obligó a tocar ninguna llamada existente.

Sincronizar sin pisar nada

Compartir backend tiene un riesgo que un servidor propio escondía: un error de sincronización ya no se queda en tu móvil. La auditoría de agosto encontró justo eso: al sincronizar credenciales SSH, de bases de datos y de Firebase, la app usaba la posición en la lista local como identificador en el servidor, así que una edición o un borrado podía caer sobre un registro que no le tocaba.

El arreglo dejó tres reglas que hoy son convención del proyecto: las actualizaciones y los borrados remotos van siempre por el identificador del servidor, la fusión es aditiva y conserva los secretos locales, y una respuesta dudosa nunca sobrescribe la caché local —una lista donde se esperaba un objeto llegó a vaciarla—. Lo vigilan 21 tests propios.

En desarrollo, y la app lo dice

DragoTerminal ya está en Google Play, pero no esconde lo que le falta: con cada versión nueva avisa de que está en beta y de que cuentas, pagos y sincronización dependen de un backend que todavía no está conectado. El cableado de la app está hecho; falta el paso a producción del backend compartido. La pantalla de pagos es una maqueta funcional de interfaz —valida la tarjeta, pero no hay pasarela y no cobra nada— y ARENA, el modo social competitivo, está terminado por dentro pero apagado por fuera: hoy solo tiene un backend simulado. Son decisiones conscientes, no olvidos.

Estado real

El proyecto suma 140.801 líneas de Dart en 220 ficheros, escritas entre enero y agosto de 2026. La 2.1.4, la versión que está en Google Play desde el 21 de agosto, salió con el análisis estático limpio y 190 tests en verde, entre ellos un smoke test por cada uno de los 36 minijuegos rápidos. El proyecto se ha auditado internamente y las incidencias graves están corregidas.

Las deudas también están dichas: ningún juego tiene sonido todavía, la accesibilidad está pendiente con un plan por fases, no hay integración continua —el análisis y los tests se lanzan a mano— y, aunque Flutter es multiplataforma, en la práctica todo el código nativo es de Android.

Pendientes y hoja de ruta

  • Poner en producción el backend compartido y cerrar de principio a fin el alta de la clave API desde la app.
  • Decidir qué pasa con las cuentas del servidor antiguo: migrarlas a la web o pedir un registro nuevo.
  • Récords compartidos entre app y web: hoy coinciden los catálogos de juegos, no las clasificaciones.
  • Sonido en el arcade: ninguno de los 59 juegos tiene efectos todavía.
  • Accesibilidad: etiquetas semánticas y textos que respeten el tamaño de letra del sistema.
  • Integración continua, para que el análisis y los tests no dependan de lanzarlos a mano.
  • Conectar ARENA a un backend real en lugar del simulado.
  • Dividir el estado central de la app (casi 1.200 líneas) y unificar los cuatro clientes de IA, hoy casi idénticos.
  • Guardar el historial del terminal SSH entre sesiones.
  • Compilar y probar en iOS: la configuración existe, pero no hay ninguna build probada.

Compatibilidad

3/5 ✓
DispositivoVersiónEstadoTamaño
Android 7.0+ (API 24)2.1.4Funciona—
Android 16 (API 36, objetivo)2.1.4Funciona—
Wear OS (Tile, API 26+)2.1.4Funciona—
iOS-No funcionaPendiente
Linux Desktop-No funcionaPendiente

Materiales / Compra

Tienda: Construida con Flutter y Dart, con Kotlin para las piezas nativas de Android y Wear OS. SSH con dartssh2; documentos con Syncfusion; mapas con teselas de OpenStreetMap; tipografía FiraCode. La cuenta y la sincronización van contra el mismo backend FastAPI de esta web. Los proveedores de IA se usan con la clave de API del propio usuario.

Aprendizajes

El aprendizaje central fue el valor de los contratos compartidos: un shell común para 59 juegos, un registro declarativo para 34 herramientas y una sola función de autenticación para la app y la web permiten que una persona lo mantenga todo con convenciones uniformes. El reverso es que un bug de una línea afecta a todo a la vez, así que las auditorías periódicas del propio código se volvieron parte del método. La otra lección: local-first simplifica todo, porque nada del arranque depende de la red y la cuenta suma sin ser imprescindible.