mcpField
C
claude-history-ingest

claude-history-ingest

github.com/ar9av生产力3.6k3.0k 次安装2 天前更新
代码仓库

关于 claude-history-ingest

claude-history-ingest 将 Claude Code 对话、记忆文件及桌面 Agent 会话中的信息整理到 Obsidian wiki。它支持增量处理、清单追踪和预提取文本,并按项目筛选及抽样会话。

主要功能

  1. 01读取记忆文件、对话记录和桌面会话审计日志
  2. 02依据清单处理新增或修改的来源
  3. 03优先使用预提取的对话文本
  4. 04按项目抽样会话并报告覆盖范围
  5. 05支持忽略指定项目和完整导入

适用场景

  1. 01将 Claude Code 新会话整理到 wiki
  2. 02从项目记忆文件提取已整理的信息
  3. 03通过桌面会话审计日志查找 Agent 操作记录
  4. 04重建 wiki 时执行完整历史导入

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ar9av/obsidian-wiki --skill claude-history-ingest

安装后在 Claude Code 中输入/claude-history-ingest确认已加载。

附带文件references/claude-data-format.md

详细介绍

Claude History Ingest — 对话挖掘

从用户过去的 Claude Code 对话中提取知识,并将其提炼到 Obsidian 知识库中。对话内容丰富但杂乱,你的工作是找出关键信息并加以整理。

此技能可直接调用,也可通过 wiki-history-ingest 路由调用(/wiki-history-ingest claude)。

开始之前

写作风格配置: 在起草或改写自然语言 Markdown 前,阅读并应用 llm-wiki/SKILL.md 中的 Writing Profile Resolution 部分。框架架构、来源信息、安全性及具体操作要求优先。 WRITING.md 中的偏好仅适用于新起草或改写的自然语言 Markdown;请保留源内容和结构化记录。

  1. 解析配置 — 遵循 llm-wiki/SKILL.md 中的 Config Resolution Protocol(内联 @name 覆盖 → 沿 CWD 向上查找 .env → 全局配置 → 提示用户设置)。这会提供 OBSIDIAN_VAULT_PATH 和 CLAUDE_HISTORY_PATH(默认为 ~/.claude)
  2. 读取知识库根目录中的 .manifest.json,检查已经摄取的内容
  3. 读取知识库根目录中的 index.md,了解知识库已有的内容
  4. 项目范围限定 — 从配置中读取 WIKI_SKIP_PROJECTS(以逗号分隔的子字符串)。以下每个步骤(扫描、增量检查、抽样、清单写入)都要排除名称包含这些子字符串的项目目录。如果用户要求本次额外跳过其他项目,也一并添加。统一应用排除规则;不要在各条命令中分别手写 grep -v 过滤条件,以免扫描步骤与清单步骤出现偏差。

摄取模式

追加模式(默认)

针对每个源文件(对话 JSONL、记忆文件)检查 .manifest.json。仅处理:

  • 清单中没有的文件(新对话、新记忆文件、新项目)
  • 修改时间晚于清单中 ingested_at 时间的文件

通常情况下,这就是你想要的模式——用户运行了几次新会话,并希望捕获新增内容。

比较时使用可移植键。 清单键遵循 llm-wiki/SKILL.md → .manifest.json 中定义的来源键规范(v2)。$HOME 下的会话使用相对于 ~ 的键(~/.claude/projects/.../abc.jsonl),而不是展开后的机器路径;另外两种形式是相对于知识库的路径和伪键。在判断文件是否为“新文件”之前,要以工具相同的方式解析存储的键(展开 ~/环境变量,将相对于知识库的路径解析为相对于知识库根目录)——否则,已跟踪的文件会被误认为新文件并再次摄取。scripts/manifest.py 可帮助你完成此操作:

# 遵循 WIKI_SKIP_PROJECTS + --skip,查找新增或已修改的来源:
python3 "$OBSIDIAN_WIKI_REPO/scripts/manifest.py" delta "$OBSIDIAN_VAULT_PATH" \
  --scan "$CLAUDE_HISTORY_PATH/projects/*/memory/*.md"
