Agent arayüzünüz 45 saniye boyunca hiçbir şey göstermiyor, sonra tüm yanıtı bir seferde aktarıyor. Kullanıcılar donmuş olduğunu düşünüyor. Çözüm tek bir bayrak — --output-format stream-json — ve birkaç satır NDJSON ayrıştırma.
stream-json protokolü, Claude CLI’ı gerçek zamanlı bir olay yayıcıya dönüştürür. Tüm yanıtı beklemek yerine, olaylar gerçekleşirken NDJSON olayları alırsınız — init meta verileri, token token metin, araç çağrıları, araç sonuçları, hız sınırları ve nihai özet. NDJSON (Newline Delimited JSON), satır başına bir JSON nesnesi anlamına gelir. Her olay, \n ile ayrılmış eksiksiz bir JSON nesnesidir. --input-format stream-json ile birleştirildiğinde, gerçek zamanlı arayüzler, agent zincirleri ve izleme panoları oluşturmak için çift yönlü iletişim sağlar.
Bu bölüme ihtiyacınız var eğer: özel arayüzler oluşturuyorsanız, gerçek zamanlı ilerleme çubukları uyguluyorsanız, panolar oluşturuyorsanız veya akış davranışını hata ayıklıyorsanız. Temel otomasyon için JSON modu daha basittir.
Akışı Etkinleştirme
Akış protokolünü etkinleştirmek için iki bayrak gerekir: --output-format stream-json çıktı modunu ayarlar ve --verbose tam oturum meta verilerini içeren init olayının yayılmasını sağlar. --verbose olmadan init olayı eksik olabilir — her zaman ikisini birlikte kullanın.
Çıktıdaki her satır eksiksiz, bağımsız bir JSON nesnesidir. Araç kullanımı olmayan basit bir prompt tam olarak dört olay üretir: system (init), assistant (yanıt), rate_limit_event (API durumu) ve result (nihai zarf).
Olay Türleri
Her olayın ne temsil ettiğini söyleyen bir type alanı vardır. Çoğu oturum 5 temel olay üretir: session_started -> input_sent -> started_working -> output_message -> completed. Diğerleri (tool_use, tool_result vb.) araç kullanımı, yeniden denemeler ve kısmi mesaj akışına bağlı olarak koşullu görünür.
İşte tam katalog:
Akış Olay Türleri
| Olay Türü | Alt Tür / Tetikleyici | Ne Zaman Tetiklenir | Temel Alanlar |
|---|---|---|---|
system | init | Her akıştaki ilk olay | tools, mcp_servers, model, session_id, permissionMode |
system | api_retry | Yeniden denenebilir API hatasında (hız sınırı, sunucu hatası) | attempt, max_retries, retry_delay_ms, error |
assistant | — | Model bir yanıt ürettikten sonra | message.content[], message.usage |
user | — | Bir araç çalıştırılıp sonuçları döndükten sonra | Araç sonuç içeriği |
rate_limit_event | — | Her API çağrısından sonra (izin verildiğinde bile her zaman tetiklenir) | rate_limit_info.status, resetsAt |
result | success veya error_* | Akıştaki son olay | —output-format json zarfıyla aynı alanlar |
stream_event | message_start, content_block_delta, message_stop, … | Yalnızca —include-partial-messages ile | event.delta.text — artımlı token parçaları |
Claude araç kullandığında, olaylar serpişir: bir assistant olayı araç çağrısını içerir (content[].type === "tool_use"), ardından araç sonucunu içeren bir user olayı gelir. Bu döngü, nihai assistant yanıtından önce her araç çağrısı için tekrarlanır.
Aşağıdaki etkileşimli görselleştirici gerçek bir akış oturumunu oynatır. Olayların nasıl sırayla geldiğini ve yanıtı nasıl oluşturduğunu izleyin.
Akış olaylarını kendiniz görün:
claude -p “Say hello” —output-format stream-json 2>/dev/null | head -5
İlk olayın session_id içeren init olduğuna ve sonraki olayların metin parçalarını içeren assistant olduğuna dikkat edin. Yalnızca metni çıkarmak için jq -r ‘select(.type==“assistant”) | .content’ ile pipe edin.
Init Olayı
Her akıştaki ilk olay, oturum meta verilerini içeren bir system/init yüküdür. Bu, protokoldeki en zengin olaydır ve herhangi bir arayüz veya izleme sistemini başlatmanın anahtarıdır.
Init olayını sağlık kontrolleri (MCP sunucu bağlantılarını doğrulama), araç denetimleri (izin listelerini onaylama), sürüm sabitleme (claude_code_version kontrolü) ve arayüz başlatma (araç listeleri ve model adlarını doldurma) için kullanın.
Kısmi Mesajlar
Varsayılan olarak, yanıtın tamamını tek bir assistant olayında alırsınız. --include-partial-messages eklemek, her token parçası için stream_event girdileri ekleyerek metin üretildikçe render eden daktilo tarzı arayüzleri mümkün kılar.
stream_event girdilerinin sırası katı bir düzeni izler:
message_start— model kimliği, boş içerikcontent_block_start— yeni metin bloğu başlar (indeks 0)content_block_delta— artımlı token’lar:"\n\nHello", sonra"! How", sonra" can I help you today?"content_block_stop— blok tamamlandımessage_delta—stop_reason: "end_turn", nihai kullanım istatistiklerimessage_stop— akış tamamlandı
Tam assistant olayı (birleştirilmiş tam mesajla) tüm delta’lardan sonra görünür. Daktilo arayüzü için content_block_delta olaylarını gerçek zamanlı tüketin — assistant olayını beklemeyin.
—include-partial-messages yüksek hacimlidir. 500 kelimelik bir yanıt yüzlerce stream_event satırı üretebilir. Bunu yalnızca daktilo arayüzleri için etkinleştirin, yalnızca nihai sonuca ihtiyaç duyduğunuz veri ardışık düzenleri için değil.
Çift Yönlü İletişim
Akış protokolü yalnızca çıktı değildir. --input-format stream-json eklemek, stdout’ta olaylar alırken stdin aracılığıyla Claude’a mesaj göndermenizi sağlar — gerçek zamanlı arayüzler, agent orkestrasyon sistemleri ve özel IDE entegrasyonları oluşturmayı mümkün kılar.
# Tam çift yönlü modclaude -p --input-format stream-json --output-format stream-json --verboseBu bayraklar için katı eşleşme kuralları vardır:
Giriş/Çıkış Bayrak Gereksinimleri
| Bayrak | Gerektirir | Amaç |
|---|---|---|
—input-format stream-json | —output-format stream-json | Takip mesajları için stdin’de stream-json kabul et |
—replay-user-messages | Hem —input-format hem de —output-format stream-json olarak ayarlı | Onay için kullanıcı mesajlarını stdout’a geri yansıt |
Birinin stream-json çıktısını diğerine pipe ederek Claude örneklerini de zincirleyebilirsiniz:
# İlk Claude analiz eder, ikinci Claude özetlerclaude -p "Analyze auth.py" --output-format stream-json --verbose | \ claude -p "Summarize the analysis" --input-format stream-json --output-format stream-json --verboseİkinci örnek, birinciden gelen tüm olayları — araç sonuçları ve nihai yanıt dahil — kendi görevi için bağlam olarak alır.
Gerçek Akış Yükü
İşte gerçek bir CLI çağrısından tam dört olaylık akış. Bu, araç kullanımı olmayan basit bir prompt için --output-format stream-json --verbose’un tam olarak ürettiği şeydir.
Gerçek bir akışta, bu dört nesnenin her biri aralarında virgül veya köşeli parantez olmadan kendi satırında olurdu. Yukarıda gösterilen iç içe yapı, okunabilirlik için gruplandırılmıştır — gerçek NDJSON çıktısı satır başına bir JSON nesnesidir.
Akış Olaylarını Ayrıştırma
İşte bir Claude süreci başlatan ve ayrıştırılmış olayları geldikçe veren bir Node.js üreteci:
import { spawn } from 'child_process';import { createInterface } from 'readline';
async function* streamClaude(prompt, { partial = false } = {}) { const args = ['-p', prompt, '--output-format', 'stream-json', '--verbose']; if (partial) args.push('--include-partial-messages');
const proc = spawn('claude', args); const rl = createInterface({ input: proc.stdout });
for await (const line of rl) { if (!line.trim()) continue; // bos satirlari atla try { yield JSON.parse(line); } catch (err) { console.warn(`Hatali JSON atlaniyor: ${line}`, err); } }}
// Olay turune gore dagitfor await (const event of streamClaude('Explain recursion')) { switch (event.type) { case 'system': if (event.subtype === 'init') { console.log(`Model: ${event.model}, Tools: ${event.tools.length}`); } break; case 'assistant': console.log(`Response: ${event.message.content[0].text}`); break; case 'result': console.log(`Cost: $${event.total_cost_usd.toFixed(4)}`); break; }}Üretim ayrıştırıcıları şunları yönetmelidir: eksik satırlar (\n’ye kadar tamponla), hatalı JSON (günlükle ve atla), beklenmeyen olay türleri (uyar ama devam et). Yukarıdaki örnek temel hata yönetimini gösterir — stdin’i parçalar halinde işliyorsanız tamponlama mantığı ekleyin.
Daktilo efekti için kısmi mesajları etkinleştirin ve metin delta’larını filtreleyin:
process.stdout.write('Claude says: ');for await (const event of streamClaude('Write a haiku', { partial: true })) { if (event.type === 'stream_event') { const delta = event.event?.delta; if (delta?.type === 'text_delta') { process.stdout.write(delta.text); } }}console.log();Yeniden Deneme Olayları
API yeniden denenebilir bir hata döndürdüğünde (hız sınırı veya sunucu hatası), yeniden deneme girişiminden önce bir system/api_retry olayı görünür. Bunu, arayüzünüzde yeniden deneme ilerlemesini göstermek veya özel geri çekilme mantığı uygulamak için kullanın.
{ "type": "system", "subtype": "api_retry", "attempt": 1, "max_retries": 5, "retry_delay_ms": 2000, "error_status": 529, "error": "server_error"}—verbose, —output-format stream-json ile birlikte gereklidir. Onsuz, oturum meta verilerini içeren init olayı yayılmayabilir. Her zaman iki bayrağı birlikte kullanın: —output-format stream-json —verbose.
Her satır bağımsız JSON’dur — bu NDJSON’dur, JSON dizisi değil. Nesneler arasında virgül yoktur ve sarmalayan köşeli parantez yoktur. Satır satır JSON.parse(line) ile ayrıştırın. Tam akışta JSON.parse(entireOutput) çağırmak başarısız olur.
result olayı her zaman sondadır ve —output-format json ile aynı verileri içerir. Tek bir akışta hem gerçek zamanlı akış olaylarını hem de nihai özet zarfını alırsınız — sonuç meta verilerini almak için ikinci bir çağrı yapmanıza gerek yoktur.
Üretim kodunun NDJSON akışlarını nasıl ayrıştırdığını ve gerçek zamanlı arayüz için SSE’ye nasıl köprülediğini MR Reviewer Oluşturma, Bölüm 2: Akıştan SSE’ye bölümünde görün.
İlk NDJSON olaylarınızı görmek için claude -p “Explain sessions in one paragraph” —output-format stream-json 2>/dev/null | head -5 çalıştırın. init olayının herhangi bir metin gelmeden önce session_id’yi içerdiğine dikkat edin — Claude yanıt vermeye başlamadan önce bile oturumu izlemeye başlayabilirsiniz.