--- name: launch_claude_agent_kitty kind: function lang: bash domain: infra version: "1.0.0" purity: impure signature: "launch_claude_agent_kitty(title: string, directory: string, prompt_file: string) -> string" description: "Lanza un Claude Code secundario interactivo y persistente en su propia terminal kitty, con un prompt autonomo inyectado desde un archivo y --dangerously-skip-permissions. Mecanica del modo orquestador: un Claude principal descompone una tarea y lanza N secundarios, cada uno en su kitty, que el humano ve y puede retomar. La ventana sobrevive al cierre de la terminal padre (setsid nohup ... disown) y deja una shell interactiva viva cuando el claude termina (exec zsh)." tags: [orchestration, agents, claude, kitty, agent, terminal, infra] params: - name: title desc: "Titulo de la ventana kitty. Ej: 'fn_registry · subtarea X'. Tambien se sanitiza (minusculas, no-alfanumerico -> '_') para derivar el slug del archivo de log." - name: directory desc: "Directorio de trabajo AISLADO donde arranca el claude secundario (worktree git, sub-repo, o dir cualquiera). Debe existir; si no -> error exit 2. Usar un dir aislado: dos claudes en el mismo working tree comparten HEAD y dispersan commits." - name: prompt_file desc: "Ruta a un archivo .md con el prompt autonomo a inyectar (ej. /tmp/orq_.md). Debe existir y ser legible; si no -> error exit 2." output: "Imprime en stdout el title, directory, prompt_file y la ruta del log (/tmp/orq__kitty.log) donde se ve el arranque. Exit 0 = lanzamiento disparado; exit 2 = argumentos invalidos; exit 1 = kitty no instalado." 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_claude_agent_kitty.sh" --- ## Ejemplo ```bash source bash/functions/infra/launch_claude_agent_kitty.sh # El orquestador prepara un worktree aislado y un archivo de prompt... git worktree add /tmp/orq_docs_wt -b orq/docs cat > /tmp/orq_docs.md <<'PROMPT' Eres un agente secundario. Tu tarea: revisar y mejorar la documentacion del dominio infra del registry. Trabaja SOLO en este worktree. Reporta al terminar. PROMPT # ...y lanza un claude secundario en su propia kitty: launch_claude_agent_kitty "fn_registry · docs" /tmp/orq_docs_wt /tmp/orq_docs.md # -> abre una ventana kitty titulada "fn_registry · docs", arranca claude con # el prompt inyectado, y deja /tmp/orq_fn_registry_docs_kitty.log con el arranque. ``` O directo via `fn run`: ```bash ./fn run launch_claude_agent_kitty "fn_registry · docs" /tmp/orq_docs_wt /tmp/orq_docs.md ``` ## Cuando usarla Cuando el orquestador quiere lanzar un Claude secundario **interactivo** en su propia terminal kitty para una sub-tarea que el humano quiere **ver y poder retomar**. A diferencia del `Agent` tool (sub-agente no interactivo, headless, cuyo output vuelve al padre y no deja terminal abierta), aqui cada secundario corre en una ventana visible que persiste: el humano observa el progreso en vivo y, cuando el claude termina, la shell sigue ahi para continuar manualmente o relanzar. ## Gotchas - **kitty debe estar instalado.** Si `command -v kitty` falla -> exit 1 con mensaje claro. No hay fallback a otra terminal. - **El `directory` debe ser AISLADO** (worktree git o sub-repo propio). Dos claudes apuntando al mismo working tree **comparten HEAD** y dispersan/cruzan los commits (memoria `multi-agent-git-race-same-repo`). El orquestador debe crear un worktree/clon por agente antes de llamar. - **`--dangerously-skip-permissions` corre sin pedir confirmacion** a ninguna accion (memoria `lanzar-agentes-skip-permissions`). Es a proposito para agentes autonomos desatendidos, pero es un riesgo asumido: el secundario puede tocar el sistema sin gates. No lanzar sobre directorios sensibles. - **El log de `/tmp/orq__kitty.log` es donde se ve el arranque** (errores de kitty/claude al iniciar). El `` deriva del `title` sanitizado; titulos distintos que colapsen al mismo slug sobrescriben el mismo log. - **El PID reportado no es el de kitty.** Con `setsid` el `$!` es el del proceso setsid, no el de la ventana; por eso la funcion reporta el log en vez de un PID. Para encontrar la ventana despues: `pgrep -af kitty | grep `. - **El prompt se inyecta con `"$(cat <prompt_file>)"` evaluado DENTRO de la kitty.** Si editas el `prompt_file` despues de lanzar pero antes de que la kitty arranque, el claude vera la version editada (se lee en el momento del arranque, no del lanzamiento).