关于 copilot-history-ingest
用于从 GitHub Copilot CLI 与 VS Code 对话记录中提炼知识并写入 Obsidian Wiki 的技能,适合整理项目经验的用户。它合并多种会话数据源,按主题归纳知识,而非逐条复制对话。
主要功能
- 01扫描 CLI、数据库与 VS Code 数据
- 02依据清单处理新增或变更会话
- 03优先整理检查点与会话摘要
- 04跨会话按主题归纳知识
- 05将内容写入项目或全局 Wiki 页面
适用场景
- 01把 Copilot 会话中的项目决策整理成概念页
- 02汇总多个会话反复出现的调试方法
- 03从会话文件访问记录识别重要文件
- 04将保存的计划文档纳入 Wiki
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ar9av/ obsidian-wiki --skill copilot-history-ingest安装后在 Claude Code 中输入/copilot-history-ingest确认已加载。
附带文件references/copilot-data-format.md
详细介绍
Copilot History Ingest — 对话挖掘
从用户过去的 GitHub Copilot CLI 对话中提取知识,并将其提炼到 Obsidian 知识库中。对话内容丰富,但较为杂乱——你的任务是找出有价值的信息并加以整理。
可以直接调用此技能,也可以通过 wiki-history-ingest 路由器调用(/wiki-history-ingest copilot)。
开始之前
写作风格: 在起草或改写自然语言 Markdown 之前,请阅读并应用 llm-wiki/SKILL.md 中的 Writing Profile Resolution 部分。框架架构、来源溯源、安全规范和特定操作要求优先适用。
WRITING.md 中的偏好仅适用于新起草或改写的自然语言 Markdown;保留源内容和结构化记录。
- 解析配置 — 遵循
llm-wiki/SKILL.md中的 Config Resolution Protocol(内联@name覆盖 → 从 CWD 向上查找.env→ 全局配置 → 提示用户设置)。由此获取OBSIDIAN_VAULT_PATH、COPILOT_HISTORY_PATH(默认为~/.copilot/session-state)和COPILOT_VSCODE_STORAGE_PATH(VS Code 的workspaceStorage;路径因平台而异——若缺失,请询问用户) - 读取 vault 根目录下的
.manifest.json,检查已导入的内容 - 读取 vault 根目录下的
index.md,了解知识库已有内容
导入模式
追加模式(默认)
检查 .manifest.json 中是否记录了每个源文件(events JSONL、transcript JSONL、checkpoint、session-store DB)。仅处理:
- 不在清单中的会话(新会话)
updated_at晚于清单中ingested_at的会话
通常应使用此模式——用户刚运行了几个新会话,希望记录新增内容。
完整模式
无论清单内容如何,处理所有内容。可在执行 wiki-rebuild 后使用,或在用户明确提出要求时使用。
GitHub Copilot 数据布局
Copilot 将数据存储在三个位置。请扫描全部三个位置。
来源 1:~/.copilot/session-state/(CLI 会话)
~/.copilot/session-state/
├── <session-uuid>/
│ ├── workspace.yaml # Session metadata (id, cwd, summary_count, created_at, updated_at)
│ ├── vscode.metadata.json # VS Code context (workspaceFolder, repositoryProperties, customTitle)
│ ├── events.jsonl # Full event log — all turns, tool calls, reasoning
│ ├── session.db # Per-session SQLite (todos/todo_deps only — skip for ingestion)
│ ├── index.md # Session summary written at session end
│ ├── checkpoints/ # Checkpoint JSON files (mid-session summaries)
│ │ └── <uuid>.json # title, overview, history, work_done, technical_details,
│ │ # important_files, next_steps
│ ├── files/ # Artifacts produced during session (plans, diagrams, etc.)
│ └── research/ # Research artifacts
└── ...
来源 2:~/.copilot/session-store.db(全局 SQLite)
跨会话的权威数据库。这是价值最高的来源:结构化、可查询且已预先汇总。
sessions — id, cwd, repository, branch, summary, created_at, updated_at, host_type
turns — session_id, turn_index, user_message, assistant_response, timestamp
checkpoints — session_id, checkpoint_number, title, overview, history, work_done,
technical_details, important_files, next_steps, created_at
session_files — session_id, file_path, tool_name, turn_index, first_seen_at
session_refs — session_id, ref_type (commit/pr/issue), ref_value, turn_index, created_at
search_index — FTS5 virtual table (content, session_id, source_type, source_id)
来源 3:VS Code 工作区存储(<workspaceStorage>/<hash>/GitHub.copilot-chat/)
VS Code 扩展数据,以工作区哈希为键。路径因平台而异,必须从 .env 或用户输入中获取。
<hash>/GitHub.copilot-chat/
├── transcripts/
│ └── <session-uuid>.jsonl # Conversation transcripts (same JSONL format as events.jsonl)
├── memory-tool/
│ └── memories/
│ └── <base64-session-id>/ # Per-session saved artifacts (plan.md, etc.)
│ └── plan.md
└── codebase-external.sqlite # Codebase index (skip — no conversation knowledge)
关键数据来源的价值排序:
- 检查点(
session-store.db的checkpoints表及每个会话的checkpoints/*.json)——预先提炼的摘要,包含overview、work_done、technical_details、important_files、next_steps。价值极高。 - 会话摘要(
session-store.db的sessions.summary及index.md)——每个会话一段概述。 - 轮次(
session-store.db的turns表及events.jsonl/ transcript JSONL)——完整对话。内容丰富,但较冗长。 - 记忆资源(
memory-tool/memories/<id>/plan.md等)——用户明确保存的预写计划和结构化笔记。值得原样导入(或仅做轻微概括)。 - 文件访问模式(
session_files表及tool.execution_*事件)——Agent 反复访问的文件,可揭示高价值项目文件。 - 会话引用(
session_refs表)——与会话关联的提交、PR 和议题。 vscode.metadata.json——工作区文件夹路径、分支、customTitle(用户设置的会话标签)。有助于分组和命名。
步骤 1:调查并计算增量
扫描全部三个数据位置,并与 .manifest.json 进行比较:
# --- Source 1: per-session directories ---
# Find all session directories (each has workspace.yaml)
ls ~/.copilot/session-state/
# For each session, read workspace.yaml for id/cwd/updated_at
# and vscode.metadata.json for customTitle / repositoryProperties
# --- Source 2: global database ---
# Query session-store.db with sqlite3 (or Python sqlite3)
SELECT s.id, s.cwd, s.repository, s.branch, s.summary, s.updated_at,
COUNT(DISTINCT t.turn_index) AS turn_count,
COUNT(DISTINCT c.id) AS checkpoint_count
FROM sessions s
LEFT JOIN turns t ON t.session_id = s.id
LEFT JOIN checkpoints c ON c.session_id = s.id
GROUP BY s.id
ORDER BY s.updated_at DESC;
# --- Source 3: VS Code workspace storage ---
# For each <hash> directory under workspaceStorage, check for GitHub.copilot-chat/
# Find transcript files
ls <workspaceStorage>/<hash>/GitHub.copilot-chat/transcripts/
构建统一清单——每个会话 UUID 对应一条记录——并进行分类:
- 新增 — 不在清单中 → 需要导入
- 已修改 — 在清单中,但
updated_at更新 → 需要重新导入 - 未更改 — 在清单中且没有修改 → 追加模式下跳过
向用户报告:“在 session-state 中找到 X 个会话,在 session-store.db 中找到 Y 个会话,以及 Z 个 VS Code 对话文件。检查点:A。增量:B 个新增,C 个已修改。”
步骤 2:先读取检查点和摘要
检查点已经过提炼——先处理它们,再查看原始轮次。
从 session-store.db 读取:
SELECT s.id, s.cwd, s.repository, s.branch, s.summary,
c.checkpoint_number, c.title, c.overview, c.work_done,
c.technical_details, c.important_files, c.next_steps,
c.created_at
FROM checkpoints c
JOIN sessions s ON c.session_id = s.id
ORDER BY s.updated_at DESC, c.checkpoint_number ASC;
从各会话的 checkpoints/*.json 读取:
每个检查点文件包含:title、overview、history、work_done、technical_details、important_files、next_steps。
如果存在,请阅读 index.md,将其作为会话级摘要——它通常在会话结束时编写,内容已经很精炼。
要提取的内容:
overview→ 会话完成工作的高层概述work_done→ 已完成的具体任务(适合用于技能页/项目页)technical_details→ 实现细节(适合用于概念页)important_files→ 项目中的高价值文件(适合用于项目页)next_steps→ 尚未解决的事项(适合用于关联正在进行的项目工作)
步骤 3:解析会话轮次
从 session-store.db(首选,已完成解析)或 events.jsonl/transcript JSONL 中读取轮次。
从 session-store.db 读取:
SELECT turn_index, user_message, assistant_response, timestamp
FROM turns
WHERE session_id = '<uuid>'
ORDER BY turn_index ASC;
从 events.jsonl/transcript JSONL 读取:
每个文件对应一个会话。每行都是一个 JSON 事件。完整架构请参阅 references/copilot-data-format.md。
相关事件类型:
type | 含义 | 是否值得阅读? |
|---|---|---|
session.start | 会话元数据(cwd、分支、版本) | 是——用于了解项目背景 |
user.message | 用户轮次 | 是——读取 data.content |
assistant.message | 助手轮次 | 是——读取 data.content(文本)和 data.toolRequests |
tool.execution_start | 工具调用 | 略读——了解使用了哪些文件/命令 |
tool.execution_end | 工具结果 | 否——通常是无关信息 |
assistant.message 的提取策略:
data.content是助手的文本回复——提取此内容data.reasoningText是内部推理——跳过(它是解包后的reasoningOpaque字段)data.toolRequests列出工具调用——略读工具名称和参数,了解文件访问模式- 完全跳过
type: "tool.execution_end"
步骤 3b:处理记忆文档
对于在 VS Code 工作区存储中包含 memory-tool/memories/<base64-id>/ 目录的每个会话,请读取其中保存的 Markdown 文件(通常是 plan.md)。这些是用户明确保存的文档——应视为高质量的用户原创内容。
解码 base64 目录名以获取会话 UUID:
import base64
session_id = base64.b64decode(dir_name).decode('utf-8')
根据内容类型,记忆文档可归入项目的 skills/ 或 concepts/ 页面。
步骤 3c:提取文件和引用模式
从 session-store.db 读取:
-- Most-touched files per project
SELECT repository, file_path, COUNT(*) AS touch_count
FROM session_files
GROUP BY repository, file_path
ORDER BY touch_count DESC;
-- Linked commits/PRs/issues per session
SELECT session_id, ref_type, ref_value, turn_index
FROM session_refs
ORDER BY session_id, turn_index;
文件访问模式可揭示哪些文件在架构上很重要——请在项目页中记录。
会话引用可将 Copilot 会话与 Git 历史关联起来,有助于将 Wiki 知识与具体代码更改联系起来。
步骤 4:按主题归类
不要为每个会话都创建一个 Wiki 页面。应当:
- 将不同会话中提取的知识按主题分组
- 关于“调试身份验证+设置 CI”的单个会话 → 拆分为两个主题
- 不同日期的三个“React 性能”会话 → 合并为一个主题
cwd/repository可作为自然的第一层分组依据;vscode.metadata.json的customTitle可提供易读的会话标签
步骤 5:提炼为 Wiki 页面
每个 Copilot 项目都对应知识库中的一个项目目录。根据 cwd 或 repository 推导项目名称:
C:\Users\name\git\my-project → my-project
/Users/name/code/another-app → another-app
如果 session-store.db 中有 repository(例如 owner/repo),优先使用它,而不是原始的 cwd。
项目级知识与全局知识
| 你发现的内容 | 存放位置 | 示例 |
|---|---|---|
| 项目架构决策 | 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 不变。
按照 llm-wiki 中的约定标记来源(Provenance Markers 部分):
- 检查点和 index.md由系统预先提炼——将源自检查点的主张视为提取所得(系统根据观察到的操作编写)。
- 记忆产物由用户撰写——视为提取所得。
- 对话轮次提炼大多属于推断。你是在综合多个轮次,提炼出连贯的主张。对于综合出的模式、跨会话的概括,以及“用户真正想表达的意思”等解读,应广泛使用
^[inferred]。 - 当用户在会话中途改变方向,或会话结束时问题尚未解决,应使用
^[ambiguous]。 - 在每个新建/更新的页面中添加
provenance:frontmatter 块,概述大致的来源构成。
第 6 步:更新清单、日志和特殊文件
更新 .manifest.json
对于处理的每个会话,添加/更新其条目,并包含:
ingested_at、session_id、updated_atsource_type:以下值之一:"copilot_session"、"copilot_checkpoint"、"copilot_transcript"、"copilot_memory_artifact"project:解码后的项目名称pages_created和pages_updated列表
同时更新清单中的 projects 部分:
{
"project-name": {
"repository": "owner/repo",
"cwd": "C:\\Users\\name\\git\\project-name",
"vault_path": "projects/project-name",
"last_ingested": "TIMESTAMP",
"sessions_ingested": 5,
"sessions_total": 8,
"checkpoints_ingested": 12,
"memory_artifacts_ingested": 3
}
}
创建日志条目并更新特殊文件
通过一次加锁调用更新 index.md、log.md 和 hot.md:
obsidian-wiki memory sync COPILOT_HISTORY_INGEST \
projects=<projects> sessions=<sessions> checkpoints=<checkpoints> \
pages_updated=<pages_updated> pages_created=<pages_created> \
mode=<mode> \
--takeaways "Ingested 5 Copilot sessions across 2 projects; surfaced patterns in API design and testing strategy."
切勿手动编辑 index.md、log.md 或 hot.md——该命令会获取锁,防止并行写入者丢失你的更新。--takeaways 是过去会写入 Recent Activity 的单行概念摘要;省略它即可保留之前的摘要不变。
如果现在对某个进行中的项目有了更深入的理解,请记录相关线索,以便下次会话接续:obsidian-wiki memory todo add "<thread>" --origin projects/<name>.md。
完整流程请参见 .skills/llm-wiki/references/MEMORY.md。
隐私
- 提炼并综合内容,不要逐字复制原始对话文本
- 跳过任何看起来像机密信息、API 密钥、密码或令牌的内容
- 助手事件中的
data.reasoningOpaque/data.reasoningText属于内部推理,完全跳过,绝不要复制到 wiki - 如果遇到个人或敏感内容,请先询问用户是否要将其纳入
- 用户的对话可能会提及其他人;请谨慎判断哪些内容适合放入 wiki
参考资料
详细的数据结构文档请参阅 references/copilot-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 + verifiedQMD refreshed: update only + verifiedQMD skipped: QMD_WIKI_COLLECTION unsetQMD skipped: qmd CLI unavailableQMD failed: <short error summary>