Skip to content

Repository files navigation

RAMWatch

Monitor flotante de memoria para macOS: RAM usada, presión, swap, gráfico de 3 minutos y las 5 apps que más consumen, con aviso rojo y sonido cuando la memoria se agota. Gratis y de código abierto (MIT). Swift + AppKit, sin dependencias.

A floating memory monitor for macOS: used RAM, pressure, swap, a 3-minute chart and the top 5 apps, with a red alert and sound when memory runs short. Free and open source (MIT).

Compacto Completo

Descargar / Download

  1. Descarga RAMWatch-X.Y.zip desde Releases y descomprímelo.
  2. Mueve RAMWatch.app a Aplicaciones.
  3. Ábrelo. Requiere macOS 13 o posterior; funciona en Apple Silicon e Intel.

Las versiones con firma ad-hoc no están notarizadas por Apple y macOS puede bloquearlas. Conserva la cuarentena y las comprobaciones de Gatekeeper. Comprueba el origen y el SHA-256 publicado antes de usar una descarga; un hash del mismo sitio comprueba integridad, pero no acredita la identidad del autor. Para distribución con identidad verificada, usa una versión firmada con Developer ID y notarizada. También puedes revisar el código y compilarlo localmente. Las notas de cada versión indican su firma y notarización.

Download the zip from Releases, move RAMWatch.app to Applications and open it (macOS 13+, Apple Silicon and Intel). Ad-hoc releases are not notarized. Preserve Gatekeeper checks, verify the source, and prefer a Developer ID signed and notarized release or build reviewed source locally.

Idiomas / Languages

Clic derecho → Idioma. 20 idiomas: español, English, português, français, Deutsch, italiano, Nederlands, polski, русский, українська, Türkçe, العربية, हिन्दी, 简体中文, 繁體中文, 日本語, 한국어, Bahasa Indonesia, Tiếng Việt, ไทย. Por defecto sigue el idioma del sistema (o inglés si no está disponible). Las traducciones están en src/idiomas.swift; se agradecen correcciones de hablantes nativos.

Right-click → Language. Defaults to the system language, falling back to English. Corrections from native speakers are welcome (src/idiomas.swift).

Informe técnico de la versión 2.2: INFORME_AUDITORIA_2.2.md.

Cambios y verificaciones 2.4: INFORME_CAMBIOS_2.4.md.

Revisión de seguridad y correcciones 2.3.1: INFORME_SEGURIDAD.md. Los analizadores se instalan fuera de la app; no son dependencias de ejecución.

Compilar, comprobar e instalar

Requiere las Command Line Tools de Xcode. build.sh compila para la arquitectura del Mac actual; release.sh genera el zip universal (Apple Silicon + Intel) para publicar. Destino mínimo explícito: macOS 13. Probado en macOS 26 con Apple Silicon (el binario Intel, solo bajo Rosetta); no se ha probado físicamente en macOS 13 ni en un Mac Intel.

./build.sh --check  # compila, prueba, firma y genera seis capturas; no instala
./build.sh          # lo anterior + respaldo, instalación y apertura

El instalador verifica antes de sustituir la app, conserva una copia de la instalada en build/RAMWatch-anterior-FECHA.app y mantiene el bundle en ~/Applications/RAMWatch.app, para conservar el alias del Escritorio. La firma local es ad-hoc, con Hardened Runtime activado; no está notarizada.

Publicar una versión

./release.sh                                   # zip universal, firma ad-hoc
DEVELOPER_ID="Developer ID Application: Nombre (EQUIPO)" NOTARY_PROFILE=ramwatch ./release.sh
gh release create vX.Y build/release/RAMWatch-X.Y.zip build/release/RAMWatch-X.Y.zip.sha256

La segunda forma requiere el Apple Developer Program: firma con runtime endurecido, envía a notarizar, espera la aprobación y engrapa el ticket. El perfil de credenciales se crea una vez con xcrun notarytool store-credentials ramwatch --apple-id CORREO --team-id EQUIPO (usa una contraseña de app de appleid.apple.com). La Mac App Store no es viable: RAMWatch lee todos los procesos del sistema y usa una API privada opcional, algo que el sandbox obligatorio de la tienda no permite.

