Skip to content

Releases: 447662/dsh-native-codex-cli

v0.2.3 - resolver correctness, green cross-platform CI

Choose a tag to compare

@447662 447662 released this 03 Oct 01:00

v0.2.3 — resolver correctness, and a green cross-platform CI

Follow-up to v0.2.2. That release's own CI went red on the new check, which is precisely what the check is for.

What was wrong

lib/resolve-bin.js is written to be pure and testable — it takes platform and env as parameters. But it split the candidate PATH with the host's path.delimiter instead of the target platform's. On Linux CI, a fabricated Windows PATH (A;B) was therefore treated as a single entry, and each drive letter would have been shredded into a bogus candidate.

Production was not affected: platform is process.platform there, so host and target always agreed. The defect made the self-check meaningless off-platform — which the CI caught immediately.

The fix

  • Split PATH with the target platform's separator (; on Windows, : elsewhere); join POSIX candidates with posix.join.
  • The self-check now also asserts that no drive letter is split into a bogus entry — the assertion that caught this.

Verified on Linux CI (run #4, green) and locally on Windows, including the real scenario the previous release was about: with the Codex directory removed from PATH, the resolver still finds the desktop app's CLI:

PATH = C:\Windows\system32;C:\Windows      (where.exe codex → not found)
resolveCodexBin() → C:\Users\<you>\AppData\Local\Programs\OpenAI\Codex\bin\codex.exe

CI now covers four checks

Step What it protects
Encoding guard no tracked file is non-UTF-8 or BOM-prefixed
Load-time self-check bundle preamble, six slot declarations, composer selector purity, session-mirror event shapes, the Markdown renderer
Missing-binary self-check a missing Codex CLI rejects cleanly instead of killing the DSH host
CLI resolution self-check the candidate list covers the Codex desktop app directory on Windows and POSIX

Install

dsh plugin --profile desktop add git+https://github.com/447662/dsh-native-codex-cli.git

Then restart DSH.

Full documentation: README (中文) · README (English)

v0.2.2 - find the CLI the Codex desktop app already installed

Choose a tag to compare

@447662 447662 released this 03 Oct 00:57

v0.2.2 — find the CLI the Codex desktop app already installed

The symptom

On a machine where the Codex desktop app was installed, the plugin still reported:

spawn codex ENOENT   path: 'codex'   spawnargs: [ 'app-server' ]

The CLI was there all along: the desktop installer puts it in its own directory and appends it to the user environment. But DSH is Electron, and a process that inherited a stale environment — one already running, or one started by explorer.exe, which keeps the environment it had at logon — cannot see that directory. So "Codex is installed" and "Codex is missing" looked exactly the same.

The fix

lib/resolve-bin.js no longer trusts PATH alone. It searches, in order:

Platform Locations
Windows PATH → %LOCALAPPDATA%\Programs\OpenAI\Codex\bin (the desktop app's own CLI) → %LOCALAPPDATA%\OpenAI\Codex\bin → %ProgramFiles%\OpenAI\Codex\bin → %APPDATA%\npm → %LOCALAPPDATA%\pnpm → ~/.codex/packages/standalone/current/bin → ~/.codex/bin → ~/.codex/plugins/.plugin-appserver → the standalone releases/<version>/bin tree, newest first
macOS / Linux PATH → ~/.codex/packages/standalone/current/bin → ~/.codex/bin → ~/.local/bin → /usr/local/bin → /opt/homebrew/bin → /usr/bin
  • The resolved absolute path is logged and exposed on GET /dsh-native-codex-cli/health, so support questions answer themselves.
  • An explicit codexBin is still respected verbatim — the search never silently substitutes a different binary.
  • A bare codexBin name is searched for too.
  • When nothing is found, the error now lists every directory that was searched.

Verified on a real machine with the Codex desktop app installed, with the Codex directory removed from PATH:

live resolution (stale PATH): C:\Users\<you>\AppData\Local\Programs\OpenAI\Codex\bin\codex.exe

Tests

test/resolve-bin-check.mjs injects a fake environment and asserts the candidate list for Windows and POSIX (including that PATH entries come first and that the desktop app's directory is present). It runs on CI with no Codex installed. Wired into npm run check and the workflow.

Still true from v0.2.1

A missing CLI can no longer take DSH down: the default 'error' listener, the spawn/initialize race, and the actionable message are all in place, guarded by test/spawn-failure-check.mjs.

Install

dsh plugin --profile desktop add git+https://github.com/447662/dsh-native-codex-cli.git

Then restart DSH.

Full documentation: README (中文) · README (English)

v0.2.1 - a missing Codex CLI no longer crashes DSH

Choose a tag to compare

@447662 447662 released this 03 Oct 00:53

v0.2.1 — a missing Codex CLI no longer crashes DSH

The bug

On a machine without the Codex CLI installed, starting DSH with this plugin enabled killed the whole host process:

dsh: fatal uncaught exception: Error: spawn codex ENOENT
    at onErrorNT (node:internal/child_process:508:16)
  errno: -4058,
  code: 'ENOENT',
  syscall: 'spawn codex',
  path: 'codex',
  spawnargs: [ 'app-server' ]

The app showed "应用无法启动或已意外停止" and could not start at all.

Why it was fatal rather than a normal error: the stdio transport's error handler called this.emit('error', error) on an EventEmitter with no 'error' listener. Node's EventEmitter rethrows in that case, and it rethrows synchronously inside a Node event handler — so the RPC route's try/catch never saw it. A plugin must never be able to do that.

The fix

  • A default 'error' listener is always installed, so emitting can no longer throw. Extra listeners still receive the same error.
  • start() now rejects instead of leaving the caller to wait out the 20s handshake timeout: the initialize request races the spawn failure, and the child is torn down on the losing path.
  • ENOENT / EACCES are described in terms of what to do:

    未找到 Codex CLI:无法执行 "codex"。请先安装 Codex CLI(npm i -g @openai/codex),或在配置里把 codexBin 指向它的完整路径

  • A synchronous throw from spawn (bad cwd, invalid args) is handled too.
  • The UI shows the reason in a banner that clears itself as soon as any RPC succeeds again.
  • test/spawn-failure-check.mjs runs against a deliberately missing binary and asserts that start() rejects with an actionable message, that nothing escapes as an unhandled rejection or uncaught exception, and that a retry still behaves. It is wired into npm run check and CI.

If you are stuck on the crashing version

The crash dialog has an escape hatch: "禁用第三方插件、备份 profile patch 并重启" — use it to boot DSH with third-party plugins disabled, then either install the Codex CLI or remove this plugin, restart, and install v0.2.1.

Install

dsh plugin --profile desktop add git+https://github.com/447662/dsh-native-codex-cli.git

Then restart DSH.

Also in this release

Carried over from v0.2.0: the plugin was renamed from dsh-codex (that name belongs to an unrelated plugin on npm and GitHub).

Requirements: DeepSeek Harness with the Web GUI, Codex CLI on PATH and logged in (codex --version), Node 18+ for the self-checks.

Full documentation: README (中文) · README (English)

v0.2.0 - renamed to dsh-native-codex-cli

Choose a tag to compare

@447662 447662 released this 03 Oct 00:35

v0.2.0 — renamed to dsh-native-codex-cli

Renamed from dsh-codex. That name is already used on npm and on GitHub by an unrelated plugin (Yan-Zero/dsh-codex, a ChatGPT-subscription provider for DSH) which also carries the dsh-plugin topic — two different plugins would have appeared under the same name in the plugin hub. The old repository URL redirects here, but the package name, plugin id, HTTP routes, storage directory and log file all changed, so v0.1.0 should not be installed any more.

DSH owns the chat interface; the Codex CLI owns task execution and native thread history. Tasks go straight to Codex — no second AI paraphrases them, and no chat archive is replayed to fake continuity.

What it does

  • Old conversations — list Codex threads from thread/list, restore the selected one with thread/resume
  • New task — create a native thread with an explicit working directory, model, approval policy and sandbox
  • Send — the message goes verbatim into turn/start; follow-ups during a run use turn/steer
  • Streaming — item/*/delta frames accumulate live, with tool cards for command execution (output, exit code, duration), file changes (with diff), MCP / dynamic tool calls, and errors
  • Stop — turn/interrupt, a real interrupt; pending approvals are refused first so it is not queued behind an unanswered prompt
  • Approvals & questions — command / file-change / permission requests and request_user_input become UI cards, and the choice is sent back to Codex
  • Refresh & restart — the session⇄thread binding is persisted, clientMessageId makes resends idempotent, and SSE reconnects re-read a snapshot
  • Images — paste or pick a screenshot; it is staged on disk and sent as a localImage input, and the transcript shows a thumbnail you can click to enlarge
  • Markdown — Codex's replies render properly (headings, lists, quotes, code, links)

Where it appears

A standalone Codex panel in the sidebar, a Codex view inside any session, a composer takeover for bound sessions, an @codex hand-off button in the native composer, and a main-page dock showing the Codex conversation plus its context (directory / model / approval / sandbox).

@codex is case-insensitive and also accepts the full-width @.

Verified

Check Result
npm run check:utf8 every tracked file is clean UTF-8
npm run check:load green — bundle preamble, slot declarations, event shapes, Markdown renderer
npm run check:smoke 25/25 against a real codex app-server, including a real approval round-trip and a real interrupt
npm run check:http 22/22 over the exact RPC + SSE surface the browser uses

Tested against Codex CLI 0.153.4 and the DSH Desktop desktop profile.

Install

dsh plugin --profile desktop add git+https://github.com/447662/dsh-native-codex-cli.git

Then restart DSH (a profile's bundle list is not hot-reloaded).

Requirements

  • DeepSeek Harness with the Web GUI (desktop or dsh web)
  • Codex CLI on PATH, logged in (codex --version)
  • Node 18+ for the self-checks only

Known limitations

transport: daemon is still a reserved adapter; Codex threads are process-scoped (auto-resumed on demand); thread/turns/list is unimplemented in Codex 0.153.4 so history comes from thread/resume; and assistant/message cannot be authored by a plugin (it embeds the provider stream), so the DSH session log mirrors the user side and Codex's answers render in the main-page dock. See the README for the full list.

Full documentation: README (中文) · README (English) · Protocol reference