Skip to main content

Serialized Codex collaboration for shared Git repositories

Project description

cocodex

中文说明

cocodex coordinates multiple Codex sessions that share one Git repository on one server account. It gives every developer an isolated managed worktree, then serializes the moment when a developer's work becomes the next main.

Core Rule

For day-to-day collaboration, a developer only needs one Cocodex command:

cocodex sync

sync means "move this Cocodex session to the next safe synchronization state." Depending on the session state, it can:

  • fast-forward a clean session to the latest main;
  • publish a dirty session directly when it is already based on latest main;
  • queue a dirty session for integration when main has advanced;
  • after Cocodex gives the session a task, publish the committed candidate as the new main.

Developers and Codex sessions must not run git pull main, git merge main, or git push main directly. Cocodex is the only writer to local main.

If a remote is configured, every cocodex sync also tries to force-sync local main and the current session branch to that remote. It does not push or prune other developers' branches. Remote sync is best-effort: network or authentication failures are reported as warnings and retried on later cocodex sync commands.

The daemon does not automatically integrate dirty sessions. Local work stays in the developer's managed worktree until that developer or their Codex explicitly runs cocodex sync from inside that worktree. In Codex, run it as a shell command, for example !cocodex sync.

Roles

Operator/startup commands, run from the project repository:

cocodex init --main main --remote origin
cocodex daemon
cocodex join alice

Developer collaboration command, run from inside that developer's managed worktree, usually through Codex as !cocodex sync:

cocodex sync

Inspection commands:

cocodex status
cocodex log

resume and abandon recovery commands exist for operators, but they are not part of the normal developer workflow.

Installation

After the first PyPI release:

pip install cocodex

For development from a local checkout:

pip install -e .

This installs the cocodex console command.

Repository Setup

Run these commands in the project repository that the team wants to develop with Cocodex.

The configured main branch must already exist and have an initial commit:

git switch -c main
git add .
git commit -m "initial commit"

If Cocodex should keep a remote copy of the server's local branches, add the remote before initialization:

git remote add origin <url>

Initialize Cocodex once:

cocodex init --main main --remote origin

init refuses to overwrite an existing .cocodex/config.json, because that file contains developer identities and launch commands. Use cocodex init --force only when you intentionally want to replace the existing Cocodex configuration.

Use --remote origin only if that remote exists. With a remote configured, cocodex sync force-pushes local main and the current session branch to that remote. Omit --remote for local-only coordination.

Before developers join, edit .cocodex/config.json and fill in the top-level developers object. Keep the other keys that cocodex init wrote; do not replace the whole file with only the developer fragment. A typical config looks like this:

{
  "developers": {
    "alice": {
      "git_user_name": "Alice Example",
      "git_user_email": "alice@example.com"
    },
    "bob": {
      "git_user_name": "Bob Example",
      "git_user_email": "bob@example.com"
    }
  },
  "dirty_interval_s": 2.0,
  "main_branch": "main",
  "remote": "origin",
  "socket_path": ".cocodex/cocodex.sock",
  "worktree_root": ".cocodex/worktrees"
}

Use "remote": null if the repository is local-only. The keys under developers are the only names accepted by cocodex join <user_name>, so cocodex join alice requires an alice entry.

command is optional per developer; when omitted, Cocodex starts codex. For a custom Codex launch, use a JSON string array such as "command": ["codex", "--model", "gpt-5.5"].

Starting Codex Sessions

Start one daemon in a long-running terminal from the project repository:

cocodex daemon

The daemon prints an operational log in that terminal: session joins, sync requests, queue movement, integration lock changes, publish events, remote sync failures, and recovery transitions.

Start each Codex session through Cocodex from that developer's tmux window:

cocodex join alice
cocodex join bob

join has the same form for first-time use and restart. The developer name comes from .cocodex/config.json; Git identity and the Codex launch command come from the matching config entry.

Each joined session gets:

  • a branch named cocodex/<name>;
  • a worktree under .cocodex/worktrees/<name>;
  • a session agent that receives Cocodex tasks;
  • a Git-ignored AGENTS.md in that worktree, unless the project already has its own AGENTS.md.

join reads the developer's Git identity from .cocodex/config.json and writes it into that worktree's per-worktree Git config, so Cocodex snapshot commits and Codex candidate commits have the right author.

