The archive does what it was built to do, unattended, on both machines: four providers, incremental and resumable, Markdown plus Joplin, on a schedule, with results pushed to a phone and failures that announce themselves. The one item left on the roadmap — a StartOS service that consolidates both machines into one corpus — is an optional convenience, not a gap. Hence 1.0.0 rather than another 0.x. The code in this release shipped across b6ce636..8c3e00a: the claude.ai 403 session-invalid fix, the fork-subagent recursion fix, the FAILED-push backstops on both platforms, and asset-download retries with cross-run recovery, a circuit breaker and media counts in the notification. This commit cuts the release and pays a documentation debt. The README had reached 939 lines / 6,490 words / 48 KB / 96 headings, doing four unrelated jobs at once, and FUTURE.md asked for the split to ride along with the next substantial README edit rather than break every existing anchor for its own sake. A release is that edit. README.md is now 303 lines and keeps only what you need to install and configure the tool; the rest moved verbatim into docs/providers.md, docs/cli.md, docs/scheduling.md and docs/troubleshooting.md. No section was rewritten or dropped and every original heading still exists, so each anchor still resolves somewhere — but bookmarks into moved sections now need the docs/ path, which is the cost this deferral was protecting against. .gitignore needed the fix FUTURE.md predicted: the blanket *.md rule (exported conversations are Markdown and may be private) matched all four new pages, and git check-ignore confirmed every one would have been silently ignored. !docs/*.md is added with a comment saying why. Gitea's rendering of relative docs/ links cannot be checked before pushing, so it still needs confirming after. Also corrects two stale claims in the changelog: the Windows backstop is no longer "not yet run under Windows PowerShell 5.1 or Task Scheduler" (confirmed on winmini today, LastTaskResult 0 — only the FAILED push itself remains unexercised there), and the test count is 414, not 409. 414 tests passing. No code changes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012gCWSknsWvhLnMFwa7qnGp
255 lines
8.9 KiB
Markdown
255 lines
8.9 KiB
Markdown
# 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=<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
|
|
```
|
|
|