Metadata-Version: 2.4
Name: chatgpt-export-tool
Version: 1.0.0
Summary: Stream, analyze, and export ChatGPT conversations to Markdown, text, or JSON
Author-email: Void Freud <voidfreud@gmail.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/voidfreud/chatgpt-export-tool
Project-URL: Source, https://github.com/voidfreud/chatgpt-export-tool
Project-URL: Issues, https://github.com/voidfreud/chatgpt-export-tool/issues
Keywords: chatgpt,json,export,conversations,parser
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: End Users/Desktop
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: ijson>=3.2.0
Requires-Dist: tomli>=2.0.0; python_version < "3.11"
Dynamic: license-file

<div align="center">

<br>

<img src="https://readme-typing-svg.demolab.com?font=JetBrains+Mono&weight=700&size=32&pause=1000&color=10B981&center=true&vCenter=true&random=false&width=600&height=50&lines=chatgpt-export" alt="chatgpt-export" />

<br>

**Your ChatGPT history. Clean Markdown. Zero memory overhead.**

<br>

<a href="https://www.python.org/"><img src="https://img.shields.io/badge/python-3.10+-3776AB?style=flat-square&logo=python&logoColor=white" alt="Python"></a>&nbsp;
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-10B981?style=flat-square" alt="License"></a>&nbsp;
<a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/badge/style-ruff-D7FF64?style=flat-square&logo=ruff&logoColor=black" alt="Ruff"></a>&nbsp;
<a href="https://github.com/astral-sh/uv"><img src="https://img.shields.io/badge/pkg-uv-DE5FE9?style=flat-square&logo=uv&logoColor=white" alt="uv"></a>

<br><br>

