Local Codex-to-Opencode bridge CLI
Project description
codex2opencode
codex2opencode is a local one-way bridge from Codex to Opencode.
It provides:
- a reusable Python CLI bridge
- Opencode session persistence via native
sessionID - deterministic per-thread locking
- export-backed session verification
- a thin Codex skill wrapper surface
- no non-stdlib Python runtime dependency inside the bridge
Current implementation target:
- macOS / POSIX environments with Python 3 and local Opencode CLI access
- not designed for Windows in its current
fcntl-based form
Current Status
Implemented and locally verified in this repository:
askstatusforgetgcdoctor- automatic resume via stored Opencode
sessionID - Opencode-native
--fork - Opencode-native
--title - same-thread lock conflict handling
Primary verification commands:
PYTHONPATH=bridge python3 -m unittest discover -s tests -p 'test_*.py' -v- direct
codex2opencode ask ...smoke - direct
codex2opencode doctor ...smoke - opt-in real Opencode smoke when local auth is available
Install
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install -e .
When a PyPI release is available:
python3 -m pip install codex2opencode
You can also run it directly without installing:
PYTHONPATH=bridge python3 -m codex2opencode ask --prompt "Reply with ok only" --workspace "$PWD"
After editable install, both of these work:
python -m codex2opencode --help
codex2opencode --help
Usage
Ask Opencode in the current workspace thread:
codex2opencode ask --prompt "Review this design" --workspace "$PWD"
Successful ask output begins with a one-line metadata header before the reply body, for example:
[oc provider=opencode model=mimo-v2-omni-free session=ses_...]
If session verification fails after a successful run, the bridge still prints the reply plus a minimal header with the session id, then exits non-zero.
Use a named thread:
codex2opencode ask --prompt "Continue the review" --workspace "$PWD" --thread review
Force a fresh session:
codex2opencode ask --prompt "Start over" --workspace "$PWD" --new
Fork the current mapped Opencode session:
codex2opencode ask --prompt "Take this in a different direction" --workspace "$PWD" --fork
Set an Opencode title on creation or fork:
codex2opencode ask --prompt "Review the release checklist" --workspace "$PWD" --new --title "release-review"
Inspect stored thread state:
codex2opencode status --workspace "$PWD"
Run diagnostics:
codex2opencode doctor --workspace "$PWD"
Forget the current thread and delete the mapped Opencode session:
codex2opencode forget --workspace "$PWD"
Remove stale bridge-owned files:
codex2opencode gc --max-age-days 7
Threading Model
By default, one workspace maps to one Opencode thread.
Use --thread <name> to split conversations inside the same repo:
codex2opencode ask --prompt "Review API design" --workspace "$PWD" --thread api
codex2opencode ask --prompt "Review docs tone" --workspace "$PWD" --thread docs
Use --new when you want a fresh Opencode session for the selected thread key.
Use --fork when you want Opencode to branch from the current mapped session instead of starting unrelated context. --new and --fork are intentionally mutually exclusive.
Codex Skill
The Codex-facing wrapper lives at:
skills/codex-to-opencode/SKILL.md
The skill should stay thin. It should only:
- collect the user prompt
- choose default thread, named thread,
--new, or--fork - invoke
codex2opencode - return stdout or surface stderr
It must not own JSONL parsing, session storage, retries, export verification, or custom lock handling.
Recommended high-signal trigger phrases:
Use the codex-to-opencode skillask Opencode about thisask oc about thissend this to Opencodesend this to oclet Opencode review thislet oc review thisgive this to Opencode给 Opencode 看看给oc看看让 Opencode review 一下让oc review一下问问 Opencode问问oc
Treat oc as a supported short alias for Opencode when it appears with a clear action.
Avoid relying on bare opencode by itself.
Avoid relying on bare oc by itself.
Trigger phrases should include a clear action like ask, review, check, continue, send, or look.
Practical everyday examples:
问问oc这个方案哪里最危险给oc看看这个 diff让oc review一下发布流程发给oc继续聊这个线程ask oc to review this design
Activation Scope
These paths are expected to work:
- new Codex sessions started after the skill was installed
codex execruns started after the skill was installed- direct
codex2opencodeCLI usage
Do not assume already-open Codex sessions will hot-reload newly installed or updated skills.
If you changed trigger phrases or installed the skill during an existing session, restart Codex or open a fresh session before testing.
Troubleshooting
If a trigger phrase does not route to Opencode:
- Start a new Codex session.
- Test with a high-signal phrase such as
Use the codex-to-opencode skill. Ask Opencode: reply with ok only. - Verify the bridge directly with
codex2opencode ask --prompt "Reply with ok only" --workspace "$PWD". - Run
codex2opencode doctor --workspace "$PWD"to confirm Opencode availability, debug-path output, and thread-state diagnostics.
If direct CLI usage works but a natural-language trigger does not, the issue is skill discovery in that session, not the bridge itself.
If doctor reports an orphaned thread state, the local mapping points at an Opencode session that no longer exports successfully. forget will remove that mapping and attempt remote deletion again.
Environment
CODEX2OPENCODE_OPENCODE_BIN: override the Opencode executable pathCODEX2OPENCODE_HOME: override the bridge state root without changing your real shellHOMECODEX2OPENCODE_RUN_REAL=1: enable opt-in real Opencode integration tests
Doctor Output
codex2opencode doctor --workspace "$PWD" prints JSON and checks:
- the resolved bridge root and key paths
- whether
opencode --versionis readable - whether
opencode debug pathsis readable - whether
opencode debug configis parseable - whether the selected thread state is
missing,ok,error, ororphaned - whether the mapped session can still be verified through
opencode export - whether the selected lock path is healthy or currently locked
It returns 0 when required checks are healthy and non-zero when Opencode availability checks fail, the state file is corrupted, or the mapped session is orphaned.
State Layout
Default bridge state root:
~/.codex/codex2opencode/
threads/
runs/
logs/
Key files:
threads/<thread_key>.json: current thread statethreads/<thread_key>.lock: per-thread lock fileruns/<thread_key>/*.json: per-run artifactslogs/bridge.log: append-only JSONL bridge events
Boundaries
This repository is intentionally narrow:
- one-way Codex-to-Opencode only
- no Claude orchestration here
- no roundtable or multi-model discussion system
- no bridge-owned retry orchestration
- no over-generalized multi-backend framework
For design rationale and internals, see ARCHITECTURE.md. For developer workflow, see DEVELOPMENT.md. For contribution and release details, see CONTRIBUTING.md.
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 codex2opencode-0.1.0.tar.gz.
File metadata
- Download URL: codex2opencode-0.1.0.tar.gz
- Upload date:
- Size: 24.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
75947a6b2d24ab3825000d2ffec1b2204daa105d9d70d113beda6fdbdb8f24a1
|
|
| MD5 |
1ffc4c4696b65d819068251eee9006db
|
|
| BLAKE2b-256 |
78d06fe6caab7e555284f0e0ec2d2f53d3b40773c02efc0a408a647655d90354
|
Provenance
The following attestation bundles were made for codex2opencode-0.1.0.tar.gz:
Publisher:
release.yml on Housetan218/codex2opencode
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
codex2opencode-0.1.0.tar.gz -
Subject digest:
75947a6b2d24ab3825000d2ffec1b2204daa105d9d70d113beda6fdbdb8f24a1 - Sigstore transparency entry: 1191106363
- Sigstore integration time:
-
Permalink:
Housetan218/codex2opencode@30d0ad01425a3b915329e742fe854a963f13172e -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Housetan218
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@30d0ad01425a3b915329e742fe854a963f13172e -
Trigger Event:
push
-
Statement type:
File details
Details for the file codex2opencode-0.1.0-py3-none-any.whl.
File metadata
- Download URL: codex2opencode-0.1.0-py3-none-any.whl
- Upload date:
- Size: 16.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5d5097807ae216d5b06df99ee050df9bb47d8282f4e9418155f6d607cfa361d0
|
|
| MD5 |
f8b9d2c59f3906364271223aec20e5e9
|
|
| BLAKE2b-256 |
0adc270f70e2be618943a0af66f36e0fdb13dfe551106498991556b56297b662
|
Provenance
The following attestation bundles were made for codex2opencode-0.1.0-py3-none-any.whl:
Publisher:
release.yml on Housetan218/codex2opencode
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
codex2opencode-0.1.0-py3-none-any.whl -
Subject digest:
5d5097807ae216d5b06df99ee050df9bb47d8282f4e9418155f6d607cfa361d0 - Sigstore transparency entry: 1191106368
- Sigstore integration time:
-
Permalink:
Housetan218/codex2opencode@30d0ad01425a3b915329e742fe854a963f13172e -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Housetan218
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@30d0ad01425a3b915329e742fe854a963f13172e -
Trigger Event:
push
-
Statement type: