---
name: claude_stream
kind: function
lang: go
domain: core
version: "1.0.0"
purity: impure
signature: "func StreamClaude(ctx context.Context, opts ClaudeStreamOpts) (<-chan ClaudeEvent, error)"
description: "Lanza `claude -p --output-format stream-json --verbose` como subprocess y retorna un canal de eventos decodificados (text_delta, tool_use, tool_result, result, error). Expande automaticamente los bloques de contenido de los mensajes assistant/user en eventos sinteticos de grano fino."
tags: [claude, streaming, subprocess, agent, ndjson, tool-use]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports:
  - bufio
  - context
  - encoding/json
  - fmt
  - io
  - os
  - os/exec
  - strings
tested: true
tests:
  - "system event"
  - "text delta"
  - "multiple text blocks"
  - "tool use"
  - "tool result string content"
  - "tool result array content"
  - "result event"
  - "non-zero exit"
  - "non-json line"
  - "ctx cancel"
test_file_path: "functions/core/claude_stream_test.go"
file_path: "functions/core/claude_stream.go"
params:
  - name: ctx
    desc: "Contexto de cancelacion. Al cancelar, el subprocess recibe SIGTERM/SIGKILL y el canal se cierra."
  - name: opts
    desc: "Opciones de lanzamiento: Bin (path al binario claude, default 'claude'), Args (args extra sin -p ni --output-format ni --verbose), Stdin (prompt como io.Reader), Workdir (CWD del subprocess), Env (env extra mergeado con os.Environ()), Stderr (destino del stderr del subprocess)."
output: "Canal de ClaudeEvent cerrado cuando el subprocess termina. Cada evento tiene Type discriminador y campos especificos segun el tipo. Raw contiene siempre la linea NDJSON original. Retorna error solo si el spawn falla."
---

## Tipos exportados

**ClaudeEventType** — constantes de tipo de evento:
- `system` — evento de inicializacion con session_id y model
- `assistant` — mensaje raw del asistente (tambien genera text_delta y/o tool_use sinteticos)
- `user` — mensaje raw de usuario/tool_result (tambien genera tool_result sintetico)
- `result` — evento final con stop_reason, is_error, result
- `text_delta` — (sintetico) porcion de texto del asistente
- `tool_use` — (sintetico) llamada a herramienta con tool_use_id, tool_name, tool_input
- `tool_result` — (sintetico) resultado de herramienta con tool_result_id, content, is_error
- `error` — (sintetico) linea no-JSON o exit code != 0

**ClaudeStreamOpts** — configura el subprocess:
- `Bin string` — path al binario. Si vacio, usa `exec.LookPath("claude")`.
- `Args []string` — args extra. Se anteponen automaticamente `-p --output-format stream-json --verbose`.
- `Stdin io.Reader` — prompt user. Puede ser `strings.NewReader("prompt")` o nil.
- `Workdir string` — CWD del subprocess.
- `Env map[string]string` — variables extra mergeadas con `os.Environ()`.
- `Stderr io.Writer` — destino del stderr en vivo (ej. `os.Stderr` para debug). Si nil, se descarta.

## Ejemplo

```go
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

ch, err := core.StreamClaude(ctx, core.ClaudeStreamOpts{
    Args:  []string{"responde en una frase: que es Go"},
    Stderr: os.Stderr,
})
if err != nil {
    log.Fatal(err)
}
for ev := range ch {
    switch ev.Type {
    case core.ClaudeEventTextDelta:
        fmt.Print(ev.Text)
    case core.ClaudeEventToolUse:
        fmt.Printf("\n[tool] %s(%s)\n", ev.ToolName, ev.ToolInput)
    case core.ClaudeEventToolResult:
        fmt.Printf("[result] %s\n", ev.ToolResultContent)
    case core.ClaudeEventResult:
        fmt.Printf("\n[done] stop_reason=%s\n", ev.StopReason)
    case core.ClaudeEventError:
        fmt.Fprintf(os.Stderr, "[error] %s\n", ev.Error)
    }
}
```

## Notas

- El caller DEBE consumir el canal hasta que se cierre, o cancelar el ctx. No consumir bloquea la goroutine interna.
- El canal tiene buffer de 64 para absorber ráfagas sin bloquear la lectura de stdout.
- Los eventos `assistant` y `user` raw se emiten ademas de los sinteticos, para casos no contemplados.
- `tool_result.content` puede ser string o array `[{type:text,text:"..."}]` — la funcion concatena los bloques text en ambos casos.
- Los tests usan un fake claude bash; se skipean si bash no esta disponible en el PATH.
- Equivalente Go de `projects/osint_graph/apps/graph_explorer/chat.cpp` (C++).
