Metadata-Version: 2.5
Name: netcodex-agent-exporter
Version: 0.4.0
Summary: Local-first exporter for AI agent conversations (Codex, Claude Code, Copilot, Cline, Cursor, Gemini CLI and more) to Markdown.
Project-URL: Homepage, https://gitlab.com/netcodex-tech/agent-conversation-exporter
Project-URL: Repository, https://gitlab.com/netcodex-tech/agent-conversation-exporter
Project-URL: Issues, https://gitlab.com/netcodex-tech/agent-conversation-exporter/-/issues
Author: NetCodex Technology
License-Expression: MIT
License-File: LICENSE
Keywords: ai-agents,claude-code,codex,copilot,cursor,export,markdown,transcripts
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Environment :: MacOS X
Classifier: Environment :: Web Environment
Classifier: Environment :: Win32 (MS Windows)
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development
Classifier: Topic :: Text Processing :: Markup :: Markdown
Classifier: Topic :: Utilities
Requires-Python: >=3.12
Requires-Dist: pydantic>=2.7
Requires-Dist: typer>=0.12
Provides-Extra: desktop
Requires-Dist: fastapi>=0.115; extra == 'desktop'
Requires-Dist: python-multipart>=0.0.9; extra == 'desktop'
Requires-Dist: pywebview>=5.3; extra == 'desktop'
Requires-Dist: uvicorn[standard]>=0.30; extra == 'desktop'
Provides-Extra: ui
Requires-Dist: fastapi>=0.115; extra == 'ui'
Requires-Dist: python-multipart>=0.0.9; extra == 'ui'
Requires-Dist: uvicorn[standard]>=0.30; extra == 'ui'
Provides-Extra: web
Requires-Dist: fastapi>=0.115; extra == 'web'
Requires-Dist: python-multipart>=0.0.9; extra == 'web'
Requires-Dist: uvicorn[standard]>=0.30; extra == 'web'
Description-Content-Type: text/markdown

# NetCodex Agent Conversation Exporter

Private, local-first exporter for AI agent conversations (Codex, Claude Code, Copilot, Cline,
Cursor, Gemini CLI and more) into Markdown, Quarkdown and PDF: a **desktop app** that finds
your AI tools by itself, a local web desk and a CLI.

## Status

Version 0.4. Supported tools, where each one keeps its chats, and how to import them
(`netcodex where` prints the same table with the paths that exist on your machine).

### Where are my chats?

