transcript-viewer

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Transcript 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:
  1. Current session — View the active session's transcript
  2. Specific session — View a session by its ID
  3. Agent output — View background task output files produced by subagents
  4. 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
它提供四种浏览模式:
  1. 当前会话 — 查看活跃会话的记录
  2. 特定会话 — 通过ID查看指定会话
  3. Agent输出 — 查看子Agent生成的后台任务输出文件
  4. 所有会话 — 浏览所有项目会话,支持可选的日期范围过滤

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
src/amplihack/hooks/launcher_detector.py
when directories don't exist:
bash
undefined
在浏览之前,检测当前激活的工具以设置默认日志路径。优先使用基于目录的检测(比环境变量更可靠);当目录不存在时,回退使用
src/amplihack/hooks/launcher_detector.py
中的环境变量:
bash
undefined

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"
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
}
FormatHandler
jsonl
Pass to
claude-code-log
copilot-markdown
Display inline (already readable Markdown)
markdown
Display inline
unknown
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
}
格式处理方式
jsonl
传递给
claude-code-log
copilot-markdown
直接显示(已为可读的Markdown格式)
markdown
直接显示
unknown
发出警告并显示原始内容

Tool Detection

工具检测

Before running any command, check whether
claude-code-log
is available:
bash
undefined
在运行任何命令之前,检查
claude-code-log
是否可用:
bash
undefined

Step 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=""
fi
npx --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=""
fi

Missing Tool — Graceful Error

工具缺失 — 友好错误提示

If
CCL
is empty, display this message and stop:
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.
Do not attempt to install it automatically.
如果
CCL
为空,显示以下信息并停止:
claude-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"
):
  1. Find the most recently modified JSONL file under
    ~/.claude/projects/
    :
    bash
    ls -t ~/.claude/projects/*/*.jsonl 2>/dev/null | head -1
  2. Run:
    bash
    $CCL <path-to-jsonl> --format markdown
  3. Display the Markdown output inline.
For GitHub Copilot CLI (
TOOL_CONTEXT="copilot"
):
  1. Find the most recently modified session directory under
    ~/.copilot/session-state/
    :
    bash
    ls -dt ~/.copilot/session-state/*/ 2>/dev/null | head -1
  2. Read its
    events.jsonl
    :
    bash
    LATEST_SESSION=$(ls -dt ~/.copilot/session-state/*/ 2>/dev/null | head -1)
    $CCL "${LATEST_SESSION}events.jsonl" --format markdown
  3. Display the Markdown output inline.
Example output:
markdown
undefined
触发短语:"view current transcript", "show my current session", "current log"
操作步骤
对于Claude Code
TOOL_CONTEXT="claude-code"
):
  1. 查找
    ~/.claude/projects/
    下最近修改的JSONL文件:
    bash
    ls -t ~/.claude/projects/*/*.jsonl 2>/dev/null | head -1
  2. 运行:
    bash
    $CCL <path-to-jsonl> --format markdown
  3. 直接显示Markdown输出内容。
对于GitHub Copilot CLI
TOOL_CONTEXT="copilot"
):
  1. 查找
    ~/.copilot/session-state/
    下最近修改的会话目录:
    bash
    ls -dt ~/.copilot/session-state/*/ 2>/dev/null | head -1
  2. 读取其
    events.jsonl
    文件:
    bash
    LATEST_SESSION=$(ls -dt ~/.copilot/session-state/*/ 2>/dev/null | head -1)
    $CCL "${LATEST_SESSION}events.jsonl" --format markdown
  3. 直接显示Markdown输出内容。
示例输出
markdown
undefined

Session: 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中的认证漏洞 助手:我将检查该文件... ...
undefined