[**Install**](#installation) &nbsp;&middot;&nbsp;
[**Quick Start**](#quick-start) &nbsp;&middot;&nbsp;
[**Formats**](#output-formats) &nbsp;&middot;&nbsp;
[**Filtering**](#filtering) &nbsp;&middot;&nbsp;
[**Config**](#configuration) &nbsp;&middot;&nbsp;
[**Fields Reference**](Fields.md)

<br>

</div>

Takes your `conversations.json` from ChatGPT and turns it into **clean, readable Markdown** — or plain text, or structured JSON. Uses streaming parsing ([ijson](https://github.com/ICRAR/ijson)) so even 100MB+ exports never hit memory. Every aspect of filtering, formatting, and output is configurable through CLI flags or a single TOML file.

<br>

<div align="center">

```
$ chatgpt-export export conversations.json --split subject --output-dir vault/

  Exported 824 files to vault/
```

</div>

<br>

> [!TIP]
> Export straight into your **Obsidian vault** for a fully searchable, linked archive of every conversation you've ever had with ChatGPT.

<br>

## Installation

> **Requires Python `3.10+`** &nbsp;&middot;&nbsp; managed with [uv](https://docs.astral.sh/uv/)

```bash
git clone https://github.com/voidfreud/chatgpt-export-tool.git
cd chatgpt-export-tool
uv sync
```

<details>
<summary>&nbsp;Dev tooling (pytest, ruff, coverage)</summary>

<br>

```bash
uv sync --group dev
```

</details>

Verify:

```bash
uv run chatgpt-export --help
```

<br>

## Quick Start

```bash
# Analyze — stats without loading the whole file
uv run chatgpt-export analyze conversations.json

# Export to markdown on stdout
uv run chatgpt-export export conversations.json

# One markdown file per conversation
uv run chatgpt-export export conversations.json --split subject --output-dir exports/

# JSON dump
uv run chatgpt-export export conversations.json --format json --output dump.json
```

<br>

## Output Formats

| Format | Flag | Extension | |
|:--|:--|:--|:--|
| **Markdown** | `--format md` | `.md` | `#` headings, `>` blockquoted context, `---` turn separators. **Default.** |
| **Plain text** | `--format txt` | `.txt` | Indented, plain labels — good for terminals and grep. |
| **JSON** | `--format json` | `.json` | Filtered conversation objects, valid JSON. |

Markdown and text exports follow the **active conversation branch** — you see the conversation as it played out, not the full tree with edits and branches.

<details>
<summary>&nbsp;<strong>Preview: Markdown output</strong></summary>

<br>

```markdown
# Opening bank account in Thailand
**ID:** 68ed8eba-1d00-832a-a2f1-4721496ed217
**Created:** 23:43 13-10-2025
**Turns:** 34

## Conversation Context
> User profile: The user provided the following information...
> User instructions: Speaking to Nova. Zero restraint...

## User [23:43 13-10-2025]
Can a foreigner open a Thailand bank account?

---

## Assistant [23:44 13-10-2025]
Yup — a foreigner *can* open a bank account in Thailand, but it's
*much more difficult* now than it used to be...
```

</details>

<br>

**Default transcript policy:**

| | Shown | Hidden |
|:--|:--|:--|
| | User text, assistant text, thoughts, context (compact) | Tool plumbing, code execution, reasoning recap, blank nodes |

Fully configurable via `[transcript]` in the TOML config.

<br>

## Commands

### `analyze`

Structure and statistics — without writing output files.

```bash
uv run chatgpt-export analyze data.json
uv run chatgpt-export analyze data.json --fields          # include field coverage
uv run chatgpt-export analyze data.json --verbose --output analysis.txt
uv run chatgpt-export analyze data.json --debug
```

### `export`

Convert conversations with full control over structure, metadata, and layout.

```bash
uv run chatgpt-export export data.json --fields "groups minimal"
uv run chatgpt-export export data.json --format json --split date --output-dir by-date/
uv run chatgpt-export export data.json --include "model*" --exclude plugin_ids
uv run chatgpt-export export data.json --config chatgpt_export.toml
```

<br>

## Filtering

### Structural fields &nbsp;`--fields`

```bash
--fields all                                  # everything (default)
--fields none                                 # structure only
--fields "include title,create_time,mapping"  # whitelist
--fields "exclude moderation_results"         # blacklist
--fields "groups minimal"                     # named group
```

<details>
<summary>&nbsp;<strong>Built-in groups</strong></summary>

<br>

| Group | Fields |
|:--|:--|
| `conversation` | `_id` `conversation_id` `create_time` `update_time` `title` `type` |
| `message` | `author` `content` `status` `end_turn` |
| `metadata` | `model_slug` `message_type` `is_archived` |
| `minimal` | `title` `create_time` `message` |

</details>

Full reference: [`Fields.md`](Fields.md)

### Metadata &nbsp;`--include` / `--exclude`

Runs after structural filtering. Applies to keys inside `message.metadata`.

```bash
--include model_slug
--include "model*" --exclude plugin_ids       # glob patterns
```

<br>

## Split Modes

| Mode | Flag | Output |
|:--|:--|:--|
| **single** | `--split single` | One stream or file *(default)* |
| **subject** | `--split subject` | `Title_ID.md` per conversation |
| **date** | `--split date` | Daily folders |
| **id** | `--split id` | Named by conversation ID |

> [!NOTE]
> `--output` is for single mode. Split modes use `--output-dir`.

<br>

## Configuration

Persist defaults in a single TOML file. The repo ships [`chatgpt_export.toml.example`](chatgpt_export.toml.example).

```bash
cp chatgpt_export.toml.example chatgpt_export.toml
uv run chatgpt-export export data.json --config chatgpt_export.toml
```

CLI flags always override TOML values.

<details>
<summary>&nbsp;<strong>TOML reference</strong></summary>

<br>

**`[defaults]`** — format, split, fields, output directory, metadata

**`[transcript]`** — branch following and visibility

| Key | Default | |
|:--|:--|:--|
| `show_system_messages` | `false` | System prompts |
| `show_tool_messages` | `false` | Tool/function calls |
| `show_assistant_code` | `false` | Code execution |
| `show_reasoning_recap` | `false` | Reasoning summaries |
| `user_editable_context_mode` | `"compact"` | `"compact"` or `"full"` |

**`[text_output]`** — layout and formatting

| Key | Default | |
|:--|:--|:--|
| `layout_mode` | `"reading"` | `"reading"` or `"compact"` |
| `heading_style` | `"markdown"` | `"markdown"` or `"plain"` |
| `turn_separator` | `"---"` | Between turns |
| `strip_chatgpt_artifacts` | `true` | Remove citation artifacts |
| `wrap_width` | `88` | `0` to disable |

</details>

<details>
<summary>&nbsp;<strong>Presets</strong></summary>

<br>

**Reading-first** *(default)*
```toml
[text_output]
layout_mode = "reading"
heading_style = "markdown"
strip_chatgpt_artifacts = true
wrap_width = 88
```

**Compact**
```toml
[text_output]
layout_mode = "compact"
turn_separator = ""
wrap_width = 0
```

**Terminal**
```toml
[defaults]
format = "txt"

[text_output]
heading_style = "plain"
```

</details>

<br>

## Architecture

```
chatgpt_export_tool/
├── cli.py                  ← entry point
├── commands/               ← analyze, export
└── core/
    ├── parser.py           ← streaming JSON (ijson)
    ├── filter_pipeline.py  ← field + metadata filtering
    ├── export_service.py   ← orchestration
    ├── config/             ← TOML loading & validation
    ├── transcript/         ← branch reconstruction
    ├── validation/         ← field & metadata checks
    └── output/             ← formatters, writer, paths
```

Modular by design — filtering, formatting, splitting, and writing are separate concerns.

<br>

## Development

```bash
uv run pytest
uv run pytest --cov=chatgpt_export_tool --cov-report=term-missing
uv run ruff check chatgpt_export_tool tests
uv run ruff format --check chatgpt_export_tool tests
```

<br>

<div align="center">

[MIT](LICENSE) &nbsp;&middot;&nbsp; built by [@voidfreud](https://github.com/voidfreud)

</div>
