diff --git a/.claude/commands/fleet.md b/.claude/commands/fleet.md
index b9a46356..b7a12f48 100644
--- a/.claude/commands/fleet.md
+++ b/.claude/commands/fleet.md
@@ -1,6 +1,6 @@
---
-description: Muestra la flota de Claudes vivos (sessionId + objetivo + estado) y, con argumento, salta con foco a esa conversación dentro de la sesión tmux fleet.
-argument-hint: "[texto|sessionId|PID para saltar — vacío = listar la flota]"
+description: Muestra la flota de Claudes vivos (sessionId + objetivo + estado) y, con argumento, salta con foco a esa conversación dentro de la sesión tmux fleet. `/fleet show` trae la TUI al contexto tmux actual.
+argument-hint: "[show | texto|sessionId|PID para saltar — vacío = listar la flota]"
---
# /fleet — ver y navegar la flota de Claudes
@@ -33,9 +33,32 @@ cd "${FN_REGISTRY_ROOT:-$HOME/fn_registry}/apps/fleetview" && go build -o fleetv
- la sesión actual / orquestador si la puedes identificar (su `session_id` coincide con el de quien invoca).
4. Si la lista está vacía, indícalo y sugiere que el perfil fleet podría no estar activo (revisar `$FLEET_SOCKET` y que la sesión tmux exista).
+### `show` → traer la TUI al contexto tmux actual
+
+Si `$ARGUMENTS` es exactamente `show` (alias `open`/`attach`), el usuario quiere
+volver a ver el panel FleetView en el contexto/pane actual sin abrir ninguna
+ventana ni arrancar una flota nueva. Ejecuta:
+
+```bash
+"${FN_REGISTRY_ROOT:-$HOME/fn_registry}/apps/fleetview/fleetview" show
+```
+
+Comportamiento (decidido por la app, no abre terminal externa):
+
+- **dentro de tmux con la flota viva** → `select-window` de la window `console`
+ del socket fleet (trae la TUI al frente; no abre nada).
+- **fuera de tmux** → `attach` a la sesión fleet en la terminal actual (la reutiliza).
+- **sin flota viva** → error claro, exit 1, no abre nada (sugiere arrancarla con
+ `fleetclaude`).
+
+Es el equivalente del comportamiento de `fleetclaude` sin args invocado dentro de
+una flota viva (reuse de contexto): úsalo cuando ya tengas una flota corriendo y
+solo quieras recuperar la vista del panel. Para abrir una flota NUEVA aparte, usa
+`fleetclaude --new` (no este comando).
+
### Con argumentos → saltar con foco
-El usuario quiere que la interfaz tmux salte a una conversación concreta. `$ARGUMENTS` es el query: texto del objetivo, prefijo de `sessionId`, o PID.
+El usuario quiere que la interfaz tmux salte a una conversación concreta. `$ARGUMENTS` es el query: texto del objetivo, prefijo de `sessionId`, o PID (cualquier valor que no sea `show`).
1. Ejecuta:
```bash
diff --git a/bash/functions/infra/launch_fleetclaude.md b/bash/functions/infra/launch_fleetclaude.md
index bc733ac8..652d9ffc 100644
--- a/bash/functions/infra/launch_fleetclaude.md
+++ b/bash/functions/infra/launch_fleetclaude.md
@@ -3,10 +3,10 @@ name: launch_fleetclaude
kind: function
lang: bash
domain: infra
-version: "1.6.0"
+version: "1.7.0"
purity: impure
-signature: "launch_fleetclaude [--cwd
] [--bin ] [--session ] [--reuse] [--cols ]"
-description: "Entrypoint de FleetView: abre una ventana de terminal con una sesion tmux (socket aislado por perfil) de dos panes (TUI fleetview a la izquierda, claude --dangerously-skip-permissions a la derecha) para centralizar la flota de Claudes. La terminal se AUTO-DETECTA sin config por PC: kitty si esta instalado y hay display ($DISPLAY/$WAYLAND_DISPLAY), si no Windows Terminal (wt.exe) en WSL adjuntando via wsl.exe. El pane de la TUI corre dentro del bucle supervisor supervise_fleetview_tui, que la relanza si muere (crash/panic/kill), asi el panel de control NUNCA se pierde. Soporta PERFILES multiples: sin --session/--reuse cada invocacion abre un perfil nuevo (fleet, fleet2, fleet3, ...) con su propia flota; inyecta FLEET_SOCKET/FLEET_SESSION a la TUI para que cada panel vea solo sus Claudes. Instala atajos alt+flechas/alt+enter/alt+n que controlan la TUI desde cualquier pane, y fija el ancho del sidebar con hooks."
+signature: "launch_fleetclaude [--cwd ] [--bin ] [--session ] [--reuse] [--new] [--cols ]"
+description: "Entrypoint de FleetView: abre una ventana de terminal con una sesion tmux (socket aislado por perfil) de dos panes (TUI fleetview a la izquierda, claude --dangerously-skip-permissions a la derecha) para centralizar la flota de Claudes. REUSO DE CONTEXTO: si se invoca DENTRO de una flota tmux viva (su window 'console') sin --new, NO abre ventana ni crea un perfil nuevo; trae la TUI al pane/contexto actual (equivale a 'fleetview show'). El flag --new fuerza una flota+ventana nueva aunque estes en tmux. La terminal se AUTO-DETECTA sin config por PC: kitty si esta instalado y hay display ($DISPLAY/$WAYLAND_DISPLAY), si no Windows Terminal (wt.exe) en WSL adjuntando via wsl.exe. El pane de la TUI corre dentro del bucle supervisor supervise_fleetview_tui, que la relanza si muere (crash/panic/kill), asi el panel de control NUNCA se pierde. Soporta PERFILES multiples: fuera de tmux, o con --new, cada invocacion abre un perfil nuevo (fleet, fleet2, fleet3, ...) con su propia flota; inyecta FLEET_SOCKET/FLEET_SESSION a la TUI para que cada panel vea solo sus Claudes. Instala atajos alt+flechas/alt+enter/alt+n que controlan la TUI desde cualquier pane, y fija el ancho del sidebar con hooks."
tags: [claude-fleet, infra, kitty, tmux, claude, fleetview, launcher, wsl, windows-terminal]
params:
- name: --cwd
@@ -14,12 +14,14 @@ params:
- name: --bin
desc: "Ruta al binario de la TUI fleetview que corre en el pane izquierdo. Opcional. Default: /apps/fleetview/fleetview. Si no es ejecutable, el pane izquierdo muestra un mensaje de como compilarla y deja una shell viva."
- name: --session
- desc: "Fija el perfil (socket+sesion tmux comparten nombre) por nombre exacto; reutiliza el existente si ya vive (idempotente sobre ese nombre). Opcional. Sin esta opcion, el perfil se elige automaticamente (primer nombre libre de la secuencia fleet, fleet2, ...)."
+ desc: "Fija el perfil (socket+sesion tmux comparten nombre) por nombre exacto; reutiliza el existente si ya vive (idempotente sobre ese nombre). Opcional. Sin esta opcion, el perfil se elige automaticamente (primer nombre libre de la secuencia fleet, fleet2, ...). Invocado DENTRO de tmux con un nombre DISTINTO al de la flota actual equivale a --new (pides otra flota: ventana nueva, sin reuse de contexto)."
- name: --reuse
desc: "Reattach al perfil principal 'fleet' en vez de abrir uno nuevo. Opcional. Recupera el comportamiento idempotente clasico (volver a invocar NO duplica la flota, reusa la existente)."
+ - name: --new
+ desc: "Fuerza una flota NUEVA en una ventana NUEVA (kitty/wt.exe) incluso estando dentro de una flota tmux. Opcional. Es la via explicita para abrir una FleetView aparte; sin este flag, invocado dentro de una flota viva se reusa el contexto actual (no abre ventana ni crea perfil)."
- name: --cols
desc: "Ancho en columnas del pane izquierdo (la TUI). Opcional. Default: 40."
-output: "Crea/reutiliza una sesion tmux detached con dos panes y lanza una ventana de terminal 'FleetView' adjunta a ella (kitty o Windows Terminal segun auto-deteccion), desacoplada del shell padre. Imprime el estado por stdout. Sin valor de retorno; exit 0 en exito."
+output: "Caso reuse de contexto (dentro de una flota tmux viva, sin --new): trae la TUI al pane/contexto actual con select-window de la window 'console' (o 'fleetview show' si el binario existe) y retorna 0, sin abrir nada. Caso ventana-nueva (fuera de tmux, o con --new): crea/reutiliza una sesion tmux detached con dos panes y lanza una ventana de terminal 'FleetView' adjunta (kitty o Windows Terminal segun auto-deteccion), desacoplada del shell padre. Imprime el estado por stdout. Sin valor de retorno; exit 0 en exito, !=0 con mensaje claro si no hay terminal ni contexto que reusar."
uses_functions:
- supervise_fleetview_tui_bash_infra
uses_types: []
@@ -36,32 +38,44 @@ file_path: "bash/functions/infra/launch_fleetclaude.sh"
## Ejemplo
```bash
-# Via fn run (resuelve por nombre o ID):
-fn run launch_fleetclaude
+# DENTRO de una flota tmux viva (p. ej. en el pane del orquestador): reusa el
+# contexto, trae la TUI al pane actual. NO abre ventana ni crea perfil nuevo.
+fleetclaude
-# Perfil nuevo automatico (fleet la 1a vez; fleet2, fleet3, ... si ya hay uno):
-launch_fleetclaude
+# FUERA de tmux: perfil nuevo automatico (fleet la 1a vez; fleet2, ... si ya hay
+# uno) en una ventana de terminal nueva, reutilizando la terminal actual (attach):
+fleetclaude
+
+# Forzar una flota+ventana NUEVA aunque estes dentro de una flota tmux:
+fleetclaude --new
# Reattach a la flota principal 'fleet' (comportamiento idempotente clasico):
-launch_fleetclaude --reuse
+fleetclaude --reuse
# Perfil con nombre fijo y ancho de pane personalizado:
-launch_fleetclaude --session trabajo --cols 50
+fleetclaude --session trabajo --cols 50
+
+# Via fn run (resuelve por nombre o ID):
+fn run launch_fleetclaude
```
-Tras invocarlo aparece una ventana de terminal titulada `FleetView ()` con dos
-panes lado a lado: a la izquierda la TUI `fleetview`, a la derecha una sesion de
-`claude --dangerously-skip-permissions`. Cada perfil es un socket+sesion tmux
-aislados con su propia flota: puedes tener varias FleetView abiertas a la vez.
-Por defecto, volver a invocarlo abre un perfil NUEVO (no reusa); usa `--reuse`
-o `--session ` para volver a una flota concreta.
+Dentro de una flota viva, `fleetclaude` sin args reusa el contexto (la window
+`console` pasa al frente). Fuera de tmux (o con `--new`) aparece una ventana de
+terminal titulada `FleetView ()` con dos panes lado a lado: a la izquierda
+la TUI `fleetview`, a la derecha una sesion de `claude --dangerously-skip-permissions`.
+Cada perfil es un socket+sesion tmux aislados con su propia flota: puedes tener
+varias FleetView abiertas a la vez con `--new`.
## Cuando usarla
Usala cuando quieras un unico punto de entrada a la flota de Claudes en vez de
N ventanas kitty sueltas: lanzas `fleetclaude` y tienes la TUI de control y un
Claude listo para trabajar en la misma ventana. Tipico al empezar la jornada o
-al retomar el trabajo en el repo `fn_registry`.
+al retomar el trabajo en el repo `fn_registry`. Si **ya estas dentro de una
+flota** (en el pane del orquestador) y solo quieres volver a ver la TUI, lanza
+`fleetclaude` sin args: trae el panel al contexto actual sin abrir otra ventana
+ni arrancar una flota duplicada. Usa `--new` solo cuando quieras DELIBERADAMENTE
+una segunda flota aparte.
## Gotchas
@@ -87,10 +101,27 @@ al retomar el trabajo en el repo `fn_registry`.
funciona en un PC con kitty y en otro WSL sin kitty, cada uno elige su
terminal. Causa raiz del sintoma "se lanza la flota pero no se ve": kitty no
instalado en WSL hacia que la sesion tmux se creara sin ventana que la mostrara.
-- **Dentro de tmux abre ventana nueva**: si invocas `fleetclaude` desde dentro de
- una sesion tmux (`$TMUX` definido), NO hace `attach` anidado (rompe / avisa de
- nesting); cae a la ruta ventana-nueva (auto-deteccion de terminal). Fuera de
- tmux y con TTY, reutiliza la terminal actual con `exec tmux attach`.
+- **Dentro de una flota tmux viva: reuse de contexto (no ventana nueva)**: si
+ invocas `fleetclaude` sin `--new` desde dentro de una flota fleetview viva
+ (`$TMUX` definido y el socket actual tiene una sesion homonima con window
+ `console`), NO abre ventana ni crea un perfil `fleetN+1`: trae la TUI al pane
+ actual (`fleetview show`, o `tmux -L select-window -t :console`
+ si el binario no esta compilado) y retorna 0. El perfil de la flota actual se
+ deriva de `$TMUX` (basename del socket = nombre `-L`), senal fiable aunque
+ `$FLEET_SOCKET` venga vacio (ver `detect_fleet_context`). **`--new`** fuerza el
+ comportamiento clasico (flota+ventana nueva); pasar `--session ` distinto
+ al perfil actual equivale a `--new` implicito. Fuera de tmux y con TTY, reutiliza
+ la terminal actual con `exec tmux attach` (nunca `attach` anidado dentro de
+ tmux). Sin TTY ni contexto que reusar (atajo de escritorio/cron) cae a la ruta
+ ventana-nueva. Antes de este fix (v1.6.0 y anteriores) cualquier `fleetclaude`
+ dentro de tmux abria una kitty nueva y un socket `fleetN+1` — el sintoma que
+ acumulaba 6+ sockets `fleet*`.
+- **`local x` unbound bajo `set -u`**: el archivo corre con `set -euo pipefail`.
+ `local left_pane right_pane` dejaba esas vars *unbound* (no vacias), asi que la
+ rama "reutilizar sesion existente" (`--reuse`/`--session `) reventaba con
+ `left_pane: unbound variable` al evaluar `[[ -z "$left_pane" ]]`. Se inicializan
+ explicitamente a `""` (`local left_pane="" right_pane=""`). Si tocas estas vars,
+ no vuelvas a declararlas sin valor.
- **kitty detached (setsid)**: la ventana kitty se lanza con `setsid ... &` para
sobrevivir al cierre de la terminal que la invoco. La ventana de Windows
Terminal (wt.exe) ya es un proceso Windows independiente del arbol Linux, asi
@@ -128,15 +159,29 @@ al retomar el trabajo en el repo `fn_registry`.
- **Ancho del sidebar via hooks**: `client-resized` y `window-layout-changed`
re-fijan el pane 0 (TUI) a `--cols` columnas, porque el `attach` de kitty y el
conmutar de Claude redistribuyen el espacio.
-- **tmux siempre; terminal (kitty/wt.exe) solo sin TTY**: `tmux` es obligatorio
- (aborta != 0 si falta). Una terminal nueva (kitty o Windows Terminal) solo se
- necesita en la ruta sin-TTY (dentro de tmux, atajo de escritorio, cron, script),
- donde abre una ventana nueva. Invocado desde una terminal interactiva fuera de
- tmux (el caso normal del alias `fleetclaude`), reutiliza la terminal actual con
- `exec tmux attach` y no necesita ni kitty ni wt.exe.
+- **tmux siempre; terminal (kitty/wt.exe) solo en la ruta ventana-nueva**: `tmux`
+ es obligatorio (aborta != 0 si falta). Una terminal nueva (kitty o Windows
+ Terminal) solo se necesita en la ruta ventana-nueva: `--new`, o sin TTY ni flota
+ viva que reusar (atajo de escritorio, cron, script). Dentro de una flota viva sin
+ `--new` se reusa el contexto (ni kitty ni wt.exe). Invocado desde una terminal
+ interactiva fuera de tmux (el caso normal del alias `fleetclaude`), reutiliza la
+ terminal actual con `exec tmux attach` y tampoco necesita kitty ni wt.exe.
## Capability growth log
+- v1.7.0 (2026-06-30) — **reuse de contexto dentro de la flota + flag `--new`**.
+ Invocado sin `--new` desde dentro de una flota tmux viva (su window `console`),
+ `fleetclaude` ya NO abre una kitty nueva ni crea un perfil `fleetN+1`: trae la
+ TUI al pane/contexto actual (`fleetview show`, o `tmux -L select-window
+ -t :console` como fallback sin binario) y retorna 0. El perfil actual se
+ deriva de `$TMUX` (basename del socket); pasar `--session ` distinto al
+ actual equivale a `--new` implicito. Nuevo flag `--new` para forzar la ruta
+ clasica (flota+ventana nueva) aun dentro de tmux. Fuera de tmux el comportamiento
+ es intacto (`exec tmux attach` reutiliza la terminal). Arregla el sintoma de que
+ lanzar `fleetclaude` dentro de una flota abria ventana kitty + socket nuevo
+ (`fleet7`, `fleet8`, ...). Fix incidental: `local left_pane="" right_pane=""`
+ (antes `local left_pane right_pane` reventaba con `unbound variable` bajo
+ `set -u` al reutilizar una sesion existente).
- v1.6.0 (2026-06-29) — **auto-deteccion de terminal (kitty ↔ Windows Terminal)**.
La ruta ventana-nueva ya no asume kitty: elige terminal segun el host. kitty si
esta instalado y hay display (`$DISPLAY`/`$WAYLAND_DISPLAY`); si no, en WSL abre
diff --git a/bash/functions/infra/launch_fleetclaude.sh b/bash/functions/infra/launch_fleetclaude.sh
index 853171e1..8850a6a0 100644
--- a/bash/functions/infra/launch_fleetclaude.sh
+++ b/bash/functions/infra/launch_fleetclaude.sh
@@ -23,6 +23,7 @@ launch_fleetclaude() {
local cols=52
local explicit_session=0 # 1 si el usuario pasó --session a mano
local reuse=0 # 1 si el usuario pidió --reuse (reattach al perfil principal)
+ local want_new=0 # 1 si el usuario pidió --new (forzar flota+ventana nueva)
local T="" # socket tmux aislado; se fija al resolver el perfil
# -----------------------------------------------------------------------
@@ -46,6 +47,9 @@ launch_fleetclaude() {
--reuse)
reuse=1
;;
+ --new)
+ want_new=1
+ ;;
--cols)
shift
cols="${1:-40}"
@@ -62,6 +66,11 @@ Claudes). Sin --session ni --reuse, cada invocacion abre un perfil NUEVO: usa
el primer nombre libre de la secuencia fleet, fleet2, fleet3, ... Asi puedes
tener varias FleetView abiertas a la vez, cada una con su flota independiente.
+REUSO DE CONTEXTO: si ya estas DENTRO de una flota tmux viva (p. ej. en el pane
+del orquestador), 'fleetclaude' sin args NO abre una ventana ni crea un perfil
+nuevo: trae la TUI al contexto/pane actual (equivale a 'fleetview show'). Para
+abrir explicitamente una flota aparte en una ventana nueva, usa --new.
+
Opciones:
--cwd Directorio de trabajo de los panes.
Default: raiz del repo fn_registry (derivada dinamicamente).
@@ -69,13 +78,21 @@ Opciones:
Default: /apps/fleetview/fleetview
--session Fija el perfil (socket+sesion) por nombre exacto; reutiliza
el existente si ya esta vivo. Sin esta opcion, perfil auto.
+ Si se invoca DENTRO de tmux con un nombre DISTINTO al de la
+ flota actual, equivale a --new (pides otra flota).
--reuse Reattach al perfil principal 'fleet' en vez de abrir uno
nuevo (vuelve al comportamiento idempotente clasico).
+ --new Fuerza una flota NUEVA en una ventana NUEVA (kitty/wt.exe),
+ incluso dentro de tmux. Es la via explicita para tener una
+ FleetView aparte; sin este flag, dentro de tmux se reusa el
+ contexto actual.
--cols Ancho (columnas) del pane izquierdo. Default: 40.
-h, --help Muestra esta ayuda.
Ejemplos:
- launch_fleetclaude # perfil nuevo (fleet, luego fleet2, ...)
+ launch_fleetclaude # dentro de la flota: reusa el contexto;
+ # fuera de tmux: perfil nuevo (fleet, ...)
+ launch_fleetclaude --new # flota+ventana nueva aunque estes en tmux
launch_fleetclaude --reuse # reattach a la flota principal 'fleet'
launch_fleetclaude --session trabajo # perfil con nombre fijo 'trabajo'
launch_fleetclaude --cwd ~/fn_registry --cols 50
@@ -127,6 +144,45 @@ USAGE
return 1
fi
+ # -----------------------------------------------------------------------
+ # REUSO DE CONTEXTO (sin --new): si ya estamos DENTRO de una flota tmux
+ # viva, 'fleetclaude' sin args NO abre una ventana/terminal nueva ni crea
+ # un perfil fleetN+1 — trae la TUI al contexto/pane actual, igual que
+ # 'fleetview show'. El flag --new fuerza el comportamiento clasico (flota
+ # nueva en ventana nueva); --reuse mantiene su semantica historica.
+ #
+ # El perfil de la flota actual se deriva de $TMUX (el basename del socket
+ # es el nombre -L; senal fiable aunque $FLEET_SOCKET venga vacio, ver
+ # detect_fleet_context). Si se paso --session con un nombre DISTINTO al
+ # actual, es pedir OTRA flota -> se trata como --new implicito (no reusa).
+ # "Flota viva" = el socket tiene una sesion homonima con una window
+ # 'console' (la firma de una FleetView), no un tmux cualquiera.
+ # -----------------------------------------------------------------------
+ if [[ "$want_new" -eq 0 && "$reuse" -eq 0 && -n "${TMUX:-}" ]]; then
+ local current_socket target_socket
+ current_socket="$(basename "${TMUX%%,*}")"
+ target_socket="$current_socket"
+ [[ "$explicit_session" -eq 1 ]] && target_socket="$session"
+
+ if [[ "$target_socket" == "$current_socket" ]] \
+ && tmux -L "$current_socket" has-session -t "$current_socket" 2>/dev/null \
+ && tmux -L "$current_socket" list-windows -t "$current_socket" \
+ -F '#{window_name}' 2>/dev/null | grep -qx console; then
+ # Traer la TUI al contexto actual sin abrir nada nuevo. Preferimos
+ # el binario (centraliza la politica en la app: 'fleetview show');
+ # si no esta compilado, caemos a 'select-window' directo, que es lo
+ # que 'show' hace por dentro dentro de tmux (cero dependencia).
+ if [[ -x "$bin" ]] \
+ && FLEET_SOCKET="$current_socket" FLEET_SESSION="$current_socket" \
+ "$bin" show 2>/dev/null; then
+ return 0
+ fi
+ tmux -L "$current_socket" select-window -t "$current_socket":console
+ echo "launch_fleetclaude: flota '$current_socket' viva; TUI traida al contexto actual (sin ventana nueva)."
+ return 0
+ fi
+ fi
+
# -----------------------------------------------------------------------
# Resolver el PERFIL (socket+sesion tmux comparten nombre).
#
@@ -200,7 +256,10 @@ USAGE
# indice 1 y cualquier referencia a console.0 falla con
# "can't find pane: 0". Los pane ID son estables e inmunes al base-index.
# -----------------------------------------------------------------------
- local left_pane right_pane
+ # Inicializadas a "" (no solo declaradas): bajo `set -u` una `local x` sin
+ # valor queda *unbound*, y al reutilizar una sesion existente el `[[ -z
+ # "$left_pane" ]]` de mas abajo reventaba con "unbound variable".
+ local left_pane="" right_pane=""
if $T has-session -t "$session" 2>/dev/null; then
echo "launch_fleetclaude: la sesion tmux '$session' ya existe; reutilizandola."
else