Repository navigation
Codex extension interop - #2
Merged
Merged
Conversation
#1) New default-off codex_interop option ({ import, export, codex_home }): - import: Codex's consolidated MEMORY.md/memory_summary.md are byte-compared and copied into extensions/codex_import/ inside the claimed phase-2 job (after baseline, before diff capture), so changes consolidate in the same run. Artifacts-gone drops the copies as a forgetting signal; an unreachable Codex home is a no-op, never a deletion signal. - export: after a successful consolidation, validated artifacts are copied into $CODEX_HOME/memories/extensions/opencode_import/ with instructions for Codex's consolidator. Strictly additive: never bootstraps Codex's workspace, never touches its state DB. Both instructions files carry provenance tags ([from codex]/[from opencode]) and forbid re-importing the other side's tag, so memories don't ping-pong. Follows the extension mechanism Codex itself uses to import Claude memories (external_agent_import); adaptation recorded in codex-map.yaml.
…rules The overlap guard case-folded paths on darwin/win32 only. Actual case sensitivity is per volume/directory (case-sensitive APFS, per-dir Windows flags, casefold ext4), and Unicode normalization aliases paths besides case. Compare existing paths by dev:ino instead: self-or-ancestor walk catches case aliasing, NFC/NFD aliasing, symlinks, and bind mounts on any platform, and walks over nonexistent tail components. When both roots exist and the inode walk finds no relation, trust it over the lexical guess (a case-variant path on case-sensitive APFS is a real, distinct directory). The case-folding lexical comparison remains only as fallback for roots that do not exist yet.
The plugin never hard-fails on invalid options, and plugin console warnings are effectively invisible in the TUI — so there was no reliable place to verify the configuration took effect. Move the options state into src/options.ts (leaf module, no import cycle) with a config-warning registry; applyPluginOptions records unknown-key and malformed-value warnings there. memory_inspect now echoes the effective (post-parse, post-clamp) options, any recorded warnings, and the resolved codex_interop state including whether the Codex memories root exists. Document memory_inspect as the configuration check in the README.
Drift audit 6c00dc0..4c43465 (17 watched files, +1209/-656): all changes are no-ops for the port. - state/runtime/memories.rs: is_pinned column plumbing only; memory eligibility query passes is_pinned: None (no pin filter). Claim/lease/ enqueue/watermark/cooldown semantics untouched. - memories/write/runtime.rs: StartThreadOptions spawn refactor with equivalent defaults; ItemIds feature retired (always-on). - ext/memories: step-store trait-param removal; injection/gating identical. - features/config: Memories + ExternalAgentMemoryImport specs and MemoriesToml defaults/clamps unchanged. - codex-mcp/mcp_tool_call: connection-set refactor; pollutes_memory still unconditionally true, marking still gated on disable_on_external_context. - external-agent-migration memory importer: zero diff (memory_import.rs, memory.rs, detect/memory.rs); upstream additions are provider-attribution import-history bookkeeping in the state-DB layer the port deliberately lacks. - thread pinning is memory-neutral (reconcile stamps no memory_mode). No ports, no note changes needed.
moritzfl
force-pushed
the
codex-extension-interop
branch
from
July 25, 2026 05:39
740a80e to
a38375f
Compare
moritzfl
marked this pull request as ready for review
July 25, 2026 05:40
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1
What this adds
If you use both OpenCode and the Codex CLI on the same machine, this plugin can now share consolidated memory between the two — in either or both directions. Everything is off by default and enabled per direction:
{ "plugin": [ ["opencode-codex-memory", { "codex_interop": { "import": true, "export": true } }] ] }import(what [feature-request] : Is it possible to reuse the Codex memory? #1 asked for): Codex's consolidatedMEMORY.md/memory_summary.mdare copied into a memory extension (extensions/codex_import/) during each consolidation pass. The consolidator merges what is new into OpenCode's memory, tagging it[from codex].export(the symmetric return path): after each successful consolidation, this plugin's consolidated memory is written into Codex's workspace as an extension (extensions/opencode_import/), together with aninstructions.mdfor Codex's own consolidator. Codex picks it up on its next consolidation — no Codex-side configuration needed.codex_homeoverrides where Codex lives (default:$CODEX_HOME, else~/.codex).How it works
Both memory systems already ship a generic extension contract: whenever
extensions/exists, the consolidation prompt instructs the agent to read every extension'sinstructions.mdand interpret its resources. Codex itself uses exactly this mechanism to import Claude memories (external_agent_import). This PR mirrors that pattern in both directions: byte-equality change detection, per-file replace, deletion of copies as the "forgetting" signal in the workspace diff, and resource files placed so retention pruning never touches them.To keep memories from ping-ponging between the systems, both instruction files enforce provenance tags (
[from codex]/[from opencode]) and forbid re-importing content that carries the other side's tag. Foreign metadata (Codex thread UUIDs, OpenCodeses_*ids, citation blocks) is never reinterpreted.Why not the originally discussed approach
The first design explored for #1 mounted Codex's memory directory as a second, read-only memory root. That made imported memory instantly readable, but it dragged complexity into the core of the memory implementation: every read tool needed to become source-aware, the injected summary needed a split token budget across two roots, search results needed virtual path prefixes, and the "memory is global, one root" invariant — which this port inherits from Codex — would have been strained permanently.
The extension approach keeps the core untouched: no read-path changes, no schema changes, no source-aware tools. Sharing is pure content that flows through the consolidation pipeline both systems already have. The trade-off is latency: imported knowledge becomes visible after the next consolidation pass rather than immediately. In exchange, the imported material is properly merged, deduplicated, routed, and pruned like any other memory instead of being a second bolted-on view.
Safety properties
$CODEX_HOME/memories), never modifies Codex-owned files, and never touches Codex's state database. Deletions cannot escapeextensions/opencode_import/.memory_inspectnow echoes the effective plugin options, configuration warnings (unknown/malformed keys), and the resolved interop state, so the setup can be verified in-band.