Migrating from Codex / Claude Code
Three migration paths: model-level compatibility (Responses API), reusing existing hooks.json (hook bridges), and native Cordis plugins
If you currently use OpenAI Codex or Anthropic Claude Code, DeepSeek Harness offers three gradual migration paths. This page is compiled from the upstream hooks subsystem documentation and the official DeepSeek API announcement.
First: decide whether to migrate at all
The harness is still in the developer preview stage, while Codex and Claude Code are mature products. If your current tool already fits, there is no need to switch just because DeepSeek's official benchmarks use the harness — those scores are system scores of "model + harness + configuration + tool environment", see benchmark interpretation.
The three paths can be combined as needed:
| Path | Approach | Best for |
|---|---|---|
| 1. Model-level compatibility | Keep Codex, point the model at the DeepSeek API | Using DeepSeek V4 first without switching tools |
| 2. Hook bridges | Move to dsh, reuse your existing hooks.json | Teams with established hook workflows that want a smooth switch |
| 3. Native plugins | Rewrite custom logic as Cordis plugins on extension points | Long-term investment needing typed returns and stronger capabilities |
Path 1: model-level compatibility
The DeepSeek API natively supports the OpenAI Responses API format, adapted for Codex; the official docs provide a one-click configuration script to wire Codex up (see the DeepSeek API announcement). For model setup details, see configure models.
Nearly zero cost
No workflow or editor changes — just swap the model endpoint — and you can compare DeepSeek models on your own tasks. This is also the fastest way to evaluate "model vs tool" contributions.
Path 2: hook bridges
The harness's hooks subsystem lets you point existing Claude Code / Codex hook configurations at bridge plugins, so those external shell hooks keep running on the harness's typed interception points. Both bridges are Cordis plugins:
Claude Code bridge (dsh-hooks-claude-code)
Reads a Claude Code hooks.json (or a settings file's hooks key). The mapped hook points:
| Claude Code hook | Behavior |
|---|---|
SessionStart | additionalContext injected into the new session (cannot block) |
UserPromptSubmit | deny → reject the step; additionalContext → appended context |
PreToolUse | deny → deny the tool call; ask → convert to an approval request |
PostToolUse | deny → block with feedback; additionalContext → prepended context |
Stop | block Stop and steer the reason back, forcing the agent to run one more step |
SubagentStart / SubagentStop | inject context / observe only |
Enable it in cordis.yml:
- dsh-hooks-claude-code:
configPath: ./.claude/hooks.json
pluginRoot: ./.claude/plugins/my-plugin
projectDir: .configPath: required; a process-level config, parsed once at load.pluginRoot: replaces${CLAUDE_PLUGIN_ROOT}in command strings.projectDir: replaces${CLAUDE_PROJECT_DIR}and sets the hook env var; defaults to the session cwd.- Only
type: 'command'hooks run;http/mcp_tool/prompt/agentare parsed and skipped (with a warning). - Hook processes run in the session workspace directory; multiple hooks on one point run serially in config order, with decisions folded by strictness (
deny > ask > allow).
Codex bridge (dsh-hooks-codex)
Reads a Codex hook configuration, implementing 5 of its 10 hook points: PreToolUse, PostToolUse, SessionStart, UserPromptSubmit, Stop.
- dsh-hooks-codex:
configPath: ./.codex/hooks.json
model: deepseek-v4- Matchers are always interpreted as regular expressions; the stdin payload is snake_case with extra
turn_idandmodelfields. - No Codex plugin env injection and no config-time placeholder substitution.
- No tool pre-approval or rewrite paths: hooks can block, but never pre-approve or replace tool input.
- Only synchronous
type: 'command'hooks run;async: truehooks are skipped (with a warning).
Bridge boundaries
Bridges are compatibility paths, not the full capability
Both bridges cover only a deliberate subset of their protocols. Parse failures are isolated (a warning, and nothing is registered) so a typo never stops the agent; but native Cordis plugins can do everything a bridge does, with typed returns and no serialization boundary. All deep customization should move to native plugins (see the developer guide).
Path 3: native Cordis plugins
Underneath, the bridges sit on the harness's typed interception points (agent/pre-step, tools/pre-execute, tools/post-execute, etc. — see Host Services & Events). A "native hook" is just an ordinary Cordis plugin mounted on those same points: the bridges translate the external shell-hook protocol onto them, and your own plugins can consume them directly.
Concept mapping
| Codex / Claude Code | DeepSeek Harness |
|---|---|
hooks.json (shell hooks) | cordis.yml plugins (or hook bridges as a compatibility layer) |
PreToolUse deny / ask | tools/pre-execute waterfall decisions (deny / ask) |
${CLAUDE_PLUGIN_ROOT} | the bridge's pluginRoot config |
| Product-built approvals | Built-in permission presets and approval policy |
| Terminal CLI | Web GUI / headless / CLI entry modes |
Suggested route
- Get model-level compatibility working first (path 1) and A/B on your own task set;
- Add the bridges when you need your hook workflows (path 2), gradually rewriting high-frequency hooks as native plugins (path 3);
- Keep the old tool as a fallback during migration — run both in parallel until you are ready to switch.
Related pages
- Model and endpoint setup: configure models
- Permissions and approvals: security & compliance
- Plugin installation: plugin ecosystem
- Writing native plugins: Cordis primer
Python SDK
Install the Python SDK, run the checked-in agent composition, and call the same API from your own program
Configuration Reference
Curated lookup of the DeepSeek Harness settings, credentials, environment variables, model routes, sandbox modes, and persistence options users and plugin authors touch most