<!-- netcodex:where:start (generated by scripts/export_locations.py) -->
| Tool | Status | Windows | macOS / Linux | Import via |
| --- | --- | --- | --- | --- |
| Codex CLI / VS Code / Desktop | supported; override: `CODEX_HOME` | `%USERPROFILE%\.codex\sessions\YYYY\MM\DD\rollout-*.jsonl`<br>`%USERPROFILE%\.codex\archived_sessions\rollout-*.jsonl`<br>`%USERPROFILE%\.codex\state_*.sqlite`<br>`%USERPROFILE%\.codex\session_index.jsonl` | `~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl`<br>`~/.codex/archived_sessions/rollout-*.jsonl`<br>`~/.codex/state_*.sqlite`<br>`~/.codex/session_index.jsonl` | Upload files, Local sources, CLI |
| Claude Code CLI / VS Code | supported; override: `CLAUDE_CONFIG_DIR` | `%USERPROFILE%\.claude\projects\<project>\<session>.jsonl` | `~/.claude/projects/<project>/<session>.jsonl` | Upload files, Local sources, CLI |
| Claude Desktop (Code tab) | supported; override: `CLAUDE_CONFIG_DIR` | `%APPDATA%\Claude\claude-code-sessions\**\local_*.json`<br>`%USERPROFILE%\.claude\projects\<project>\<session>.jsonl` | `<config>/Claude/claude-code-sessions/**/local_*.json`<br>`~/.claude/projects/<project>/<session>.jsonl` | Local sources, CLI |
| Claude Cowork | supported | `%APPDATA%\Claude\local-agent-mode-sessions\**\local_<id>.json`<br>`%APPDATA%\Claude\local-agent-mode-sessions\**\local_<id>\.claude\projects\**\*.jsonl` | `<config>/Claude/local-agent-mode-sessions/**/local_<id>.json`<br>`<config>/Claude/local-agent-mode-sessions/**/local_<id>/.claude/projects/**/*.jsonl` | Local sources, CLI |
| Claude.ai (official data export) | supported; override: `NETCODEX_CLAUDE_AI_EXPORT` | `%USERPROFILE%\Downloads\data-*.zip`<br>`%USERPROFILE%\Downloads\<folder>\conversations.json` | `~/Downloads/data-*.zip`<br>`~/Downloads/<folder>/conversations.json` | Local sources, CLI |
| GitHub Copilot Chat | supported | `%APPDATA%\<editor>\User\workspaceStorage\<hash>\chatSessions\*.jsonl`<br>`%APPDATA%\<editor>\User\workspaceStorage\<hash>\chatSessions\*.json`<br>`%APPDATA%\<editor>\User\globalStorage\emptyWindowChatSessions\*.json` | `<config>/<editor>/User/workspaceStorage/<hash>/chatSessions/*.jsonl`<br>`<config>/<editor>/User/workspaceStorage/<hash>/chatSessions/*.json`<br>`<config>/<editor>/User/globalStorage/emptyWindowChatSessions/*.json` | Local sources, CLI |
| GitHub Copilot CLI | supported | `%USERPROFILE%\.copilot\session-state\<id>\events.jsonl` | `~/.copilot/session-state/<id>/events.jsonl` | Local sources, CLI |
| Cline / Roo Code / Kilo Code | supported | `%APPDATA%\<editor>\User\globalStorage\saoudrizwan.claude-dev\tasks\<id>\api_conversation_history.json`<br>`%APPDATA%\<editor>\User\globalStorage\rooveterinaryinc.roo-cline\tasks\<id>\api_conversation_history.json`<br>`%APPDATA%\<editor>\User\globalStorage\kilocode.kilo-code\tasks\<id>\api_conversation_history.json` | `<config>/<editor>/User/globalStorage/saoudrizwan.claude-dev/tasks/<id>/api_conversation_history.json`<br>`<config>/<editor>/User/globalStorage/rooveterinaryinc.roo-cline/tasks/<id>/api_conversation_history.json`<br>`<config>/<editor>/User/globalStorage/kilocode.kilo-code/tasks/<id>/api_conversation_history.json` | Local sources, CLI |
| Cursor | supported | `%APPDATA%\Cursor\User\globalStorage\state.vscdb` | `<config>/Cursor/User/globalStorage/state.vscdb` | Local sources, CLI |
| Gemini CLI | supported | `%USERPROFILE%\.gemini\tmp\<hash>\chats\session-*.json`<br>`%USERPROFILE%\.gemini\tmp\<hash>\logs.json` | `~/.gemini/tmp/<hash>/chats/session-*.json`<br>`~/.gemini/tmp/<hash>/logs.json` | Local sources, CLI |
| Continue | supported | `%USERPROFILE%\.continue\sessions\*.json` | `~/.continue/sessions/*.json` | Local sources, CLI |
| Aider | supported; override: `NETCODEX_AIDER_PATHS` | `<repo>\.aider.chat.history.md` | `<repo>/.aider.chat.history.md` | Local sources, CLI |
| Google Antigravity | best effort | `%USERPROFILE%\.gemini\antigravity\conversation_summaries.db`<br>`%USERPROFILE%\.gemini\antigravity\conversations\*.db` | `~/.gemini/antigravity/conversation_summaries.db`<br>`~/.gemini/antigravity/conversations/*.db` | Local sources, CLI |
| Trae | encrypted, not supported | `%APPDATA%\Trae\ModularData\ai-agent\database.db`<br>`%APPDATA%\Trae CN\ModularData\ai-agent\database.db` | `<config>/Trae/ModularData/ai-agent/database.db`<br>`<config>/Trae CN/ModularData/ai-agent/database.db` | - |
| Windsurf | encrypted, not supported | `%USERPROFILE%\.codeium\windsurf\cascade\*.pb` | `~/.codeium/windsurf/cascade/*.pb` | - |

