Nuupa: dependencias globales sin perderme en la terminal
Hay tareas tan pequeñas que uno las tolera durante años. En mi caso era abrir la terminal, revisar los paquetes globales de npm, luego los de pnpm, acordarme de Bun, actualizar algunos y cerrar todo con la sospecha de que algo se me había escapado.
No era un problema serio. Justo por eso nunca lo resolvía.
Después de repetir el ritual suficientes veces terminé haciendo Nuupa, una aplicación de escritorio para ver y actualizar esas dependencias sin saltar entre comandos. La idea era sencilla: construir algo útil, rápido y pequeño mientras aprendía Rust.
Una molestia pequeña fue suficiente
Nuupa se ocupa únicamente de paquetes instalados de forma global con npm, pnpm y Bun. No entra a proyectos, workspaces ni lockfiles. Quise mantener ese límite desde el inicio porque era muy fácil imaginar un administrador universal y terminar con algo enorme que no resolviera bien mi problema original.
La aplicación detecta qué gestores están instalados, mantiene separados sus paquetes y muestra la versión actual, la más reciente y lo que sigue desactualizado. Puedo actualizar uno o lanzar una actualización general con progreso visible. También puedo excluir herramientas que prefiero mantener en cierta versión sin perder la opción de actualizarlas manualmente.
Eso es casi todo, y me gusta que sea así.
npm puede devolver código de salida 1 al consultar paquetes desactualizados y aun así entregar información útil. Si trataba cualquier valor distinto de cero como un error definitivo, Nuupa ignoraba justo los datos que necesitaba. La detección también debía seguir la versión activa de Node cuando uso nvm; de otro modo, la aplicación y mi terminal podían mostrar instalaciones distintas.
Las actualizaciones se pueden cancelar, aunque no existe rollback. Lo que ya terminó permanece actualizado y solo se detiene lo pendiente. No es perfecto, pero es honesto. Prefiero explicar ese límite antes que fingir una transacción que los propios gestores no ofrecen.
Vue adelante, Rust detrás
Ya conocía Vue 3, así que lo usé para la interfaz y dejé que Tauri 2 conectara esa parte familiar con el backend en Rust. Fue una combinación cómoda: podía avanzar sin pelearme con todo a la vez y concentrar el aprendizaje en procesos del sistema, manejo de errores y decisiones que Rust obliga a hacer explícitas.
Era una excusa para aprender, sí, pero debía funcionar en mi máquina. Un ejemplo termina cuando imprime una línea correcta; Nuupa tenía que convivir con herramientas reales, salidas inesperadas y entornos distintos.
Me gustó aprender así. No sentí que estuviera completando ejercicios para después buscar dónde aplicarlos. Cada cosa nueva terminaba resolviendo una molestia concreta en la ventana que tenía enfrente.
Salir un rato de la web
Mi trabajo normalmente vive entre documentación, compilación, pruebas, SonarQube y pipelines parecidos. Todo eso es necesario, pero después de mucho tiempo la ruta se vuelve conocida.
Nuupa se sintió refrescante porque el resultado era una aplicación de escritorio. Seguía escribiendo Vue, pero ahora también había procesos locales, permisos, instaladores y sistemas operativos distintos. No era otra página esperando un servidor.
La parte de releases me llamó especialmente la atención. El workflow de GitHub Actions construye para macOS arm64, macOS x64, Linux x64, Linux arm64 y Windows x64, genera los artefactos de cada plataforma y valida las versiones. Ver salir paquetes para cinco objetivos fue más satisfactorio de lo que esperaba. No porque el pipeline tenga algo mágico, sino porque me sacó de mi rutina web.
Uno de los RPM para Linux arm64 rondó los 4.26 MB. Es solo una referencia, no un benchmark. Los benchmarks me cansan cuando un número aislado se convierte en argumento de venta. Lo agradable fue ver una aplicación útil mantenerse pequeña sin hacer malabares.
Lo que me gusta
- Resuelve el olvido que la originó sin intentar administrar proyectos completos.
- Vue me dejó moverme en terreno conocido mientras Rust concentraba el aprendizaje.
- El progreso, las exclusiones y la cancelación me dan control sin devolverme al ritual de comandos.
- Empaquetar para cinco objetivos me obligó a pensar fuera del navegador.
Lo que me preocupa
- Cancelar no revierte las actualizaciones que ya terminaron.
- La aplicación depende de comportamientos particulares de npm, pnpm y Bun.
- Tauri y Cargo marcan la versión 0.3.5, pero el
package.jsonraíz todavía dice 0.3.1. Ese desfase puede confundir y merece corregirse.
Por ahora, esto era suficiente
Nuupa no nació de una gran visión. Nació porque me perdía entre tres gestores y quería volver a Rust con algo que no abandonara después del primer ejemplo.
El proyecto todavía tiene bordes por pulir, pero ya hace lo que necesitaba y sigue siendo lo bastante pequeño para entenderlo sin perderme dentro. También me recordó algo que a veces olvido entre builds, pruebas y SonarQube: programar puede sentirse ligero. No fácil, pero sí cercano.
Hice una ventana, conecté comandos que ya usaba y terminé con una herramienta que ahora me evita volver a ellos cada vez. Por ahora, eso me basta.