# 如果清单中仍有旧版绝对路径键,可一次性修复:
python3 "$OBSIDIAN_WIKI_REPO/scripts/manifest.py" migrate "$OBSIDIAN_VAULT_PATH" --dry-run

此辅助脚本为可选项;如果无法使用,请在每次查询和写入清单前以内联方式执行相同的路径解析。

预提取(推荐——摄取前运行)

原始 JSONL 文件中有 80%–90% 是噪声:按字节数计算,tool_use 块、thinking 块、progress 事件和 file-history-snapshot 条目占据了大部分内容。scripts/extract-jsonl.py 助手脚本会剔除所有这些内容,并将仅含有效信息的紧凑 JSON 写入 ~/.claude/extracted/,将 文件大小缩减 50–200 倍(例如,12 MB JSONL → 64 KB 提取文件)。这样一来,在相同的令牌预算内,每次运行都能让技能读取 5–10 倍的对话内容。

调用此技能前,请先运行该脚本:

# First run — extract everything (skip excluded projects)
python3 "$OBSIDIAN_WIKI_REPO/scripts/extract-jsonl.py" --skip tsg,autom8

# Incremental — only sessions modified in the last day
python3 "$OBSIDIAN_WIKI_REPO/scripts/extract-jsonl.py" \
    --since "$(date -v-1d +%Y-%m-%d)" --skip tsg,autom8

提取后的文件位于 ~/.claude/extracted/<project-dir>/<session-id>.json,包含:

{
  "session_id": "uuid",
  "project": "-Users-name-myapp",
  "cwd": "/Users/name/myapp",
  "start_ts": "...",
  "end_ts": "...",
  "n_turns": 18,
  "n_user_words": 620,
  "turns": [
    {"role": "user",      "text": "..."},
    {"role": "assistant", "text": "..."}
  ]
}

步骤 3 读取对话时,始终优先使用提取后的文件,而非原始 JSONL。(参见步骤 3。)

如果未先运行 extract-jsonl.py,则回退到原始 JSONL——但请注意,由于读取每个原始文件消耗的令牌多得多,覆盖范围会更浅。

对话抽样启发式

