Local-first ChatGPT, Claude, and DeepSeek conversation export viewer and converter.
Conversation Export Workbench turns exported AI chat histories from OpenAI ChatGPT, Anthropic Claude, and DeepSeek into readable HTML, Markdown, or normalized JSON. It can also build a searchable local single-page workbench for browsing conversations across providers.
The runtime is Python-standard-library only. Conversion happens on your machine: the tool reads local export files and writes local output; it does not require a hosted backend or an API key.
Start here: Installers · Quick start · CLI binaries · Latest release
| Provider | Input | Auto-detect | HTML | Markdown | Normalized JSON |
|---|---|---|---|---|---|
| ChatGPT / OpenAI | official conversation export JSON or ZIP containing conversations.json |
Yes | Yes | Yes | Yes |
| Claude / Anthropic | conversation export JSON or ZIP containing conversations.json |
Yes | Yes | Yes | Yes |
| DeepSeek | conversation export JSON or ZIP containing conversations.json |
Yes | Yes | Yes | Yes |
Provider detection is structural and template-based. If an export does not match a known provider signature, the CLI asks you to choose a provider instead of silently guessing.
- One workbench for three AI chat providers — browse ChatGPT, Claude, and DeepSeek histories with the same local tooling.
- Local-first processing — no account credentials, API keys, telemetry service, or remote conversion backend required.
- Readable exports — produce styled HTML, portable Markdown, or a provider-neutral JSON representation.
- Searchable conversation viewer — generate a single-page browser with provider filters, full-text search, sorting, jump navigation, and scroll memory.
- Reasoning-aware rendering — preserve DeepSeek THINK fragments and Claude thinking blocks as collapsible sections.
- DeepSeek search rendering — render SEARCH fragments with titles, URLs, and snippets.
- Zero runtime package dependencies — source mode uses Python 3.11+ standard library only.
- Portable
.cewarchives — CEW v2 adds canonical conversations, deterministic search, source provenance, duplicate-aware merge/history, and optional verified attachment payloads. - True offline viewer — the generated SPA no longer loads Tailwind or other runtime resources from a CDN.
- Pre-built executables — release binaries are published for Linux, macOS, and Windows with SHA-256 checksums and release provenance attestations.
- Offline Android/iOS/PWA client — imports
.cewplus raw ChatGPT, Claude, and DeepSeek ZIP/JSON exports, with local search, themes, app lock, statistics, and safe attachment sharing. - Extensible provider model — detection templates and provider-specific formatter modules are separated cleanly.
The v0.3 release pipeline produces Windows Setup EXE, macOS PKG, Linux DEB, Android APK/AAB when release signing is configured (otherwise a sideload APK), portable desktop binaries, and an iOS Simulator artifact. A signed iOS IPA/TestFlight upload is produced when Apple signing credentials are configured.
See INSTALL.md for platform-specific installation instructions.
Download the current release from the Releases page. Asset names are versioned:
| Platform | Release asset pattern |
|---|---|
| Linux x86_64 | conv-tool-vX.Y.Z-linux |
| macOS | conv-tool-vX.Y.Z-macos |
| Windows | conv-tool-vX.Y.Z-windows.exe |
The binary has four subcommands:
conv-tool format # convert an export
conv-tool generate-spa # build output/index.html + search-index.json
conv-tool serve # serve the local viewer
conv-tool bundle # build or inspect a portable .cew archive
See BINARY_USAGE.md for examples and checksum verification.
git clone https://github.com/ngallodev-software/conversation-export-workbench.git
cd conversation-export-workbench
python3 format_conversations.py --input /path/to/export.zip --format html --yes
python3 generate_spa.py --output output --yes
python3 serve_spa.pyRequirements: Python 3.11 or newer. No pip install is required for runtime use.
# List conversations from an export
python3 format_conversations.py --input ~/Downloads/export.zip --list
# Convert everything to HTML
python3 format_conversations.py --input ~/Downloads/export.zip --format html --yes
# Convert to Markdown
python3 format_conversations.py --input ~/Downloads/export.zip --format md --yes
# Export one conversation by provider ID
python3 format_conversations.py --input conversations.json --id <conversation-id>
# Force a provider only when detection is ambiguous
python3 format_conversations.py --input conversations.json --provider claude --format html
# Combine all conversations into one HTML document
python3 format_conversations.py --input conversations.json --format html --combined --yesRun python3 format_conversations.py with no arguments in a terminal for guided discovery of ZIP and JSON files in the current directory.
Create a provider-neutral offline archive for transfer between desktop and mobile:
python3 bundle_conversations.py --input ~/Downloads/export.zip --output my-chats.cew
python3 bundle_conversations.py --input ~/Downloads/export.zip --attachments-dir ~/Downloads/export-files --output with-files.cew
python3 bundle_conversations.py --merge archive-a.cew archive-b.cew --output merged.cew
python3 bundle_conversations.py --input merged.cew --inspectCEW v2 contains canonical cew.conversation/v1 records, deterministic search data, a canonical-payload bundle ID, source SHA-256 provenance, merge history, duplicate resolution metadata, and optional attachment payloads. CEW v1 remains readable.
After generating HTML files:
python3 generate_spa.py --output output --yes
python3 serve_spa.py --output outputThe generated viewer includes:
- provider filtering for ChatGPT, Claude, DeepSeek, or all conversations;
- corpus-wide full-text search, including conversations not yet opened in the browser;
- newest/oldest and alphabetical sorting;
- jump navigation across user turns and assistant headings;
- timestamp visibility controls;
- per-conversation visibility controls;
- scroll-position memory;
- lazy loading and in-memory caching;
- collapsible reasoning/thinking sections;
- provider-specific visual accents.
The viewer is intentionally served over local HTTP because its conversation pages and search index are loaded with browser fetch(). By default the server binds only to loopback; non-loopback serving requires the explicit --allow-network flag.
One styled HTML document per conversation, or a combined document. Provider-specific structures such as thinking blocks and DeepSeek search results are retained in readable form.
Portable text suitable for source control, note systems, search/indexing pipelines, or downstream processing.
Provider-specific exports are converted into the versioned cew.conversation/v1 shape:
{
"schema_version": "cew.conversation/v1",
"provider": "chatgpt",
"id": "...",
"title": "...",
"started_at": "...",
"updated_at": "...",
"messages": [
{
"role": "user",
"timestamp": "...",
"parts": [
{ "type": "text", "content": "..." }
]
}
]
}This is useful when ChatGPT, Claude, and DeepSeek history need to feed the same downstream tooling.
The mobile/ directory contains a Capacitor 8 client and installable PWA. It imports CEW v1/v2 or raw ChatGPT, Claude, and DeepSeek ZIP/JSON exports, normalizes them on-device, stores the archive inside the app sandbox, and searches locally. It includes an optional PIN app lock, system/light/dark themes, archive statistics, verified attachment Share / Save, and no hosted backend.
Android release signing and iOS IPA/TestFlight publication are wired through repository secrets without storing credentials in source. See mobile/README.md.
Detection templates live in provider_templates/. Each describes structural keys that must or must not exist in a provider's conversation objects. Formatter code lives in formatters/.
To add another provider:
- add a
provider_templates/<provider>.conversations-template.jsonsignature; - add a formatter module implementing the provider adapter functions;
- register the formatter in
format_conversations.py; - add sample data and regression coverage.
This keeps provider recognition separate from rendering and prevents heuristic guessing from being mixed into formatter logic.
conversation-export-workbench/
├── format_conversations.py # source CLI: detect + convert exports
├── generate_spa.py # build viewer + local full-text index
├── serve_spa.py # privacy-gated local HTTP server
├── bundle_conversations.py # build/inspect portable .cew archives
├── workbench_bundle.py # .cew bundle implementation
├── canonical.py # provider-neutral cew.conversation/v1 model
├── canonical_render.py # shared canonical HTML/Markdown renderer
├── cli_main.py # packaged binary entry point
├── formatters/ # ChatGPT, Claude, DeepSeek + shared rendering
├── provider_templates/ # structural provider detection signatures
├── config/ # SPA config and CSS templates
├── sample_data/ # synthetic fixtures and generated samples
├── readme_assets/ # README screenshots
├── mobile/ # Capacitor Android/iOS offline viewer source
├── docs/UPGRADE_PLAN.md # ordered security/offline/mobile roadmap
├── scripts/smoke_test.sh # all-provider smoke test
└── tests/ # regression, security, bundle/search tests
Runtime code intentionally stays dependency-light. The test suite uses pytest.
python -m pip install pytest==9.1.1
python -m pytest -q tests
./scripts/smoke_test.shGitHub Actions runs regression/security tests on Python 3.11–3.14 plus mobile provider-adapter tests and locked npm ci builds. Release candidates build Windows, macOS, Linux, Android, and iOS Simulator artifacts; signed Android and iOS device channels activate only when private signing credentials are configured. Published assets receive SHA-256 checksums and GitHub provenance attestations.
AI conversation exports can contain sensitive personal or business information. Keep real exports outside source control.
The repository ignores common local export paths and generated output:
| Path | Repository behavior |
|---|---|
conversations.json |
ignored |
*.zip |
ignored |
output/ |
ignored |
sample_data/ |
tracked synthetic/sample data |
provider_templates/ |
tracked |
formatters/ |
tracked |
The tool does not need your ChatGPT, Claude, or DeepSeek credentials. For security reporting, see SECURITY.md.
Contributions are welcome for provider compatibility, rendering fidelity, viewer usability, tests, and documentation. See CONTRIBUTING.md.
Please do not submit real conversation exports or other private chat data as fixtures.
MIT — see LICENSE.



