Pular para o conteúdo principal
H

dsh-claude-codex-mode

hotheat/dsh-claude-codex-mode

Keeps discussion read-only and hands every repository code edit to the Codex CLI through a bundled MCP server; switches between the DSH model and the Claude Code CLI in the plugin form, with preflight checks and a write guard that blocks structured edits to repo files.

Instalar

dsh plugin --profile web add github:hotheat/dsh-claude-codex-mode

README

dsh-claude-codex-mode

English | 简体中文

Discuss / Execute Split is a DeepSeek Harness (DSH) bundle that splits the work in two: discussion stays read-only, and every repository code edit goes to Codex.

  • Discussion covers requirements, plans, architecture, docs, reading code, and judging whether a fix is worth making. The DSH model does this itself, or forwards it to the Claude Code CLI. The bundle is designed with Claude in mind, so in api mode pick a Claude model as the DSH default.
  • Edits to code or config inside a Git repository go to the Codex CLI through a bundled MCP server. They happen only after you say so ("开始吧 / 做吧 / 执行", that is, "go ahead"). DSH then reviews git status, git diff, and the test results itself before reporting back.

A write guard enforces this split. If the model tries to write a repository code file with a structured edit tool, the guard blocks it and tells the model how to hand the edit to Codex.

Modes

You choose the mode in this plugin's form on the DSH Plugins page. Switching takes effect without restarting DSH.

ModeWho discussesWho editsMCP servers mounted
api (default)The DSH model itself. You configure an Anthropic provider (API key) on the Models page and pick ClaudeCodexcodex-cli
claude-code-cliThe DSH model forwards discussion to the Claude Code CLI in read-only review mode, using your Claude subscription login (no API key)Codex, called by the DSH modelcodex-cli + claude-code

In claude-code-cli mode, Claude Code cannot see the DSH session. The routing prompt therefore tells the DSH model to:

  • send your words and any needed context in each mcp__claude-code__claude_code_run call;
  • continue a topic with resumeSessionId;
  • relay Claude Code's conclusions faithfully.

Preflight checks

When the form opens, it checks the current mode and shows the result:

  • If the current mode passes, the form says so and lists any warnings.
  • If it fails, the form lists each failed check with a fix hint and also checks the other mode. If the other mode passes, its card says it can be switched to.
  • Clicking the card of the other mode checks that mode right away and shows the result. The click only selects the mode; it does not save it.
  • The mode never changes automatically.

When the API card is selected, the form also shows the Anthropic provider settings DSH is using:

  • the base URL;
  • the name of the key variable, and where the key comes from (saved in DSH, the environment, or missing);
  • the configured models and the default model.

These are read-only here. To change them, open Settings → Models. A plugin form cannot open that page for you.

Test connection asks the provider for its model list (GET /v1/models) with the current key, so it uses no tokens.

  • The result tells apart a rejected key, an unreachable address, a timeout, and configured models missing from the list.
  • Some relays don't offer a model list. Then the test can't tell whether the key works, and it shows a warning instead of a failure.
  • The test runs only when you click the button.
  • Redirects are refused, so the key is never sent to a second address.

Clicking Check and save runs a preflight check for the target mode first. If any blocking check fails, the save is refused, the current mode stays, and the form lists each failed check with a fix hint.

ScopeCheckLevel
All modesNode.js ≥ 20Blocking
All modescodex --version succeedsBlocking
All modescodex login status reports logged inBlocking
All modesBundled mcp/codex-cli/server.mjs existsBlocking
apillm-pi-ai has an anthropic provider with at least one modelBlocking
apiThe credential its apiKeyEnv points to exists (checked for presence only)Blocking
apiThe default model is not ClaudeWarning
claude-code-cliclaude --version succeedsBlocking
claude-code-cliclaude auth status reports loggedIn: trueBlocking
claude-code-cliBundled mcp/claude-code/server.mjs existsBlocking

About these checks:

  • Every external command has a timeout.
  • The output reports only whether a check passed. It never shows command output or credential values.
  • The same checks run when DSH starts. At startup a failure only logs a warning.
  • The same checks are available from the command line (see Diagnostics).