./tests/run.sh
build/RAMWatch --dump
build/RAMWatch --render archivo.png
build/RAMWatch --render archivo.png completo alerta
build/RAMWatch --render archivo.png critico

Las capturas usan datos actuales y un historial sintético para mostrar el diseño; no son evidencia de tres minutos de medición. Los modos forzados cambian el color, sin fingir presión crítica en las métricas reales. --render no activa sonidos ni temporizadores. Los errores de lectura o escritura devuelven un código distinto de cero.

Funcionamiento

  • Una cola de trabajo hace las lecturas cada dos segundos, sin bloquear los clics. No admite dos escaneos simultáneos. AppKit recibe los resultados en el hilo principal.
  • Memoria.leer() usa host_statistics64 y sysctl, libera el derecho Mach de cada lectura y rechaza las lecturas fallidas. La interfaz conserva el último valor, muestra SIN DATO y avisa que está reintentando.
  • Rastreador agrupa ri_phys_footprint por responsable, bundle o ascendencia. Comprueba la fecha de creación del proceso antes de reutilizar la caché; elimina PIDs desaparecidos y refresca las atribuciones cada 60 segundos.
  • Tablero comparte las rutinas de cabecera y filas entre los dos tamaños. Los iconos tienen una caché limitada a 32 entradas.
  • Controlador maneja la ventana, alarmas, menú y preferencias. Core Animation produce el pulso: no hay temporizador que dibuje la interfaz 30 veces por segundo. Al ocultar, se suspende la animación; la vigilancia de memoria continúa.

Métricas

usada = (max(internal_page_count − purgeable_count, 0)
         + wire_count + compressor_page_count) × tamaño de página
presión = kern.memorystatus_vm_pressure_level (1 normal, 2 alta, 4 crítica)
swap = vm.swapusage.xsu_used
swap activo = incremento de swapouts entre muestras válidas

La RAM usada es una estimación basada en contadores del sistema, coherente con memoria de aplicaciones + cableada + comprimida. No se garantiza igualdad exacta con Monitor de Actividad, que puede actualizar en otro instante y aplicar su propia atribución. El footprint por proceso y el total de memoria usada no son magnitudes que deban sumarse entre sí.

La atribución intenta, en este orden:

  1. El proceso responsable, mediante una API privada cargada opcionalmente. Si es un terminal, se ignora.
  2. El primer bundle .app del ejecutable.
  3. Hasta 12 padres; al llegar a un terminal se deja de subir.
  4. El nombre del ejecutable, con nombres amigables para Node.js, Python y otros. Claude Code mantiene su grupo propio.

Los nombres de bundles se obtienen del nombre de la carpeta y se cachean, evitando consultas de presentación a Finder en cada proceso. Pueden diferir del nombre localizado. Los procesos que macOS no permite leer se omiten. Si desaparece la API privada, permanecen los pasos 2 a 4. Las atribuciones son heurísticas: cambios de ascendencia o ejecutable dentro de la misma vida de un PID pueden tardar hasta 60 segundos en reflejarse.

Alarmas

Desde 2.4, el porcentaje ocupado por sí solo nunca dispara sonido ni rojo:

Estado Se activa con cualquiera de estas condiciones
EXIGIDA, ámbar presión ≥ 2, uso ≥ umbral elegido, o escritura activa a swap
ALERTA, rojo presión ≥ 4, o escritura a swap ≥ 10 MiB/s sostenida durante al menos 4 segundos

Umbral de aviso ámbar predeterminado: 90 %, configurable entre 75 y 95 %. Se conserva el valor que ya tuviera el usuario. Al cesar la causa crítica, sale del rojo aunque la RAM siga ocupada; se elimina la retención del rojo por porcentaje. El pulso es de 1,2 ciclos por segundo; Sosumi puede sonar cada 20 segundos y silenciarse durante 30 minutos. “Probar alarma” fuerza el estado durante unos seis segundos; vuelve a evaluarse en el siguiente muestreo.

