transcript-viewer
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTranscript Viewer Skill
会话记录查看器Skill
Purpose
用途
This skill converts and browses session transcripts from two supported tools:
- Claude Code — JSONL logs auto-saved to
~/.claude/projects/ - GitHub Copilot CLI — JSONL logs auto-saved to
~/.copilot/session-state/*/events.jsonl
It provides four browsing modes:
- Current session — View the active session's transcript
- Specific session — View a session by its ID
- Agent output — View background task output files produced by subagents
- All sessions — Browse all project sessions, with optional date-range filtering
本Skill可转换并浏览来自两个支持工具的会话记录:
- Claude Code — JSONL日志自动保存至
~/.claude/projects/ - GitHub Copilot CLI — JSONL日志自动保存至
~/.copilot/session-state/*/events.jsonl
它提供四种浏览模式:
- 当前会话 — 查看活跃会话的记录
- 特定会话 — 通过ID查看指定会话
- Agent输出 — 查看子Agent生成的后台任务输出文件
- 所有会话 — 浏览所有项目会话,支持可选的日期范围过滤
Tool Context Auto-Detection
工具上下文自动检测
Before browsing, detect which tool is active to set default log paths.
Prefer directory-based detection (more reliable than env vars); fall back to env vars
from when directories don't exist:
src/amplihack/hooks/launcher_detector.pybash
undefined在浏览之前,检测当前激活的工具以设置默认日志路径。优先使用基于目录的检测(比环境变量更可靠);当目录不存在时,回退使用中的环境变量:
src/amplihack/hooks/launcher_detector.pybash
undefinedPrimary: 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"
if [[ -d "$HOME/.copilot/session-state" ]]; then
检查是否存在会话
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
# 两个目录都存在但为空 — 使用环境变量决定
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)
回退:环境变量检测(与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
When both `~/.copilot/session-state/` and `~/.claude/projects/` exist with sessions,
offer the user a choice: "Found sessions for both Claude Code and GitHub Copilot CLI.
Which would you like to browse? [1] Claude Code [2] GitHub Copilot CLI"
The user can always override with an explicit path.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
注意:有意排除GITHUB_TOKEN — 它过于通用,会出现在非Copilot的CI环境中,导致误判。
TOOL_CONTEXT="copilot"
DEFAULT_LOG_DIR="$HOME/.copilot/session-state"
else
默认使用claude-code — 安全的回退选项(适用于大多数用户)
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"
用户始终可以通过指定明确路径来覆盖自动检测结果。Log Format Auto-Detection
日志格式自动检测
When given a file path, detect its format before processing:
bash
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
}| Format | Handler |
|---|---|
| Pass to |
| Display inline (already readable Markdown) |
| Display inline |
| Warn and display raw |
当提供文件路径时,先检测其格式再进行处理:
bash
detect_log_format() {
local file="$1"
if [[ "$file" == *.jsonl ]]; then
echo "jsonl"
elif [[ "$file" == *.md ]]; then
# 检查Copilot /share导出特征 — 仅匹配特定头部
# 注意:不要仅匹配"/share"(过于通用 — 会出现在文档、README中)
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文件可能是纯文本或Agent JSONL格式;检查内容
local first_char
first_char=$(head -c 1 "$file" 2>/dev/null)
if [[ "$first_char" == "{" ]]; then
echo "jsonl"
else
echo "plain-log"
fi
else
# 检查其他扩展名文件的第一个字节
local first_char
first_char=$(head -c 1 "$file" 2>/dev/null)
if [[ "$first_char" == "{" ]]; then
echo "jsonl"
else
echo "unknown"
fi
fi
}| 格式 | 处理方式 |
|---|---|
| 传递给 |
| 直接显示(已为可读的Markdown格式) |
| 直接显示 |
| 发出警告并显示原始内容 |
Tool Detection
工具检测
Before running any command, check whether is available:
claude-code-logbash
undefined在运行任何命令之前,检查是否可用:
claude-code-logbash
undefinedStep 1: direct install check
步骤1:直接检查是否安装
which claude-code-log 2>/dev/null
which claude-code-log 2>/dev/null
Step 2: npx fallback
步骤2:回退使用npx
npx --yes claude-code-log --version 2>/dev/null
Set `CCL` to the resolved command:
```bash
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=""
finpx --yes claude-code-log --version 2>/dev/null
将`CCL`设置为解析后的命令:
```bash
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=""
fiMissing Tool — Graceful Error
工具缺失 — 友好错误提示
If is empty, display this message and stop:
CCLclaude-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.Do not attempt to install it automatically.
如果为空,显示以下信息并停止:
CCLclaude-code-log未安装。
全局安装方式:
npm install -g claude-code-log
或无需安装直接运行(需要npx):
npx claude-code-log --help
安装完成后,请重试您的请求。不要尝试自动安装。
Modes
模式说明
Mode 1: Current Session
模式1:当前会话
Trigger phrases: "view current transcript", "show my current session", "current log"
What to do:
For Claude Code ():
TOOL_CONTEXT="claude-code"- Find the most recently modified JSONL file under :
~/.claude/projects/bashls -t ~/.claude/projects/*/*.jsonl 2>/dev/null | head -1 - Run:
bash
$CCL <path-to-jsonl> --format markdown - Display the Markdown output inline.
For GitHub Copilot CLI ():
TOOL_CONTEXT="copilot"- Find the most recently modified session directory under :
~/.copilot/session-state/bashls -dt ~/.copilot/session-state/*/ 2>/dev/null | head -1 - Read its :
events.jsonlbashLATEST_SESSION=$(ls -dt ~/.copilot/session-state/*/ 2>/dev/null | head -1) $CCL "${LATEST_SESSION}events.jsonl" --format markdown - Display the Markdown output inline.
Example output:
markdown
undefined触发短语:"view current transcript", "show my current session", "current log"
操作步骤:
对于Claude Code():
TOOL_CONTEXT="claude-code"- 查找下最近修改的JSONL文件:
~/.claude/projects/bashls -t ~/.claude/projects/*/*.jsonl 2>/dev/null | head -1 - 运行:
bash
$CCL <path-to-jsonl> --format markdown - 直接显示Markdown输出内容。
对于GitHub Copilot CLI():
TOOL_CONTEXT="copilot"- 查找下最近修改的会话目录:
~/.copilot/session-state/bashls -dt ~/.copilot/session-state/*/ 2>/dev/null | head -1 - 读取其文件:
events.jsonlbashLATEST_SESSION=$(ls -dt ~/.copilot/session-state/*/ 2>/dev/null | head -1) $CCL "${LATEST_SESSION}events.jsonl" --format markdown - 直接显示Markdown输出内容。
示例输出:
markdown
undefinedSession: 2025-11-23 19:32
会话: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...
...
undefined模型:claude-sonnet-4-6
消息数:42
用户:修复login.py中的认证漏洞
助手:我将检查该文件...
...
undefinedMode 2: Specific Session by ID
模式2:按ID查看特定会话
Trigger phrases: "view session <ID>", "show transcript <ID>", "open log <ID>"
What to do:
For Claude Code ():
TOOL_CONTEXT="claude-code"- Search for the JSONL file matching the session ID:
Or, if the ID looks like a filename fragment, use:bash
find ~/.claude/projects -name "*.jsonl" | xargs grep -l "<SESSION_ID>" 2>/dev/null | head -1bashls ~/.claude/projects/*/ | grep "<SESSION_ID>" - Run:
bash
$CCL <path-to-jsonl> --format markdown - Display the output. If no file matches, report:
No session found with ID: <SESSION_ID> Available sessions: run "view all sessions" to list them.
For GitHub Copilot CLI ():
TOOL_CONTEXT="copilot"- The session ID is the directory name under . Check directly:
~/.copilot/session-state/If the full ID is not known, search for a partial match:bashSESSION_DIR="$HOME/.copilot/session-state/<SESSION_ID>" if [[ -d "$SESSION_DIR" ]]; then EVENTS_FILE="$SESSION_DIR/events.jsonl" fibashls -d ~/.copilot/session-state/*/ 2>/dev/null | grep "<SESSION_ID>" - Run:
bash
$CCL "$EVENTS_FILE" --format markdown - Display the output. If no directory matches, report:
No Copilot session found with ID: <SESSION_ID> Available sessions: run "browse all sessions" to list them.
触发短语:"view session <ID>", "show transcript <ID>", "open log <ID>"
操作步骤:
对于Claude Code():
TOOL_CONTEXT="claude-code"- 搜索与会话ID匹配的JSONL文件:
或者,如果ID看起来像文件名的一部分,使用:bash
find ~/.claude/projects -name "*.jsonl" | xargs grep -l "<SESSION_ID>" 2>/dev/null | head -1bashls ~/.claude/projects/*/ | grep "<SESSION_ID>" - 运行:
bash
$CCL <path-to-jsonl> --format markdown - 显示输出内容。如果未找到匹配文件,提示:
未找到ID为<SESSION_ID>的会话。 可用会话:运行"view all sessions"查看列表。
对于GitHub Copilot CLI():
TOOL_CONTEXT="copilot"- 会话ID是下的目录名称。直接检查:
~/.copilot/session-state/如果不知道完整ID,搜索部分匹配项:bashSESSION_DIR="$HOME/.copilot/session-state/<SESSION_ID>" if [[ -d "$SESSION_DIR" ]]; then EVENTS_FILE="$SESSION_DIR/events.jsonl" fibashls -d ~/.copilot/session-state/*/ 2>/dev/null | grep "<SESSION_ID>" - 运行:
bash
$CCL "$EVENTS_FILE" --format markdown - 显示输出内容。如果未找到匹配目录,提示:
未找到ID为<SESSION_ID>的Copilot会话。 可用会话:运行"browse all sessions"查看列表。
Mode 3: Agent Background Task Output
模式3:Agent后台任务输出
Trigger phrases: "view agent output", "show background task output", "agent log"
What to do:
- Find or
.logfiles created by background agent tasks. These are typically written to the current working directory or a temp path with a name matching.jsonlor similar:.agent-step-*.logbashls -t .agent-step-*.log 2>/dev/null ls -t /tmp/*.agent*.log 2>/dev/null - For each file found, run to classify it:
detect_log_format <file>- → run
jsonl$CCL <file> --format markdown - → display directly with
plain-logcat
- This ensures JSONL-formatted files (rare but possible) are rendered properly.
.log - If no agent output files are found:
No agent background task output files found in the current directory. Background agents write their output to files named .agent-step-<ID>.log.
触发短语:"view agent output", "show background task output", "agent log"
操作步骤:
- 查找由后台Agent任务创建的或
.log文件。这些文件通常写入当前工作目录或临时路径,文件名类似.jsonl:.agent-step-*.logbashls -t .agent-step-*.log 2>/dev/null ls -t /tmp/*.agent*.log 2>/dev/null - 对每个找到的文件,运行进行分类:
detect_log_format <file>- → 运行
jsonl$CCL <file> --format markdown - → 使用
plain-log直接显示cat
- 这确保了JSONL格式的文件(虽然少见但可能存在)能正确渲染。
.log - 如果未找到Agent输出文件:
当前目录下未找到Agent后台任务输出文件。 后台Agent会将输出写入名为.agent-step-<ID>.log的文件。
Mode 4: All Sessions (Browse)
模式4:浏览所有会话
Trigger phrases: "browse all sessions", "list transcripts", "view all sessions",
"show session history"
What to do:
For Claude Code ():
TOOL_CONTEXT="claude-code"- List all JSONL files under :
~/.claude/projects/bashfind ~/.claude/projects -name "*.jsonl" -printf "%T@ %p\n" 2>/dev/null \ | sort -rn | awk '{print $2}' - For each file, extract the session date and first user message:
bash
$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',''))" - Print a summary table:
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 ... - Offer to open a specific session: "Enter a number to view that session."
For GitHub Copilot CLI ():
TOOL_CONTEXT="copilot"- List all session directories under sorted by modification time:
~/.copilot/session-state/bashls -dt ~/.copilot/session-state/*/ 2>/dev/null - For each session directory, read its to extract the timestamp:
events.jsonlbashfor 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 - Print a summary table:
Available Sessions (GitHub Copilot CLI) ======================================== # Date Session ID 1 2025-11-23 19:32:36 abc1234567890abcdef1234567890abcd 2 2025-11-22 14:10:05 def4567890abcdef1234567890abcdef ... - Offer to open a specific session: "Enter a number to view that session."
触发短语:"browse all sessions", "list transcripts", "view all sessions",
"show session history"
操作步骤:
对于Claude Code():
TOOL_CONTEXT="claude-code"- 列出下所有JSONL文件:
~/.claude/projects/bashfind ~/.claude/projects -name "*.jsonl" -printf "%T@ %p\n" 2>/dev/null \ | sort -rn | awk '{print $2}' - 对每个文件,提取会话日期和第一条用户消息:
bash
$CCL <file> --format markdown --summary # 如果不支持--summary标志,仅显示文件名和日期 head -1 <file> | python3 -c "import sys,json; d=json.loads(sys.stdin.read()); print(d.get('timestamp',''))" - 打印摘要表格:
可用会话(Claude Code) ================================= # 日期 会话ID / 文件 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/bashls -dt ~/.copilot/session-state/*/ 2>/dev/null - 对每个会话目录,读取其文件以提取时间戳:
events.jsonlbashfor 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 - 打印摘要表格:
可用会话(GitHub Copilot CLI) ======================================== # 日期 会话ID 1 2025-11-23 19:32:36 abc1234567890abcdef1234567890abcd 2 2025-11-22 14:10:05 def4567890abcdef1234567890abcdef ... - 提供打开特定会话的选项:"输入编号以查看对应会话。"
Date-Range Filtering
日期范围过滤
When the user specifies a date range (e.g., "last 7 days", "between 2025-11-01 and 2025-11-30"):
bash
undefined当用户指定日期范围时(例如:"最近7天"、"2025-11-01至2025-11-30之间"):
bash
undefinedFilter by modification time (last N days)
按修改时间过滤(最近N天)
find ~/.claude/projects -name "*.jsonl" -mtime -7
find ~/.claude/projects -name "*.jsonl" -mtime -7
Filter by date range using find -newer
使用find -newer按日期范围过滤
find ~/.claude/projects -name "*.jsonl"
-newer /tmp/start_date_ref
! -newer /tmp/end_date_ref
-newer /tmp/start_date_ref
! -newer /tmp/end_date_ref
Create the reference files with `touch -d`:
```bash
touch -d "2025-11-01" /tmp/start_date_ref
touch -d "2025-11-30" /tmp/end_date_reffind ~/.claude/projects -name "*.jsonl"
-newer /tmp/start_date_ref
! -newer /tmp/end_date_ref
-newer /tmp/start_date_ref
! -newer /tmp/end_date_ref
使用`touch -d`创建参考文件:
```bash
touch -d "2025-11-01" /tmp/start_date_ref
touch -d "2025-11-30" /tmp/end_date_refOutput Formats
输出格式
Markdown (default)
Markdown(默认)
Pass to . The output is printed inline in the
conversation. Best for quick reading in the terminal or Claude Code.
--format markdownclaude-code-log向传递参数。输出内容直接显示在对话中。最适合在终端或Claude Code中快速阅读。
claude-code-log--format markdownHTML
HTML
Pass to . Write the output to a file and open it:
--format htmlclaude-code-logbash
$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."The user can request HTML explicitly: "view transcript as HTML" or "export to HTML".
向传递参数。将输出写入文件并打开:
claude-code-log--format htmlbash
$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已保存至/tmp/transcript-view.html — 请在浏览器中打开。"用户可以明确请求HTML格式:"view transcript as HTML"或"export to HTML"。
GitHub Copilot CLI Support
GitHub Copilot CLI支持
Automatic Log Persistence
自动日志持久化
GitHub Copilot CLI automatically saves session data to disk at:
~/.copilot/session-state/{session-id}/Each session directory contains:
- — JSONL session history (similar format to Claude Code logs)
events.jsonl - — session metadata (working directory, session ID, etc.)
workspace.yaml - — implementation plan for the session
plan.md - — compaction history (older event snapshots)
checkpoints/
Legacy sessions may also exist at .
~/.copilot/history-session-state/GitHub Copilot CLI会自动将会话数据保存到磁盘,路径为:
~/.copilot/session-state/{session-id}/每个会话目录包含:
- — JSONL格式的会话历史(与Claude Code日志格式类似)
events.jsonl - — 会话元数据(工作目录、会话ID等)
workspace.yaml - — 会话的实现计划
plan.md - — 压缩历史(旧的事件快照)
checkpoints/
旧版会话可能存储在。
~/.copilot/history-session-state/JSONL Format
JSONL格式
Copilot contains one JSON object per line, similar to Claude Code format:
events.jsonljson
{"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-logCopilot的每行包含一个JSON对象,与Claude Code格式类似:
events.jsonljson
{"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-logViewing a Copilot Session
查看Copilot会话
When the user wants to view a Copilot session (by directory detection or explicit path):
- Locate the for the session:
events.jsonlbash# 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" - Run:
bash
$CCL "$EVENTS_FILE" --format markdown - Display the output inline.
当用户想要查看Copilot会话时(通过目录检测或明确路径):
- 定位会话的文件:
events.jsonlbash# 当前会话(最近的) LATEST_SESSION=$(ls -dt ~/.copilot/session-state/*/ 2>/dev/null | head -1) EVENTS_FILE="${LATEST_SESSION}events.jsonl" # 按ID查看特定会话 EVENTS_FILE="$HOME/.copilot/session-state/<SESSION_ID>/events.jsonl" - 运行:
bash
$CCL "$EVENTS_FILE" --format markdown - 直接显示输出内容。
Detecting Available Sessions
检测可用会话
To check if Copilot sessions exist:
bash
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检查是否存在Copilot会话:
bash
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 "找到$SESSION_COUNT个Copilot会话"
fi
fiFull Workflow
完整工作流程
When the user invokes this skill, follow this decision tree:
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.当用户调用本Skill时,遵循以下决策树:
0. 检测工具上下文(优先基于目录,然后回退到环境变量):
- ~/.copilot/session-state/存在会话 → copilot
- ~/.claude/projects/存在会话 → claude-code
- 两者都存在会话 → 让用户选择
- 目录检测失败,使用环境变量:
- 设置了CLAUDE_CODE_SESSION / CLAUDE_SESSION_ID / ANTHROPIC_API_KEY → claude-code
- 设置了GITHUB_COPILOT_TOKEN / COPILOT_SESSION → copilot
- 都不满足 → 默认使用claude-code(安全回退)
1. 检测CCL(which claude-code-log / npx回退)
→ 如果缺失:显示安装说明并停止
→ 所有模式都需要(Claude Code和Copilot都使用JSONL格式)
2. 如果用户提供明确的文件路径:
a. 检测其格式(使用上述detect_log_format函数)
b. jsonl或events.jsonl → 传递给$CCL
c. unknown → 发出警告并显示原始内容
3. 根据用户消息确定模式:
- 提到"current"或未指定会话 → 模式1(当前会话)
- 提到会话ID或哈希值 → 模式2(特定会话)
- 提到"agent"或"background" → 模式3(Agent输出)
- 提到"all", "browse", "list" → 模式4(所有会话)
4. 确定输出格式:
- "as HTML"或"export HTML" → html
- 默认 → markdown
5. 执行相应模式(使用TOOL_CONTEXT选择正确路径)并显示结果。Error Handling
错误处理
| Situation | Response |
|---|---|
| Show install instructions, stop |
| JSONL file not found | "No session file found at <path>" |
| Session ID not found | "No session with ID <ID>. Run 'browse all sessions' to list available ones." |
| No agent output files | "No agent background task output found in current directory." |
| Empty JSONL file | "Session file is empty — no messages to display." |
| Date range produces no results | "No sessions found between <start> and <end>." |
| Display stderr and suggest |
| "No Copilot sessions found. Start a session with GitHub Copilot CLI to create logs." |
| Copilot session dir exists but no events.jsonl | "Session directory found but events.jsonl is missing at <path>" |
| Unknown file format | Warn user and display raw content |
| 场景 | 响应 |
|---|---|
| 显示安装说明,停止 |
| JSONL文件未找到 | "未在<path>找到会话文件" |
| 会话ID未找到 | "未找到ID为<ID>的会话。运行'browse all sessions'查看可用列表。" |
| 无Agent输出文件 | "当前目录下未找到Agent后台任务输出。" |
| JSONL文件为空 | "会话文件为空 — 无消息可显示。" |
| 日期范围无结果 | "在<start>至<end>之间未找到会话。" |
| 显示stderr并建议使用 |
| "未找到Copilot会话。请使用GitHub Copilot CLI启动会话以创建日志。" |
| Copilot会话目录存在但无events.jsonl | "找到会话目录但<path>下缺失events.jsonl" |
| 未知文件格式 | 向用户发出警告并显示原始内容 |
Implementation Notes
实现说明
Detecting Session IDs
检测会话ID
Claude Code session IDs are UUID-like strings. If the user writes something like
"view session abc123" or "show log def456", treat the last word as the session ID
and search for matching JSONL filenames.
Claude Code的会话ID是类似UUID的字符串。如果用户输入类似"view session abc123"或"show log def456"的内容,将最后一个单词视为会话ID,并搜索匹配的JSONL文件名。
JSONL Structure (Claude Code)
JSONL结构(Claude Code)
Claude Code session JSONL files contain one JSON object per line:
json
{"type":"user","message":{"role":"user","content":[{"type":"text","text":"..."}]},"timestamp":"...","sessionId":"..."}
{"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"..."}]},"timestamp":"..."}claude-code-logClaude Code的会话JSONL文件每行包含一个JSON对象:
json
{"type":"user","message":{"role":"user","content":[{"type":"text","text":"..."}]},"timestamp":"...","sessionId":"..."}
{"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"..."}]},"timestamp":"..."}claude-code-logCopilot JSONL Structure (GitHub Copilot CLI)
Copilot JSONL结构(GitHub Copilot CLI)
Copilot CLI files contain one JSON object per line, stored at
:
events.jsonl~/.copilot/session-state/{session-id}/events.jsonljson
{"type":"user","message":{"role":"user","content":[{"type":"text","text":"..."}]},"timestamp":"...","sessionId":"..."}
{"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"..."}]},"timestamp":"...","sessionId":"..."}The format is compatible with . Additional per-session files:
claude-code-log- — session metadata
workspace.yaml - — implementation plan
plan.md - — compaction history (older snapshots)
checkpoints/
Legacy sessions may be stored at with the same structure.
~/.copilot/history-session-state/Copilot CLI的文件每行包含一个JSON对象,存储在:
events.jsonl~/.copilot/session-state/{session-id}/events.jsonljson
{"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会话存储在,结构相同。
~/.copilot/history-session-state/Philosophy Alignment
设计理念
- Thin wrapper: Delegates to for all JSONL (both Claude Code and Copilot)
claude-code-log - Graceful degradation: Clear error messages when tool is missing or no sessions found
- Single responsibility: Only views/converts transcripts, never modifies them
- No hidden state: All file paths are shown to the user
- 轻量级封装:所有JSONL解析(Claude Code和Copilot)都委托给
claude-code-log - 优雅降级:当工具缺失或无会话时显示清晰的错误消息
- 单一职责:仅查看/转换会话记录,绝不修改
- 无隐藏状态:所有文件路径都向用户显示
Limitations
局限性
- Requires (npm) or
claude-code-logto convert JSONL (both Claude Code and Copilot) to HTML/Markdownnpx - Cannot view transcripts from remote machines
- Date filtering relies on filesystem modification times, not session timestamps
- flag availability depends on
--summaryversionclaude-code-log - Legacy Copilot sessions in are not auto-discovered (must use explicit path)
~/.copilot/history-session-state/ - When both Claude Code and Copilot sessions exist, the skill prompts the user to choose rather than merging them
- 需要(npm包)或
claude-code-log来将JSONL(Claude Code和Copilot)转换为HTML/Markdownnpx - 无法查看远程机器上的会话记录
- 日期过滤依赖文件系统修改时间,而非会话时间戳
- 标志的可用性取决于
--summary的版本claude-code-log - 中的旧版Copilot会话不会被自动发现(必须使用明确路径)
~/.copilot/history-session-state/ - 当Claude Code和Copilot会话同时存在时,Skill会提示用户选择,而非合并显示
Quick Reference
快速参考
| User says | Tool | Mode | Command |
|---|---|---|---|
| "view current transcript" | Claude Code | Current session | |
| "show session abc123" | Claude Code | Specific session | |
| "view agent output" | Claude Code | Agent output | |
| "browse all sessions" | Claude Code | All sessions | list + summarize all |
| "view transcript as HTML" | Claude Code | Any + HTML | |
| "last 7 days" (with browse) | Claude Code | Date filter | |
| "view current copilot session" | Copilot | Current session | |
| "show copilot session abc123" | Copilot | Specific session | |
| "browse copilot sessions" | Copilot | All sessions | list dirs in |
| "view copilot session as HTML" | Copilot | Any + HTML | |
| 用户输入 | 工具 | 模式 | 命令 |
|---|---|---|---|
| "view current transcript" | Claude Code | 当前会话 | |
| "show session abc123" | Claude Code | 特定会话 | |
| "view agent output" | Claude Code | Agent输出 | |
| "browse all sessions" | Claude Code | 所有会话 | 列出并汇总所有 |
| "view transcript as HTML" | Claude Code | 任意模式+HTML | |
| "last 7 days"(搭配browse) | Claude Code | 日期过滤 | |
| "view current copilot session" | Copilot | 当前会话 | |
| "show copilot session abc123" | Copilot | 特定会话 | |
| "browse copilot sessions" | Copilot | 所有会话 | 列出 |
| "view copilot session as HTML" | Copilot | 任意模式+HTML | |