Requirements

  • DSH >=0.2.1-rc.2 <0.3.0, Node.js ≥ 20.
  • Codex CLI on PATH and logged in (codex login).
  • For api mode: an Anthropic provider for llm-pi-ai with a saved API key (see below).
  • For claude-code-cli mode: Claude Code on PATH and logged in (claude auth login).

The executables are found through the PATH of the DSH process. To point at a specific binary, set CODEX_CLI_PATH or CLAUDE_CODE_CLI_PATH before starting DSH.

Install

dsh plugin --profile web add github:hotheat/dsh-claude-codex-mode

Then enable it on the Plugins page. It is listed as Discuss / Execute Split, or 讨论执行分工 (claude-codex-mode) in Chinese. No build step is needed.

Configure Claude for api mode

Add an Anthropic provider to your profile patch (for example ~/.dsh/profiles/web/cordis.patch.yml):

- id: llm-pi-ai
  config:
    providers:
      anthropic:
        apiKeyEnv: ANTHROPIC_API_KEY
        # baseURL: <optional relay base URL>
        models:
          - id: claude-sonnet-5-5
          - id: claude-opus-5-5
  • Save the key on the Models page, or put it in the environment or in ~/.dsh/.env. The patch should name only the environment variable, never the key itself.
  • Pick Claude in the model selector and save it as the default model. The bundle cannot set the default model for you, because the profile's agent-default-model row is applied after bundles.
  • Existing sessions keep their model. Switch them with /model.

Write guard

The guard checks the path arguments of four structured file-writing tools: write, edit, str_replace_editor, and apply_patch.

  • str_replace_editor with command: "view" is read-only and always allowed.
  • apply_patch is listed for forward compatibility. DSH 0.2.1-rc.2 has no such tool.
  • bash / pwsh are not checked. The routing prompt tells the model not to use sed -i, heredocs, or redirection to get around the guard, but nothing enforces that.

How each write is decided:

  1. Read the tool's path argument.
  2. Resolve it against the session's current working directory.
  3. Find the nearest Git root and check for the bypass marker.
  4. Allow the write, or deny it with Codex instructions.

Relative paths with no known session directory are denied, and the model is asked to use an absolute path.

The guard allows these writes directly:

  • Files ending in .md, .mdx, .markdown, .txt, .canvas, .base, or .rst (case-insensitive). The exceptions are requirements*.txt, constraints*.txt, and CMakeLists.txt, which count as config.
  • Anything under ~/.claude.
  • Files outside any Git repository.
  • Repositories that contain .claude/direct-edit at their root.
  • Every write, when DSH is started with DSH_DIRECT_EDIT=1 or CLAUDE_DIRECT_EDIT=1.

If the Codex tools fail to come online, the guard stays active, and its deny message says that Codex is unavailable.

Diagnostics

From a clone of this repository:

npm install
npm run doctor
npm run doctor -- --mode claude-code-cli --profile web
  • doctor runs the same preflight checks offline and exits non-zero if a blocking check fails.
  • In api mode it reads the selected profile's cordis.patch.yml without evaluating !!js expressions.
  • It looks for the credential in the DSH credential store, the process environment, the project .env, and ~/.dsh/.env.

Codex and Claude Code background job state is stored under <DSH home>/claude-codex-mode/.

Development

npm test
node --test mcp/*/tests/*.test.mjs

npm test runs four suites:

  • the policy tests;
  • table-driven preflight tests with injected command results;
  • the doctor and form tests;
  • a real Cordis load test that switches modes both ways and checks how the MCP servers mount and unmount.

The load test finds Cordis through DSH_CORDIS_PATH, and failing that through a global @deepseek-ai/dsh install (npm root -g). If neither is found, it is skipped with a message.

Attribution and license

The bundled MCP servers in mcp/codex-cli and mcp/claude-code come from the author's own earlier plugins. See ATTRIBUTION.md for where each part comes from.

MIT © 2026 Jiaoguo

Plugins relacionados