ESC
开源 3 分钟阅读

ai-data-extractor:免费开源的 AI 编程助手聊天记录提取器,支持 Claude Code、Cursor、Windsurf、Aider、Cline/Roo Code 等

免费开源工具 ai-data-extractor 可自动发现并提取 Claude Code、Cursor、Windsurf、Aider、Cline/Roo Code、Gemini CLI 等十种 AI 编程助手的本地聊天记录,统一为 JSONL 格式,跨平台自动定位存储路径,仅用 Python 标准库、无任何依赖,适用于模型微调、个人数据分析和多年对话备份。

来源:GitHub

AI 编程助手数据提取

将你自己的本地聊天记录从 AI 编程助手中提取为统一的 JSONL 格式——用于微调、个人数据分析,或只是在应用的本地数据库被清空之前备份多年对话。

功能特性

自动发现并提取完整对话历史,包括:

  • 用户消息与助手回复
  • 代码上下文(文件路径、选区、代码片段)
  • 代码 diff / 建议的编辑(在工具记录了这些信息的情况下)
  • 工具调用及其结果
  • 时间戳、会话 ID、项目路径、模型名称——各工具存储中实际包含的内容

支持的来源

#工具存储方式搜索位置
1Claude CodeJSONL,每个会话一个文件~/.claude/projects/**/*.jsonl
2Codex CLIJSONL “rollout” 文件~/.codex/sessions/**/rollout-*.jsonl
3CursorSQLite (state.vscdb)~/…/Cursor/User/{global,workspace}Storage
4WindsurfSQLite,未公开的 schema(启发式)~/…/Windsurf/User/{global,workspace}Storage
5TraeSQLite + JSONL,未公开(启发式)~/…/Trae
6ContinueJSON,每个会话一个文件~/.continue/sessions/*.json
7Gemini CLIJSON,每个聊天一个文件~/.gemini/tmp/<hash>/chats/*.json
8OpenCodeJSON(session/message/part 树)~/.local/share/opencode/storage/
9Cline / Roo Code(新增)JSON,每个任务一个文件夹<editor>/User/globalStorage/<ext-id>/tasks/
10Aider(新增)每个项目一个 Markdown 记录<project>/.aider.chat.history.md

每个脚本都会自动搜索 macOS、Linux 和 Windows 的常见路径(~/Library/Application Support、~/.config、~/.local/share、%APPDATA%、%LOCALAPPDATA%)——你无需告诉它你用的是哪个操作系统。

为什么加入 Cline 和 Aider

它们是原列表遗漏的两个使用最广泛的 AI 编程工具,而且两者的存储结构确实与众不同(很有参考价值):

  • Cline(及其分支 Roo Code)是最流行的开源自主编程 agent 扩展。它按任务存储原始的 Anthropic 格式消息数组,因此它的提取器也可以作为解析该格式最简单的示例,方便你以后添加自己的工具。
  • Aider 是最流行的纯终端结对编程工具,它的结构与此处的其他工具完全不同:没有中央数据库,只有位于每个项目目录中的 Markdown 记录文件。收录它正是为了证明这套工具集可以泛化到"某个应用数据文件夹里的 SQLite 或 JSONL"之外。

快速开始

# 无依赖——仅使用标准库
python --version   # 需要 3.9+,推荐 3.10+

# 交互式:从编号菜单中选择要提取的来源
python extract.py

# 或直接驱动
python extract.py --all
python extract.py --sources cursor,claude_code,aider
python extract.py --list                    # 只显示已安装的工具,不提取
python extract.py --all --merge             # 同时生成 all_conversations.jsonl

# "提取全部"的简写
./extract_all.sh

CLI 参考

python extract.py [--all] [--sources ids] [--list] [--output-dir DIR]
                    [--search-path PATH ...] [--merge]

--all                 提取所有支持的来源,无提示。
--sources ids         逗号分隔的来源 id(名称见上表,或用 --list 查看)。跳过菜单。
--list                报告每个来源的发现结果但不提取——快速、安全的预览。
--output-dir DIR      JSONL 输出目录(默认:./extracted_data)
--search-path PATH    在常规操作系统位置之外额外搜索的目录。可重复使用。主要用于:
                         - Aider,它没有固定的应用数据文件夹,
                           需要知道你的项目在哪里
                         - 其他工具的非标准安装位置
--merge               提取完成后,将所有内容合并为 all_conversations.jsonl

每个提取器也仍然可以独立运行,与原工具集相同(在项目根目录下运行 python -m extractors.cursor,或 python extractors/cursor.py),这在调试单个来源时很方便。

输出格式

每次运行都会在 extracted_data/ 下创建带时间戳的文件:

extracted_data/
├── claude_code_conversations_20260816_143022.jsonl
├── cursor_conversations_20260816_143022.jsonl
├── aider_conversations_20260816_143022.jsonl
├── cline_conversations_20260816_143022.jsonl
└── ... 每个提取的来源一个文件,使用 --merge 时还有 all_conversations.jsonl

每行是一条 JSON 对话:

{
  "messages": [
    {
      "role": "user",
      "content": "How do I fix this TypeScript error?",
      "code_context": [
        {"file": "/Users/you/project/src/index.ts", "code": "const x: string = 123;"}
      ],
      "timestamp": "2026-01-16T14:30:22Z"
    },
    {
      "role": "assistant",
      "content": "The error occurs because you're assigning a number to a string type...",
      "tool_use": [{"name": "edit_file", "input": {"path": "src/index.ts"}}],
      "timestamp": "2026-01-16T14:30:25Z"
    }
  ],
  "source": "cursor-composer",
  "session_id": "c1a2b3...",
  "project_path": "/Users/you/project",
  "name": "TypeScript Type Error Fix",
  "created_at": 1705414222000
}

字段因来源而略有不同(并非每个工具都记录 code_context、token 用量或 project_path)——messages、source 和 session_id 是你始终可以依赖的字段。

工作原理

  1. 检测操作系统并构建一个可能的数据根目录列表 (Application Support、.config、.local/share、%APPDATA% 等)。
  2. 在每个根目录中搜索工具的已知文件夹名。
  3. 读取存储——JSONL 逐行读取,SQLite 通过只读连接读取(因此运行中的应用不会阻塞我们),或读取 JSON 树,取决于具体工具。
  4. 规范化找到的内容为上述 messages[] schema。
  5. 写入 JSONL,每行一条对话,输出到 extracted_data/。

这里的一切都不会以写入模式打开数据库,且每个读取器都有包装保护,一个损坏或被锁定的文件不会让整个运行崩溃——你会得到部分结果并继续,而不是一个堆栈跟踪。

关于 Cursor、Windsurf 和 Trae 的说明

这三者都没有公开其存储 schema,而且 schema 已多次变更(仅 Cursor 就经历了至少三种形态:workspace ItemTable 聊天、内联 composer、拆分的 bubbleId composer)。cursor.py 提取器明确实现了所有三种已知形态。windsurf.py 和 trae.py 则使用通用启发式方法(extractors/common.py::heuristic_extract_chat_from_kv),扫描聊天相关的键并遍历解析后的 JSON,寻找形如 role + text 对的对象。这是尽力的最佳尝试,而非文档化格式——如果未来版本改变形态导致不再匹配,那也在预期之内;调整相应文件中的 KEY_HINTS 或提交 PR。

关于 Aider 的说明

Aider 没有中央会话存储——每个项目目录都有自己的 .aider.chat.history.md。默认情况下,本工具集会扫描你的主目录以及若干常见的项目根目录名(projects、code、dev、repos、workspace、src、Documents),最多深入 5 层目录,跳过 node_modules、.git 等类似目录。如果你的项目存放在其他地方,直接指向它们:

python extract.py --sources aider --search-path ~/client-work --search-path /mnt/data/repos

扩展:添加新来源

每个提取器都是一个具有相同双函数接口的小模块——复制最简单的一个(continue_ext.py 是很好的模板)并填入:

DISPLAY_NAME = "My Tool"
SOURCE_ID = "my_tool"

def find_installations(extra_paths: list[Path] | None = None) -> list[Path]:
    """Return the directories/files worth scanning."""

def extract(installations: list[Path]) -> list[dict]:
    """Return a list of conversation dicts matching the schema above."""

然后在 extract.py 的 REGISTRY 列表中注册它。extractors/common.py 包含 SQLite/JSON/JSONL 读取器以及你可能会用到的两个通用启发式方法。

隐私与安全

本工具从你自己用户账户下运行的工具中提取数据。在分享或用于训练之前:

  1. 扫描密钥:
    pip install detect-secrets --break-system-packages
    detect-secrets scan extracted_data/*.jsonl
    
  2. 检查专有代码、API 密钥和个人文件路径——code_context 和 tool_use 字段是最可能发现它们的地方。
  3. 不要将 extracted_data/ 提交到公共仓库(它已在 .gitignore 中)。如果包含客户或专有工作内容,请保存在加密存储中。

训练用例

from datasets import load_dataset

dataset = load_dataset("json", data_files="extracted_data/*.jsonl", split="train")
dataset = dataset.filter(lambda x: any(m["role"] == "assistant" for m in x["messages"]))

def format_chat(example):
    return {"text": tokenizer.apply_chat_template(example["messages"], tokenize=False)}

dataset = dataset.map(format_chat)

故障排除

“No installation found”(未找到安装)——工具未安装、尚无聊天记录,或位于非标准位置。传入 --search-path 直接指向它,或检查 extractors/<tool>.py 的 SEARCH_DIRS / APP_DIR_NAMES 常量并添加你的路径。

Cursor/Windsurf 数据库被锁定——读取以 mode=ro 方式打开,专门为避免运行中的编辑器阻塞提取而设计,但如果仍看到错误,请关闭应用后重新运行。

Windsurf/Trae 找到安装但提取到 0 条对话——common.heuristic_extract_chat_from_kv 中的启发式键匹配未能识别当前的存储键。运行 --list 确认应用目录已被找到,然后直接检查 state.vscdb 的 ItemTable/cursorDiskKV 键(sqlite3 state.vscdb "SELECT key FROM ItemTable")并将匹配项添加到 KEY_HINTS。

免责声明

本工具集从你自己机器上安装的 AI 工具中提取你自己的数据。你需要负责:

  • 拥有所提取数据的相应权利,
  • 妥善处理任何敏感/专有信息,
  • 遵守每个工具的服务条款,
  • 在分享或用于训练输出之前扫描密钥。

许可证

MIT——自由使用,包括用于训练 ML 模型。