La velocidad de swap usa el tamaño real de página del kernel y el tiempo monotónico entre lecturas, también bajo Rosetta. Se descarta el intervalo inicial, un contador reiniciado y pausas mayores a diez segundos; un error de lectura reinicia la medición. El volumen de swap acumulado no dispara alarmas. Cambiar el umbral o probar el sonido no borra la actividad medida.

El criterio de 10 MiB/s durante 4 segundos es una heurística de RAMWatch, no un límite oficial de Apple ni una prueba de lentitud. Apple calcula la presión considerando memoria libre, velocidad de swap, memoria fija y caché: Monitor de Actividad.

Interacción y preferencias

  • Clic sobre una app: traerla al frente; si no puede identificarse como app, abre Monitor de Actividad.
  • Clic derecho: traer, solicitar salida normal de la app, umbral, sonido, probar alarma, tamaño, idioma, Monitor de Actividad, autoarranque, ocultar y salir.
  • El menú conserva la identidad elegida aunque cambie el orden del ranking. No usa PIDs antiguos para cerrar aplicaciones.
  • Arrastrar el fondo mueve la ventana; doble clic abre Monitor de Actividad.
  • ⌄/⌃ cambia el tamaño conservando el borde superior, salvo que deba ajustarse para caber en pantalla.
  • Al cambiar pantallas o volver a mostrarla, recupera la ventana dentro del área visible.
  • Abrir una segunda instancia instalada envía una notificación a la existente para mostrarla.

El dominio sigue siendo cl.juanluis.ramwatch, con las claves umbralRojo, muteUntil, compacto, esquina e idioma. La clave histórica umbralRojo se conserva para no perder la elección, pero ahora controla el aviso ámbar.

El inicio automático usa SMAppService.mainApp (macOS 13+) y aparece en Ajustes del Sistema > General > Ítems de inicio. Si macOS requiere aprobación, el menú muestra una marca intermedia y “Inicio pendiente: autorizar en Ajustes…”. La app no modifica esa autorización por su cuenta. Un clic en la opción principal desactiva el registro, incluso si está pendiente.

Al arrancar, se migra el LaunchAgent antiguo de RAMWatch: solo se archiva cuando el nuevo servicio está habilitado, guardando una copia íntegra en ~/Library/Application Support/RAMWatch/inicio-anterior-UUID.plist. Si el registro falla o necesita aprobación, se conserva el inicio anterior. Tras conceder aprobación, al volver a abrir RAMWatch se completa el archivo del plist. Un archivo ajeno no se modifica. El sistema administra la ubicación de la app; no se escribe una nueva ruta fija. RAMWatch.app/Contents/MacOS/RAMWatch --login-status muestra el estado sin modificarlo (0: no registrado, 1: habilitado, 2: requiere aprobación, 3: no encontrado).

Archivos y recuperación

  • src/main.swift: aplicación completa.
  • src/idiomas.swift: 20 idiomas de la interfaz y el menú.
  • release.sh: zip universal, firma Developer ID y notarización opcionales.
  • historico/: código de la versión 2.0, solo como referencia.
  • src/icono.swift y recursos/: generador del icono y recursos.
  • tests/: pruebas sin librerías adicionales, compiladas contra el código real.
  • capturas/: compacto/completo × normal/alerta/crítico.
  • build/auditoria/: copia 2.1, programas de medición y resultados locales; ignorado por Git.
  • AUDITORIA.md: guía para una próxima revisión.
  • CHANGELOG.md: cambios históricos.

El estado 2.1 sigue en Git (0595435) y en build/auditoria/RAMWatch-2.1-original.tar.gz. Para revisar cambios usa git diff. Para extraer una copia del código previo sin sobrescribir el actual:

git show 0595435:src/main.swift > build/main-2.1.swift

No se promete ausencia absoluta de errores ni una optimización máxima universal. Las pruebas, mediciones y límites concretos constan en el informe.

About

Monitor flotante de memoria para macOS · Floating memory monitor for macOS (20 idiomas / languages)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages