# CLI Reference Every command, its flags and what it does. ← [README](../README.md) · [Providers and Tokens](providers.md) · [Scheduling](scheduling.md) · [Troubleshooting](troubleshooting.md) --- ## Global flags ``` --verbose / -v DEBUG output to console --quiet / -q WARNING and above only --debug DEBUG + full tracebacks + redacted API response bodies --no-log-file Disable file logging --version Print version and exit ``` ## `auth` — Interactive token setup ```bash ai-chat-exporter auth # manual wizard (DevTools flow) ``` Guided wizard to find and save session tokens and ChatGPT project IDs. Detects OS and shows the correct DevTools shortcut, then writes the values to `.env`. ## `doctor` — Health check ```bash ai-chat-exporter doctor ``` Checks: token presence, JWT validity and expiry, directory permissions, disk space, live API reachability. Exits with code 0 if all pass, 1 if any fail. ## `export` — Export conversations ```bash # Export everything (new/updated only) ai-chat-exporter export # Single provider ai-chat-exporter export --provider claude # JSON output ai-chat-exporter export --format json # Both Markdown and JSON ai-chat-exporter export --format both # Only conversations updated since a date ai-chat-exporter export --since 2024-06-01 # Only conversations in a specific project (case-insensitive substring) ai-chat-exporter export --project "learning python" # Only conversations outside any project ai-chat-exporter export --project none # Write to a custom directory ai-chat-exporter export --output /path/to/my/notes # Preview without writing anything ai-chat-exporter export --dry-run ``` Options: `--provider [chatgpt|claude|claude-code|codex|all]`, `--format [markdown|json|both]`, `--output PATH`, `--since YYYY-MM-DD`, `--project NAME`, `--hidden-content [full|placeholder|omit]`, `--download-media [images|all|off]`, `--max-conversations N`, `--force`, `--dry-run` **Re-rendering the whole archive after an upgrade.** New formatting or features (collapse policy, media downloads) only change conversations as they're re-exported. To re-render everything you already have, use `--force` — it re-exports every conversation even if unchanged, **without** `cache --clear`, so your Joplin note links are preserved (a later `joplin` run updates the existing notes instead of duplicating them). A force re-render runs as a tracked "campaign": each run re-renders the least-recently-exported conversations, the "still to go" count shrinks each run, and finished providers do no further work. The simplest approach is one uncapped pass: ```bash ai-chat-exporter export --force # re-renders everything in one paced pass ai-chat-exporter joplin # update notes + upload media ``` Or spread the load with `--max-conversations`, re-running until it reports "Force re-render complete": ```bash ai-chat-exporter export --force --max-conversations 50 # repeat until complete ``` ## `list` — List conversations ```bash # List all conversations for all providers ai-chat-exporter list # Single provider ai-chat-exporter list --provider chatgpt # Filter by project ai-chat-exporter list --project "learning python" # Only conversations outside any project ai-chat-exporter list --project none ``` Fetches and displays all conversations without exporting them. Useful for verifying what the tool can see before running an export. ## `joplin` — Sync to Joplin ```bash # Sync all pending conversations to Joplin ai-chat-exporter joplin # Preview what would be synced without sending anything ai-chat-exporter joplin --dry-run # Sync a single provider ai-chat-exporter joplin --provider chatgpt # Sync only conversations in a specific project ai-chat-exporter joplin --project "learning python" # Sync only conversations outside any project ai-chat-exporter joplin --project none ``` Reads the local export cache and pushes each exported Markdown file to Joplin as a note. Notebooks are created automatically. Re-running is safe — notes are updated (not duplicated). **Prerequisites:** 1. Run `export` first to generate the Markdown files 2. Open Joplin → Tools → Options → Web Clipper → enable the service 3. Copy the Authorization token and add `JOPLIN_API_TOKEN=` to your `.env` 4. Joplin desktop must be open when you run this command Options: `--provider [chatgpt|claude|claude-code|codex|all]`, `--project NAME`, `--dry-run` ## `sync` — Export and sync in one run ```bash # The whole archive run: export, then push to Joplin ai-chat-exporter sync # One provider ai-chat-exporter sync --provider codex # Export only; don't touch Joplin ai-chat-exporter sync --skip-joplin # Joplin being closed is a warning, not a failure (used by the schedulers) ai-chat-exporter sync --joplin-optional ``` Equivalent to `export` followed by `joplin` with the same `--provider`. Intended for scheduled runs — see [Scheduling a Daily Run](scheduling.md#scheduling-a-daily-run). Unlike the individual commands, `sync` sets a **meaningful exit code**: non-zero if any conversation failed to export or any note failed to sync. A provider whose listing call fails outright (an expired web session token being the usual cause) counts its whole batch as failed. A provider that is simply unconfigured, or that had nothing new, is ordinary success. `export` on its own always exits 0, which is fine when you're reading the summary table and useless to a scheduler. `--joplin-optional` downgrades an unreachable Joplin to a warning: the export has already captured the local transcripts, and the notes are rebuilt from the cache by the next run that finds Joplin open. Options: `--provider [chatgpt|claude|claude-code|codex|all]`, `--since YYYY-MM-DD`, `--hidden-content [full|placeholder|omit]`, `--max-conversations N`, `--skip-joplin`, `--joplin-optional`, `--notify/--no-notify`, `--dry-run` Note this is a deliberate subset of `export`'s options — `--format`, `--output`, `--project`, `--download-media` and `--force` are not passed through. Use `export` directly for those. (`--download-media` still applies from `.env`; the flag is only a per-run override.) ## `notify` — Push-notification settings and test ```bash # Show the current settings ai-chat-exporter notify # Send a test push to confirm the topic works ai-chat-exporter notify --test ``` Shows the resolved ntfy configuration and which machine name will appear in the title. See [Getting notified](scheduling.md#getting-notified) for what a scheduled run sends. Options: `--test` ## `prune` — Delete stale export files ```bash # Preview what would be deleted ai-chat-exporter prune --dry-run # Delete (asks for confirmation; -y skips the prompt) ai-chat-exporter prune ``` Deletes export files no longer referenced by the cache manifest — leftovers from old folder layouts or fixed bugs that would otherwise double-sync into Joplin. Refuses to run when the manifest is empty (e.g. right after `cache --clear`) so it can never wipe a freshly cleared archive. The `doctor` command separately verifies that every manifest entry's file exists on disk. ## `projects` — Discover ChatGPT project IDs ```bash # List the projects your conversations belong to ai-chat-exporter projects # Also inspect conversations whose listing entry doesn't name a project ai-chat-exporter projects --deep # Write the discovered IDs straight into .env ai-chat-exporter projects --write ``` `CHATGPT_PROJECT_IDS` is maintained by hand, and a project missing from it is invisible to the listing pass — conversations that live *only* inside that project are never fetched at all. This reports every project your conversations belong to, marks the ones absent from `.env`, and prints a paste-ready line. `--deep` fetches each conversation's detail when the listing doesn't name its project: complete, but one request per conversation, so it's slow. Options: `--deep`, `--write` ## `canary` — Check for provider API drift ```bash ai-chat-exporter canary ai-chat-exporter canary --provider chatgpt ``` The web providers are undocumented internal APIs that can change shape without notice, and the failure mode is silent — a renamed field means content is quietly dropped rather than an error being raised. The canary fetches one listing page and one conversation per provider and asserts only the fields the normalizer actually depends on. Findings are `ERROR` (a load-bearing field is missing or mistyped — the parser will break or silently lose data) or `WARN` (something unfamiliar appeared; worth investigating, not necessarily broken). **Exits non-zero on any ERROR**, so it can be scheduled or run in CI. Local providers have no remote schema and are not probed. Options: `--provider [chatgpt|claude|all]` ## `cache` — Manage the sync manifest ```bash # Show statistics ai-chat-exporter cache --show # Clear all cached entries (forces full re-export next run) ai-chat-exporter cache --clear # Clear a single provider ai-chat-exporter cache --clear --provider claude ```