Cocodex assumes join is run from the developer's own tmux pane. When TMUX_PANE is present, join automatically binds the session agent to that pane, so sync tasks and restart notices are pasted into the running Codex as ordinary user prompts.

For advanced setups, override the target explicitly:

cocodex join --tmux-target "$TMUX_PANE" alice

If join is not running inside tmux, Cocodex prints the task and prompt file paths instead. The developer then needs to open the task file from the session worktree and follow it manually.

The generated AGENTS.md tells Codex that it is in a Cocodex-managed collaboration session and that normal synchronization uses only cocodex sync from inside the managed worktree.

Restarting A Session

If a developer closes their Codex window, restart with the same session name:

cocodex join alice

Cocodex reuses .cocodex/worktrees/alice and cocodex/alice. On startup, join checks for unfinished Cocodex responsibilities before normal development continues:

  • an active sync task is re-announced with its task and validation file paths;
  • a safely recoverable interrupted task is moved back to fusing;
  • a queued sync request is reported so Codex waits for the task;
  • a clean session that only fell behind main is reported, but not moved;
  • local unintegrated work is reported so Codex reviews it before starting unrelated work.

If a restart notice appears, handle that notice before accepting new feature work. In the normal tmux workflow, Cocodex pastes the notice into the Codex pane automatically.

What sync Does

Clean Session

If Alice has no local work and main has advanced, this catches Alice up:

cocodex sync

If Alice is already current, Cocodex reports that the session is already synced.

Dirty Session Based On Current Main

If Alice has local edits or commits and main has not advanced since Alice last synced, Cocodex publishes Alice's current worktree directly:

cocodex sync

If the worktree has uncommitted changes, Cocodex creates a snapshot commit with Alice's configured Git identity, fast-forwards local main to that commit, and best-effort syncs the remote. This path does not create a Codex fusion task, because there is no newer main work to merge with.

Dirty Session After Main Advanced

If Alice has local edits or commits and main has advanced since Alice last synced, cocodex sync requests integration. When Alice reaches the front of the queue, Cocodex:

  1. freezes Alice's session;
  2. snapshots Alice's current work;
  3. resets Alice's worktree to the latest main;
  4. writes a task file under .cocodex/tasks/;
  5. pastes the sync prompt into Alice's Codex terminal when tmux is available, and always prints the task file path.

Alice's Codex reads the task file and re-implements or semantically merges Alice's feature on top of the latest main. If the task arrives while Codex is working on another request, Codex should pause at a safe point, preserve that request's remaining intent, complete the sync task, and then resume the paused work after sync succeeds.

For each task, Codex designs and runs sufficient validation for the semantic merge. That can mean existing tests, new or updated tests, targeted scripts, or manual checks when the project has no suitable test framework. Before running sync again, Codex writes the requested validation report under .cocodex/tasks/. After it commits the final candidate and the worktree is clean, it runs the same command again:

cocodex sync

Cocodex then requires the validation report, fast-forwards local main, and best-effort syncs the configured remote if one exists. Other session worktrees are not moved or notified as part of this publish.

If the task cannot be completed safely, Codex should stop and explain the blocker in its session output. An operator can inspect cocodex status and cocodex log before deciding how to recover.

Normal Example

Alice and Bob both start Codex through Cocodex. Alice implements feature A; Bob implements feature B. Neither branch is integrated automatically.

Alice runs:

!cocodex sync

If no one else has advanced main since Alice last synced, Cocodex publishes Alice directly. If main has advanced, Cocodex gives Alice's Codex a task; Alice's Codex applies feature A on latest main, commits, and runs:

!cocodex sync

Now feature A is the new main.

Bob later runs:

!cocodex sync

Because Alice has now advanced main, Bob receives a task based on the current main, which already includes feature A. Bob's Codex applies feature B on top of that, commits, and runs:

!cocodex sync

This gives the team a serial mainline even though the Codex sessions worked asynchronously.

Safety Behavior

Cocodex prefers stopping over guessing:

  • a dirty session is not integrated until its owner runs sync;
  • one session's sync never fast-forwards another session's worktree;
  • remote sync only force-pushes local main and the current session branch;
  • only one session owns the integration lock at a time;
  • running sync before committing a task candidate is rejected;
  • missing or insufficient validation reports keep the task locked so the same session can write the report and run sync again;
  • remote sync failures do not block local progress; Cocodex warns and retries on the next sync;
  • unexpected recovery states require operator inspection.