一个历史记录路径可能包含数百个对话 JSONL——不要试图全部读取。对每个项目:

  • 如果项目已有记忆文件(memory/*.md),请先摄取这些文件(其中已提炼出有效信息),然后也处理清单中尚未记录的对话——即使是记忆丰富的项目,也应记录新对话。
  • 如果项目没有记忆文件,则仅读取最近的 3 个对话(按 mtime 排序),以了解项目概况。优先使用预提取文件(见上文)——它们的读取成本足够低,在读取 1 个原始 JSONL 的令牌预算内可以读取 5–10 个。
  • 始终报告已抽样和已跳过的内容(例如,“agenttower:已摄取 7 个记忆文件 + 4 个新对话,跳过 14 个未更改的对话”),让覆盖范围的缺口清晰可见,而不是悄然遗漏。
完整模式

无论清单如何,都处理所有内容。在执行 wiki-rebuild 后,或用户明确要求时使用。

Claude Code 数据布局

Claude Code 将数据存储在两个位置。请扫描两个位置。

来源 1:~/.claude/(CLI 会话)
~/.claude/
├── projects/                          # Per-project directories
│   ├── -Users-name-project-a/         # Path-derived name (slashes → dashes)
│   │   ├── <session-uuid>.jsonl       # Conversation data (JSONL)
│   │   └── memory/                    # Structured memories
│   │       ├── MEMORY.md              # Memory index
│   │       ├── user_*.md              # User profile memories
│   │       ├── feedback_*.md          # Workflow feedback memories
│   │       └── project_*.md           # Project context memories
│   ├── -Users-name-project-b/
│   │   └── ...
├── sessions/                          # Session metadata (JSON)
│   └── <pid>.json                     # {pid, sessionId, cwd, startedAt, kind, entrypoint}
├── history.jsonl                      # Global session history
├── tasks/                             # Subagent task data
├── plans/                             # Saved plans
└── settings.json
来源 2:~/Library/Application Support/Claude/local-agent-mode-sessions/(桌面应用 Agent 会话)

请先进行预检查。 许多用户只使用 CLI,没有桌面会话。在遍历下方结构前,请先确认该目录非空:

DESKTOP_SESSIONS="$HOME/Library/Application Support/Claude/local-agent-mode-sessions"
[ -d "$DESKTOP_SESSIONS" ] && find "$DESKTOP_SESSIONS" -name "audit.jsonl" | head -1

如果没有任何输出,则跳过本节(来源 2 + 步骤 3b),也不要提及本节。

Claude 桌面应用会在此处存储本地 Agent 模式会话。目录结构层级很深:

~/Library/Application Support/Claude/local-agent-mode-sessions/
└── <outer-uuid>/
    └── <inner-uuid>/
        ├── local_<session-uuid>.json          # Session metadata
        └── local_<session-uuid>/
            ├── audit.jsonl                    # Audit log — tool calls, file reads, commands run
            └── .claude/
                └── projects/
                    └── <path-encoded-name>/   # Same path-encoding as ~/.claude/projects/
                        └── <uuid>.jsonl       # Conversation transcript (same JSONL format as CLI)

如何查找所有本地 Agent 模式会话:

# Find all session metadata files
find ~/Library/Application\ Support/Claude/local-agent-mode-sessions -name "local_*.json" -maxdepth 4

# Find all audit logs
find ~/Library/Application\ Support/Claude/local-agent-mode-sessions -name "audit.jsonl"

# Find all conversation transcripts
find ~/Library/Application\ Support/Claude/local-agent-mode-sessions -name "*.jsonl" -path "*/.claude/projects/*"

会话元数据(local_<uuid>.json)——包含 sessionId、cwd、startedAt、model、title 等字段的 JSON 文件。请先读取此文件,了解会话上下文,再打开会话记录。

审计日志(audit.jsonl)——每行都是一条 JSON 记录,记录一次 Agent 操作:工具调用(Read、Write、Bash、Edit)、文件访问、执行的 shell 命令、MCP 调用。可用于了解 Agent 实际执行了什么——通常比单独查看对话文本包含更丰富的信息。字段:type、toolName、input、output、timestamp、sessionId。

对话记录(.claude/projects/.../<uuid>.jsonl)——格式与 CLI 对话 JSONL 相同。请使用与解析 ~/.claude/projects/*/*.jsonl 相同的方法。

按价值排序的关键数据源(合并两个位置):
  1. 记忆文件(~/.claude/projects/*/memory/*.md)——经过预先提炼,已适合用于 Wiki。非常有价值。
  2. 对话 JSONL(~/.claude/projects/*/*.jsonl 和桌面应用转录记录)——完整的对话转录记录。内容丰富,但噪声较多。
  3. 审计日志(桌面会话中的 audit.jsonl)——工具调用级别的操作记录。即使对话内容稀少,也有助于提取具体操作、文件模式和命令模式。
  4. 会话元数据(sessions/*.json 和 local_*.json)——用于了解项目、时间和 CWD。

第 1 步:调查并计算差异

扫描两个数据位置,并与 .manifest.json 对比:

# --- Source 1: CLI sessions (~/.claude) ---
# Find all projects
Glob: ~/.claude/projects/*/

# Find memory files (highest value)
Glob: ~/.claude/projects/*/memory/*.md

# Find conversation JSONL files
Glob: ~/.claude/projects/*/*.jsonl

# --- Source 2: Desktop app local-agent-mode sessions ---
DESKTOP_SESSIONS="$HOME/Library/Application Support/Claude/local-agent-mode-sessions"

# Session metadata
find "$DESKTOP_SESSIONS" -name "local_*.json" -maxdepth 4

# Audit logs
find "$DESKTOP_SESSIONS" -name "audit.jsonl"

# Conversation transcripts
find "$DESKTOP_SESSIONS" -name "*.jsonl" -path "*/.claude/projects/*"

建立统一清单并对每个文件分类:

  • 新增 — 清单中没有 → 需要导入
  • 已修改 — 在清单中,但文件更新日期更晚 → 需要重新导入
  • 未更改 — 在清单中且未修改 → 追加模式下跳过

向用户报告:“找到 X 个 CLI 项目、Y 个桌面会话。记忆文件:A。对话:B。审计日志:C。差异:新增 D 个,已修改 E 个。”

第 2 步:先导入记忆文件

记忆文件已经采用 YAML frontmatter 结构化:

---
name: memory-name
description: one-line description
type: user|feedback|project|reference
---

Memory content here.

对于每个记忆文件:

  • 读取文件并解析 frontmatter
  • user 类型 → 写入介绍用户的实体页面,或介绍其领域的概念页面
  • feedback 类型 → 写入技能页面(工作流模式、有效做法和无效做法)
  • project 类型 → 写入介绍该项目的实体页面
  • reference 类型 → 写入指向外部资源的参考页面

每个项目中的 MEMORY.md 索引文件是快速摘要——先读取它,以决定哪些单独的记忆文件值得完整阅读。

第 3 步:解析对话 JSONL

始终先检查是否有预提取文件(见上文“预提取”部分)。对于每个对话 ~/.claude/projects/<proj>/<uuid>.jsonl,查找其对应文件 ~/.claude/extracted/<proj>/<uuid>.json。如果找到,则读取该文件——其中已筛选出用户和助手的文本轮次,与原始 JSONL 相比,所需 token 少 50–200 倍。

# Resolution order for each session:
1. ~/.claude/extracted/<project>/<session-id>.json   ← prefer (compact, signal-only)
2. ~/.claude/projects/<project>/<session-id>.jsonl   ← fallback (raw, noisy)

**读取预提取文件:**其中只包含所需的轮次。直接遍历 turns[].{role, text}。顶层字段(cwd、start_ts、n_user_words 等)可提供项目信息,无需进一步解析。

**读取原始 JSONL(备用方案):**每行都是一个 JSON 对象:

{
  "type": "user|assistant|progress|file-history-snapshot",
  "message": {
    "role": "user|assistant",
    "content": "text string"
  },
  "uuid": "...",
  "timestamp": "2026-03-15T10:30:00.000Z",
  "sessionId": "...",
  "cwd": "/path/to/project",
  "version": "2.1.59"
}

对于助手消息,content 可能是内容块数组:

{
  "content": [
    {"type": "thinking", "text": "..."},
    {"type": "text", "text": "The actual response..."},
    {"type": "tool_use", "name": "Read", "input": {...}}
  ]
}
  • 仅筛选 type: "user" 和 type: "assistant" 条目
  • 对于助手条目,提取 text 块(跳过 thinking 和 tool_use——这些都是噪声)
  • cwd 字段用于确定此对话所属的项目
  • 跳过 type: "progress"——内部 Agent 进度更新
  • 跳过 type: "file-history-snapshot"——文件状态跟踪
  • 跳过子 Agent 对话(位于 subagents/ 子目录中)——除非用户提出要求

步骤 3b:解析审计日志(仅限桌面会话)

对于在 local-agent-mode-sessions/ 下找到的每个 audit.jsonl,逐行读取。每行都是一条记录 Agent 操作的 JSON 记录:

{
  "type": "tool_call",
  "toolName": "Bash",
  "input": {"command": "npm test"},
  "output": "...",
  "timestamp": "2026-04-10T14:22:00Z",
  "sessionId": "..."
}

从审计日志中提取的内容:

  • 文件访问模式 — Agent 反复读取或编辑了哪些文件?这些是项目中的高价值文件。将它们记为项目参考资料。
  • Shell 命令 — 反复出现的 Bash 命令可以揭示项目的构建、测试和部署工作流。将这些内容提炼成 skills/ 页面(例如“如何构建和测试此项目”)。
  • 工具调用顺序 — 如果 Agent 总是按特定顺序执行读取 → 编辑 → Bash,这种工作流模式值得记录。
  • 错误模式 — 失败的工具调用(非零退出代码、错误输出)可以揭示痛点、已知问题或反复出现的错误。
  • MCP 工具调用 — 对 MCP 工具的调用可以揭示项目集成了哪些外部服务和 API。

从审计日志中跳过:

  • 没有规律的常规文件读取(例如只读取一次配置文件)
  • 纯属噪声的工具输出(冗长的堆栈跟踪、详细日志)——概括错误类别,而非完整输出
  • 命令参数或输出中任何看起来像秘密、令牌或凭据的内容

与对话记录交叉参考: 审计日志告诉你发生了什么;对话告诉你为什么。同一会话的两者都可用时,请结合使用——审计日志可以用具体操作为对话内容提供依据。

处理审计日志前,先读取配对的 local_<uuid>.json 会话元数据——其中的 cwd、startedAt 和 title 可为这些操作提供背景信息。

步骤 4:按主题归类

不要为每段对话都创建一个 Wiki 页面。请改为:

  • 将不同对话中提取的知识按主题分组
  • 一段关于“调试身份验证 + 设置 CI”的对话 → 拆分为两个独立主题
  • 不同日期的三段关于“React 性能”的对话 → 合并为一个主题
  • 项目目录名称可作为自然的第一级分组

步骤 5:提炼为 Wiki 页面

每个 Claude 项目都对应知识库中的一个项目目录。~/.claude/projects/ 中的项目目录名称编码了原始路径——解码后即可得到简洁的项目名称:

-Users/Documents/projects/my-Project   → myproject
-Users/Documents/projects/Another-app  → anotherapp
项目专属知识与全局知识
你发现的内容应存放的位置示例
项目架构决策projects/<name>/concepts/projects/my-project/concepts/main-architecture.md
项目专属调试经验projects/<name>/skills/projects/my-project/skills/api-rate-limiting.md
用户学到的一般概念concepts/(全局)concepts/react-server-components.md
多个项目中反复出现的问题skills/(全局)skills/debugging-hydration-errors.md
使用的工具/服务entities/(全局)entities/vercel-functions.md
多次对话中出现的模式synthesis/(全局)synthesis/common-debugging-patterns.md

对于包含内容的每个项目,请在 projects/<name>/<name>.md 创建或更新项目概览页面——文件名应当使用项目名称,而不是 _project.md。Obsidian 的图谱视图使用文件名作为节点标签,因此 _project.md 会让所有项目在图谱中都显示为 _project。将文件命名为 <name>.md,可让每个项目都有独特且易读的节点名称。

**重要:**提炼_知识_,而不是对话内容。不要写“在 3 月 15 日的一次对话中,用户询问了 X。”应直接写出知识本身,并将对话列为来源。

为每个新建或更新的页面编写 summary: frontmatter 字段——用 1–2 句话、不超过 200 个字符说明“此页面介绍什么”,让尚未打开页面的读者也能了解内容。wiki-query 的快速检索路径会读取此字段,以避免打开页面正文。

为每个新建页面的 frontmatter 添加置信度和生命周期字段:

base_confidence: 0.42
lifecycle: draft
lifecycle_changed: <obsidian-wiki memory now --date>

更新页面时,保持 lifecycle 和 lifecycle_changed 不变——只有人工编辑者才能转换生命周期状态。

按照 llm-wiki 中的约定标记来源(“Provenance Markers”一节):

  • 记忆文件大多是提取而来的——它们由用户手动编写,且已经过提炼。除非你要整合多个记忆文件中的说法,否则应将源自记忆的说法视为提取所得。
  • 对话提炼大多是推断所得。你需要综合多轮对话中的内容得出连贯的观点,通常还要补足隐含的推理。对于综合得出的模式、跨会话归纳,以及对“用户真正想表达的意思”的解读,请广泛使用 ^[inferred]。
  • 如果用户在不同会话中改变了想法,或者助手与用户相互矛盾且无法明确判断如何解决,请使用 ^[ambiguous]。
  • 为每个新建或更新的页面编写 provenance: frontmatter 块,概述来源的大致构成。

第 6 步:更新 Manifest、日志和特殊文件

更新 .manifest.json

对于处理过的每个源文件,添加或更新其条目,包含:

  • ingested_at、size_bytes、modified_at
  • source_type:取值为 "claude_conversation"、"claude_memory"、"claude_audit_log"、"claude_desktop_session" 之一
  • project:解码后的项目名称
  • pages_created 和 pages_updated 列表

同时更新 manifest 的 projects 部分:

{
  "project-name": {
    "source_path": "~/.claude/projects/-Users-...",
    "vault_path": "projects/project-name",
    "last_ingested": "TIMESTAMP",
    "conversations_ingested": 5,
    "conversations_total": 8,
    "memory_files_ingested": 3,
    "desktop_sessions_ingested": 2,
    "audit_logs_ingested": 2
  }
}
创建日志条目并更新特殊文件

使用一次带锁的调用更新 index.md、log.md 和 hot.md:

obsidian-wiki memory sync CLAUDE_HISTORY_INGEST \
  projects=<projects> conversations=<conversations> \
  desktop_sessions=<desktop_sessions> audit_logs=<audit_logs> \
  pages_updated=<pages_updated> pages_created=<pages_created> \
  mode=<mode> \
  --takeaways "Ingested 5 Claude conversations across 2 projects; surfaced patterns in API design and testing strategy."

绝不要手动编辑 index.md、log.md 或 hot.md——该命令会获取锁,防止并行写入者丢失你的更新。--takeaways 是过去用于“最近活动”的单行概念摘要;省略它即可保留之前的 takeaways 不变。

如果你现在对某个进行中的项目有了更深入的理解,请记录相关事项,以便下一个会话接续处理:obsidian-wiki memory todo add "<thread>" --origin projects/<name>.md。

完整流程请参阅 .skills/llm-wiki/references/MEMORY.md。

隐私

  • 提炼并综合内容——不要逐字复制原始对话文本
  • 跳过任何看起来像机密、API 密钥、密码或令牌的内容
  • 如果遇到个人或敏感内容,请先征求用户同意再纳入
  • 用户的对话可能会提及其他人——谨慎决定哪些内容写入知识库

参考

有关数据结构的更多详情,请参阅 references/claude-data-format.md。

写入 Vault 后刷新 QMD

QMD 是搜索索引,不是事实来源。如果 $QMD_WIKI_COLLECTION 为空或未设置,请跳过此步骤。仅在此技能写入或重写 vault Markdown 后运行。如果 QMD 刷新失败,不要回滚 vault 更改;请单独报告 QMD 状态。

如果设置了 $QMD_CLI,请使用它;否则使用 qmd。

${QMD_CLI:-qmd} update

如果输出提示需要向量或嵌入可能已过时,请运行:

${QMD_CLI:-qmd} embed

使用以下任一方式验证集合:

${QMD_CLI:-qmd} ls "$QMD_WIKI_COLLECTION"

或者,如果已知特定页面路径:

${QMD_CLI:-qmd} get "qmd://$QMD_WIKI_COLLECTION/<page>.md" -l 5

记录以下其中一项:

  • QMD refreshed: update + embed + verified
  • QMD refreshed: update only + verified
  • QMD skipped: QMD_WIKI_COLLECTION unset
  • QMD skipped: qmd CLI unavailable
  • QMD failed: <short error summary>

评论

支持 Markdown