---
title: Claude Code JSONL 过滤：区分事件、正文块与遗漏
description: 沿 ChatCrystal 的相关性判断、内容提取和标签清理检查 JSONL，解释顶层过滤与嵌套 thinking、工具标记的差别。
image: "https://zengliangyi.com/og/blog/claude-code-jsonl-noise-filter.png"
---

同一个名字出现在 JSONL 的顶层和消息内容数组里，处理方式可能不同。把 `thinking`、`tool_use` 全部描述成“会删除的噪音”，就会误解当前解析器保留了什么。

本文检查 [ChatCrystal 的 Claude Code 适配器](https://github.com/ZengLiangYi/ChatCrystal/blob/764276814e5c5a33ecbfeae63754f74b9261a3a8/server/src/parser/adapters/claude-code.ts)，版本为 [`7642768`](https://github.com/ZengLiangYi/ChatCrystal/tree/764276814e5c5a33ecbfeae63754f74b9261a3a8)。目标是解释应用的投影视图，不是宣称完整复原 Claude Code 的内部状态；目录与操作步骤见 [导入指南](/blog/claude-code-conversation-import)。

## 第一层：决定是否处理这条事件

`isRelevantMessage` 要求记录有 `uuid`，排除已知跳过类型和所有顶层 `system`，最终只接受顶层 `user`、`assistant`。文件历史、进度、流式片段等不进入正文提取路径。

这里的“不进入”是知识提取用途的选择，不代表这些记录对源工具没有价值，也不能仅凭缺少 uuid 认定任意记录都是流式消息。解析器使用的是明确字段规则。

下面是构造样本，用于比较顶层事件与嵌套块：



```json
{  "uuid"  :  "sample-1"  ,  "type"  :  "thinking"  ,  "thinking"  :  "顶层事件"  }  
  {  "uuid"  :  "sample-2"  ,  "type"  :  "assistant"  ,  "message"  :{  "content"  :[{  "type"  :  "thinking"  ,  "thinking"  :  "嵌套推理"  },{  "type"  :  "text"  ,  "text"  :  "可阅读的结论"  }]}}
```



第一条被顶层规则跳过；第二条进入助手消息提取，正文和 thinking 分别保留。不能用第一条的行为推导第二条也会丢弃。

## 第二层：提取正文与辅助字段

字符串 content 经过清理成为正文。数组 content 按块类型处理：

| 嵌套块 | 当前处理 |

| --- | --- |

| `text` | 拼接为正文，再进行标签清理 |

| `thinking` | 收集到独立的 `thinking` 字段 |

| `tool_use` | 设置 `hasToolUse`，不保存为正文 |

| `tool_result` | 不进入正文提取 |

只有工具标记或 thinking、没有普通正文的相关消息，也可能被保留。工具标记说明曾使用工具，不是工具参数、输出和执行链的完整档案。检索或摘要中缺少某段输出时，应回到原始记录确认它是否被该规则排除。

独立保存也不等于参与摘要。[摘要输入准备代码](https://github.com/ZengLiangYi/ChatCrystal/blob/764276814e5c5a33ecbfeae63754f74b9261a3a8/server/src/services/transcript.ts)读取消息的 `type`、`content`、`has_tool_use`，没有读取 `thinking`。因此，已导入的 thinking 不会沿这条路径进入摘要输入。

## 第三层：清理指定标签

`sanitizeContent` 删除 `system-reminder`、命令回显和部分本地命令标签。它使用具体正则表达式，不是通用 XML 解析器，也不是对所有潜在指令的安全判定。

构造输入如下：



```text
<system-reminder>示例系统提示</system-reminder>  
  真正的调试结论。
```



清理后正文保留后面的调试结论。`system-reminder` 和 `local-command-caveat` 的模式支持跨行；部分命令标签的内容模式使用 `[^<]*`，有嵌套标签、属性或其他变形时，不能保证全部移除。用户正文里恰好包含这些标签的示例，也可能一起被删掉。

清理意味着内容转换，应同时验证去掉了什么和留下了什么。原文件仍是追溯依据；经过清理的导入消息不应冒充字节级备份。

## 为错误路径准备样本

用临时文件或测试副本构造至少四类输入：坏 JSON 行、无 uuid 行、含嵌套 thinking 的助手消息、正文只包含待清理标签的消息。检查坏行是否跳过、相邻好消息是否还在、正文与 thinking 是否分别正确。

还需区分 JSON 语法无效与 JSON 有效但字段类型错误。当前逐行 `JSON.parse` 的异常可跳过；后续逻辑仍依赖内容数组和字符串等形状，不能承诺所有合法 JSON 都不会导致解析失败。增加字段类型错误、缺失时间与未知块类型作为兼容性检查，比只测试正常文本更有价值。

## 判断过滤是否适合知识提取

先选一条包含实际问题、处理过程和结论的会话，比较原始记录、导入后的消息和最终笔记。检查关键诊断是否只出现在已排除的工具输出中，代码示例是否被标签清理改变，以及摘要是否保留适用条件。

“消息被保留”也不代表会生成笔记。导入与经验门槛、摘要、向量是不同阶段，见 [找回调试方案](/blog/recover-debugging-notes)。当上下文不足时，应承认遗漏并回看来源，不能把过滤后的简洁度当作知识准确度。

分享：

##  相关文章

[##  导入 Claude Code 对话：路径、解析与验收

按 ChatCrystal 当前适配器检查 Claude Code 历史位置、JSONL 过滤、增量导入和监听限制，避免把导入成功误读为完整保存或自动生成笔记。          曾亮懿       2026年10月3日      阅读约 5 分钟

#ChatCrystal

#Claude Code

#数据解析](/blog/claude-code-conversation-import)    [##  配置 ChatCrystal MCP：让 Claude Code 可检查地调用知识库

用 Claude Code 的项目级 stdio 配置连接 ChatCrystal MCP，核对七个工具、HTTP 后端、审批和真实调用链路。          曾亮懿       2026年10月3日      阅读约 3 分钟

#ChatCrystal

#MCP

#Claude Code](/blog/chatcrystal-mcp-setup)    [##  MCP 与 Claude Code 记忆工作流：回忆、验证，再写回

用 recall_for_task、validate_task_memory 和 write_task_memory 组织可审计的任务记忆流程，不把工具配置误当成自动记忆保证。          曾亮懿       2026年10月3日      阅读约 4 分钟

#ChatCrystal

#MCP

#Claude Code](/blog/claude-code-memory-workflow)

##  从文章到代码

到我的 GitHub 看看 ChatCrystal、开发者工具和日常学习记录，欢迎交流实现细节。

[访问我的 GitHub](https://github.com/ZengLiangYi)

```json
{
  "@context": "https://schema.org",
  "@type": "WebSite",
  "name": "ZengLiangYi Blog",
  "alternateName": [
    "Zeng Liangyi",
    "ZengLiangYi",
    "zengliangyi.com"
  ],
  "url": "https://zengliangyi.com",
  "description": "曾亮懿的个人网站。记录 AI Native 探索、开发者工具与全栈产品实践。"
}
{
  "@context": "https://schema.org",
  "@type": "BlogPosting",
  "headline": "Claude Code JSONL 过滤：区分事件、正文块与遗漏",
  "description": "沿 ChatCrystal 的相关性判断、内容提取和标签清理检查 JSONL，解释顶层过滤与嵌套 thinking、工具标记的差别。",
  "url": "https://zengliangyi.com/blog/claude-code-jsonl-noise-filter/",
  "image": "https://zengliangyi.com/images/blog/claude-code-jsonl-noise-filter.svg",
  "datePublished": "2026-10-03T00:00:00.000Z",
  "dateModified": "2026-10-03T00:00:00.000Z",
  "author": {
    "@type": "Person",
    "name": "曾亮懿",
    "url": "https://zengliangyi.com/about"
  },
  "publisher": {
    "@type": "Organization",
    "name": "ZengLiangYi Blog",
    "logo": {
      "@type": "ImageObject",
      "url": "https://zengliangyi.com/favicon-96x96.png"
    }
  },
  "mainEntityOfPage": {
    "@type": "WebPage",
    "@id": "https://zengliangyi.com/blog/claude-code-jsonl-noise-filter/"
  }
}
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "position": 1,
      "name": "首页",
      "item": "https://zengliangyi.com/"
    },
    {
      "@type": "ListItem",
      "position": 2,
      "name": "文章",
      "item": "https://zengliangyi.com/blog"
    },
    {
      "@type": "ListItem",
      "position": 3,
      "name": "Claude Code JSONL 过滤：区分事件、正文块与遗漏",
      "item": "https://zengliangyi.com/blog/claude-code-jsonl-noise-filter/"
    }
  ]
}
```