Recovery And Resume

Use cocodex status first. It shows each session state, active task, blocked reason, configured remote, and whether the integration lock is held.

For normal task blocks, do not use resume immediately. If a session is blocked with a task id because the candidate was not committed, the worktree is dirty before validation, or the validation report is missing, the owning Codex should fix that issue in the same managed worktree and run cocodex sync again. The integration lock remains with that task so no other session can publish over it.

Use cocodex resume <name> when status shows a blocked or recovery session that no longer owns the integration lock. This is an operator action from the project repository, not a normal developer command. Fix the underlying blocker first, then resume. For example, if direct publish failed because the project repository's main worktree had local files that would be overwritten, clean or move those files in the main worktree, then run:

cocodex resume alice

After resume, Cocodex queues that session again and retries when the daemon can process it. If the session's Codex window was closed, restart it with:

cocodex join alice

Use cocodex abandon <name> only when the active Cocodex task should be discarded or manually recovered outside Cocodex. abandon clears Cocodex's queue/task/lock bookkeeping for that session; it does not revert files or commits in the session worktree.

Keep the project repository's main worktree clean during normal operation. Developer edits belong in .cocodex/worktrees/<name>. Uncommitted files in the main worktree can block Cocodex from fast-forwarding local main.

Command Reference

Normal developer command:

cocodex sync

Common operator commands:

cocodex init --main main --remote origin
cocodex daemon
cocodex join alice
cocodex status
cocodex log
cocodex resume alice
cocodex abandon alice

Troubleshooting

Developer 'alice' is not configured in .cocodex/config.json means the operator has not added an alice entry under developers, or the command is being run from a repository with a different Cocodex config.

cocodex sync must run inside a Git worktree or Run cocodex sync inside a managed worktree means the command was not run from .cocodex/worktrees/<name>. Start or re-enter the session with cocodex join <name>, then run !cocodex sync from that Codex session.

If Cocodex prints task and prompt file paths instead of pasting into Codex, join probably was not started from a tmux pane, or tmux prompt injection failed. Read the task file in the session worktree and follow it manually, or restart the session from the developer's tmux pane with cocodex join <name>.

Remote sync warnings are non-fatal. Fix the network or Git authentication problem when convenient; Cocodex retries remote synchronization on later cocodex sync commands.

If local main advances but the Git remote never changes, check cocodex status and .cocodex/config.json. Cocodex only pushes when remote is configured, for example "remote": "origin". A repository can have a Git origin remote while Cocodex still shows remote: none if it was initialized without --remote origin; edit the config or reinitialize intentionally before expecting remote sync.

sync already in progress (publishing) should be short-lived. If it persists, run cocodex status and cocodex log. A blocked session with no lock usually means the operator should fix the logged blocker and run cocodex resume <name>. A publishing session with no lock after a daemon crash should be handled by restarting the daemon so startup recovery can move it to recovery_required.

Implementation details are documented in docs/DEV.md.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cocodex-0.1.2.tar.gz (64.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cocodex-0.1.2-py3-none-any.whl (37.3 kB view details)

Uploaded Python 3

File details

Details for the file cocodex-0.1.2.tar.gz.

File metadata

  • Download URL: cocodex-0.1.2.tar.gz
  • Upload date:
  • Size: 64.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for cocodex-0.1.2.tar.gz
Algorithm Hash digest
SHA256 1c1e3e5eeaa943e536d798ad333b274ae31d797b56193e5f72c61d47e1a486dd
MD5 178b35f1790f77ee8ee49ce409f8369a
BLAKE2b-256 28f6861272c296313193208637cb452bb660f2bc71d7e7f2a5f98eb23edf77ca

See more details on using hashes here.

Provenance

The following attestation bundles were made for cocodex-0.1.2.tar.gz:

Publisher: release.yml on ivowang/cocodex

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cocodex-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: cocodex-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 37.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for cocodex-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 5273f4de1efcdabf326a5882455c849ccdd65618363a97b5a3ef66f23f174ece
MD5 b4edd501f0a1c3235e334c42394e6692
BLAKE2b-256 3af9fc1b92c0c3e02435f83f25361be38ec5fac6397b37f18f8788e3f2977858

See more details on using hashes here.

Provenance

The following attestation bundles were made for cocodex-0.1.2-py3-none-any.whl:

Publisher: release.yml on ivowang/cocodex

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page