codex_thread_porter.py moves selected Codex desktop threads from one machine
to another. It exports the thread database rows and rollout JSONL files, plus
Git metadata that helps rebuild the project working directory on the target
machine.
Personal project note: this is a personal project by Zackary Skelly. It is not affiliated with, sponsored by, or endorsed by Dragonfly or any employer.
It does not copy auth.json, config.toml, logs databases, model caches, or
other machine-local Codex state.
This is not an official Codex migration tool. It relies on Codex's current local desktop storage layout and may need updates if that layout changes.
- macOS or another Unix-like environment.
- Python 3.11+.
- Git if you want the importer to clone or check out project repos.
- GitHub CLI
ghonly if you use GitHub to move the archive or clone private repos over authenticated HTTPS.
This repo includes a Codex skill wrapper at skills/codex-thread-porter/. It
bundles the same CLI script and gives Codex the operating procedure for
agent-assisted thread exports/imports.
Install it into local Codex skills:
mkdir -p ~/.codex/skills
cp -R skills/codex-thread-porter ~/.codex/skills/codex-thread-porterThen ask Codex on the source machine:
Use $codex-thread-porter to export the Codex threads for my-api-project.
The destination machine still needs to run the import because the importer writes into that machine's local Codex state.
You can run this yourself, or ask Codex on the source machine to do it:
export the Codex threads for my-api-project
Codex should use this tool to list local threads, resolve your description to
specific thread ids, ask you to choose if the match is ambiguous, and create a
portable .tar.gz archive.
List threads:
python3 codex_thread_porter.py list
python3 codex_thread_porter.py list --query my-api-projectExport one thread by id prefix:
python3 codex_thread_porter.py export \
--thread 019c20dc \
--output ~/Desktop/codex-threads.tar.gzExport all matching threads:
python3 codex_thread_porter.py export \
--query my-api-project \
--output ~/Desktop/my-api-project-codex-threads.tar.gzFor very large threads, create a compact handoff instead of a full same-thread archive:
python3 codex_thread_porter.py compact-export \
--thread <thread-id-prefix> \
--tail-events 200 \
--output ~/Desktop/my-thread-handoff.tar.gzCompact exports contain metadata, Git context, a Markdown handoff, and a bounded tail of recent events. They are meant for starting a fresh Codex thread on the destination machine; they are not exact resumable thread transfers.
Close Codex before importing, then run a dry run:
python3 codex_thread_porter.py import ~/Desktop/codex-threads.tar.gz \
--workspace-root ~/Coding \
--dry-runIf the repos are already cloned under a different path, map the old path to the new one:
python3 codex_thread_porter.py import ~/Desktop/codex-threads.tar.gz \
--cwd-map /Users/source-user/Coding=/Users/destination-user/CodingIf the repos should be cloned from GitHub during import:
python3 codex_thread_porter.py import ~/Desktop/codex-threads.tar.gz \
--workspace-root ~/Coding \
--clone-reposBy default, existing destination threads with the same id are skipped. Use
--on-conflict overwrite only when you intentionally want the archive copy to
replace the destination row and rollout file.
The importer writes a backup under:
~/.codex/thread_porter_backups/<timestamp>/
Reopen Codex after the import. Imported threads should appear with their original titles and point at the remapped or cloned project directory.
The exporter is read-only against Codex state. It writes only the archive you ask it to create.
The importer writes only selected per-thread state into the destination Codex home:
~/.codex/state_5.sqlite~/.codex/session_index.jsonl- rollout JSONL files under
~/.codex/sessions/...
It creates a backup before import unless --no-backup is passed.