Mode 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"
):
  1. Search for the JSONL file matching the session ID:
    bash
    find ~/.claude/projects -name "*.jsonl" | xargs grep -l "<SESSION_ID>" 2>/dev/null | head -1
    Or, if the ID looks like a filename fragment, use:
    bash
    ls ~/.claude/projects/*/ | grep "<SESSION_ID>"
  2. Run:
    bash
    $CCL <path-to-jsonl> --format markdown
  3. 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"
):
  1. The session ID is the directory name under
    ~/.copilot/session-state/
    . Check directly:
    bash
    SESSION_DIR="$HOME/.copilot/session-state/<SESSION_ID>"
    if [[ -d "$SESSION_DIR" ]]; then
      EVENTS_FILE="$SESSION_DIR/events.jsonl"
    fi
    If the full ID is not known, search for a partial match:
    bash
    ls -d ~/.copilot/session-state/*/ 2>/dev/null | grep "<SESSION_ID>"
  2. Run:
    bash
    $CCL "$EVENTS_FILE" --format markdown
  3. 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"
):
  1. 搜索与会话ID匹配的JSONL文件:
    bash
    find ~/.claude/projects -name "*.jsonl" | xargs grep -l "<SESSION_ID>" 2>/dev/null | head -1
    或者,如果ID看起来像文件名的一部分,使用:
    bash
    ls ~/.claude/projects/*/ | grep "<SESSION_ID>"
  2. 运行:
    bash
    $CCL <path-to-jsonl> --format markdown
  3. 显示输出内容。如果未找到匹配文件,提示:
    未找到ID为<SESSION_ID>的会话。
    可用会话:运行"view all sessions"查看列表。
对于GitHub Copilot CLI
TOOL_CONTEXT="copilot"
):
  1. 会话ID是
    ~/.copilot/session-state/
    下的目录名称。直接检查:
    bash
    SESSION_DIR="$HOME/.copilot/session-state/<SESSION_ID>"
    if [[ -d "$SESSION_DIR" ]]; then
      EVENTS_FILE="$SESSION_DIR/events.jsonl"
    fi
    如果不知道完整ID,搜索部分匹配项:
    bash
    ls -d ~/.copilot/session-state/*/ 2>/dev/null | grep "<SESSION_ID>"
  2. 运行:
    bash
    $CCL "$EVENTS_FILE" --format markdown
  3. 显示输出内容。如果未找到匹配目录,提示:
    未找到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:
  1. Find
    .log
    or
    .jsonl
    files created by background agent tasks. These are typically written to the current working directory or a temp path with a name matching
    .agent-step-*.log
    or similar:
    bash
    ls -t .agent-step-*.log 2>/dev/null
    ls -t /tmp/*.agent*.log 2>/dev/null
  2. For each file found, run
    detect_log_format <file>
    to classify it:
    • jsonl
      → run
      $CCL <file> --format markdown
    • plain-log
      → display directly with
      cat
  3. This ensures JSONL-formatted
    .log
    files (rare but possible) are rendered properly.
  4. 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"
操作步骤
  1. 查找由后台Agent任务创建的
    .log
    .jsonl
    文件。这些文件通常写入当前工作目录或临时路径,文件名类似
    .agent-step-*.log
    bash
    ls -t .agent-step-*.log 2>/dev/null
    ls -t /tmp/*.agent*.log 2>/dev/null
  2. 对每个找到的文件,运行
    detect_log_format <file>
    进行分类:
    • jsonl
      → 运行
      $CCL <file> --format markdown
    • plain-log
      → 使用
      cat
      直接显示
  3. 这确保了JSONL格式的
    .log
    文件(虽然少见但可能存在)能正确渲染。
  4. 如果未找到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"
):
  1. List all JSONL files under
    ~/.claude/projects/
    :
    bash
    find ~/.claude/projects -name "*.jsonl" -printf "%T@ %p\n" 2>/dev/null \
      | sort -rn | awk '{print $2}'
  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',''))"
  3. 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
    ...
  4. Offer to open a specific session: "Enter a number to view that session."
For GitHub Copilot CLI (
TOOL_CONTEXT="copilot"
):
  1. List all session directories under
    ~/.copilot/session-state/
    sorted by modification time:
    bash
    ls -dt ~/.copilot/session-state/*/ 2>/dev/null
  2. For each session directory, read its
    events.jsonl
    to extract the timestamp:
    bash
    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
  3. 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
    ...
  4. 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"
):
  1. 列出
    ~/.claude/projects/
    下所有JSONL文件:
    bash
    find ~/.claude/projects -name "*.jsonl" -printf "%T@ %p\n" 2>/dev/null \
      | sort -rn | awk '{print $2}'
  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',''))"
  3. 打印摘要表格:
    可用会话(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
    ...
  4. 提供打开特定会话的选项:"输入编号以查看对应会话。"
对于GitHub Copilot CLI
TOOL_CONTEXT="copilot"
):
  1. 列出
    ~/.copilot/session-state/
    下所有会话目录,按修改时间排序:
    bash
    ls -dt ~/.copilot/session-state/*/ 2>/dev/null
  2. 对每个会话目录,读取其
    events.jsonl
    文件以提取时间戳:
    bash
    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
  3. 打印摘要表格:
    可用会话(GitHub Copilot CLI)
    ========================================
    #   日期                  会话ID
    1   2025-11-23 19:32:36   abc1234567890abcdef1234567890abcd
    2   2025-11-22 14:10:05   def4567890abcdef1234567890abcdef
    ...
  4. 提供打开特定会话的选项:"输入编号以查看对应会话。"

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
undefined

Filter 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

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_ref
find ~/.claude/projects -name "*.jsonl"
-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_ref

Output Formats

输出格式

Markdown (default)

Markdown(默认)

Pass
--format markdown
to
claude-code-log
. The output is printed inline in the conversation. Best for quick reading in the terminal or Claude Code.
claude-code-log
传递
--format markdown
参数。输出内容直接显示在对话中。最适合在终端或Claude Code中快速阅读。

HTML

HTML

Pass
--format html
to
claude-code-log
. Write the output to a file and open it:
bash
$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 html
参数。将输出写入文件并打开:
bash
$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:
  • events.jsonl
    — JSONL session history (similar format to Claude Code logs)
  • workspace.yaml
    — session metadata (working directory, session ID, etc.)
  • plan.md
    — implementation plan for the session
  • checkpoints/
    — compaction history (older event snapshots)
Legacy sessions may also exist at
~/.copilot/history-session-state/
.
GitHub Copilot CLI会自动将会话数据保存到磁盘,路径为:
~/.copilot/session-state/{session-id}/
每个会话目录包含:
  • events.jsonl
    — JSONL格式的会话历史(与Claude Code日志格式类似)
  • workspace.yaml
    — 会话元数据(工作目录、会话ID等)
  • plan.md
    — 会话的实现计划
  • checkpoints/
    — 压缩历史(旧的事件快照)
旧版会话可能存储在
~/.copilot/history-session-state/

JSONL Format

JSONL格式

Copilot
events.jsonl
contains one JSON object per line, similar to Claude Code format:
json
{"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
handles parsing these files since the format is compatible.
Copilot的
events.jsonl
每行包含一个JSON对象,与Claude Code格式类似:
json
{"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
可以解析这些文件,因为格式兼容。

Viewing a Copilot Session

查看Copilot会话

When the user wants to view a Copilot session (by directory detection or explicit path):
  1. Locate the
    events.jsonl
    for the session:
    bash
    # 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"
  2. Run:
    bash
    $CCL "$EVENTS_FILE" --format markdown
  3. Display the output inline.
当用户想要查看Copilot会话时(通过目录检测或明确路径):
  1. 定位会话的
    events.jsonl
    文件:
    bash
    # 当前会话(最近的)
    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"
  2. 运行:
    bash
    $CCL "$EVENTS_FILE" --format markdown
  3. 直接显示输出内容。

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
fi

Full 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

错误处理

SituationResponse
claude-code-log
not installed
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>."
claude-code-log
returns non-zero exit
Display stderr and suggest
--help
~/.copilot/session-state/
exists but empty
"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 formatWarn user and display raw content
场景响应
claude-code-log
未安装
显示安装说明,停止
JSONL文件未找到"未在<path>找到会话文件"
会话ID未找到"未找到ID为<ID>的会话。运行'browse all sessions'查看可用列表。"
无Agent输出文件"当前目录下未找到Agent后台任务输出。"
JSONL文件为空"会话文件为空 — 无消息可显示。"
日期范围无结果"在<start><end>之间未找到会话。"
claude-code-log
返回非零退出码
显示stderr并建议使用
--help
~/.copilot/session-state/
存在但为空
"未找到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-log
handles parsing; this skill does not re-implement it.
Claude 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-log
负责解析;本Skill不重复实现解析逻辑。

Copilot JSONL Structure (GitHub Copilot CLI)

Copilot JSONL结构(GitHub Copilot CLI)

Copilot CLI
events.jsonl
files contain one JSON object per line, stored at
~/.copilot/session-state/{session-id}/events.jsonl
:
json
{"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
claude-code-log
. Additional per-session files:
  • workspace.yaml
    — session metadata
  • plan.md
    — implementation plan
  • checkpoints/
    — compaction history (older snapshots)
Legacy sessions may be stored at
~/.copilot/history-session-state/
with the same structure.
Copilot CLI的
events.jsonl
文件每行包含一个JSON对象,存储在
~/.copilot/session-state/{session-id}/events.jsonl
json
{"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
    claude-code-log
    for all JSONL (both Claude Code and Copilot)
  • 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
    claude-code-log
    (npm) or
    npx
    to convert JSONL (both Claude Code and Copilot) to HTML/Markdown
  • Cannot view transcripts from remote machines
  • Date filtering relies on filesystem modification times, not session timestamps
  • --summary
    flag availability depends on
    claude-code-log
    version
  • Legacy Copilot sessions in
    ~/.copilot/history-session-state/
    are not auto-discovered (must use explicit path)
  • When both Claude Code and Copilot sessions exist, the skill prompts the user to choose rather than merging them
  • 需要
    claude-code-log
    (npm包)或
    npx
    来将JSONL(Claude Code和Copilot)转换为HTML/Markdown
  • 无法查看远程机器上的会话记录
  • 日期过滤依赖文件系统修改时间,而非会话时间戳
  • --summary
    标志的可用性取决于
    claude-code-log
    的版本
  • ~/.copilot/history-session-state/
    中的旧版Copilot会话不会被自动发现(必须使用明确路径)
  • 当Claude Code和Copilot会话同时存在时,Skill会提示用户选择,而非合并显示

Quick Reference

快速参考

User saysToolModeCommand
"view current transcript"Claude CodeCurrent session
$CCL <latest.jsonl> --format markdown
"show session abc123"Claude CodeSpecific session
$CCL ~/.claude/projects/**/*abc123*.jsonl --format markdown
"view agent output"Claude CodeAgent output
cat .agent-step-*.log
or
$CCL *.jsonl
"browse all sessions"Claude CodeAll sessionslist + summarize all
~/.claude/projects/**/*.jsonl
"view transcript as HTML"Claude CodeAny + HTML
$CCL <file> --format html > /tmp/view.html
"last 7 days" (with browse)Claude CodeDate filter
find ... -mtime -7
"view current copilot session"CopilotCurrent session
$CCL ~/.copilot/session-state/<latest>/events.jsonl --format markdown
"show copilot session abc123"CopilotSpecific session
$CCL ~/.copilot/session-state/abc123/events.jsonl --format markdown
"browse copilot sessions"CopilotAll sessionslist dirs in
~/.copilot/session-state/
, show session IDs
"view copilot session as HTML"CopilotAny + HTML
$CCL <events.jsonl> --format html > /tmp/view.html
用户输入工具模式命令
"view current transcript"Claude Code当前会话
$CCL <latest.jsonl> --format markdown
"show session abc123"Claude Code特定会话
$CCL ~/.claude/projects/**/*abc123*.jsonl --format markdown
"view agent output"Claude CodeAgent输出
cat .agent-step-*.log
$CCL *.jsonl
"browse all sessions"Claude Code所有会话列出并汇总所有
~/.claude/projects/**/*.jsonl
"view transcript as HTML"Claude Code任意模式+HTML
$CCL <file> --format html > /tmp/view.html
"last 7 days"(搭配browse)Claude Code日期过滤
find ... -mtime -7
"view current copilot session"Copilot当前会话
$CCL ~/.copilot/session-state/<latest>/events.jsonl --format markdown
"show copilot session abc123"Copilot特定会话
$CCL ~/.copilot/session-state/abc123/events.jsonl --format markdown
"browse copilot sessions"Copilot所有会话列出
~/.copilot/session-state/
下的目录,显示会话ID
"view copilot session as HTML"Copilot任意模式+HTML
$CCL <events.jsonl> --format html > /tmp/view.html