🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

Codex 迁移 BigBlueBaby/codex2dsh

DeepSeek Harnessv0.1.4
BigBlueBaby69 天前有提交已提供中文文档扫描:含敏感能力

把 Codex 的配置与记忆一键搬进 DSH

29.9/100
综合分
3
GitHub 星标
229
npm 周下载
—/5
用户评分

数据截至 2026/9/20 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add codex2dsh
npm 源 · codex2dsh 的发布者账号已校验与本仓库一致

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么[目录]—
dsh 原生插件 · chat
暂无时间戳·判据 →
装得上吗[实装验证]✓
静态安装检查通过
未做真实安装
L4 · 真实安装等级说明 →
数据截至 2026/10/29·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/04·判据 →
还在维护吗[仓库]—
更新放缓:最近一次提交在 69 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →

可信度证据

安装兼容性检查✓ 自动检查通过
展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包codex2dsh @ 0.1.4
✓Node 引擎要求 >=22.19 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/9/21 23:45:22

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

读写/删除本地文件发起外部网络请求
查看扫描证据(共 144 处,展示前 83 条)
  • 发起网络请求
    client/index.js:190
    const res = await fetch(path, body
  • 读取本地文件
    bin/codex2dsh.mjs:135
    if (!existsSync(skillsDir)) return fail(`未找到技能目录 ${skillsDir}`)
  • 读取本地文件
    lib/tools.mjs:114
    if (!existsSync(skillsDir)) {
  • 读取本地文件
    lib/scan.mjs:26
    if (existsSync(configPath)) {
  • 读取本地文件
    lib/scan.mjs:27
    parsed = parseCodexConfig(readFileSync(configPath, 'utf8'))
  • 读取本地文件
    lib/scan.mjs:52
    if (existsSync(skillsDir)) {
  • 读取本地文件
    lib/scan.mjs:53
    const names = readdirSync(skillsDir, { withFileTypes: true })
  • 读取本地文件
    lib/scan.mjs:62
    if (existsSync(p)) {
  • 读取本地文件
    lib/scan.mjs:63
    items.push({ kind: 'instruction', name: f, status: 'previewed', note: `${statSync(p).size} bytes` })
  • 读取本地文件
    lib/ledger.mjs:14
    if (!existsSync(file)) return []
  • 读取本地文件
    lib/ledger.mjs:15
    const raw = readFileSync(file, 'utf8')
  • 写入本地文件
    lib/ledger.mjs:31
    mkdirSync(dir, { recursive: true })
  • 读取本地文件
    lib/ledger.mjs:33
    const entries = existsSync(file) ? readLedger(ledgerDir) : []
  • 写入本地文件
    lib/ledger.mjs:40
    writeFileSync(tmp, JSON.stringify(entries, null, 2), 'utf8')
  • 写入本地文件
    lib/ledger.mjs:41
    renameSync(tmp, file)
  • 读取本地文件
    lib/mcp.mjs:117
    if (existsSync(dir)) {
  • 读取本地文件
    lib/mcp.mjs:127
    for (const e of readdirSync(dir, { withFileTypes: true })) {
  • 读取本地文件
    lib/mcp.mjs:130
    else if (e.isFile()) total += statSync(p).size
  • 读取本地文件
    lib/mcp.mjs:359
    if (!mirrorPath || !existsSync(mirrorPath)) return []
  • 读取本地文件
    lib/mcp.mjs:362
    text = readFileSync(mirrorPath, 'utf8')
  • 读取本地文件
    lib/skills.mjs:68
    if (!existsSync(srcDir)) return
  • 写入本地文件
    lib/skills.mjs:69
    mkdirSync(dstDir, { recursive: true })
  • 读取本地文件
    lib/skills.mjs:70
    for (const e of readdirSync(srcDir, { withFileTypes: true })) {
  • 读取本地文件
    lib/skills.mjs:76
    if (existsSync(d) && readFileSync(s, 'utf8') !== readFileSync(d, 'utf8')) {
  • 读取本地文件
    lib/skills.mjs:76
    if (existsSync(d) && readFileSync(s, 'utf8') !== readFileSync(d, 'utf8')) {
  • 读取本地文件
    lib/skills.mjs:79
    writeFileSync(d, readFileSync(s))
  • 写入本地文件
    lib/skills.mjs:79
    writeFileSync(d, readFileSync(s))
  • 读取本地文件
    lib/skills.mjs:89
    if (!existsSync(alt)) return alt
  • 写入本地文件
    lib/skills.mjs:227
    mkdirSync(targetDir, { recursive: true })
  • 写入本地文件
    lib/skills.mjs:241
    writeFileSync(targetMd, e.content, 'utf8')
  • 读取本地文件
    lib/instructions.mjs:39
    exists: existsSync(p),
  • 读取本地文件
    lib/instructions.mjs:40
    size: existsSync(p) ? statSync(p).size : 0,
  • 读取本地文件
    lib/instructions.mjs:40
    size: existsSync(p) ? statSync(p).size : 0,
  • 读取本地文件
    lib/instructions.mjs:46
    if (existsSync(configPath)) {
  • 读取本地文件
    lib/instructions.mjs:47
    const { config } = parseCodexConfig(readFileSync(configPath, 'utf8'))
  • 读取本地文件
    lib/instructions.mjs:50
    projects.push({ path, trustLevel: info.trustLevel, hasAgents: existsSync(agents), agentsPath: agents })
  • 写入本地文件
    lib/instructions.mjs:247
    mkdirSync(dshHome, { recursive: true })
  • 写入本地文件
    lib/instructions.mjs:248
    writeFileSync(target, adapt.adapted, 'utf8')
  • 读取本地文件
    lib/memory.mjs:69
    if (existsSync(configPath)) {
  • 读取本地文件
    lib/memory.mjs:70
    const { config } = parseCodexConfig(readFileSync(configPath, 'utf8'))
  • 读取本地文件
    lib/memory.mjs:77
    if (existsSync(dir)) {
  • 读取本地文件
    lib/memory.mjs:78
    for (const e of readdirSync(dir, { withFileTypes: true })) {
  • 读取本地文件
    lib/memory.mjs:83
    files.push({ name: e.name, path: p, size: statSync(p).size, kind: TEXT_EXT.includes(ext) ? 'text' : 'json' })
  • 读取本地文件
    lib/memory.mjs:88
    const sqlite = existsSync(sqlitePath) ? { path: sqlitePath, size: statSync(sqlitePath).size } : null
  • 写入本地文件
    lib/memory.mjs:163
    mkdirSync(outDir, { recursive: true })
  • 写入本地文件
    lib/memory.mjs:164
    writeFileSync(target, content, 'utf8')
  • 写入本地文件
    lib/memory.mjs:188
    mkdirSync(outDir, { recursive: true })
  • 写入本地文件
    lib/memory.mjs:189
    writeFileSync(target, md, 'utf8')
  • 写入本地文件
    lib/memory.mjs:408
    mkdirSync(join(root, 'runtime'), { recursive: true })
  • 写入本地文件
    lib/memory.mjs:409
    writeFileSync(join(root, 'runtime', 'memories.json'),
  • 读取本地文件
    lib/settings.mjs:34
    if (!existsSync(configPath)) {
  • 读取本地文件
    lib/settings.mjs:41
    const { config } = parseCodexConfig(readFileSync(configPath, 'utf8'))
  • 读取本地文件
    lib/settings.mjs:122
    const existing = existsSync(target) ? readFileSync(target, 'utf8') : null
  • 读取本地文件
    lib/settings.mjs:122
    const existing = existsSync(target) ? readFileSync(target, 'utf8') : null
  • 写入本地文件
    lib/settings.mjs:126
    mkdirSync(dirname(target), { recursive: true })
  • 写入本地文件
    lib/settings.mjs:127
    writeFileSync(target, yamlText, 'utf8')
  • 读取本地文件
    lib/settings.mjs:135
    target: existsSync(target) ? target : undefined,
  • 读取本地文件
    lib/delegate.mjs:21
    if (!existsSync(root)) return { count: 0, bytes: 0, firstTs: null, lastTs: null }
  • 读取本地文件
    lib/delegate.mjs:26
    for (const e of readdirSync(dir, { withFileTypes: true })) {
  • 读取本地文件
    lib/delegate.mjs:32
    bytes += statSync(p).size
  • 读取本地文件
    lib/title.mjs:63
    if (!existsSync(path)) return map
  • 读取本地文件
    lib/title.mjs:66
    text = readFileSync(path, 'utf8')
  • 读取本地文件
    lib/title.mjs:141
    if (!rolloutPath || !existsSync(rolloutPath)) return null
  • 读取本地文件
    lib/title.mjs:143
    return firstUserQuestionFromRolloutText(readFileSync(rolloutPath, 'utf8'))
  • 读取本地文件
    lib/title.mjs:420
    const buf = readFileSync(path)
  • 写入本地文件
    lib/title.mjs:472
    truncateSync(path, truncateTo)
  • 读取本地文件
    lib/verify.mjs:26
    if (/[ /]/.test(command) || /^[A-Za-z]:/.test(command)) return existsSync(command)
  • 读取本地文件
    lib/verify.mjs:31
    if (existsSync(join(dir, command + ext))) return true
  • 读取本地文件
    lib/verify.mjs:54
    if (!mirrorPath || !existsSync(mirrorPath)) return []
  • 读取本地文件
    lib/verify.mjs:57
    text = readFileSync(mirrorPath, 'utf8')
  • 读取本地文件
    lib/verify.mjs:107
    if (!existsSync(profilesRoot)) return out
  • 读取本地文件
    lib/verify.mjs:108
    for (const e of readdirSync(profilesRoot, { withFileTypes: true })) {
  • 读取本地文件
    lib/regroup.mjs:55
    if (!existsSync(path)) return empty
  • 读取本地文件
    lib/regroup.mjs:58
    gs = JSON.parse(readFileSync(path, 'utf8'))
  • 读取本地文件
    lib/regroup.mjs:159
    const buf = readFileSync(logPath)
  • 写入本地文件
    lib/regroup.mjs:168
    writeFileSync(logPath, Buffer.concat([newHeader, buf.subarray(headerFrame.end)]))
  • 写入本地文件
    lib/regroup.mjs:177
    writeFileSync(logPath, Buffer.concat([Buffer.from(JSON.stringify(next) + '\n'), buf.subarray(nl + 1)]))
  • 写入本地文件
    lib/regroup.mjs:194
    mkdirSync(newDir, { recursive: true })
  • 写入本地文件
    lib/regroup.mjs:195
    renameSync(oldDir, target)
  • 读取本地文件
    lib/regroup.mjs:223
    if (!existsSync(targetDir) || !statSync(targetDir).isDirectory()) {
  • 读取本地文件
    lib/regroup.mjs:223
    if (!existsSync(targetDir) || !statSync(targetDir).isDirectory()) {
  • 读取本地文件
    lib/regroup.mjs:288
    if (!logPath || !existsSync(logPath)) {
  • 读取本地文件
    lib/sessionlog.mjs:70
    const buf = readFileSync(path)
扫描于 2026/11/4(1 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

社区实装还没有人打卡 · 装过的第一个就是你
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-tools@deepseek-ai/cordis@deepseek-ai/schemastery
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 迁移MCP服务器
  • 迁移技能与全局指令
  • 迁移记忆与会话历史
展开完整介绍(125 字)↓

把 Codex(OpenAI Codex CLI / Desktop)的 MCP 服务器、技能、全局指令、记忆与会话历史一键迁移进 DeepSeek Harness(DSH)——可视化面板 + CLI,源码只读、dry-run 预览、密钥按原样迁移。

README

由 DeepSeek 最新模型翻译生成
🔁 Codex2DSH 把 Codex(OpenAI Codex CLI / Desktop)的 MCP 服务器、技能、全局配置、记忆,一键迁移进 DeepSeek Harness(DSH)—— 全程可视化操作,无需命令行。 npm version npm downloads CI License: MIT Node.js >= 22.19 dsh >= 0.1.x 简体中文 · English 🖥️ 可视化使用指南 · 📥 安装 · ✨ 功能 · 🔒 安全说明 · ❓ 常见问题 · 📚 文档 一句话:Codex 的配置是资产,不是牢笼。codex2dsh 帮你把多年积累的 MCP 服务器、技能、全局规则、记忆、会话历史「翻译」成 DSH 原生形态——迁移全程可视化操作、源码只读、密钥按原样迁移、dry-run 预览、人工确认。
展开完整文档(README 剩余 1 节)
🔁 Codex2DSH

把 Codex(OpenAI Codex CLI / Desktop)的 MCP 服务器、技能、全局配置、记忆,一键迁移进 DeepSeek Harness(DSH)—— 全程可视化操作,无需命令行。

npm version
npm downloads
CI
License: MIT
Node.js >= 22.19
dsh >= 0.1.x

简体中文 · English

🖥️ 可视化使用指南 · 📥 安装 · ✨ 功能 · 🔒 安全说明 · ❓ 常见问题 · 📚 文档

一句话:Codex 的配置是资产,不是牢笼。codex2dsh 帮你把多年积累的 MCP 服务器、技能、全局规则、记忆、会话历史「翻译」成 DSH 原生形态——迁移全程可视化操作、源码只读、密钥按原样迁移、dry-run 预览、人工确认。

搜索关键词:Codex → DeepSeek Harness 迁移 · MCP 服务器镜像 · 技能(Skills)转换 · 全局指令(AGENTS.md)· 记忆迁移 · 会话历史导入 · DSH 插件 · 可视化迁移面板 · 无命令行迁移

📸 截图预览

| 插件首页:状态总览 + 迁移选项 + 全量迁移向导 + 分类迁移卡片 | 插件底页:分类卡片(含会话导入「修复标题」)+ 最近结果 |
| 插件首页 | 插件底页 |

🖥️ 可视化使用指南(推荐)

打开迁移面板

安装插件并重启 DSH 后:

1. 打开 设置 → 插件
2. 找到 「Codex 迁移」 标签页
3. 面板包含 5 个区域,从下到上操作即可完成迁移

面板功能一览

| 区域 | 功能 |
| ① 状态总览 | 源配置根路径、全部可迁移资产清单(MCP/技能/指令/记忆/会话)、迁移台账条数、凭据文件黄色警告 |
| ② 迁移选项 | 「密钥脱敏」开关(默认原样迁移,直接可用)、「随迁本地工具目录」开关(默认开) |
| ③ 全量迁移向导 | 一键走完 1 预览 → 2 选择 → 3 执行 → 4 完成 四步全流程(推荐首次迁移使用) |
| ④ 分类迁移 | 7 张独立卡片:MCP 服务器、技能、全局指令、记忆、配置建议、会话导入、迁移体检——每张卡片有勾选清单 + 「预览 / 执行」按钮 |
| ⑤ 最近结果 | 最近一次执行的徽章式结果(已迁移=绿 / 跳过=灰 / 无效=红 / 预览=蓝)+ 警告列表 |

推荐流程(首次迁移)

1. 看状态:打开面板先看「状态总览」——确认源配置根正确、了解有哪些资产、注意黄色凭据警告
2. 走向导:点「开始全量迁移」
- 第 1 步 预览:查看各分类资产规模(零副作用)
- 第 2 步 选择:勾选要迁移的分类;MCP 与技能可在下方分类卡片细化勾选
- 第 3 步 执行:自动按 MCP → 技能 → 指令 → 记忆 → 配置 顺序执行,显示进度
- 第 4 步 完成:查看每类结果汇总(成功 / 跳过 / 警告)
3. 细化选择(可选):在「分类迁移」里
- MCP 服务器:勾选要迁移的服务器(如只留 google-mcp-toolbox),本地工具目录会自动随迁并重写路径
- 技能:勾选想要的技能;用「排除前缀」批量取消勾选整套技能(如输入 ccpanes- 排除全部 ccpanes 技能)
4. 收尾:迁移产物(如 mcp-mirror.cordis.yml)生成后,按产物中的提示人工审阅并合并进 DSH profile 即可使用(见 常见问题)

💡 每个「执行」按钮点击前都有确认框;所有写盘操作默认先「预览」,确认后再执行。

📥 安装

环境要求

- Node.js ≥ 22.13
- DeepSeek Harness dsh ≥ 0.1.x(本插件在 0.1.1-rc.2 实测)
- 本机已有 Codex 配置(~/.codex/,Windows 为 C:\Users\\.codex\)方式一:npm 包安装(推荐)

DSH Desktop 用户(desktop profile):
dsh plugin --profile desktop add codex2dsh

或 dsh CLI / Web profile 用户:
dsh plugin --profile web add codex2dsh

安装后重启 DSH,即可在「设置 → 插件」看到「Codex 迁移」面板。

方式二:本地开发 / 试用最新版

dsh plugin --profile desktop add -w link:D:/Projects/codex2dsh # 替换为你的项目路径

卸载:dsh plugin --profile remove codex2dsh,已迁移的资产不会被删除。

✨ 功能

| 能力 | 入口 | 说明 |
| 🖥️ 可视化迁移面板 | 设置 → 插件 → Codex 迁移 | 状态总览 + 迁移选项 + 全量迁移向导(预览→选择→执行→完成)+ 分类迁移卡片 + 结果徽章 |
| 全量迁移向导 | 面板「开始全量迁移」 | 四步向导一键迁移全部资产,逐步展示进度与结果 |
| MCP 镜像 | 面板 MCP 卡片 / migrate_codex_mcp | 解析 config.toml 的 [mcp_servers.] 生成可合并的 DSH MCP client YAML;密钥默认原样迁移(可选脱敏);include/exclude 选择性迁移;本地工具目录(如 mcp-toolbox)随迁并重写路径 |
| 技能转换 | 面板技能卡片 / migrate_codex_skills | ~/.codex/skills//SKILL.md → DSH 技能资产(frontmatter 适配 kind: dsh),脚本目录随迁,冲突自动消歧、幂等跳过;支持按前缀批量排除(如 ccpanes-) |
| 全局指令 | 面板指令卡片 / migrate_codex_instructions | AGENTS.md / instructions.md → $DSH_HOME/AGENTS.md(DSH 用户全局指令唯一位置);自动适配 Codex 专属引用:本地工具路径改写为迁移后目录(~/.codex/tools/... → $DSH_HOME/codex2dsh/tools/...)、MCP 工具前缀归一(mcp__google_mcp_toolbox__ → mcp__google-mcp-toolbox__)、未配置的 MCP 服务器引用逐条警告 |
| 迁移验证 | 面板体检卡片「验证迁移」/ codex2dsh_verify / CLI verify | 只读验证「在 DSH 中真实可用」:MCP 镜像是否已合并进 profile(未合并 = DSH 中未加载)、stdio 服务器命令/配置路径是否存在、AGENTS.md 引用是否在 DSH 配置中成立 |
| 记忆迁移 | 面板记忆卡片 / migrate_codex_memory | Codex 记忆(含 sqlite 只读探测)→ DSH 记忆资产,不可读时降级报告 |
| 记忆导入 dsh-mnemon | codex2dsh_import_memory / CLI memory-import | 把迁移的 Codex 记忆导入 dsh-mnemon(全局记忆引擎,~/.mnemon):Runtime 层提炼 memory_summary.md 为每轮注入的 USER/MEMORY 条目(容量裁剪、合并去重);Documents 层导入三份完整记忆原文(可搜索)——恢复"像 Codex 一样自动读取/查询/写入" |
| 配置建议 | 面板配置卡片 / migrate_codex_config | 模型 / Provider / 权限 / 项目信任 → 只读建议片段(绝不自动改 settings.yaml) |
| 会话导入 | 面板会话卡片 / migrate_codex_sessions | 统计会话规模并委托 import_chat(dsh-chat-import)导入为可续聊会话 |
| 会话标题回填 | 面板会话卡片「修复标题」/ codex2dsh_fix_titles | import_chat 不写 session/title 事件导致中文标题丢失(显示成工作区名):从 ~/.codex/session_index.jsonl 的 thread_name 或 rollout 首条真实提问回填标题(只补不覆盖、幂等、live 会话跳过);委托导入后自动执行 |
| 坏标题修复 | CLI codex2dsh repair-titles | 修复 0.1.1 早期缺陷误写的 session/title surfaceOp 坏事件(会话打不开 SessionPersistenceCorruptionError);截断式修复零数据丢失,修复后重启 DSH 再回填 |
| 工作区归组 | 面板会话卡片「整理工作区」/ codex2dsh_regroup_sessions / CLI codex2dsh regroup | Codex 非工作区会话(projectless)迁移后每个会话一个独立工作区、列表乱序:统一改写 header.cwd 并移动日志目录,归入单个 DSH 工作区(projectless-thread-ids 权威判定;其余会话不动;执行后重启 DSH) |
| 迁移体检 | 面板体检卡片 / codex2dsh_doctor | 逐资产状态:已迁移 / 待迁移 / 不可迁移 / 密钥残留 |
| 命令行 | codex2dsh | 无 GUI 环境的同能力 CLI:preview / mcp / skills / instructions / memory / config / sessions / titles / repair-titles / regroup / doctor / ledger |

🔧 命令行(可选)

codex2dsh preview # 只读预览全部可迁移资产 codex2dsh mcp --apply # 生成 MCP 镜像(密钥默认原样;--mask-secrets 脱敏)bash codex2dsh skills --apply --exclude ccpanes- # 技能迁移(排除 ccpanes) codex2dsh titles # 预览:哪些导入会话缺标题、将补什么标题 codex2dsh repair-titles --apply # 修复坏标题事件(0.1.1 缺陷导致会话打不开;修复后重启 DSH) codex2dsh regroup --apply # 整理工作区:非工作区会话统一归组(执行后重启 DSH) codex2dsh doctor # 迁移体检 codex2dsh ledger # 查看迁移台账

🔒 安全说明

| 承诺 | 说明 |
| 源码只读 | ~/.codex/* 任何文件永不写入、永不移动、永不删除 |
| 密钥原样迁移(默认) | 为让迁移后配置直接可用,password/token 等敏感值按原样写入产物;产物含真实凭据,请勿提交公开仓库;面板「迁移选项」可一键切换为脱敏(***) |
| 凭据文件不触碰 | auth.json、.codex-global-state.json 等只报告存在,不读取、不迁移 |
| 默认预览 | 一切写盘操作默认 dry-run,确认后才执行 |
| profile 不自动改 | MCP / 配置只生成待审阅片段,由你人工合并,绝不自动修改 |
| 幂等不覆盖 | 目标已存在且内容不同时拒绝覆盖(需 force),防覆盖人工修改 |

❓ 常见问题

MCP 迁移后如何让 DSH 真正用上这些服务器?
迁移生成的是待审阅片段(如 ~/.dsh/codex2dsh/mcp-mirror.cordis.yml)。请把片段中的 - insert: dsh-mcp-client 块合并进 profile 的 cordis.patch.yml(~/.dsh/profiles//cordis.patch.yml),然后重启 DSH。

我该用哪个 profile?
DSH Desktop 用户看「设置 → 关于/插件」里当前激活的 profile(通常是 desktop 或你切换后的 web)——插件要装到当前激活的 profile 才会出现在设置里。用 dsh plugin --profile add codex2dsh。

连接 MCP 服务器失败?
部分服务器(如 Google MCP Toolbox)的 stdio transport 走 NDJSON 而非标准帧格式,DSH 的 MCP 客户端可能连不上。此时可改用 HTTP 模式:toolbox serve 常驻 + 镜像配置 type: http(url: http://127.0.0.1:5000/mcp)。如遇此类问题,可在 Issues 反馈,我们会给出适配指引。

迁移后技能/指令去哪了?
- 技能 → ~/.agents/skills//(可用 DSH_AGENTS_HOME 覆盖)
- 指令 → ~/.agents/instructions/
- 记忆 → ~/.dsh/memories/codex/
- MCP 镜像与台账 → ~/.dsh/codex2dsh/

导入的 Codex 会话标题丢了 / 显示成工作区名?
import_chat 不写 session/title 事件,DSH 会回退到首条 user 消息——而 Codex rollout 首条常是 harness 注入( / AGENTS.md),所以显示成路径/工作区名。修复:面板「会话导入 → 修复标题」按钮(或 codex2dsh_fix_titles 工具,apply: true),标题取自 ~/.codex/session_index.jsonl 的 thread_name,缺失时取 rollout 首条真实提问;只补不覆盖、可重复执行。委托导入后也会自动补。

会话打不开,报 SessionPersistenceCorruptionError: ... is not surface-eligible ...?
这是 0.1.1 早期回填缺陷:session/title 误带 surfaceOp 导致整份日志校验失败。修复:在 DSH 外执行 codex2dsh repair-titles --apply(截断清除坏事件,零数据丢失),重启 DSH 后重新点「修复标题」即可。

会话列表很乱:非工作区会话每个一个工作区、还排在最上面?
DSH 的 workspace 按会话工作目录(cwd)分组,而 Codex 非工作区会话的 cwd 是 Documents\Codex\\ 这类一次性目录,迁移后各自成组,又因 C: 前缀字母序排前。修复:面板「会话导入 → 整理工作区」(或 codex2dsh regroup --apply)——按 Codex 官方标记(projectless-thread-ids)把非工作区会话统一改写 header.cwd 并移动到同一工作区目录,重启 DSH 后生效;其余工作区会话不动,排序恢复为按时间、与 Codex 一致。

卸载后数据会丢吗?
不会。插件从不自动删除已迁移资产;卸载只移除插件本身。

📚 文档

| 文档 | 内容 |
| 01-总体架构 | 项目目标、DSH 插件体系、技术栈 |
| 02-Codex配置解剖 | Codex 配置全解剖(config.toml / skills / 记忆 / 凭据) |
| 03-映射规范 | 逐项映射规范(MCP / 技能 / 指令 / 记忆 / 配置) |
| 04-插件API参考 | 开发者:插件 API 与 client 注入契约 |
| 05-实现方案 | 开发者:模块划分与实现细节 |
| 06-测试与验收 | 测试策略与验收矩阵 |
| 07-发布与分享 | 开发者:npm 发布与社区市场收录 |
| 08-路线图 | 里程碑与需求清单 |
| 09-安全边界 | 安全承诺与密钥策略 |

🤝 参与

- 使用中发现问题或有新想法 → Issues
- 想直接上手 → CONTRIBUTING.md 与 docs/05-实现方案.md
- 版本历史 → CHANGELOG.md

🙏 致谢与引用的开源项目

本插件无运行时依赖,以下项目以可选协同 / 目标平台 / 格式契约方式被引用,特此致谢:

- dsh-chat-import(Nwflower)— 会话历史导入委托(import_chat,format: 'codex')
- dsh-mnemon(omdsh-dev)— Codex 记忆导入目标引擎(全局记忆)
- DeepSeek Harness — 插件宿主平台与 @deepseek-ai/dsh-mcp-client 契约

完整清单与致谢详见 docs/10-致谢与引用.md。

📄 许可

MIT License —— 见 LICENSE。

⚠️ 免责声明:本插件只负责「翻译」配置,不承担目标服务器、凭据与访问策略的合规责任;迁移含密钥的 MCP 配置前请务必阅读 docs/09-安全边界.md。
预览分享卡片长什么样 ↓BigBlueBaby/codex2dsh
分享 · DeepSeek Harness Hub
BigBlueBaby/codex2dsh

把 Codex 的配置与记忆一键搬进 DSH

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部