
Plataforma de control autoalojada y escritorio remoto para estaciones de trabajo Linux a través de Tailscale, con transmisión WebRTC, control por voz con LLM local, macros de escena, entrada virtual, transferencia de archivos y telemetría del sistema en vivo.
Convierte un teléfono Android de repuesto (o cualquier dispositivo con un navegador) en una consola de control autogestionada y escritorio remoto para tu estación de trabajo Linux, a través de tu red privada de Tailscale, sin aplicaciones de terceros.
Comenzó como "¿qué hago con un teléfono viejo?" y se convirtió en un plano de control para un rig Hyprland: control de ventanas/espacios de trabajo, macros de escena, un enrutador de voz push-to-talk con un asistente LLM local, controles contextuales dentro de las aplicaciones, transmisión bidireccional de audio + pantalla, un escritorio remoto táctil, un teclado/ratón virtual, transferencia de archivos + uso compartido teléfono→PC, y telemetría en vivo, todo servido como un PWA instalado con apariencia de terminal de fósforo.
Nota sobre portabilidad. Esto fue construido para una configuración específica: Linux basado en Arch (Garuda) + Hyprland + PipeWire + NVIDIA + Tailscale, con los dotfiles end-4 / illogical-impulse. La arquitectura es genérica, pero varias integraciones son específicas del entorno (nombres de monitores, enlaces de espacios de trabajo, ruta del tema matugen,
cpupower/nvidia-smi). Tómalo como una referencia funcional para adaptar, no como un paquete listo para usar.
La interfaz es una aplicación web oscura, con pestañas y apaisada (sincronizada con el tema de tu escritorio):
| Pestaña | Qué hace |
|---|---|
| Workspaces | Cuadrícula de espacios de trabajo en vivo por monitor (toca para cambiar), lista de ventanas en vivo (toca para enfocar), alternancia DPMS por monitor + brillo con ddcutil |
| Remote | Trackpad en pantalla (arrastrar/tocar/dos dedos) + teclado virtual con modificadores y combinaciones, a través de un dispositivo uinput del kernel |
| Modes | Macros de escena con un toque: lanzar/cerrar/organizar diseños completos de aplicaciones en todos los monitores (p. ej., "Trabajo" / "Ocio") |
| Voice | Enrutador de voz push-to-talk (faster-whisper, CPU): canales de palabra clave — macro (ejecutar un modo/comando), type (dictado), input (frase → combinación de teclas) — con confirmar antes de ejecutar, además de "friday", un respondedor LLM local de solo lectura (Ollama + Qwen) con búsqueda web autogestionada y conocimiento del estado del sistema en vivo |
| Audio | Silenciar micrófono/altavoz, volumen, selectores de dispositivos de salida y entrada, transporte playerctl + carátula (sigue el reproductor MPRIS activo) |
| Stream | Audio WebRTC bidireccional (PC↔teléfono, con el teléfono como micrófono y salida solo para el teléfono) + vídeo de pantalla, y toca para controlar la pantalla transmitida = un verdadero escritorio remoto |
| System | Alternancia del modo de rendimiento, cambio de tema en vivo, estado de Tailscale, procesos principales (toca para matar), bloqueo, reinicio de NetworkManager, suspender/reiniciar/apagar |
| Files | Captura de pantalla de un monitor → ver/descargar en el teléfono; soltar un archivo del teléfono al PC |
| Config | Editar los archivos de configuración commands.json / modes.json (y contexto/voz) desde el teléfono (validación JSON) |
Siempre visible, sobre las pestañas: una barra de contexto que muestra lo que está sucediendo ahora mismo: una llamada activa (silenciar / saltar a ella), multimedia en reproducción + transporte, y controles de teclado en la aplicación para la aplicación enfocada (YouTube / Brave / Teams), entregados sin robar el foco.
Dos más, fuera de las pestañas:
Además: inicio de sesión con PIN de teclado numérico en pantalla, bloqueo de pantalla, PWA a pantalla completa apaisada, y bloqueo por fuerza bruta en el inicio de sesión.
teléfono / portátil (navegador PWA)
│ HTTPS + WSS (solo Tailscale)
▼
tailscale serve ──► Aplicación web FastAPI ── Socket Unix ──► deckd
(certificado TLS real) (se ejecuta como tu usuario) (nombres de acción) (se ejecuta como root)
│ │
hyprctl · pactl · ddcutil · grim · lista blanca fija de
wf-recorder · uinput · WebRTC comandos privilegiados
(cpupower, nvidia-smi,
systemctl, …)
Dos procesos:
app/ — la aplicación web se ejecuta como tu usuario normal. Hace todo lo que no necesita root: control de Hyprland, audio, brillo, captura de pantalla, entrada virtual, transmisión WebRTC, transferencia de archivos.deckd/ — un pequeño ayudante root (solo stdlib, sin dependencias) para las pocas acciones privilegiadas. La aplicación web nunca le envía cadenas de shell, solo nombres de acción de una lista blanca fija (governor_performance, gpu_power_limit, suspend, …), validados en deckd/actions.py antes de ejecutar cualquier cosa. Incluso si la aplicación web estuviera completamente comprometida, el radio de explosión son exactamente las acciones de la lista blanca, sin inyección de argumentos. El socket es root:<grupo> modo 0660.tailscale serve lo expone en tu nombre MagicDNS con un certificado real de Let's Encrypt; nunca se vincula a 0.0.0.0.La aplicación web puede ejecutar tus comandos de shell configurados e inyectar entrada como tu usuario — es, por diseño, un control remoto para tu máquina. Mantenla en tu tailnet, detrás del PIN, y no la expongas públicamente.
pactl/PulseAudio)hyprctl, pactl / pw-record / pw-play, playerctl, ddcutil,
wf-recorder, grim, cpupower, nvidia-smi, kitty (o tu terminal)input (para /dev/uinput) y i2c (para ddcutil)aiortc + PyAV (instalado vía uv) para transmisión de audio/vídeogit clone <tu-url-del-repositorio> phone-deck
cd phone-deck
uv sync # crea .venv e instala dependencias
uv run python -m app.set_pin # establece tu PIN de desbloqueo
deckd)Primero edita systemd/deckd.service — establece las rutas y DECK_SOCKET_GROUP a un grupo al que pertenezca tu usuario (normalmente tu grupo principal):
sudo cp systemd/deckd.service /etc/systemd/system/
sudo systemctl daemon-reload && sudo systemctl enable --now deckd
deckd ejecuta el Python del sistema (solo stdlib — no necesita venv).