关于 transcript-viewer
transcript-viewer 是用于查看 Claude Code 和 GitHub Copilot CLI 会话记录的技能,适合需要回顾当前或历史会话的开发者。它支持按会话、后台 Agent 输出或日期范围浏览,并可将记录呈现为 Markdown 或 HTML。
主要功能
- 01自动识别 Claude Code 与 Copilot CLI
- 02查看当前或指定会话记录
- 03浏览后台 Agent 任务输出
- 04按日期范围筛选会话
- 05导出为 Markdown 或 HTML
适用场景
- 01回顾当前编码会话
- 02查找特定 ID 的历史记录
- 03检查后台 Agent 任务输出
- 04筛选一段日期内的会话
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ rysweet/ amplihack --skill transcript-viewer安装后在 Claude Code 中输入/transcript-viewer确认已加载。
附带文件tests/test_transcript_viewer.sh
详细介绍
Transcript Viewer 技能
用途
此技能可转换和浏览来自两种受支持工具的会话记录:
- Claude Code — 自动保存到
~/.claude/projects/的 JSONL 日志 - GitHub Copilot CLI — 自动保存到
~/.copilot/session-state/*/events.jsonl的 JSONL 日志
它提供四种浏览模式:
- 当前会话 — 查看活动会话的记录
- 指定会话 — 按会话 ID 查看会话
- Agent 输出 — 查看子 Agent 生成的后台任务输出文件
- 所有会话 — 浏览项目的所有会话,可按日期范围筛选
工具上下文自动检测
浏览前,检测当前使用的工具,以设置默认日志路径。
优先使用基于目录的检测(比环境变量更可靠);如果目录不存在,则回退到
src/amplihack/hooks/launcher_detector.py 中的环境变量:
# Primary: directory-based detection (most reliable)
if [[ -d "$HOME/.copilot/session-state" ]]; then
# Check if there are any sessions present
COPILOT_SESSIONS=$(ls -d "$HOME/.copilot/session-state/"*/ 2>/dev/null | wc -l)
CLAUDE_SESSIONS=$(ls "$HOME/.claude/projects/"*/*.jsonl 2>/dev/null | wc -l)
if [[ "$COPILOT_SESSIONS" -gt 0 && "$CLAUDE_SESSIONS" -eq 0 ]]; then
TOOL_CONTEXT="copilot"
DEFAULT_LOG_DIR="$HOME/.copilot/session-state"
elif [[ "$CLAUDE_SESSIONS" -gt 0 ]]; then
TOOL_CONTEXT="claude-code"
DEFAULT_LOG_DIR="$HOME/.claude/projects"
else
# Both dirs exist but empty — use env vars to decide
TOOL_CONTEXT="claude-code"
DEFAULT_LOG_DIR="$HOME/.claude/projects"
fi
elif [[ -d "$HOME/.claude/projects" ]]; then
TOOL_CONTEXT="claude-code"
DEFAULT_LOG_DIR="$HOME/.claude/projects"
# Fallback: env var detection (same vars as launcher_detector.py)
elif [[ -n "${CLAUDE_CODE_SESSION:-}${CLAUDE_SESSION_ID:-}${ANTHROPIC_API_KEY:-}" ]]; then
TOOL_CONTEXT="claude-code"
DEFAULT_LOG_DIR="$HOME/.claude/projects"
elif [[ -n "${GITHUB_COPILOT_TOKEN:-}${COPILOT_SESSION:-}" ]]; then
# Note: GITHUB_TOKEN is intentionally excluded — it's too generic and
# appears in non-Copilot CI contexts, causing false positives.
TOOL_CONTEXT="copilot"
DEFAULT_LOG_DIR="$HOME/.copilot/session-state"
else
# Default to claude-code — safe fallback (most users)
TOOL_CONTEXT="claude-code"
DEFAULT_LOG_DIR="$HOME/.claude/projects"
fi
如果 ~/.copilot/session-state/ 和 ~/.claude/projects/ 都存在会话,
请向用户提供选择:“找到 Claude Code 和 GitHub Copilot CLI 的会话。
您想浏览哪一种?[1] Claude Code [2] GitHub Copilot CLI”
用户始终可以通过指定路径覆盖默认设置。
日志格式自动检测
收到文件路径时,处理前先检测其格式:
detect_log_format() {
local file="$1"
if [[ "$file" == *.jsonl ]]; then
echo "jsonl"
elif [[ "$file" == *.md ]]; then
# Check for Copilot /share export signature — specific header only
# Note: do NOT match on "/share" alone (too generic — appears in docs, READMEs)
if grep -q "Copilot Session Export\|copilot-session" "$file" 2>/dev/null; then
echo "copilot-markdown"
else
echo "markdown"
fi
elif [[ "$file" == *.log ]]; then
# .log files may be plain text or agent JSONL; check content
local first_char
first_char=$(head -c 1 "$file" 2>/dev/null)
if [[ "$first_char" == "{" ]]; then
echo "jsonl"
else
echo "plain-log"
fi
else
# Inspect first byte for other extensions
local first_char
first_char=$(head -c 1 "$file" 2>/dev/null)
if [[ "$first_char" == "{" ]]; then
echo "jsonl"
else
echo "unknown"
fi
fi
}
| 格式 | 处理方式 |
|---|---|
jsonl | 传递给 claude-code-log |
copilot-markdown | 内嵌显示(已是易读的 Markdown) |
markdown | 内嵌显示 |
unknown | 发出警告并显示原始内容 |
工具检测
运行任何命令前,检查 claude-code-log 是否可用:
# Step 1: direct install check
which claude-code-log 2>/dev/null
# Step 2: npx fallback
npx --yes claude-code-log --version 2>/dev/null
将解析出的命令设为 CCL:
if which claude-code-log &>/dev/null; then
CCL="claude-code-log"
elif npx --yes claude-code-log --version &>/dev/null 2>&1; then
CCL="npx claude-code-log"
else
CCL=""
fi
缺少工具 — 优雅处理错误
如果 CCL 为空,显示此消息并停止:
claude-code-log is not installed.
To install it globally:
npm install -g claude-code-log
Or run without installing (requires npx):
npx claude-code-log --help
After installing, retry your request.
不要尝试自动安装。
模式
模式 1:当前会话
触发短语:“查看当前记录”、“显示我的当前会话”、“当前日志”
操作:
对于 Claude Code(TOOL_CONTEXT="claude-code"):
- 查找
~/.claude/projects/下最近修改的 JSONL 文件:ls -t ~/.claude/projects/*/*.jsonl 2>/dev/null | head -1 - 运行:
$CCL <path-to-jsonl> --format markdown - 内嵌显示 Markdown 输出。
对于 GitHub Copilot CLI(TOOL_CONTEXT="copilot"):
- 查找
~/.copilot/session-state/下最近修改的会话目录:ls -dt ~/.copilot/session-state/*/ 2>/dev/null | head -1 - 读取其
events.jsonl:LATEST_SESSION=$(ls -dt ~/.copilot/session-state/*/ 2>/dev/null | head -1) $CCL "${LATEST_SESSION}events.jsonl" --format markdown - 内嵌显示 Markdown 输出。
输出示例:
# Session: 2025-11-23 19:32
**Model**: claude-sonnet-4-6
**Messages**: 42
---
**User**: Fix the authentication bug in login.py
**Assistant**: I'll examine the file...
...
模式 2:按 ID 指定会话
触发短语:“查看会话 ”、“显示记录 ”、“打开日志 ”
操作:
对于 Claude Code(TOOL_CONTEXT="claude-code"):
- 搜索与会话 ID 匹配的 JSONL 文件:
或者,如果 ID 看起来像文件名片段,则使用:find ~/.claude/projects -name "*.jsonl" | xargs grep -l "<SESSION_ID>" 2>/dev/null | head -1ls ~/.claude/projects/*/ | grep "<SESSION_ID>" - 运行:
$CCL <path-to-jsonl> --format markdown - 显示输出。如果没有匹配的文件,则报告:
No session found with ID: <SESSION_ID> Available sessions: run "view all sessions" to list them.
对于 GitHub Copilot CLI(TOOL_CONTEXT="copilot"):
- 会话 ID 是
~/.copilot/session-state/下的目录名。直接检查:
如果不知道完整 ID,则搜索部分匹配项:SESSION_DIR="$HOME/.copilot/session-state/<SESSION_ID>" if [[ -d "$SESSION_DIR" ]]; then EVENTS_FILE="$SESSION_DIR/events.jsonl" fils -d ~/.copilot/session-state/*/ 2>/dev/null | grep "<SESSION_ID>" - 运行:
$CCL "$EVENTS_FILE" --format markdown - 显示输出。如果没有匹配的目录,则报告:
No Copilot session found with ID: <SESSION_ID> Available sessions: run "browse all sessions" to list them.
模式 3:Agent 后台任务输出
触发短语:“查看 Agent 输出”、“显示后台任务输出”、“Agent 日志”
操作:
- 查找后台 Agent 任务创建的
.log或.jsonl文件。这些文件 通常写入当前工作目录或临时路径,名称与.agent-step-*.log或类似模式匹配:ls -t .agent-step-*.log 2>/dev/null ls -t /tmp/*.agent*.log 2>/dev/null - 对找到的每个文件,运行
detect_log_format <file>进行分类:jsonl→ 运行$CCL <file> --format markdownplain-log→ 使用cat直接显示
- 这样可以确保 JSONL 格式的
.log文件(虽然少见,但有可能出现)得到正确渲染。 - 如果未找到 Agent 输出文件:
No agent background task output files found in the current directory. Background agents write their output to files named .agent-step-<ID>.log.
模式 4:所有会话(浏览)
触发短语:“浏览所有会话”、“列出对话记录”、“查看所有会话”、 “显示会话历史记录”
操作:
对于 Claude Code(TOOL_CONTEXT="claude-code"):
- 列出
~/.claude/projects/下的所有 JSONL 文件:find ~/.claude/projects -name "*.jsonl" -printf "%T@ %p\n" 2>/dev/null \ | sort -rn | awk '{print $2}' - 对于每个文件,提取会话日期和第一条用户消息:
$CCL <file> --format markdown --summary # If --summary flag is not supported, just show filename and date head -1 <file> | python3 -c "import sys,json; d=json.loads(sys.stdin.read()); print(d.get('timestamp',''))" - 打印摘要表格:
Available Sessions (Claude Code) ================================= # Date Session ID / File 1 2025-11-23 19:32:36 ~/.claude/projects/foo/abc123.jsonl 2 2025-11-22 14:10:05 ~/.claude/projects/foo/def456.jsonl ... - 提供打开特定会话的选项:“输入编号以查看该会话。”
对于 GitHub Copilot CLI(TOOL_CONTEXT="copilot"):
- 按修改时间排序,列出
~/.copilot/session-state/下的所有会话目录:ls -dt ~/.copilot/session-state/*/ 2>/dev/null - 对于每个会话目录,读取其
events.jsonl以提取时间戳:for session_dir in $(ls -dt ~/.copilot/session-state/*/); do session_id=$(basename "$session_dir") events_file="$session_dir/events.jsonl" if [[ -f "$events_file" ]]; then timestamp=$(head -1 "$events_file" | python3 -c \ "import sys,json; d=json.loads(sys.stdin.read()); print(d.get('timestamp',''))" 2>/dev/null) echo "$timestamp $session_id" fi done - 打印摘要表格:
Available Sessions (GitHub Copilot CLI) ======================================== # Date Session ID 1 2025-11-23 19:32:36 abc1234567890abcdef1234567890abcd 2 2025-11-22 14:10:05 def4567890abcdef1234567890abcdef ... - 提供打开特定会话的选项:“输入编号以查看该会话。”
日期范围筛选
当用户指定日期范围时(例如,“最近 7 天”、“2025-11-01 到 2025-11-30 之间”):
# Filter by modification time (last N days)
find ~/.claude/projects -name "*.jsonl" -mtime -7
# Filter by date range using find -newer
find ~/.claude/projects -name "*.jsonl" \
-newer /tmp/start_date_ref \
! -newer /tmp/end_date_ref
使用 touch -d 创建参考文件:
touch -d "2025-11-01" /tmp/start_date_ref
touch -d "2025-11-30" /tmp/end_date_ref
输出格式
Markdown(默认)
向 claude-code-log 传入 --format markdown。输出会直接显示在对话中。适合在终端或 Claude Code 中快速阅读。
HTML
向 claude-code-log 传入 --format html。将输出写入文件并打开:
$CCL <file> --format html > /tmp/transcript-view.html
open /tmp/transcript-view.html 2>/dev/null \
|| xdg-open /tmp/transcript-view.html 2>/dev/null \
|| echo "HTML saved to /tmp/transcript-view.html — open it in your browser."
用户可以明确要求 HTML:“以 HTML 格式查看对话记录”或“导出为 HTML”。
GitHub Copilot CLI 支持
自动持久化日志
GitHub Copilot CLI 会自动将会话数据保存到磁盘上的:
~/.copilot/session-state/{session-id}/
每个会话目录包含:
events.jsonl— JSONL 会话历史记录(格式与 Claude Code 日志类似)workspace.yaml— 会话元数据(工作目录、会话 ID 等)plan.md— 会话的实施计划checkpoints/— 压缩历史记录(较早的事件快照)
旧版会话也可能位于 ~/.copilot/history-session-state/。
JSONL 格式
Copilot 的 events.jsonl 每行包含一个 JSON 对象,格式与 Claude Code 类似:
{"type":"user","message":{"role":"user","content":[{"type":"text","text":"Fix the bug"}]},"timestamp":"2025-11-23T19:32:36Z","sessionId":"abc1234567890"}
{"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"I'll examine the file..."}]},"timestamp":"2025-11-23T19:32:40Z","sessionId":"abc1234567890"}
由于格式兼容,claude-code-log 可以解析这些文件。
查看 Copilot 会话
当用户想要查看 Copilot 会话时(通过目录检测或明确指定路径):
- 找到该会话的
events.jsonl:# Current session (most recent) LATEST_SESSION=$(ls -dt ~/.copilot/session-state/*/ 2>/dev/null | head -1) EVENTS_FILE="${LATEST_SESSION}events.jsonl" # Specific session by ID EVENTS_FILE="$HOME/.copilot/session-state/<SESSION_ID>/events.jsonl" - 运行:
$CCL "$EVENTS_FILE" --format markdown - 在对话中直接显示输出。
检测可用会话
要检查是否存在 Copilot 会话:
if [[ -d "$HOME/.copilot/session-state" ]]; then
SESSION_COUNT=$(ls -d "$HOME/.copilot/session-state/"*/ 2>/dev/null | wc -l)
if [[ "$SESSION_COUNT" -gt 0 ]]; then
echo "Found $SESSION_COUNT Copilot session(s)"
fi
fi
完整工作流
用户调用此技能时,遵循以下决策树:
0. Detect tool context (directory-based first, then env var fallback):
- ~/.copilot/session-state/ exists with sessions → copilot
- ~/.claude/projects/ exists with sessions → claude-code
- Both exist with sessions → offer user a choice
- Directory detection fails, use env vars:
- CLAUDE_CODE_SESSION / CLAUDE_SESSION_ID / ANTHROPIC_API_KEY set → claude-code
- GITHUB_COPILOT_TOKEN / COPILOT_SESSION set → copilot
- Neither → default to claude-code (safe fallback)
1. Detect CCL (which claude-code-log / npx fallback)
→ If missing: show install instructions and STOP
→ Required for ALL modes (both Claude Code and Copilot use JSONL format)
2. If user provides an explicit file path:
a. Detect its format (detect_log_format function above)
b. jsonl or events.jsonl → pass to $CCL
c. unknown → warn and display raw
3. Determine mode from user message:
- mentions "current" or no session specified → Mode 1 (Current Session)
- mentions a session ID or hash → Mode 2 (Specific Session)
- mentions "agent" or "background" → Mode 3 (Agent Output)
- mentions "all", "browse", "list" → Mode 4 (All Sessions)
4. Determine output format:
- "as HTML" or "export HTML" → html
- default → markdown
5. Execute the appropriate mode (using TOOL_CONTEXT to choose correct paths) and display results.
错误处理
| 情况 | 响应 |
|---|---|
未安装 claude-code-log | 显示安装说明,然后停止 |
| 未找到 JSONL 文件 | “在 处未找到会话文件” |
| 未找到会话 ID | “未找到 ID 为 的会话。运行 'browse all sessions' 以列出可用会话。” |
| 没有 Agent 输出文件 | “在当前目录中未找到 Agent 后台任务输出。” |
| JSONL 文件为空 | “会话文件为空 — 没有可显示的消息。” |
| 日期范围内没有结果 | “在 和 之间未找到会话。” |
claude-code-log 返回非零退出码 | 显示 stderr 并建议使用 --help |
~/.copilot/session-state/ 存在但为空 | “未找到 Copilot 会话。使用 GitHub Copilot CLI 启动会话以创建日志。” |
| Copilot 会话目录存在,但没有 events.jsonl | “已找到会话目录,但 处缺少 events.jsonl” |
| 文件格式未知 | 警告用户并显示原始内容 |
实现说明
检测会话 ID
Claude Code 会话 ID 是类似 UUID 的字符串。如果用户输入类似“查看会话 abc123”或“显示日志 def456”的内容,则将最后一个词视为会话 ID,并搜索匹配的 JSONL 文件名。
JSONL 结构(Claude Code)
Claude Code 会话 JSONL 文件每行包含一个 JSON 对象:
{"type":"user","message":{"role":"user","content":[{"type":"text","text":"..."}]},"timestamp":"...","sessionId":"..."}
{"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"..."}]},"timestamp":"..."}
claude-code-log 会负责解析;此技能不会重新实现解析功能。
Copilot JSONL 结构(GitHub Copilot CLI)
Copilot CLI 的 events.jsonl 文件每行包含一个 JSON 对象,存储在
~/.copilot/session-state/{session-id}/events.jsonl:
{"type":"user","message":{"role":"user","content":[{"type":"text","text":"..."}]},"timestamp":"...","sessionId":"..."}
{"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"..."}]},"timestamp":"...","sessionId":"..."}
此格式兼容 claude-code-log。每个会话还包含以下文件:
workspace.yaml— 会话元数据plan.md— 实施计划checkpoints/— 压缩历史记录(较早的快照)
旧版会话可能存储在 ~/.copilot/history-session-state/ 中,结构相同。
理念契合
- 轻量封装:所有 JSONL(Claude Code 和 Copilot)操作均委托给
claude-code-log - 优雅降级:工具缺失或找不到会话时,提供明确的错误消息
- 单一职责:仅查看和转换对话记录,不对其进行修改
- 无隐藏状态:向用户显示所有文件路径
限制
- 需要
claude-code-log(npm)或npx才能将 JSONL(Claude Code 和 Copilot)转换为 HTML/Markdown - 无法查看远程计算机上的对话记录
- 日期筛选依据文件系统修改时间,而非会话时间戳
--summary标志是否可用取决于claude-code-log版本- 不会自动发现
~/.copilot/history-session-state/中的旧版 Copilot 会话(必须使用显式路径) - 如果 Claude Code 和 Copilot 会话同时存在,该技能会提示用户选择,而不会将它们合并
快速参考
| 用户说 | 工具 | 模式 | 命令 |
|---|---|---|---|
| “查看当前对话记录” | Claude Code | 当前会话 | $CCL <latest.jsonl> --format markdown |
| “显示会话 abc123” | Claude Code | 指定会话 | $CCL ~/.claude/projects/**/*abc123*.jsonl --format markdown |
| “查看 Agent 输出” | Claude Code | Agent 输出 | cat .agent-step-*.log 或 $CCL *.jsonl |
| “浏览所有会话” | Claude Code | 所有会话 | 列出并汇总所有 ~/.claude/projects/**/*.jsonl |
| “以 HTML 查看对话记录” | Claude Code | 任意会话 + HTML | $CCL <file> --format html > /tmp/view.html |
| “最近 7 天”(与浏览一起使用) | Claude Code | 日期筛选 | find ... -mtime -7 |
| “查看当前 Copilot 会话” | Copilot | 当前会话 | $CCL ~/.copilot/session-state/<latest>/events.jsonl --format markdown |
| “显示 Copilot 会话 abc123” | Copilot | 指定会话 | $CCL ~/.copilot/session-state/abc123/events.jsonl --format markdown |
| “浏览 Copilot 会话” | Copilot | 所有会话 | 列出 ~/.copilot/session-state/ 中的目录并显示会话 ID |
| “以 HTML 查看 Copilot 会话” | Copilot | 任意会话 + HTML | $CCL <events.jsonl> --format html > /tmp/view.html |