Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
8deba48
feat: convert Codex plugin to OpenCode plugin (Phase 0+1)
TheRealDinghyDog Jul 7, 2026
a8683ab
fix: capture OpenCode structured (json_schema) output for reviews
TheRealDinghyDog Jul 7, 2026
b667fb2
feat: Phase 2 — server lock, targeted cancel, review test hardening
TheRealDinghyDog Jul 7, 2026
06cf42e
feat: Phase 3 — transfer Claude sessions into OpenCode
TheRealDinghyDog Jul 8, 2026
ab3917d
fix: transfer — skip sidechain/subagent entries; harden import test
TheRealDinghyDog Jul 8, 2026
68570a0
fix(#2): recover slow turns instead of failing on transport timeout
TheRealDinghyDog Jul 8, 2026
f69ee41
Fix issue #4 state races
TheRealDinghyDog Jul 8, 2026
e1315b4
fix: address issue #2 transport review fixes
TheRealDinghyDog Jul 8, 2026
8ff877b
test(#2): fix resume regression test to match realpath'd workspace
TheRealDinghyDog Jul 8, 2026
38bc9f7
Fix issue #4 lease dedupe review
TheRealDinghyDog Jul 8, 2026
e9f9560
Merge pull request #7 from TheRealDinghyDog/fix/issue-2-transport
TheRealDinghyDog Jul 8, 2026
2b56236
Merge pull request #8 from TheRealDinghyDog/fix/issue-4-state-races
TheRealDinghyDog Jul 8, 2026
322429f
Fix correctness bugs from issue #3
TheRealDinghyDog Jul 8, 2026
3d1be6a
Merge pull request #9 from TheRealDinghyDog/fix/issue-3-correctness
TheRealDinghyDog Jul 8, 2026
7ac899a
Fix resource leaks (#5)
TheRealDinghyDog Jul 8, 2026
cdbbc5c
Fix issue #5 finding 3 session cleanup
TheRealDinghyDog Jul 8, 2026
a99a89b
Merge pull request #10 from TheRealDinghyDog/fix/issue-5-leaks
TheRealDinghyDog Jul 8, 2026
f03d874
Fix error-handling gaps (#6)
TheRealDinghyDog Jul 8, 2026
bcb754a
Merge pull request #11 from TheRealDinghyDog/fix/issue-6-error-handling
TheRealDinghyDog Jul 8, 2026
e4a5a09
Fix issue #12 async OpenCode turn transport
TheRealDinghyDog Jul 9, 2026
d0cf2cc
Fix OpenCode sync transport recovery for issue #12
TheRealDinghyDog Jul 9, 2026
9103bea
test(#12): drop bogus turnId assertion in pop-fallback recovery test
TheRealDinghyDog Jul 9, 2026
d97b1ed
Merge pull request #14 from TheRealDinghyDog/fix/issue-12-transport-a…
TheRealDinghyDog Jul 9, 2026
7137dab
fix: avoid reading untracked symlink targets (#16)
TheRealDinghyDog Jul 9, 2026
c07fc6f
fix: harden cancel teardown leases (#13)
TheRealDinghyDog Jul 9, 2026
94edd96
Harden OpenCode turn transport and recovery (#15)
TheRealDinghyDog Jul 10, 2026
453a0be
Merge pull request #20 from TheRealDinghyDog/fix/issue-13-cancel-hard…
TheRealDinghyDog Jul 10, 2026
7e89328
Merge pull request #21 from TheRealDinghyDog/fix/issue-15-transport-h…
TheRealDinghyDog Jul 10, 2026
53b5f49
Merge pull request #22 from TheRealDinghyDog/fix/issue-16-symlink
TheRealDinghyDog Jul 10, 2026
47d3599
Fail closed when the stop-review gate's reviewer is unavailable (#18)
TheRealDinghyDog Jul 10, 2026
a5abc05
Tighten npm-pack surface; drop Codex conversion residue (#17)
TheRealDinghyDog Jul 10, 2026
be87a3d
Merge pull request #24 from TheRealDinghyDog/fix/issue-18-stopgate
TheRealDinghyDog Jul 10, 2026
5ec0dae
Merge pull request #23 from TheRealDinghyDog/fix/issue-17-packaging
TheRealDinghyDog Jul 10, 2026
153f9ba
Harden server lifecycle and state-lock robustness (#19)
TheRealDinghyDog Jul 10, 2026
185005b
Merge remote-tracking branch 'origin/opencode-conversion' into fix/is…
TheRealDinghyDog Jul 10, 2026
4bdc1c5
Merge pull request #25 from TheRealDinghyDog/fix/issue-19-lifecycle
TheRealDinghyDog Jul 10, 2026
aa766f0
Deny gated permissions in headless runs; drop the session wildcard (#26)
TheRealDinghyDog Jul 10, 2026
16d2a8e
Merge pull request #34 from TheRealDinghyDog/fix/issue-26-write-permi…
TheRealDinghyDog Jul 10, 2026
c73978a
Authenticate plugin-owned OpenCode servers; support secured external …
TheRealDinghyDog Jul 10, 2026
2940cde
Merge pull request #35 from TheRealDinghyDog/fix/issue-27-server-auth
TheRealDinghyDog Jul 10, 2026
a13c272
Merge PR #35 (server auth) into opencode-conversion
TheRealDinghyDog Jul 10, 2026
531edc7
Implement the real OpenCode event contract; reject headless questions…
TheRealDinghyDog Jul 10, 2026
ed8ac3d
Merge pull request #36 from TheRealDinghyDog/fix/issue-28-event-contract
TheRealDinghyDog Jul 10, 2026
0508cc4
Bind requests to the invoking workspace; persist server ownership (#29)
TheRealDinghyDog Jul 10, 2026
ba7e063
Merge pull request #37 from TheRealDinghyDog/fix/issue-29-directory-o…
TheRealDinghyDog Jul 10, 2026
2f7d100
Poll for recovery after a stream drop instead of failing at the grace…
TheRealDinghyDog Jul 10, 2026
547a0d2
Merge pull request #38 from TheRealDinghyDog/fix/issue-30-stream-drop…
TheRealDinghyDog Jul 10, 2026
67429a4
Verify server PID identity before teardown kills (#31)
TheRealDinghyDog Jul 10, 2026
63ce798
Split normal vs adversarial review prompts; honest setup provider che…
TheRealDinghyDog Jul 10, 2026
26f3137
Fix install docs, widen CI matrix, neutral transfer metadata (#33)
TheRealDinghyDog Jul 10, 2026
7803a66
Merge pull request #39 from TheRealDinghyDog/fix/issue-31-server-pid-…
TheRealDinghyDog Jul 10, 2026
d008cd3
Merge pull request #40 from TheRealDinghyDog/fix/issue-32-review-and-…
TheRealDinghyDog Jul 10, 2026
a4d6f83
Fix the Windows failures the new CI matrix surfaced (#33)
TheRealDinghyDog Jul 11, 2026
d28899e
Merge pull request #41 from TheRealDinghyDog/fix/issue-33-docs-and-ci
TheRealDinghyDog Jul 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
{
"name": "openai-codex",
"name": "opencode",
"owner": {
"name": "OpenAI"
"name": "OpenCode"
},
"metadata": {
"description": "Codex plugins to use in Claude Code for delegation and code review.",
"description": "OpenCode plugins to use in Claude Code for delegation and code review.",
"version": "1.0.5"
},
"plugins": [
{
"name": "codex",
"description": "Use Codex from Claude Code to review code or delegate tasks.",
"name": "opencode",
"description": "Use OpenCode from Claude Code to review code or delegate tasks.",
"version": "1.0.5",
"author": {
"name": "OpenAI"
"name": "OpenCode"
},
"source": "./plugins/codex"
"source": "./plugins/opencode"
}
]
}
20 changes: 11 additions & 9 deletions .github/workflows/pull-request-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,17 @@ permissions:

jobs:
ci:
name: CI
runs-on: ubuntu-latest
name: CI (Node ${{ matrix.node-version }}, ${{ matrix.os }})
runs-on: ${{ matrix.os }}
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
node-version: [18.18, 20, 22]
include:
- os: windows-latest
node-version: 22

steps:
- name: Check out repository
Expand All @@ -19,17 +27,11 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 22
node-version: ${{ matrix.node-version }}
cache: npm

- name: Install dependencies
run: npm ci

- name: Install Codex CLI
run: npm install -g @openai/codex

- name: Run test suite
run: npm test

- name: Run build
run: npm run build
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,6 @@ vite.config.ts.timestamp-*
.vite/

output/
plugins/codex/.generated/

# Local Codex rescue-subagent config (not part of the OpenCode plugin)
.codex/
46 changes: 46 additions & 0 deletions IMPLEMENTATION_NOTES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Implementation Notes

## Status: Phase 0 + Phase 1 complete and verified live

### Phase 0 — scaffold (done)
- Plugin moved to `plugins/opencode`; manifests/package metadata updated; `OPENCODE_COMPANION_*` env vars adopted; Codex app-server type generation and TS build removed.

### Phase 1 — runtime bridge (done, verified against a real `opencode serve`)
- `server-lifecycle.mjs` (ensure/reuse/teardown a headless `opencode serve`, health-poll startup, `OPENCODE_COMPANION_SERVER_URL` override), `opencode-server.mjs` (zero-dep fetch + SSE client), `opencode.mjs` (SSE turn capture). Codex app-server broker files deleted.
- Fake `opencode serve` test harness with HTTP/SSE endpoints and permission prompts.

### Fixes applied after the initial implementation (all verified)
The first pass shipped unrun (the build sandbox couldn't bind 127.0.0.1). Running against a real server surfaced and fixed:
1. **create-session body** — removed `directory` and `model` (the real `POST /session` returns HTTP 400 on both; `additionalProperties:false`, and `model` is sent per-message). `title` included only when a non-empty string.
2. **Headless permission auto-approval** — write sessions attach `{permission:"*",action:"allow",pattern:"*"}`; read-only uses the built-in `plan` agent. `respondPermission` posts `{ response: "always" | "reject" }` (the endpoint enum is once|always|reject, additionalProperties:false).
3. **Model normalization** — `spark` → `openai/gpt-5.3-codex-spark`, `provider/model` → `{providerID,modelID}`; bare/partial model → null (avoids a 400).
4. **Final message** — reasoning parts excluded so the answer isn't prefixed with reasoning text.
5. **`extractPermissionId`** — prefers the permission id over the `evt_` envelope id.
6. **`session.error`** — extracts a readable message instead of `[object Object]`.
7. **Fake fixture** — `/event` flushes SSE headers; create-session now rejects `directory`/`model`, and the permission endpoint enforces the `response` enum, so the tests guard these regressions.

### Live verification (real `opencode serve`, this machine)
- Write turn: edit auto-approved with no permission stall; `smoke.txt` written. ✓
- Read-only turn: clean answer, no edits (read-only respected). ✓
- Created sessions visible in `opencode session list` for the project dir (characteristic #2). ✓
- Progress streamed to the Claude TUI (Starting / Session ready / Edited / Assistant message / Turn completed). ✓
- `npm test` — 30/30 green. ✓
- Codex read-only review of the fixes: all 7 confirmed correct; LOW findings (title/model guards, fixture schema enforcement) applied.

## Phase 2 — command surface + hardening (done)
Delegated to Codex, then a two-way review round (Claude reviewed Codex; Codex reviewed the result), then Codex's findings fixed. `npm test` 32/32.
- **`/opencode:review` structured output** — OpenCode returns `json_schema` output as a synthetic `StructuredOutput` tool part (`state.input`), not text; captured it (was returning unparseable prose). Regression test added.
- **`ensureServer` inter-process lock** — atomic `mkdirSync` lock with token-matched release, double-checked healthy-session read, and dead-PID/age stale detection. Codex's review found 3 real bugs, now fixed: stale-takeover TOCTOU → atomic single-winner rename-steal; leaked lock on owner-file write failure → cleanup-on-failure; age note. Race-safe boot-marker test (serverStarts counter was itself racy).
- **Targeted cancel** — per-job `serverUrl` recorded so cancel aborts the exact server that ran the turn (fallback to `ensureServer`).
- **Prompting skill** — `gpt-5-4-prompting` generalized to be provider-neutral; `codex-prompt-*.md` → `opencode-prompt-*.md`.
- **Housekeeping** — dropped unused `typescript` devDep; `.codex/` gitignored; removed stale CI `npm run build`.

## Phase 3 — transfer (done)
Delegated to Codex; live-verified end-to-end by Claude (real transcript → `opencode import` → resumable session with correct roles/order/text). `npm test` 35/35.
- **`transfer`** — converts the Claude JSONL transcript to an OpenCode import document and runs `opencode import <file>`; returns the new `ses_...` id and prints `opencode --session <id>` for resume.
- Non-text content (thinking/tool_use/tool_result/images) is skipped; timestamps are normalized to strictly increasing so order is preserved.
- Edge-case fix (found via live testing): assistant turns before the first user message are dropped — `opencode import` rejects a null `parentID`.

## Deferred
- **Review sessions persist** — read-only review sessions are not deleted; acceptable, or delete for ephemeral parity.
- **Optional** — regenerate TypeScript types from OpenCode's OpenAPI (`GET /doc`) to restore a type-check build.
Loading