`<config>` is `~/Library/Application Support` on macOS and `~/.config` on Linux. `<editor>` is any VS Code-family editor: Code, Code - Insiders, VSCodium, Cursor, Windsurf, Trae, Trae CN, Antigravity, Kiro, Positron.
<!-- netcodex:where:end -->

Find them on your machine with `netcodex where` (`--json`, `--patterns`), or open the desk
(`netcodex ui`) and click **Where are my chats?**: it lists every tool with its status, the
resolved folder on this computer (Copy path / Open folder) and what to import. Encrypted
stores (current Trae, Windsurf) are reported but cannot be exported. claude.ai chats are not
stored locally: request the official data export (Settings > Privacy > Export data) and save
the `data-*.zip` / `conversations.json` in Downloads or point `NETCODEX_CLAUDE_AI_EXPORT` at it.

Client labels written to the `tool` field: `codex-cli`, `codex-vscode`, `codex-desktop`,
`claude-code-cli`, `claude-code-vscode`, `claude-desktop`, `claude-cowork`,
`copilot-chat-<editor>`, `cline-*`, `roo-code-*`, `kilo-code-*`, `cursor`, `copilot-cli`,
`gemini-cli`, `continue`, `aider`, `claude-ai`, `antigravity`.

All parsers map to one canonical model (`Conversation` -> `Turn` -> `MessagePart`
with `text`, `tool_call`, `tool_result`, `reasoning`, `image`, `attachment`,
`system_context` and `summary` parts). Tool results are attached to their call,
injected environment/instruction/hook context is classified as system context,
and mirrored Codex `event_msg` messages are de-duplicated.

Raw conversations stay local by default. Generated exports are written under
`exports/`, which is intentionally ignored by Git.

## Install

NetCodex runs on your own machine; it reads the local conversation stores and never
uploads them. Python 3.12+ is required for the package installs.

| How | Command | Notes |
| --- | --- | --- |
| Desktop app (Windows) | Download `NetCodex-Setup-<version>-x64.exe` from the landing page (Download for Windows) | Per-user install, no admin, no Python. Portable `NetCodex-<version>-portable.exe` too. |
| Desktop app (any OS) | `pipx install "netcodex-agent-exporter[desktop]"` then `netcodex desktop` | Native window via pywebview. |
| pipx | `pipx install "netcodex-agent-exporter[ui]"` | Recommended. Drop `[ui]` for the CLI only. |
| uv | `uv tool install "netcodex-agent-exporter[ui]"` | Same, using uv. |
| Binary | Download `netcodex-<version>-windows-x86_64.exe` or `-linux-x86_64` from the GitLab Release | Single file, no Python needed; includes the UI. |
| From source | `git clone ... && uv sync && uv run netcodex --help` | For development. |

