Skip to content
曾亮懿 ZengLiangYi Blog

Filtering Claude Code JSONL: Events, Blocks, and Omissions

Follow ChatCrystal relevance checks, content extraction, and tag cleanup to distinguish top-level filtering from nested thinking and tool flags.

曾亮懿

曾亮懿

4 min read
Table of contents Show Hide

A name appearing at the top level of a JSONL record and inside its content array can receive different treatment. Calling every thinking or tool_use item discarded noise misstates what the current parser preserves.

This article checks ChatCrystal’s Claude Code adapter at 7642768. It explains the application’s projection, not complete reconstruction of Claude Code’s internal state. See the import guide for directories and operations.

First layer: decide whether to process an event

isRelevantMessage requires uuid, excludes known skipped types and every top-level system record, and ultimately accepts only top-level user and assistant. File history, progress, and streaming fragments do not enter content extraction.

Exclusion serves knowledge extraction; it does not make those records valueless to their original tool. Nor does absence of uuid prove that any arbitrary record is a streaming message. The parser applies specific field rules.

These constructed samples compare a top-level event with a nested block:

{"uuid":"sample-1","type":"thinking","thinking":"Top-level event"}
{"uuid":"sample-2","type":"assistant","message":{"content":[{"type":"thinking","thinking":"Nested reasoning"},{"type":"text","text":"Readable conclusion"}]}}

The first is skipped by the top-level rule. The second enters assistant extraction, which retains body and thinking separately. The first behavior does not establish that the second is also discarded.

Second layer: extract body and supporting fields

String content becomes the body after cleanup. Array content is processed by block type:

Nested block Current handling
text Combine into body text, then clean tags
thinking Collect in a separate thinking field
tool_use Set hasToolUse; do not save as body text
tool_result Exclude from body extraction

A relevant message with only a tool flag or thinking and no ordinary body can still be retained. A tool flag records usage, not a complete archive of parameters, outputs, and execution chains. When retrieval or summaries lack an output, return to the original record to check whether this rule excluded it.

Separate storage does not establish inclusion in summaries. The transcript preparation code reads message type, content, and has_tool_use, but not thinking. Imported thinking therefore does not enter the summary input through this path.

Third layer: remove specified tags

sanitizeContent removes system-reminder, command echoes, and some local-command tags. It uses specific regular expressions, not a general XML parser or a security judgment covering every potential instruction.

A constructed input:

<system-reminder>Example system prompt</system-reminder>
The actual debugging conclusion.

Cleanup keeps the conclusion that follows. Patterns for system-reminder and local-command-caveat handle multiple lines; some command-tag patterns use [^<]* for content. Nested tags, attributes, or other variations are not guaranteed to be removed. Examples containing these literal tags in user text can also be deleted.

Cleanup transforms content, so verify both removal and retention. Original files remain the traceability source. Cleaned imported messages should not be presented as a byte-for-byte backup.

Prepare failure-path samples

Use temporary files or test copies for at least four inputs: malformed JSON, a record without uuid, an assistant message with nested thinking, and a body containing only tags targeted for cleanup. Check whether malformed lines are skipped, neighboring valid messages survive, and body and thinking are correct separately.

Distinguish invalid JSON syntax from valid JSON with incorrect field types. The current line-level JSON.parse exception can be skipped; later logic still depends on array and string shapes. It cannot promise that all valid JSON is safe to parse. Add incorrect types, missing times, and unknown block types to compatibility checks instead of testing only ordinary text.

Evaluate suitability for knowledge extraction

Choose a conversation with a real problem, handling, and conclusion. Compare its original records, imported messages, and final note. Check whether essential diagnosis appears only in excluded tool outputs, tag cleanup changes a code example, or the summary loses applicability conditions.

Retained messages do not guarantee a generated note. Import, the experience gate, summaries, and vectors are separate stages; see recovering a debugging solution. Where context is insufficient, acknowledge omissions and inspect the source. Concision after filtering is not evidence of accurate knowledge.

Share:

Related Posts

Importing Claude Code history: paths, parsing, and verification

Check history paths, JSONL filtering, incremental import, and watcher limitations against the current ChatCrystal adapter.

曾亮懿 曾亮懿
4 min read
#ChatCrystal #Claude Code #Data parsing

Set up ChatCrystal MCP: make Claude Code calls reviewable

Connect ChatCrystal to Claude Code with a project-scoped stdio server, then verify its seven tools, HTTP backend, approvals, and request path.

曾亮懿 曾亮懿
3 min read
#ChatCrystal #MCP #Claude Code

Claude Code memory workflow: recall, verify, then write back

Use recall_for_task, validate_task_memory, and write_task_memory as an auditable workflow without treating MCP configuration as an automatic-memory guarantee.

曾亮懿 曾亮懿
4 min read
#ChatCrystal #MCP #Claude Code

From writing to code

Explore ChatCrystal, developer tools and daily learning notes on my GitHub. Questions about the implementation are welcome.