Copyright (C) 2025 Brian Hetro whee@smaertness.net
Convert GitHub Copilot chat exports to Markdown.
- Converts GitHub Copilot chat exports (single files or whole directories) to Markdown
- Shows model, agent, and attached context by default
- Optional inclusion of tool invocations and timestamps
- Recurses through directories, processes only JSON exports, and sorts/deduplicates inputs for deterministic output
- CLI-friendly:
cp2md [OPTIONS] -o <OUTPUT> <INPUT>...
Download a prebuilt binary from GitHub Releases, or build from source:
cargo build --release
./target/release/cp2md --helpcp2md [OPTIONS] -o <OUTPUT> <INPUT>...<INPUT>...- Input JSON files or directories containing exports
-o, --output <OUTPUT>- Output directory (or file with--concat, or-for stdout)--concat- Combine all inputs into a single output--heading-offset <N>- Shift heading levels by N (0-5, default: 0)
Notes:
- Without
--concat,-omust point to a directory (or-for stdout) and stdout is only allowed when converting a single input file. - With
--concat,-ois treated as a single output file (or-for stdout) and is required to combine multiple inputs.
Use --show-* or --hide-* flags to control what appears in output:
| Flag | Default | Description |
|---|---|---|
--show-timestamps / --hide-timestamps |
off | Timestamps for each message |
--show-model / --hide-model |
on | Model identifier (e.g., claude-sonnet-4) |
--show-agent / --hide-agent |
on | VS Code agent name (e.g., @workspace) |
--show-context / --hide-context |
on | Attached files, selections, folders, and instruction files |
--show-tools / --hide-tools |
off | Tool invocations (searches, reads) |
--show-edits / --hide-edits |
off | Full code content for file edits |
-v, --verbose is an alias for --show-tools.
--compact hides all metadata (model, agent, context, tools, timestamps).
If you pass both show/hide forms for the same field, the last flag wins.
When timestamps are enabled (--show-timestamps):
| Flag | Description |
|---|---|
--utc-time |
Render in UTC (default) |
--local-time |
Render in local timezone |
--timestamps-both |
Render as <local> / <utc> |
-q, --quiet- Suppress progress messages-n, --dry-run- Show what would be processed without writing-f, --force- Overwrite existing output files-h, --help- Print help-V, --version- Print version
Convert a single chat export:
cp2md chat.json -o output/Convert all JSON files in a directory:
cp2md ~/copilot-exports/ -o markdown/Include tool invocations (searches, file reads, etc.):
cp2md chat.json -o output/ --verboseMinimal output (just messages):
cp2md chat.json -o - --hide-model --hide-agent --hide-contextPreview what would be converted without writing:
cp2md ~/copilot-exports/ -o markdown/ --dry-runCombine multiple chats into a single file:
cp2md chat1.json chat2.json -o combined.md --concatOutput to stdout (useful for piping):
cp2md chat.json -o - | lessExport chat history using the VS Code command palette: Copilot: Export Chat...
Each input file foo.json produces foo.md in the output directory. The Markdown includes:
- Model identifier and agent name in the metadata line (shown by default when present and not hidden)
- Attached context in a collapsible details block (files, selections, folders, instruction files) when present and not hidden
- User prompts and assistant responses
- Timestamps (when
--show-timestampsis set) - Tool invocations with past-tense messages (when
--show-tools/--verboseis set) - File modification summaries for edits (with line counts) when a text edit group is present
Headings in user/assistant content are shifted down to prevent them from disrupting document structure. XML-like tags are escaped to render literally.
Example output:
# Copilot Chat
## User
*claude-sonnet-4 · @workspace*
<details>
<summary>📎 Context</summary>
- `main.rs` (file)
- `lib.rs`:10-25 (selection)
</details>
How do I reverse a string in Python?
## Assistant
You can reverse a string using slicing: `[::-1]`This program is free software: you can redistribute it and/or modify it under the terms of version 3 of the GNU General Public License as published by the Free Software Foundation.
See LICENSE for the full text.