App que obtiene la respuesta de claude como dato parseando su TUI interactiva,
en lugar de usar claude -p. Compone tres funciones del registry:
- pty_capture_idle_go_infra: captura el render de la TUI via PTY headless.
- vt_render_go_tui: reconstruye el layout 2D como texto plano.
- parse_claude_tui_go_tui: extrae los turnos + la respuesta final.
Salida por defecto con el mismo shape que claude -p --output-format json.
Formatos: json, text, turns, screen. Validada end-to-end: el campo result
coincide exacto con claude -p nativo (PONG == PONG). e2e_checks deterministas
con un fake TUI (tests/fake_claude.sh) que no gasta llamadas reales.
Fase 1 (one-shot). El streaming incremental queda como fase 2.
Alternativa a 'claude -p' que obtiene la respuesta de claude como dato PARSEANDO su TUI interactiva: captura el render via PTY, reconstruye el layout y extrae los turnos + la respuesta final. Emite JSON con el mismo shape que 'claude -p --output-format json'. Para interaccion programatica robusta prefiere el camino stream-json (claude_stream_go_core); esta app es la variante que va a traves de la TUI.
cli
claude
terminal
pty
tui
parser
pty_capture_idle_go_infra
vt_render_go_tui
parse_claude_tui_go_tui
claude_tui_parse_go_tui
claude_turn_go_tui
main.go
apps/claude_pipe
phosphor
accent
faders
#0ea5e9
id
cmd
timeout_s
build
CGO_ENABLED=1 go build -tags fts5 -o claude_pipe .
120
id
cmd
expect_stdout_contains
timeout_s
smoke_fake_text
./claude_pipe --bin ./tests/fake_claude.sh --warmup 300ms --step-delay 100ms --idle 700ms --max 5s --format text test
Devuelve la respuesta de claude como dato parseando su TUI interactiva, en lugar de usar
claude -p. Internamente lanza el claude interactivo dentro de un pseudo-terminal, captura el
render de la pantalla, reconstruye el layout 2D, y extrae los turnos de la conversacion mas la
respuesta final del asistente. La salida por defecto imita claude -p --output-format json.
Es la respuesta a "quiero parsear la TUI y que devuelva lo mismo que claude -p". Para la mayoria
de los casos programaticos el camino limpio es stream-json (ver claude_stream_go_core), que no
toca la TUI; claude_pipe existe para cuando se quiere expresamente ir a traves de la TUI.
Arquitectura (composicion de funciones del registry)
claude (TUI) ─pty_capture_idle_go_infra─▶ bytes crudos del terminal
─vt_render_go_tui──────────▶ pantalla como texto plano (layout 2D)
─parse_claude_tui_go_tui───▶ ClaudeTUIParse {Turns, Answer}
─(esta app)────────────────▶ JSON estilo claude -p / texto / turns
La app no aporta logica reutilizable: solo orquesta las tres funciones y elige el formato de salida.
claude -p --output-format json (campos esenciales)
text
solo el texto de la respuesta
claude -p plano
turns
el ClaudeTUIParse completo: cada turno visible (user/assistant/tool_use/tool_result) + answer
— (mas rico que claude -p)
screen
el render de la pantalla sin parsear
debug
Ejemplo
cd apps/claude_pipe
CGO_ENABLED=1 go build -tags fts5 -o claude_pipe .
# Respuesta como JSON (mismo shape que claude -p --output-format json)
./claude_pipe --cwd /home/enmanuel/fn_registry "responde unicamente con la palabra PONG"# {"type":"result","subtype":"success","is_error":false,"result":"PONG"}# Solo el texto
./claude_pipe --format text --cwd /home/enmanuel/fn_registry "resume el README en 3 lineas"# Todos los turnos visibles (incluye tool_use/tool_result que la TUI muestra)
./claude_pipe --format turns --cwd /home/enmanuel/fn_registry "lee main.go y resumelo"# Prompt por stdinecho"explica este error"| ./claude_pipe --cwd /home/enmanuel/fn_registry
Flags
Flag
Default
Que hace
--prompt
—
Prompt a enviar. Si vacio, se toma del arg posicional o de stdin.
--format
json
json | text | turns | screen.
--cwd
—
Directorio donde se lanza claude (usa un repo con los MCP aprobados, para saltar el dialogo de arranque).
--bin
claude
Binario claude a lanzar (o un fake para tests).
--warmup
4s
Espera antes de enviar el prompt, para que la TUI cargue.
--step-delay
600ms
Espera entre teclear el prompt y pulsar Enter.
--idle
4s
Corta la captura tras este silencio (respuesta terminada de renderizar).
--max
120s
Timeout duro de toda la captura.
Cuando usarla
Cuando quieras la respuesta de una sesion claude como dato yendo a traves de la TUI
(no via claude -p).
Para auditar/scriptear lo que la TUI muestra y obtener ademas los tool_use/tool_result
visibles (--format turns).
Si no necesitas pasar por la TUI, usa claude_stream_go_core (stream-json) — es mas robusto.
Gotchas
No reemplaza 1:1 a claude -p: el campo result (la respuesta) coincide, pero NO se
extraen los metadatos (cost, tokens, session_id, duration_ms) porque la TUI no los
expone de forma fiable.
Truncacion por scroll: la captura solo ve el grid visible (40x120). Una respuesta mas larga
que la pantalla se trunca por arriba (el render no guarda scrollback). Respuestas cortas/medias
van bien.
Heuristico y version-dependiente: el parser asume el layout actual de la TUI de claude. Si
claude cambia su UI, hay que ajustar parse_claude_tui_go_tui.
Dialogo de arranque: en un cwd cuyos MCP no estan aprobados, claude bloquea con "new MCP
servers found". Usa --cwd <repo-raiz-aprobado>.
Latencia: anade warmup + idle (por defecto ~8s de overhead) sobre el tiempo de respuesta
de claude. claude -p no tiene ese overhead. Es el precio de ir por la TUI.
Linux/Unix only: hereda el PTY POSIX de pty_capture_idle_go_infra.
Streaming: esta version es one-shot (espera la respuesta completa y luego parsea). El
streaming incremental de la TUI esta planificado como fase 2 (requiere capturar snapshots
durante el render).