feat(infra): grupo claude-fleet — FleetView TUI + orquestacion de Claudes
Sistema FleetView para centralizar la flota de procesos Claude Code vivos en una sola ventana kitty + tmux (socket aislado -L fleet) con un panel TUI: - list_claude_fleet (+ tipo claude_fleet): escanea ~/.claude/sessions + goals + runtime, valida procesos vivos (anti-PID-reciclado), join por sessionId. - list_resumable_claudes (+ tipo resumable_claude): sesiones cerradas reanudables. - wrappers tmux: tmux_new_claude_window (con --resume), tmux_swap_window_into_console (preserva ancho del sidebar), tmux_map_claude_panes. - launch_kittyclaude: comando entrypoint; instala atajos alt+flechas/enter/n/0/k/r, mouse on, remain-on-exit off; fija el ancho del sidebar con hooks. - docs/capabilities/claude-fleet.md + entrada en el INDEX. Incluye ademas funciones datascience en progreso (excel/duckdb/postgres) y ajustes varios de docs e infra de otra sesion, agrupados aqui para no perderlos. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
---
|
||||
name: launch_kittyclaude
|
||||
kind: function
|
||||
lang: bash
|
||||
domain: infra
|
||||
version: "1.1.0"
|
||||
purity: impure
|
||||
signature: "launch_kittyclaude [--cwd <dir>] [--bin <path>] [--session <name>] [--cols <n>]"
|
||||
description: "Entrypoint de FleetView: abre una ventana kitty con una sesion tmux (socket aislado -L fleet) de dos panes (TUI fleetview a la izquierda, claude --dangerously-skip-permissions a la derecha) para centralizar la flota de 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]
|
||||
params:
|
||||
- name: --cwd
|
||||
desc: "Directorio de trabajo de ambos panes tmux. Opcional. Default: raiz del repo fn_registry, derivada dinamicamente via git rev-parse desde la ubicacion del script (sin hardcodear paths de usuario)."
|
||||
- name: --bin
|
||||
desc: "Ruta al binario de la TUI fleetview que corre en el pane izquierdo. Opcional. Default: <repo>/apps/fleetview/fleetview. Si no es ejecutable, el pane izquierdo muestra un mensaje de como compilarla y deja una shell viva."
|
||||
- name: --session
|
||||
desc: "Nombre de la sesion tmux a crear o reutilizar. Opcional. Default: fleet. La funcion es idempotente sobre este nombre."
|
||||
- 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 kitty 'FleetView' adjunta a ella, desacoplada del shell padre (setsid). Imprime el estado por stdout. Sin valor de retorno; exit 0 en exito."
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: []
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "bash/functions/infra/launch_kittyclaude.sh"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```bash
|
||||
# Via fn run (resuelve por nombre o ID):
|
||||
fn run launch_kittyclaude
|
||||
|
||||
# Directo, con cwd explicito:
|
||||
launch_kittyclaude --cwd ~/fn_registry
|
||||
|
||||
# Sesion y ancho de pane personalizados:
|
||||
launch_kittyclaude --session fleet --cols 50
|
||||
```
|
||||
|
||||
Tras invocarlo aparece una ventana kitty titulada `FleetView` con dos panes
|
||||
lado a lado: a la izquierda la TUI `fleetview`, a la derecha una sesion de
|
||||
`claude --dangerously-skip-permissions`. Volver a invocarlo NO duplica la
|
||||
sesion: reusa la existente y solo abre otra kitty adjunta.
|
||||
|
||||
## Cuando usarla
|
||||
|
||||
Usala cuando quieras un unico punto de entrada a la flota de Claudes en vez de
|
||||
N ventanas kitty sueltas: lanzas `kittyclaude` 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`.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Idempotencia tmux**: si la sesion `<session>` (default `fleet`) ya existe,
|
||||
NO se recrea el layout; solo se abre una kitty nueva adjunta a la misma
|
||||
sesion. Para empezar de cero: `tmux kill-session -t fleet` antes de invocar.
|
||||
- **kitty detached (setsid)**: la ventana se lanza con `setsid ... &` para
|
||||
sobrevivir al cierre de la terminal que la invoco. No bloquea al shell padre.
|
||||
- **`exec` en los panes**: tanto la TUI como `claude` se lanzan con `exec`, asi
|
||||
que al terminar el proceso el pane se cierra en vez de dejar una shell zombie
|
||||
colgando. Excepcion: el fallback cuando `fleetview` no esta compilado deja una
|
||||
shell interactiva a proposito (para que veas el mensaje y puedas compilar).
|
||||
- **Requiere fleetview compilado**: el default `--bin` apunta a
|
||||
`<repo>/apps/fleetview/fleetview`. Si ese binario no existe, el pane izquierdo
|
||||
muestra `cd apps/fleetview && go build -o fleetview .` en lugar de fallar en
|
||||
silencio. Compila la TUI antes para el flujo completo.
|
||||
- **Socket tmux aislado (`-L fleet`)**: toda la sesion vive en un server tmux
|
||||
propio, separado del tmux por defecto del usuario. Asi los atajos `bind -n`
|
||||
NO afectan otras sesiones (ej. una sesion `mobile-1` del movil) y matar el
|
||||
server fleet no toca nada mas: `tmux -L fleet kill-server`.
|
||||
- **Atajos en el socket, NO en kitty.conf**: instala `bind -n` para
|
||||
`alt+flechas` (mover el cursor de la TUI), `alt+enter` (conmutar al Claude
|
||||
seleccionado) y `alt+n` (abrir Claude nuevo). Son bindings de tmux que
|
||||
redirigen la tecla al pane de la TUI (`send-keys -t console.0`), asi funcionan
|
||||
ESTES DONDE ESTES (incluido escribiendo en el pane de Claude). No modifican la
|
||||
configuracion de kitty ni los atajos globales del escritorio.
|
||||
- **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.
|
||||
- **Necesita kitty y tmux en el PATH**: aborta con codigo != 0 si falta alguno.
|
||||
|
||||
## Capability growth log
|
||||
|
||||
- v1.2.0 (2026-06-16) — ancho del sidebar por defecto 47 columnas; `ctrl+0` como
|
||||
atajo alterno para abrir Claude nuevo; `mouse on` (clic/rueda enrutados a la
|
||||
TUI) y `extended-keys on` (para que `ctrl+0` llegue distinguible por el
|
||||
protocolo de teclado de kitty).
|
||||
- v1.1.0 (2026-06-16) — socket tmux aislado `-L fleet`; instala atajos
|
||||
`alt+flechas` / `alt+enter` / `alt+n` que controlan la TUI desde cualquier
|
||||
pane; hooks que mantienen fijo el ancho del sidebar tras attach/conmutar.
|
||||
@@ -0,0 +1,196 @@
|
||||
#!/usr/bin/env bash
|
||||
# launch_kittyclaude — Entrypoint MVP de FleetView.
|
||||
#
|
||||
# Abre UNA ventana kitty corriendo una sesion tmux de dos panes:
|
||||
# - pane izquierdo: la TUI 'fleetview' (la flota de Claudes centralizada).
|
||||
# - pane derecho: 'claude --dangerously-skip-permissions'.
|
||||
#
|
||||
# Objetivo: dejar de tener N ventanas kitty dispersas y centralizar el control
|
||||
# de los Claudes en una sola ventana.
|
||||
#
|
||||
# Funcion IMPURA: lanza procesos (tmux + kitty) con efectos secundarios.
|
||||
# - Crea/reusa una sesion tmux detached llamada <session> (idempotente).
|
||||
# - Lanza una ventana kitty desacoplada del shell padre (setsid) para que
|
||||
# sobreviva al cierre de la terminal que la invoco.
|
||||
# - No toca atajos de teclado ni kitty.conf.
|
||||
set -euo pipefail
|
||||
IFS=$' \t\n'
|
||||
|
||||
launch_kittyclaude() {
|
||||
local cwd=""
|
||||
local bin=""
|
||||
local session="fleet"
|
||||
local cols=47
|
||||
local T="tmux -L fleet" # socket tmux aislado: no toca el tmux normal del usuario
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Parseo de argumentos
|
||||
# -----------------------------------------------------------------------
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--cwd)
|
||||
shift
|
||||
cwd="${1:-}"
|
||||
;;
|
||||
--bin)
|
||||
shift
|
||||
bin="${1:-}"
|
||||
;;
|
||||
--session)
|
||||
shift
|
||||
session="${1:-}"
|
||||
;;
|
||||
--cols)
|
||||
shift
|
||||
cols="${1:-40}"
|
||||
;;
|
||||
-h|--help)
|
||||
cat <<'USAGE'
|
||||
Uso: launch_kittyclaude [opciones]
|
||||
|
||||
Abre una ventana kitty con una sesion tmux de dos panes: la TUI fleetview a la
|
||||
izquierda y 'claude --dangerously-skip-permissions' a la derecha.
|
||||
|
||||
Opciones:
|
||||
--cwd <dir> Directorio de trabajo de los panes.
|
||||
Default: raiz del repo fn_registry (derivada dinamicamente).
|
||||
--bin <path> Ruta al binario de la TUI fleetview.
|
||||
Default: <repo>/apps/fleetview/fleetview
|
||||
--session <name> Nombre de la sesion tmux. Default: fleet.
|
||||
--cols <n> Ancho (columnas) del pane izquierdo. Default: 40.
|
||||
-h, --help Muestra esta ayuda.
|
||||
|
||||
Ejemplos:
|
||||
launch_kittyclaude
|
||||
launch_kittyclaude --cwd ~/fn_registry
|
||||
launch_kittyclaude --session fleet --cols 50
|
||||
USAGE
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
echo "launch_kittyclaude: opcion desconocida: '$1' (usa -h)" >&2
|
||||
return 2
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Derivar la raiz del repo fn_registry dinamicamente (NO hardcodear paths
|
||||
# de usuario). Estrategia: subir desde la ubicacion del script con
|
||||
# 'git rev-parse --show-toplevel'; fallbacks razonables si no aplica.
|
||||
# -----------------------------------------------------------------------
|
||||
local script_dir repo_root=""
|
||||
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# El script vive en <repo>/bash/functions/infra/, asi que la raiz son 3
|
||||
# niveles arriba; pero preferimos git para robustez.
|
||||
repo_root="$(git -C "$script_dir" rev-parse --show-toplevel 2>/dev/null || true)"
|
||||
if [[ -z "$repo_root" ]]; then
|
||||
# Fallback 1: navegacion relativa desde la ubicacion del script.
|
||||
repo_root="$(cd "$script_dir/../../.." 2>/dev/null && pwd || true)"
|
||||
fi
|
||||
if [[ -z "$repo_root" ]]; then
|
||||
# Fallback 2: variable de entorno del registry o el cwd actual.
|
||||
repo_root="${FN_REGISTRY_ROOT:-$PWD}"
|
||||
fi
|
||||
|
||||
# Defaults derivados de la raiz del repo.
|
||||
[[ -z "$cwd" ]] && cwd="$repo_root"
|
||||
[[ -z "$bin" ]] && bin="$repo_root/apps/fleetview/fleetview"
|
||||
|
||||
# Validar cwd: si no existe, caer al repo_root.
|
||||
if [[ ! -d "$cwd" ]]; then
|
||||
echo "launch_kittyclaude: --cwd '$cwd' no existe; usando '$repo_root'." >&2
|
||||
cwd="$repo_root"
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Comprobar herramientas necesarias.
|
||||
# -----------------------------------------------------------------------
|
||||
if ! command -v tmux >/dev/null 2>&1; then
|
||||
echo "launch_kittyclaude: tmux no esta instalado." >&2
|
||||
return 1
|
||||
fi
|
||||
if ! command -v kitty >/dev/null 2>&1; then
|
||||
echo "launch_kittyclaude: kitty no esta instalado." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Comando para el pane izquierdo:
|
||||
# - Si el binario fleetview existe -> ejecutarlo (exec, sin shell colgado).
|
||||
# - Si NO existe -> mensaje claro + shell interactiva (no falla en silencio).
|
||||
# -----------------------------------------------------------------------
|
||||
local left_cmd
|
||||
if [[ -x "$bin" ]]; then
|
||||
left_cmd="exec $(printf '%q' "$bin")"
|
||||
else
|
||||
# Fallback claro: instruye como compilar la TUI y deja una shell viva.
|
||||
left_cmd="echo 'fleetview no compilado: cd apps/fleetview && go build -o fleetview .'; exec \"\$SHELL\""
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Montar la sesion tmux SOLO si no existe (idempotencia). Socket aislado $T.
|
||||
# -----------------------------------------------------------------------
|
||||
if $T has-session -t "$session" 2>/dev/null; then
|
||||
echo "launch_kittyclaude: la sesion tmux '$session' ya existe; reutilizandola."
|
||||
else
|
||||
echo "launch_kittyclaude: creando sesion tmux '$session' en '$cwd'."
|
||||
|
||||
# Sesion detached con ventana 'console', pane 0 en el cwd objetivo.
|
||||
$T new-session -d -s "$session" -n console -c "$cwd"
|
||||
|
||||
# pane 0 (izquierda) = la TUI fleetview (o el fallback claro).
|
||||
$T send-keys -t "$session":console.0 "$left_cmd" C-m
|
||||
|
||||
# pane 1 (derecha) = claude, dividiendo horizontalmente (split lado a lado).
|
||||
$T split-window -h -t "$session":console -c "$cwd"
|
||||
$T send-keys -t "$session":console.1 "exec claude --dangerously-skip-permissions" C-m
|
||||
|
||||
# Fijar el ancho del pane izquierdo en columnas.
|
||||
$T resize-pane -t "$session":console.0 -x "$cols"
|
||||
|
||||
# Foco inicial en el pane de claude (derecha).
|
||||
$T select-pane -t "$session":console.1
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Atajos globales (alt+*) en el socket aislado: redirigen la tecla al pane
|
||||
# de la TUI (console.0) ESTES DONDE ESTES, para controlar la flota sin salir
|
||||
# del pane de Claude. La TUI (fleetview) es quien interpreta Up/Down/Enter/n.
|
||||
# `bind -n` = tabla root (sin prefijo). Idempotente: re-set en cada lanzamiento.
|
||||
# -----------------------------------------------------------------------
|
||||
$T bind -n M-Up send-keys -t "$session":console.0 Up
|
||||
$T bind -n M-Down send-keys -t "$session":console.0 Down
|
||||
$T bind -n M-Enter send-keys -t "$session":console.0 Enter
|
||||
$T bind -n M-n send-keys -t "$session":console.0 n
|
||||
$T bind -n M-0 send-keys -t "$session":console.0 n
|
||||
$T bind -n M-k send-keys -t "$session":console.0 k
|
||||
$T bind -n M-r send-keys -t "$session":console.0 r
|
||||
# Raton: enruta clicks/rueda al pane bajo el cursor; la TUI los interpreta.
|
||||
$T set -g mouse on
|
||||
# Al salir un Claude (exit / Ctrl-D / kill), cerrar su window en vez de
|
||||
# dejarla muerta ("dead" pane) en la sesion.
|
||||
$T set -g remain-on-exit off
|
||||
|
||||
# Mantener el ancho del sidebar (pane 0) cuando kitty redimensiona la ventana
|
||||
# tras el attach, o cuando se conmuta de Claude (window-linked / layout change).
|
||||
$T set-hook -g client-resized "resize-pane -t $session:console.0 -x $cols"
|
||||
$T set-hook -g window-layout-changed "resize-pane -t $session:console.0 -x $cols"
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Lanzar kitty adjuntando la sesion, DESACOPLADA del shell padre con
|
||||
# setsid, para que no muera al cerrar la terminal invocadora.
|
||||
# (Mismo patron que reboot_all_claudes para relanzar terminales.)
|
||||
# -----------------------------------------------------------------------
|
||||
setsid kitty --title "FleetView" -e tmux -L fleet attach -t "$session" </dev/null >/dev/null 2>&1 &
|
||||
disown 2>/dev/null || true
|
||||
|
||||
echo "launch_kittyclaude: ventana kitty 'FleetView' adjunta a la sesion tmux '$session'."
|
||||
return 0
|
||||
}
|
||||
|
||||
# Permitir ejecutar el archivo directamente (no solo como funcion sourced).
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
launch_kittyclaude "$@"
|
||||
fi
|
||||
Reference in New Issue
Block a user