The PyPI package and release binaries are published from `v*` tags (first release:
v0.3.0). Extras: `[desktop]` adds pywebview plus the UI server for `netcodex desktop`;
`[ui]` (alias `[web]`) adds FastAPI/uvicorn for `netcodex ui` and the upload API; the core
CLI only needs Pydantic and Typer. PDF export needs the external
[Quarkdown](https://github.com/iamgio/quarkdown) binary on `PATH` (no Python extra).

### Desktop app

Download the Windows installer from the landing page (or the GitLab Release), run it, and open
**NetCodex** from the Start menu. With Python on any OS:
`pipx install "netcodex-agent-exporter[desktop]"` and `netcodex desktop`.

- A native window titled NetCodex opens (Edge WebView2 on Windows, WebKit on macOS, GTK or Qt on
  Linux) over a local service on a random `127.0.0.1` port with a per-launch token. The window
  is opened on a single-use launch link that sets an HttpOnly session cookie, so the token never
  appears in a URL. Closing the window stops the service.
- **Detected on this computer**: on open it scans every supported tool through the source
  registry and shows a card per installed tool (status, conversation count, last activity,
  workspaces). Encrypted stores (Trae, Windsurf) are flagged; tools that are not installed are
  collapsed. **Export all**, per-tool **Export**, and **Choose...** (search, date range and
  workspace filters) write Markdown plus an `index.md` into the output folder, incrementally
  (unchanged conversations are skipped; untick *Incremental* to re-export). **Open output
  folder** opens it in Explorer/Finder.
- Default output folder: `Documents\NetCodex Exports` (Windows Known Folder, so OneDrive-redirected
  Documents work). Change it with **Change...**; it is remembered in `settings.json` under
  `%APPDATA%\NetCodex` (macOS `~/Library/Application Support/NetCodex`, Linux
  `~/.config/netcodex`; `NETCODEX_APP_DIR` overrides). No conversation content is stored there.
- **Upload files** and **Where are my chats?** stay available (the full export desk).
- Single instance: launching it again brings the open window to the front.
- No WebView2 runtime (rare on Windows 10/11): a message offers the
  [WebView2 download](https://go.microsoft.com/fwlink/p/?LinkId=2124703) and the app opens in
  your default browser instead (`netcodex desktop --browser` does that on purpose).
- `netcodex desktop --smoke` starts the service, checks it answers and exits (used by CI).

Windows packaging lives in `packaging/windows/`: `build.ps1` (PyInstaller onedir app + portable
single-file exe, both smoke-tested, then Inno Setup 6 `netcodex.iss` -> per-user installer with
Start menu entry, optional desktop shortcut, uninstaller, icon and version metadata) and
`test-install.ps1` (silent `/VERYSILENT /CURRENTUSER` install, smoke test, silent uninstall).
Icons are generated from the brand mark by `scripts/make_icons.py`.

**SmartScreen and code signing.** The installer is not code-signed yet, so Windows SmartScreen
shows "Windows protected your PC" on first run (More info > Run anyway). The release job signs
the exes and the installer with `signtool` automatically once the masked CI/CD variables
`CODE_SIGNING_PFX_BASE64` (base64 of a code-signing .pfx) and `CODE_SIGNING_PFX_PASSWORD`
(optional `CODE_SIGNING_TIMESTAMP_URL`) exist; without them the step is skipped.

**macOS and Linux desktop builds** are not produced by CI: a macOS app bundle needs a macOS
runner (`packaging/icons/netcodex.icns` is ready), and a Linux AppImage would have to bundle
GTK/WebKit2. On both, use `pipx install "netcodex-agent-exporter[desktop]"`; on Linux also
install a pywebview backend (`sudo apt install python3-gi gir1.2-webkit2-4.1` with
`pipx inject netcodex-agent-exporter pygobject`, or `pipx inject netcodex-agent-exporter "pywebview[qt]"`),
or run `netcodex desktop --browser`.

### Local UI: the Conversation export desk

```powershell
netcodex ui            # opens http://127.0.0.1:<port>/app/#token=... in your browser
netcodex ui --port 8765 --out D:\exports --no-open
netcodex --version
```

`netcodex ui` serves the full export desk from your own machine: an upload rail for
JSONL/SQLite/ZIP files with source auto-detection, a **Local sources** tab that reads the
detected tools directly (Codex, Claude Code, Copilot, Cline, Cursor, Gemini CLI, ...),
MD/QD/PDF formats with Quarkdown templates, the Upload > Analyze > Review > Export > Done
tracker, a system activity log, the preview and the export summary with the ZIP download.
The preview shows the Quarkdown HTML for QD/PDF exports and a rendered (sanitized) Markdown
view for Markdown-only exports, plus the Markdown source tab. **Where are my chats?** (header
button and Upload rail link) lists every supported tool with its status, the folder found on
this computer (Copy path / Open folder) and what to import. QD and PDF need the Quarkdown CLI;
the desk says so when it is missing.

Everything runs on 127.0.0.1: `--host` with a non-loopback address is refused unless
`--allow-remote` is given, API calls need the per-launch token from the URL (exchanged
for an HttpOnly, SameSite=Strict session cookie), and requests whose `Host` is not a
loopback name are rejected. Nothing is sent to a NetCodex server.

The desk is the Next.js app in `web/`, built as a static site by `npm run desk:build`
(`scripts/build-desk.mjs`) into `src/netcodex/web/desk/` and shipped in the wheel. A
source checkout without that build falls back to a minimal built-in page.

## License

MIT, see [LICENSE](LICENSE).

## Setup (development)

```powershell
uv sync
uv run netcodex --help
```

## Common Commands

```powershell
uv run netcodex sources                      # registered sources, found / not found
uv run netcodex where                        # where each tool keeps its chats, and what is on this machine
uv run netcodex where --json                 # same, machine-readable (also: sources --paths)
uv run netcodex scan --sources all
uv run netcodex analyze --source auto --json
uv run netcodex export --all --out exports   # every available source, every session
uv run netcodex export --all --since 7d --workspace my-repo
uv run netcodex export --source claude --formats md,qd --limit 1
uv run netcodex export --local --source codex --formats md,qd,pdf --template galactic-guide --json
uv run netcodex validate exports
```

`export` accepts `--source auto|all|<name>[,<name>]` (or `--all`), `--limit N` per
source (default `0` = all sessions), `--since`/`--until` (ISO date or an age such
as `7d`, `12h`, `2w`) and `--workspace <text>` (case-insensitive match on the
session's working directory). Tool inputs/outputs are capped per block with
`--max-tool-output-lines` (default 200) and `--max-tool-output-bytes` (default
32000); the Markdown notes how much was left out. Payloads over 200k characters
are also cut at import time, before redaction.

Exports are incremental: `<out>/.netcodex-state.json` records a fingerprint of
each session's source files (size and mtime, including subagent files), its title
and the export options. Re-running `export` into the same folder only re-renders new
or changed conversations (renamed ones replace their old folder); `--force`
re-exports everything and `--no-incremental` ignores the state file. To keep a
folder up to date continuously:

```powershell
uv run netcodex watch --out exports --interval 60   # Ctrl+C to stop
```

Large exports use worker processes (`--jobs`, default automatic, up to 4).

The "Where are my chats?" table above, `netcodex where`, the desk help panel and the public
`/where` page all come from `netcodex.sources.locations`. After changing it, regenerate the
README table and `web/lib/chat-locations.json` with `uv run python scripts/export_locations.py`
(a test fails while they are out of date).

Sources live in a registry (`netcodex.sources.registry`). Store locations come
from a per-platform path matrix (`netcodex.sources.paths`: Windows
`%APPDATA%`, macOS `~/Library/Application Support`, Linux `~/.config`) that also
enumerates VS Code-family editors (Code, Insiders, VSCodium, Cursor, Windsurf,
Trae, Antigravity, Kiro, Positron).

Each export creates one folder per conversation named
`<source>/<date>-<title-slug>-<short-id>/` containing `conversation.md`,
`metadata.json` and `netcodex-manifest.json`, plus an `index.md` table (date,
title, tool, turns, link) at the export root.

`conversation.md` (Markdown v2) starts with YAML frontmatter (`title`, `id`,
`source`, `tool`, `originator`, `model`, `workspace`, `git_branch`,
`started_at`, `ended_at`, `turn_count`, `subagent_count`, `parent_id`), uses one
`## Role · timestamp` heading per turn, keeps code fences intact and puts tool
calls/results and reasoning in collapsible `<details>` blocks. Images and
attachments become placeholders. Content switches:

```powershell
uv run netcodex export --source codex --limit 20 `
  --no-reasoning --no-tool-output --include-system-context --no-subagents `
  --max-tool-output-lines 50
```

Every export records the shared workflow `analyze -> parse -> render -> package`
inside `netcodex-manifest.json`, including generated artifact hashes without
storing transcript bodies.

PDF export uses Quarkdown for the MVP. If Quarkdown or its browser runtime is
not available, the CLI reports the missing dependency instead of failing
silently.

## Releasing

1. Bump `version` in `pyproject.toml` and `src/netcodex/__init__.py`, merge to `main`.
2. Push a tag `vX.Y.Z` matching that version. The tag pipeline builds the sdist and
   wheel, PyInstaller single-file CLI binaries for Linux and Windows, the Windows desktop app
   (`release:desktop-windows` on the GitLab.com Windows runner: installer + portable exe,
   smoke-tested and install-tested), uploads everything to the project's generic package
   registry, writes the pointer `netcodex-desktop/latest/latest.json` (version, file names,
   sizes, SHA-256), creates the GitLab Release, publishes to PyPI with the masked, protected
   CI/CD variable `PYPI_TOKEN` (job skipped when the variable is absent) and, when the
   masked variable `DOKPLOY_DEPLOY_TOKEN` exists, redeploys the public landing
   (`release:landing`) so its download button serves the new installer.
3. macOS binaries need a macOS runner; build them locally with
   `uv run pyinstaller --onefile --name netcodex --collect-submodules netcodex --collect-submodules uvicorn --collect-data netcodex scripts/netcodex_entry.py`.

## Development

```powershell
uv run ruff check .
uv run pytest
uv build
npm run diagrams:check
```

## Local Web

Install dependencies once:

```powershell
uv sync
npm install
npm install --prefix web
```

Run the local API and web UI together from one terminal:

```powershell
npm run dev
```

This starts:

- API: `http://localhost:8000`
- Web: `http://127.0.0.1:3100`

You can still run each side separately when debugging:

```powershell
npm run api:dev
npm run web:dev
```

In development (`npm run dev`) the desk reads `NEXT_PUBLIC_API_URL` (default
`http://localhost:8000`) and the dev API also serves the local-sources endpoints. The MVP web flow accepts `.jsonl`, `.sqlite`, and
`.zip` uploads, analyzes detected Claude/Codex sessions, previews Markdown,
and downloads generated artifacts plus `netcodex-manifest.json` as a ZIP.

### Public landing deployment (landing-only mode)

The web app can be deployed publicly as a marketing site (e.g. Dokploy/Nixpacks
with build path `web`, `npm run build` then `npm run start`). Because the export
workspace needs the local API, a production build runs in **landing-only mode**
when `NEXT_PUBLIC_LANDING_ONLY=1` is set, or when `NEXT_PUBLIC_API_URL` is unset:
`/app` shows a "This tool runs locally" panel with install instructions instead
of the upload form, and every "Open app" call to action points to `/install`.
Set `NEXT_PUBLIC_LANDING_ONLY=0` to force the full workspace in a production
build. `next dev` always keeps the local workspace.

**Download for Windows.** The GitLab project is private, so visitors cannot download Release
assets. The landing serves the installer itself: `npm run build` runs `prebuild`
(`web/scripts/fetch-downloads.mjs`), which reads `latest.json` from the generic package registry
with a project deploy token that only has `read_package_registry`, downloads the installer and
the portable exe into `web/public/downloads/`, verifies size and SHA-256 and writes
`web/lib/downloads.json` (version, size, SHA-256 shown on the page). Configure it as build-time
environment of the landing app (never commit it): `GITLAB_DEPLOY_TOKEN_USER`,
`GITLAB_DEPLOY_TOKEN` (optional `GITLAB_PROJECT_ID`, `GITLAB_URL`,
`NETCODEX_DOWNLOADS_REQUIRED=1` to fail the build when the download fails). Without a token the
page shows the pipx instructions only. The token is used only during the build; it never
reaches the browser.

See `docs/web/local-web-api.md` for the API contract and temporary file cleanup
policy.

## Architecture

The canonical architecture model lives in `docs/architecture/likec4/model.c4`
and is validated with LikeC4. GitLab-friendly Mermaid mirrors live in
`docs/architecture/c4.md`.

VS Code users should open the `.c4` file with the LikeC4 extension installed.
The expected extension id is `likec4.likec4-vscode`.

## GitLab Flow

NetCodex uses GitLab Flow, not Git Flow:

- `main` is protected and always releasable.
- Work starts from issue branches named `issue/<iid>-<short-slug>`.
- Every change goes through a merge request into `main`.
- Merge requires a green pipeline and resolved discussions.
- `release/*` branches and `v*` tags are reserved for release preparation.

See `docs/development/gitlab-flow.md` for the full policy.

## Privacy Rules

- Do not commit real exports, raw `.jsonl` files, SQLite databases or local
  attachments.
- Use sanitized fixtures only.
- Keep parsers read-only against source directories.
- Use `--include-paths` only when full local paths are intentionally needed in
  the generated metadata.
