diff --git a/workloads/docs-portal/docs/arquitectura/sesion-tmux-persistente.md b/workloads/docs-portal/docs/arquitectura/sesion-tmux-persistente.md
new file mode 100644
index 0000000..5f9f81e
--- /dev/null
+++ b/workloads/docs-portal/docs/arquitectura/sesion-tmux-persistente.md
@@ -0,0 +1,121 @@
+# Sesión persistente de Claude Code (tmux en Docker)
+
+## Problema que resuelve
+
+Correr Claude Code directo en una shell SSH sobre el NAS lo ata al
+ciclo de vida de esa conexión: un corte de red, cambiar de laptop a
+tablet, o cerrar la terminal por accidente mata el proceso y con él
+todo el contexto de trabajo en curso — no hay forma de "retomar
+donde quedó" porque el proceso ya no existe.
+
+**Esto es un problema distinto al de los límites de uso/cuota de
+Claude Code.** Este setup no aumenta cuota de mensajes ni tokens —
+eso lo controla el backend de Anthropic sin importar dónde corra el
+CLI. Lo único que resuelve es que la *sesión de terminal* sobreviva
+a cortes de red o cambios de dispositivo; si la cuota se agota, sigue
+agotada exactamente igual dentro de este setup.
+
+## Por qué Docker y no instalación nativa
+
+ZimaOS no tiene gestor de paquetes tradicional utilizable para esto:
+`/` está montado como `squashfs` de solo lectura (imagen del SO
+inmutable), y `/usr` es un overlay de solo lectura sobre eso —
+`/usr/local/bin` ni siquiera existe y no se puede crear, tampoco como
+root (`mkdir` falla con "Read-only file system"). No hay dónde
+instalar Node.js, npm ni tmux directamente sobre el host.
+
+Un contenedor Docker sortea esto por completo: tiene su propio
+filesystem de escritura (overlay2), independiente del `squashfs` del
+host — ahí es donde `npm install -g` deja el binario de `claude` sin
+tocar el host en absoluto. Lo único que el contenedor toma del host
+es lo que se monta explícitamente como volumen.
+
+## Arquitectura
+
+```mermaid
+flowchart LR
+ SSH["Cliente SSH
(laptop / tablet / lo que sea)"] -->|docker exec| C["Contenedor tmux-host
--network host, --restart unless-stopped"]
+ C --> T["tmux server
sesión 'lab'"]
+ T --> CC["proceso claude
(Claude Code)"]
+ C -.->|bind mount| DATA["/DATA (host)
repos y configs del lab"]
+ C -.->|bind mount| SOCK["/var/run/docker.sock (host)
control de Docker/k3d"]
+ C -.->|bind mount| HOME["/DATA/AppData/k3d-lab-v3/claude-code-home (host)
-> /root/.claude"]
+```
+
+El contenedor sigue vivo aunque la conexión SSH se corte — es el
+servidor tmux, no la shell del cliente, el que sostiene el proceso de
+Claude Code. `--restart unless-stopped` además lo revive si el NAS
+reinicia.
+
+## Contenedor: `tmux-host`
+
+```bash
+docker run -d \
+ --name tmux-host \
+ --restart unless-stopped \
+ -v /DATA:/DATA \
+ -v /var/run/docker.sock:/var/run/docker.sock \
+ -v /DATA/AppData/k3d-lab-v3/claude-code-home:/root/.claude \
+ --network host \
+ alpine sh -c "apk add --no-cache tmux docker-cli bash curl git kubectl nodejs npm && npm install -g @anthropic-ai/claude-code && tail -f /dev/null"
+```
+
+| Volumen | Destino | Por qué |
+|---|---|---|
+| `/DATA` | `/DATA` | Acceso a los repos (`apps-registry`, `platform-infra`, `scripts`) y configs del lab, mismos paths que en el host |
+| `/var/run/docker.sock` | `/var/run/docker.sock` | Seguir controlando Docker y k3d (contenedores, `k3d node`, etc.) desde dentro del contenedor |
+| `/DATA/AppData/k3d-lab-v3/claude-code-home` | `/root/.claude` | Persistir login/config de Claude Code — sobrevive no solo a un `docker restart`, sino a recrear el contenedor entero |
+
+Sobre paquetes: alpine (imagen `alpine` sin pin de versión, la misma
+que uso este setup) sí trae `kubectl` en sus repos — no hizo falta
+cambiar de imagen base ni instalarlo por binario aparte, contrario a
+lo que se sospechaba inicialmente. `nodejs`/`npm` (v24/v11 al momento
+de escribir esto) también están en los repos de alpine y cumplen de
+sobra el mínimo que pide Claude Code.
+
+**Nota sobre `--network host` + `docker.sock`:** el contenedor tiene,
+en la práctica, control equivalente a root sobre el NAS (puede lanzar
+cualquier otro contenedor con cualquier mount). Es una concesión
+deliberada — es exactamente lo que hace falta para seguir operando
+Docker/k3d desde dentro — no un descuido.
+
+## Reconexión: un solo comando
+
+```bash
+/media/HDD-Storage/AppData/k3d-lab-v3/lab-cruzcloud/scripts/lab-session.sh
+```
+
+El script (`scripts/lab-session.sh`) es intencionalmente el mismo
+comando sin importar el estado previo:
+
+```bash
+docker exec -it "$CONTAINER" tmux attach -t "$SESSION" || \
+ docker exec -it "$CONTAINER" tmux new -s "$SESSION"
+```
+
+Si la sesión `lab` existe, se adjunta a ella (mismo shell, mismo
+`claude` corriendo, mismo directorio de trabajo). Si no existe —por
+ejemplo justo después de que el contenedor se recreó desde cero— la
+crea. No hay que recordar cuál de los dos casos aplica.
+
+## Qué sobrevive a qué
+
+| Evento | ¿Sobrevive la sesión tmux (`lab`)? | ¿Sobrevive el login de Claude Code? |
+|---|---|---|
+| Corte de SSH / cerrar la terminal / cambiar de dispositivo | Sí — es exactamente el caso que este setup resuelve | Sí |
+| `docker restart tmux-host` (reinicio del NAS) | **No** — el proceso `tmux server` muere con el contenedor; `lab-session.sh` crea una sesión nueva automáticamente | Sí, vía el volumen montado en `/root/.claude` |
+| `docker rm` + recrear el contenedor desde cero | No | Sí, vía el mismo volumen — no hace falta volver a autenticar |
+
+## Validación en vivo
+
+Confirmado en este mismo lab (2026-08-27): se dejó una variable de
+entorno (`export MARCA_PERSISTENCIA=ok_`) corriendo dentro
+de la sesión `lab` vía `tmux send-keys`, y una invocación
+*completamente separada* de `docker exec` (equivalente a una nueva
+conexión) leyó de vuelta el mismo valor — confirma que el estado vive
+en el servidor tmux del contenedor, no en el cliente que se conecta.
+`claude --version` respondió `2.1.250` dentro de esa misma sesión, y
+un archivo de prueba escrito en `/root/.claude` dentro del contenedor
+apareció de inmediato en
+`/DATA/AppData/k3d-lab-v3/claude-code-home` en el host, confirmando
+el bind mount de credenciales.
diff --git a/workloads/docs-portal/mkdocs.yml b/workloads/docs-portal/mkdocs.yml
index d9c7d71..1048e4f 100644
--- a/workloads/docs-portal/mkdocs.yml
+++ b/workloads/docs-portal/mkdocs.yml
@@ -85,6 +85,7 @@ nav:
- Red y exposición: arquitectura/red-y-exposicion.md
- Flujo GitOps: arquitectura/gitops-flujo.md
- Agente de monitoreo: arquitectura/agente-monitoreo.md
+ - Sesión tmux persistente: arquitectura/sesion-tmux-persistente.md
- Glosario: arquitectura/glosario.md
- Decisiones (ADRs):
- "0001 · Por qué k3d": decisiones/0001-por-que-k3d.md