Created
February 19, 2026 02:05
-
-
Save miketheprogrammer/8e84ecfaa17fa73a8ae58467c19b5446 to your computer and use it in GitHub Desktop.
asd
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "bufio" | |
| "context" | |
| "encoding/json" | |
| "fmt" | |
| "log" | |
| "os" | |
| "os/exec" | |
| "strings" | |
| "sync" | |
| "sync/atomic" | |
| ) | |
| var requestCounter atomic.Int64 | |
| func nextRequestID() string { | |
| n := requestCounter.Add(1) | |
| return fmt.Sprintf("req_%d", n) | |
| } | |
| func main() { | |
| ctx, cancel := context.WithCancel(context.Background()) | |
| defer cancel() | |
| cmd := exec.CommandContext(ctx, "claude", | |
| "--output-format", "stream-json", | |
| "--input-format", "stream-json", | |
| "--include-partial-messages", | |
| "--verbose", | |
| "--setting-sources", "", | |
| "--permission-mode", "acceptEdits", | |
| ) | |
| stdin, err := cmd.StdinPipe() | |
| if err != nil { | |
| log.Fatalf("stdin pipe: %v", err) | |
| } | |
| stdout, err := cmd.StdoutPipe() | |
| if err != nil { | |
| log.Fatalf("stdout pipe: %v", err) | |
| } | |
| stderr, err := cmd.StderrPipe() | |
| if err != nil { | |
| log.Fatalf("stderr pipe: %v", err) | |
| } | |
| if err := cmd.Start(); err != nil { | |
| log.Fatal(err) | |
| } | |
| var stdinMu sync.Mutex | |
| sendJSON := func(v interface{}) { | |
| b, _ := json.Marshal(v) | |
| stdinMu.Lock() | |
| _, writeErr := fmt.Fprintf(stdin, "%s\n", b) | |
| stdinMu.Unlock() | |
| if writeErr != nil { | |
| fmt.Fprintf(os.Stderr, "[ERROR] write to stdin: %v\n", writeErr) | |
| } | |
| fmt.Fprintf(os.Stderr, "[SENT] %s\n", b) | |
| } | |
| // Drain stderr | |
| go func() { | |
| scanner := bufio.NewScanner(stderr) | |
| scanner.Buffer(make([]byte, 0), 1*1024*1024) | |
| for scanner.Scan() { | |
| fmt.Fprintf(os.Stderr, "[claude stderr] %s\n", scanner.Text()) | |
| } | |
| }() | |
| // Channels for coordination | |
| initDone := make(chan struct{}, 1) // handshake complete, can send first message | |
| turnDone := make(chan struct{}, 1) // current turn complete, can send next message | |
| var sessionID string | |
| // Read NDJSON from stdout | |
| go func() { | |
| defer func() { | |
| // Unblock anything waiting | |
| select { | |
| case initDone <- struct{}{}: | |
| default: | |
| } | |
| select { | |
| case turnDone <- struct{}{}: | |
| default: | |
| } | |
| }() | |
| scanner := bufio.NewScanner(stdout) | |
| scanner.Buffer(make([]byte, 0), 10*1024*1024) | |
| for scanner.Scan() { | |
| line := scanner.Bytes() | |
| fmt.Fprintf(os.Stderr, "[RECV] %s\n", string(line)) | |
| var msg map[string]interface{} | |
| if err := json.Unmarshal(line, &msg); err != nil { | |
| fmt.Fprintf(os.Stderr, "[WARN] parse error: %v\n", err) | |
| continue | |
| } | |
| msgType, _ := msg["type"].(string) | |
| switch msgType { | |
| case "system": | |
| subtype, _ := msg["subtype"].(string) | |
| if sid, ok := msg["session_id"].(string); ok { | |
| sessionID = sid | |
| } | |
| fmt.Fprintf(os.Stderr, "[INFO] system subtype=%q session=%q\n", subtype, sessionID) | |
| case "rate_limit_event": | |
| info, _ := msg["rate_limit_info"].(map[string]interface{}) | |
| status, _ := info["status"].(string) | |
| if sid, ok := msg["session_id"].(string); ok && sessionID == "" { | |
| sessionID = sid | |
| } | |
| fmt.Fprintf(os.Stderr, "[INFO] rate_limit: status=%q\n", status) | |
| // CLI responds to our initialize request | |
| case "control_response": | |
| fmt.Fprintf(os.Stderr, "[INFO] control_response received (init handshake complete)\n") | |
| select { | |
| case initDone <- struct{}{}: | |
| default: | |
| } | |
| // CLI asks us for permissions, hooks, etc. | |
| case "control_request": | |
| reqID, _ := msg["request_id"].(string) | |
| request, _ := msg["request"].(map[string]interface{}) | |
| subtype, _ := request["subtype"].(string) | |
| fmt.Fprintf(os.Stderr, "[INFO] control_request subtype=%q id=%q\n", subtype, reqID) | |
| switch subtype { | |
| case "can_use_tool": | |
| sendJSON(map[string]interface{}{ | |
| "type": "control_response", | |
| "request_id": reqID, | |
| "response": map[string]interface{}{ | |
| "behavior": "allow", | |
| }, | |
| }) | |
| default: | |
| sendJSON(map[string]interface{}{ | |
| "type": "control_response", | |
| "request_id": reqID, | |
| "response": map[string]interface{}{}, | |
| }) | |
| } | |
| case "stream_event": | |
| event, _ := msg["event"].(map[string]interface{}) | |
| eventType, _ := event["type"].(string) | |
| if eventType == "content_block_delta" { | |
| delta, _ := event["delta"].(map[string]interface{}) | |
| if delta["type"] == "text_delta" { | |
| text, _ := delta["text"].(string) | |
| fmt.Print(text) | |
| } | |
| } | |
| case "assistant": | |
| // With --include-partial-messages, text already printed | |
| // via stream_event. Log tool use here. | |
| message, _ := msg["message"].(map[string]interface{}) | |
| if message != nil { | |
| content, _ := message["content"].([]interface{}) | |
| for _, block := range content { | |
| b, _ := block.(map[string]interface{}) | |
| if b["type"] == "tool_use" { | |
| name, _ := b["name"].(string) | |
| fmt.Fprintf(os.Stderr, "\n[TOOL] %s\n", name) | |
| } | |
| } | |
| } | |
| case "user": | |
| fmt.Fprintf(os.Stderr, "[INFO] user message (tool result)\n") | |
| case "result": | |
| fmt.Println() | |
| subtype, _ := msg["subtype"].(string) | |
| costUSD, _ := msg["total_cost_usd"].(float64) | |
| fmt.Fprintf(os.Stderr, "[INFO] result: subtype=%q cost=$%.4f\n", subtype, costUSD) | |
| fmt.Printf("--- Done (cost: $%.4f) ---\n", costUSD) | |
| select { | |
| case turnDone <- struct{}{}: | |
| default: | |
| } | |
| default: | |
| fmt.Fprintf(os.Stderr, "[DEBUG] unhandled: %q\n", msgType) | |
| } | |
| } | |
| if err := scanner.Err(); err != nil { | |
| fmt.Fprintf(os.Stderr, "[ERROR] stdout scanner: %v\n", err) | |
| } | |
| fmt.Fprintf(os.Stderr, "[INFO] stdout closed\n") | |
| }() | |
| // ── Initialize handshake ───────────────────────────────────── | |
| fmt.Println("Claude CLI Streaming Test") | |
| fmt.Println("Sending initialize handshake...") | |
| sendJSON(map[string]interface{}{ | |
| "type": "control_request", | |
| "request_id": nextRequestID(), | |
| "request": map[string]interface{}{ | |
| "subtype": "initialize", | |
| }, | |
| }) | |
| // Wait for the control_response (init ack) | |
| <-initDone | |
| fmt.Printf("Initialized! session=%s\n", sessionID) | |
| fmt.Println("Type a message and press Enter. 'quit' to exit.\n") | |
| reader := bufio.NewReader(os.Stdin) | |
| for { | |
| fmt.Print("> ") | |
| text, err := reader.ReadString('\n') | |
| if err != nil { | |
| break | |
| } | |
| text = strings.TrimSpace(text) | |
| if text == "" { | |
| continue | |
| } | |
| if text == "quit" || text == "exit" { | |
| fmt.Println("Bye!") | |
| break | |
| } | |
| sendJSON(map[string]interface{}{ | |
| "type": "user", | |
| "session_id": sessionID, | |
| "parent_tool_use_id": nil, | |
| "message": map[string]interface{}{ | |
| "role": "user", | |
| "content": text, | |
| }, | |
| }) | |
| // Wait for the result message before accepting next input | |
| <-turnDone | |
| } | |
| stdin.Close() | |
| cmd.Wait() | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment