Local-first Codex state sync utility
Project description
codexSync
Open-source utility for syncing local Codex state between personal machines using a cloud-synced folder.
[!IMPORTANT] Current real-world validation is Windows-to-Windows only. macOS support exists in code/CI, but end-to-end handoff on real macOS machines is not yet validated.
Why
Developers may want to continue working with Codex on another machine without losing local session state.
What this does
- Syncs local Codex state directory
- Works only after Codex process is closed
- Uses any cloud-synced folder (Dropbox, OneDrive, Syncthing, etc.)
What this does NOT do
- No integration with Codex internals
- No API usage
- No token extraction
- No network interception
- No real-time sync
- No checks for cloud client process/health
- No checks for free space in cloud/network storage
Design principles
- Simple and predictable
- Safe (no corruption)
- Offline-friendly
- Backup-first
- Windows-first
How it works (MVP)
-
Detect if Codex is running
-
If not running:
- Compare local and cloud state
- Sync newer files
- Create backup before overwrite
Conflict policy
conflict.policy supports:
manual_abort: report conflict and stop (default)prefer_cloud: auto-resolve conflict by taking cloud versionprefer_local: auto-resolve conflict by taking local versionprefer_newer_mtime: auto-resolve conflict by taking side with newer mtime
Sync options
sync.compare controls file comparison strategy:
mtime(default): compare bysize + mtimemtime_hash_fallback: fastsize + mtimepath, but when values are equal/close (within tolerance), compare file content hash (SHA-256)
sync.equal_mtime_action controls behavior when file mtimes are equal (within sync.time_tolerance_seconds) but files differ:
skip: do not copy (default)prefer_local: copy local version to cloudprefer_cloud: copy cloud version to localmanual_abort: mark as conflict and stop inmanual_abortconflict mode
sync.session_mode controls scope of sessions sync:
all: sync allsessionscontent (default behavior)last_date_only: sync only the latest date-based folder undersessions- supported layouts:
sessions/YYYY-MM-DD/...andsessions/YYYY/MM/DD/... - if no date-based layout is detected, codexSync logs a warning and syncs all
sessionsfiles
- supported layouts:
Backups
backup.compressionsupports:none(default): backup snapshot is stored as directory treezip: backup snapshot is stored as a single.zipfile
restoresupports both snapshot formats and auto-selects the latest by mtime if--fromis omitted.
Logging
- Levels:
DEBUG|INFO|WARNING|ERROR - Formats (configurable):
text|json|logfmt - Rotation/size/retention/archive rules apply equally to all formats (
text,json,logfmt) - UTF-8 for all log files
- Daily log files with machine id (
<stem>-<machine>-YYYY-MM-DD[.N].log) - Daily/time rotation + size rotation (
logging.max_file_size_mb, default10) - Retention cleanup (
logging.retention_days, default7) - Old log storage mode (
logging.archive_mode):zip(default): archive rotated/old logs into.ziptext: keep rotated logs as plain text files
Platform and CI
- Runtime support is currently Windows-first.
- macOS support is allowed in current project scope (Apple Silicon target).
- Linux runtime support is intentionally out of MVP scope for now.
- CI currently runs on:
windows-latestmacos-latest
CLI commands
Run from project root:
python -m codexsync -c config.toml <command>
Generate config.toml from bundled template:
python -m codexsync init-config
Generate to a custom location:
python -m codexsync init-config --output D:\codexSync\config.toml
Overwrite existing config file:
python -m codexsync init-config --output D:\codexSync\config.toml --force
Validation:
python -m codexsync -c config.toml validate
Preflight diagnostics (same behavior for doctor and preflight):
python -m codexsync -c config.toml doctor
python -m codexsync -c config.toml preflight
Build sync plan (no changes):
python -m codexsync -c config.toml plan
Build plan with process snapshot (--verbose):
python -m codexsync -c config.toml -v plan
Sync simulation (safe test):
python -m codexsync -c config.toml sync --dry-run
Sync simulation with process snapshot (--verbose):
python -m codexsync -c config.toml -v sync --dry-run
Real sync (writes files):
python -m codexsync -c config.toml sync --apply
Typical handoff to another machine:
python -m codexsync -c config.toml sync --apply
Restore from latest backup snapshot to local state:
python -m codexsync -c config.toml restore --apply
Restore from specific backup snapshot:
python -m codexsync -c config.toml restore --from <snapshot_dir_name> --apply
Restore from specific zip snapshot:
python -m codexsync -c config.toml restore --from <snapshot_name.zip> --apply
Restore to cloud target instead of local:
python -m codexsync -c config.toml restore --target cloud --apply
Preview restore without writing:
python -m codexsync -c config.toml restore --dry-run
List CLI help:
python -m codexsync -h
Process termination behavior:
- On Windows, if Codex is still running during
sync/restore, codexSync can terminate Codex processes before continuing. - By default, manual GUI confirmation is enabled (
process_detection.manual_terminate_confirmation = true). - Background process tracking is configured by OS in
process_detection.background_process_names:windows = ["codex-windows-sandbox"]macos = []linux = []
- Confirmation channel is configured by
process_detection.terminate_confirmation_mode = "gui" | "console"(default:gui). - All confirmation prompts are in English in both GUI and console modes.
- If
codex-windows-sandboxis detected, codexSync reports that Codex is still running and exits with code3(no auto-terminate). - If
codex.exeis running butcodex-windows-sandboxis not detected, codexSync asks whether to terminate Codex and continue. - You can force manual confirmation from CLI:
python -m codexsync -c config.toml --manual-terminate-confirmation sync --apply
- You can force auto-terminate without manual confirmation for the current run only:
python -m codexsync -c config.toml --auto-terminate-without-confirmation sync --apply
- On macOS/Linux, previous behavior is kept: running Codex process fails safety precondition.
--verboseworks forplan,sync --dry-run,sync --apply,restore --dry-run, andrestore --apply; it logs tracked processes with PID/name.- In verbose mode on Windows, codexSync logs only:
- whether
codex.exeis running, - whether
codex-windows-sandboxis detected, - subprocesses under
codex.exe(PID/name/cmd).
- whether
Termination-related exit codes for automation:
3Codex is running / sandbox detected / user rejected termination5termination was approved but failed before timeout (fail-safe)
CLI exit codes
0success1runtime error2conflict detected (manual resolution required)3Codex is running (cold sync precondition failed)4invalid config or CLI arguments5safe abort (fail-safe)
doctor/preflight return:
0when all checks passed or warnings only5when at least one preflight check failed
Required operation protocol
This tool assumes a strict handoff flow between machines:
- Close Codex on machine A.
- Wait until cloud sync fully propagates machine A changes.
- Run codexSync on machine B.
- Start Codex on machine B only after sync completes.
- Sign in to Codex again on machine B after file sync.
Important: per OpenAI licensing constraints, authentication tokens are not transferred by codexSync.
The project intentionally does not verify cloud-provider sync status, cloud client process state, or free space on cloud/network storage. These are user responsibilities.
Scheduler setup scripts
This repository includes editable scheduler setup templates:
- Windows Task Scheduler:
scripts/scheduler/windows/task.config.ps1scripts/scheduler/windows/install-task.ps1scripts/scheduler/windows/remove-task.ps1- detailed guide: scripts/scheduler/windows/README.MD
- macOS launchd (LaunchAgent):
scripts/scheduler/macos/launchd.config.shscripts/scheduler/macos/install-launchd.shscripts/scheduler/macos/uninstall-launchd.sh- detailed guide: scripts/scheduler/macos/README.MD
Windows install:
cd scripts/scheduler/windows
# 1) Edit task.config.ps1
.\install-task.ps1
Windows remove:
cd scripts/scheduler/windows
.\remove-task.ps1
macOS install:
cd scripts/scheduler/macos
# 1) Edit launchd.config.sh
chmod +x install-launchd.sh uninstall-launchd.sh run-codexsync.sh
./install-launchd.sh
macOS remove:
cd scripts/scheduler/macos
./uninstall-launchd.sh
Important:
- These scripts only register scheduled jobs, not OS services.
- Keep
MODE="dry-run"while validating behavior; switch toapplyonly when ready. - Cold sync protocol still applies: codexSync must run only when Codex is not running.
Status
MVP (ready for public repository and community testing)
Publishing
See release checklist: docs/PUBLISHING.MD Release notes: CHANGELOG.MD
Licensing
This project uses dual licensing:
- Open-source license:
GPL-3.0-or-later(see LICENSE) - Commercial licensing path: see COMMERCIAL_LICENSE.MD
Contributions are accepted under project contribution terms in:
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file codexsync-0.1.1.tar.gz.
File metadata
- Download URL: codexsync-0.1.1.tar.gz
- Upload date:
- Size: 56.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
77ef5b9fbef0a1c867214265fbe83770f5315fb2c8757bb1cf84df087d7d6691
|
|
| MD5 |
08c3bbbedb9bc9986836bf716f8f7022
|
|
| BLAKE2b-256 |
58f3628bdec738a8d47a3b8ac64e728473885e4cc301a5b881ecb8bfa976a869
|
File details
Details for the file codexsync-0.1.1-py3-none-any.whl.
File metadata
- Download URL: codexsync-0.1.1-py3-none-any.whl
- Upload date:
- Size: 47.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
555d62b0c108d0bc12cacd050bdbe3d1adc0c00bd22a593dafc001ac65d6860a
|
|
| MD5 |
7cbd8c1b5316b0a2e5128e5527112f33
|
|
| BLAKE2b-256 |
e2f41e45bdbcc3ef0244919e61e606f1e986c07c23b05ba060999d66ab2882fd
|