---
slug: "claude-stream-json-jq"
title: "Parsing Claude Code stream-json output with jq — extract .event.delta.text in real time"
description: "Extract `.event.delta.text` from Claude Code's `--output-format=stream-json` using `jq -j` to avoid the per-fragment newline issue with `jq -r`. Includes a working one-liner."
url: "https://www.ytyng.com/en/blog/claude-stream-json-jq"
publish_date: "2026-01-09T01:55:59.348Z"
created: "2026-01-09T01:55:59.350Z"
updated: "2026-04-20T01:19:22.172Z"
categories: []
keywords: ""
featured_image_url: "https://media.ytyng.com/resize/20260109/888ffa26f30b4dd89c2c134aee2956ca.png.webp?width=768"
has_video: true
has_music: true
video_urls: ["https://media.ytyng.net/ytyng-blog/327/featured-video-1.mp4", "https://media.ytyng.net/ytyng-blog/327/featured-video-2.mp4", "https://media.ytyng.net/ytyng-blog/327/featured-video-3.mp4"]
music_urls: ["https://media.ytyng.net/ytyng-blog/327/featured-music-327-1.mp3", "https://media.ytyng.net/ytyng-blog/327/featured-music-327-2.mp3"]
lang: "en"
---

# Parsing Claude Code stream-json output with jq — extract .event.delta.text in real time

## Background / Problem

When you use Claude Code’s `--output-format=stream-json` option, you get streaming output in JSON Lines format like this:

```json
{"type":"stream_event","event":{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"容を"}},...}
{"type":"stream_event","event":{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"レビューして"}},...}
{"type":"stream_event","event":{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"問"}},...}
```

From this stream, you want to extract only the text content in the `.event.delta.text` field and display it in real time in the terminal.

### Requirements
- Output the text fragments continuously (no newline per fragment)
- Only print a newline when `\n` appears in the text
- Support real-time streaming

## Attempt 1: The problem with `jq -r`

The first method tried:

```bash
claude code ... | jq -r '.event.delta.text? // empty'
```

**Issues:**
- The `-r` (`--raw-output`) option appends a newline after each output result
- Fragments like “容を”, “レビューして”, “問” end up each on their own line
- As a result, text that should be continuous gets broken up unnaturally

## Solution: The `jq -j` option

**Final solution:**

```bash
claude code の ${HOME}/.claude/local/claude \
  --verbose --permission-mode delegate \
  --print --output-format=stream-json --include-partial-messages "/push-with-review" \
  | jq -j '.event.delta.text? // empty'
```

### Characteristics of `jq -j` (`--join-output`)
- Does not automatically add newlines when printing output
- Concatenates text as-is
- Any `\n` inside the text is displayed as an actual newline
- Ideal for streaming processing

### When you need to handle multiple message types

```bash
| jq -j '
  (.event.delta.text? // empty),
  (.message.content[]?.text? // empty)
'
```

This lets you continuously output text from both `stream_event` and `assistant` messages.

## `jq` filter details

### `jq` features used

1. **Optional operator (`?`)**
   - Using `.event.delta.text?` prevents errors even if the field doesn’t exist

2. **Alternative operator (`//`)**
   - `// empty` outputs nothing when the value is null or undefined

3. **Strict filtering with `select()` (alternative)**
   ```bash
   | jq -j 'select(.event.delta.text != null) | .event.delta.text'
   ```

## Reference

### `jq` option comparison

| Option | Behavior | Use case |
|--------|----------|----------|
| `-r` (`--raw-output`) | Adds a newline after each result | When you want to process line by line |
| `-j` (`--join-output`) | Does not add newlines | When you want continuous text output |
| `-c` (`--compact-output`) | Compresses JSON into one line | Keep JSON structure while compacting |

### Reference URLs
- jq Manual: https://jqlang.org/manual/
- JSON Lines format: https://jsonlines.org/

## Conclusion

To extract only the text from Claude Code’s streaming output, **`jq`’s `-j` option** is the best fit.

- Simple
- Fast
- Works with real-time streaming
- No need to build a dedicated tool in Rust, etc.

### Practical examples

```bash
# Basic form
claude -p "タスク内容" | jq -j '.event.delta.text? // empty'

# Filter only stream_event
claude -p "タスク内容" | jq -j 'select(.type == "stream_event") | .event.delta.text? // empty'
```

With this, you can display Claude Code output in a human-readable format in real time.
