最近刚把手头 WorkBuddy 里的几百条笔记、任务和归档文件迁到了 dsh折腾了差不多一个下午中间踩了不少坑。趁热打铁把这套 workbuddy-to-dsh 迁移流程整理出来希望能帮到同样打算从 WorkBuddy 切到 dsh 的朋友。先说结论工具本身不复杂核心是把 WorkBuddy 导出的数据转换成 dsh 能识别的结构再配合插件市场把日常需要的归档、检索和桌面端能力补齐。整篇文章会覆盖为什么要迁、工具怎么装、具体转换怎么做、以及我在迁移过程中遇到的大坑和对应的排查方法适合所有正在考虑迁移或已经卡在转换环节的用户。1. 为什么选择从 WorkBuddy 迁移到 dsh1.1 WorkBuddy 的现状与我的真实痛点我用 WorkBuddy 管理笔记和日常归档差不多两年。客观说它的编辑体验不错但有一个越来越难忍的痛点数据封闭。WorkBuddy 的存储格式是私有结构导出的内容很难被其他工具直接使用。我用它积累的几百篇笔记每次想用脚本批量处理一次都要先把导出文件做一层手工清洗。当时因为我的很多笔记都是纯文本加标签换工具的成本还不算太大真正让我下决心迁移的是 dsh 的插件体系太有吸引力了。dsh 本身是一个以数据整理为核心的命令行加桌面端工具但又不止于归档它提供了一套插件机制可以自由扩展数据处理流程。我需要的归档管理、内容检索、标签批量整理都能在 dsh 插件市场里找到现成方案。WorkBuddy 的社区也有人在写插件但无论是安装方式还是维护活跃度都和 dsh 相差很远。最关键的一点是WorkBuddy 的挂件、模板和自动化规则都绑定在它自己的运行时里一旦软件停止维护这些东西全都作废。dsh 的数据文件是开放格式哪怕哪天 dsh 本体不更新了我手里还是一堆通用的 Markdown 和结构化文本换任何工具都能继续用。1.2 dsh 插件生态有什么不一样第一次接触 dsh 插件市场时我本来以为又要手动下载安装包、放到指定目录、再改配置。结果它内置了一套类似包管理器的机制一条命令就能添加第三方插件市场源。比如我现在的 web 环境下要加载 dshmarket 插件市场直接执行dsh plugin --profile web add dshmarket这条命令的意思是把 dshmarket 注册到当前 web profile 的插件源列表里之后就能用dsh plugin install安装该市场下的所有插件。这种设计比传统拷贝文件的方式高效太多而且插件和 profile 绑定换环境不需要重新折腾一堆配置文件。对从 WorkBuddy 迁移过来的用户来说插件生态还有一个实际好处很多迁移后收尾工作比如给笔记重新打标签、生成归档索引都能用插件自动完成而不是像以前那样全靠手写脚本。我实际用下来dsh 的这种“数据目录 插件 profile”的架构解决了 WorkBuddy 时代最大的一个麻烦工具和数据强耦合。在 WorkBuddy 里数据格式不公开扩展能力也极其有限。而 dsh 的核心数据是一堆结构化文本插件负责把文本转换成不同视图。换句话说数据是私有的但数据和功能是解耦的。这也是我敢把手头所有数据迁过去的最重要原因。1.3 迁移方案对比直接拷贝、脚本转换与 workbuddy-to-dsh在确定用 workbuddy-to-dsh 之前我其实试过两条路。第一条是粗暴拷贝直接把 WorkBuddy 的导出文件扔到 dsh 项目目录里祈祷 dsh 能识别。结果当然不行WorkBuddy 的 JSON 结构和 dsh 需要的文档目录结构完全不同dsh 只认它自己的索引文件和 Markdown 约定。第二条是自己写 Python 脚本思路也不复杂读 WorkBuddy JSON按字段生成 Markdown再手工写索引。试了十几个笔记的小样例确实能做出来但遇到嵌套标签和附件路径后就撑不住了脚本越写越复杂最终放弃。对比下来workbuddy-to-dsh 的价值在于它把数据模型映射和索引生成都封装好了。它不是简单地改扩展名而是理解 WorkBuddy 导出里的字段含义再按照 dsh 的规则重建目录结构。虽然它不完美但至少帮我省了两天时间。工具本身还支持增量转换我第一次只处理了 50 条笔记验证流程确认没问题后再跑全量这个能力也是自己写脚本时很难快速实现的。2. workbuddy-to-dsh 工具到底做了什么2.1 数据模型映射逻辑用 workbuddy-to-dsh 之前先理解它转的是什么。WorkBuddy 导出的文件通常是 JSON 或者 Markdown 包的混合体里面有笔记、待办事项、标签、元数据、附件路径等信息。dsh 侧的数据模型则更偏向文件夹加文档每个项目一个目录每个文档一个文本文件标签通过 frontmatter 记录待办事项用任务标记表示。所以这个转换工具本质上做的是字段映射和结构重排不是简单的文本替换。workbuddy-to-dsh 的映射规则我整理如下WorkBuddy 字段dsh 目标字段处理方式note.body正文内容直接写入.md文件note.tagstagsfrontmatter批量替换为 dsh 标签格式task.title任务标题生成- [ ]待办清单task.status任务状态转换成[x]或保留[ ]attachment.path附件引用复制到 dsh 资源目录并相对引用note.createdAtcreatedfrontmatterISO 时间戳转换实际转换时工具会在目标目录下生成一个_dsh_index.json的索引文件dsh 桌面版启动后会先读这个索引再加载对应文档。这也是为什么迁移后第一次打开 dsh 会有几秒钟的解析时间索引越大越明显。索引文件里保存的是每个文档的路径、标题、标签和最后修改时间dsh 靠它实现快速搜索而不是每次启动都扫一遍所有文件。2.2 安装与前置准备workbuddy-to-dsh 目前以 Python 工具的方式发布安装依赖pip。前提是环境里已经装好了 Python 3.9 以上版本建议用虚拟环境隔离避免依赖冲突。我是在一个干净的虚拟环境里装好的python -m venv wb2dsh-venv source wb2dsh-venv/bin/activate pip install workbuddy-to-dsh装完后跑一下版本号确认安装成功workbuddy-to-dsh --version如果看到输出类似workbuddy-to-dsh 0.4.2就没问题。这里有个小坑如果你原来的系统 Python 版本是 3.8 或更低直接安装会报typing_extensions依赖错误解决办法是先升级 Python或者手动安装高版本的typing_extensions再重试。我一开始就在老环境的 Python 3.8 上踩到这个问题折腾了十几分钟。另外WorkBuddy 最好先做一次完整的导出。WorkBuddy 的导出功能在设置里可以导出为“WorkBuddy 备份包JSON 格式”。导出得到的文件是个单文件压缩包里面包含所有笔记和任务。不要只复制笔记文件夹下的某个.json片段那样转换出来的数据会缺一半。导出后建议确认文件大小和你手头的数据量匹配我见过有人导出文件只有 1KB打开一看是空的备份头压根没有包含数据。2.3 转换过程中字段映射的几个坑接着说一下工具不会替你处理的部分。第一个坑是时间格式。WorkBuddy 导出的时间字段五花八门有的带时区有的是 Unix 时间戳如果不先统一格式转换完成后 dsh 的排序和过滤会完全错乱。我的做法是在转换前先用一个简单脚本把时间字段统一成 ISO 8601再交给 workbuddy-to-dsh。比如原字段是2023-08-15 14:30:00我统一成2023-08-15T14:30:0008:00这样导入后 dsh 才能正确识别时区。第二个坑是附件路径。WorkBuddy 附件在导出包里通常被重命名成一串 hash如果直接转换dsh 里的附件链接会失效。我最终是把附件目录整体拷贝到 dsh 项目下的assets文件夹然后让工具以assets/实际文件名的形式生成链接转换时再手动把 hash 文件名映射成可读名称。这个步骤没有自动化工作量取决于你附件数量。如果是大批量迁移建议先写一个映射表再批量替换 JSON 里的路径。我当时先用 Python 脚本读了一遍 WorkBuddy 的附件清单生成每个 hash 对应的原始文件名再让转换工具优先使用映射表。第三个坑是标签里的空格和特殊字符。WorkBuddy 的标签可以带空格但 dsh 的 frontmatter 标签如果保留空格会被解析成多个标签。转换工具默认会把空格替换成-如果你的标签里有中文逗号、括号这类字符转换前最好先清洗一遍。我手头有一批标题是 TODO / 写作 的笔记转换后标签变成TODO-/-写作看着难受。这种问题工具不会帮你处理只能靠转换前预处理。2.4 命令行参数详解workbuddy-to-dsh 的命令行参数不算多但每个都很关键。我最常用的是这几个--input指定 WorkBuddy 导出的 JSON 文件路径。--output指定转换后的 dsh 项目目录目录不存在时工具会自动创建。--rename-assets开启附件重命名让附件文件名从 hash 变成可读名称。--no-index跳过索引生成一般用于调试正常迁移不要加。--tag-separator自定义标签分隔符默认是-可以改成_或者别的。--debug输出完整日志遇到问题排查时必开。其中最容易混淆的是--output的行为工具不会在输出目录下再建一层子目录而是直接把 Markdown 文件放进这个目录。如果你指定--output ~/dsh-projects/my-notes那my-notes目录里应该就是一堆.md文件和_dsh_index.json不是嵌套的my-notes/notes/。我第一次用的时候误以为会生成子目录结果等了半天才发现文件都在根目录划分目录结构全靠 WorkBuddy 里的文件夹信息自动映射。3. 实操完成一次完整迁移3.1 准备 dsh 环境和插件市场迁移前先把 dsh 本体装好。根据平台不同安装方式有差异我用的是 macOS 上的 Homebrew一条命令搞定brew install dshWindows 下可以从 dsh 的官方发布页下载桌面版安装包安装完会同时提供dsh命令行工具和桌面 GUI。Linux 用户则通常从源码构建或者用发行版仓库里的包。装好之后可以先验证一下命令行可用dsh --version装好之后第一件事是添加插件市场。前面那句dsh plugin --profile web add dshmarket就是在注册插件源。这里解释一下 profile 的概念dsh 会针对不同使用场景区分 profile比如web、local、server。每个 profile 有独立的插件列表和数据目录。我日常主要在桌面版上工作数据存在本地所以当时纠结要不要用localprofile。后来发现插件市场是全局概念写在某个 profile 下也能共用。为了迁移方便我统一注册到webprofile这样命令行和桌面版都能读到。注册插件源执行的是dsh plugin --profile web add dshmarket执行后没有报错就是成功可以用dsh plugin list查看当前已注册的市场源。接下来安装我最需要的归档管理插件和批量整理插件dsh plugin install dshmarket/dsh-archive dsh plugin install dshmarket/dsh-tag-batch安装时会自动从市场拉取插件包并注册到当前 profile。如果市场源没添加成功执行 install 会提示 source not found。这个时候回去检查 add 命令里的市场名是否拼写正确或者用dsh plugin discover看当前网络环境下能否访问到市场源。3.2 导出 WorkBuddy 数据WorkBuddy 的导出路径打开 WorkBuddy 客户端进入设置-数据管理-导出备份选择 JSON 格式。导出完成后你会得到一个类似workbuddy_backup_20250501.json的文件。我检查了下这个文件大小几百条笔记大概在 30MB 左右其中大部分是附件 base64 编码纯文本内容只占一小部分。如果你不需要附件可以先把附件剥离只保留笔记和任务数据转换速度会快很多。建议在导出后立即对文件做一次校验用阅读器打开确认 JSON 结构完整没有截断或乱码。我遇到过导出文件没问题但系统自动中断导致文件不完整的案例最典型的特征是文件结尾缺少}。最简单的校验方式是使用 Pythonpython -c import json,sys; json.load(open(workbuddy_backup_20250501.json)); print(ok)如果输出ok说明文件可以被正常解析。如果报错说明导出过程可能有问题需要重新导出。3.3 运行 workbuddy-to-dsh 转换确认导出文件没问题后开始转换。我先建一个干净的导入目录mkdir -p ~/dsh-projects/my-notes然后运行转换命令把导出的 JSON 转换成 dsh 可导入的目录和索引workbuddy-to-dsh --input ./workbuddy_backup_20250501.json --output ~/dsh-projects/my-notes --rename-assets这里我额外加了--rename-assets参数表示把附件 hash 文件名重命名为可读名称。这一步实际执行了十分钟左右主要耗在附件复制上。转换完成后~/dsh-projects/my-notes下会出现很多.md文件和一个_dsh_index.json。如果日志里出现警告建议先停下来看清楚再继续比如我遇到过一次提示“tag is empty”说明原数据里有空标签这种标签转换后会被丢弃导致检索时少一个维度。打开 dsh 桌面版在项目设置里把这个目录添加为数据源dsh 会自动读取_dsh_index.json并加载全部文档。如果加载后看到文档列表为空多半是索引文件缺失或格式不对可以检查一下目录里是否有_dsh_index.json没有的话说明转换过程中跳过索引生成了重新运行命令时不要加--no-index参数。3.4 转换后验证与内容检查数据导入后不要急着删除 WorkBuddy 原数据先做几项验证。第一抽查 20 篇笔记确认正文完整、标签没有丢失、日期时间正确。第二检查附件链接随机打开几篇带附件的笔记点击链接能正常打开文件。第三检查任务状态是否所有- [x]和- [ ]都正确保留。我实际跑完后发现一个比较隐蔽的问题WorkBuddy 里的“已完成”任务在转换后有一些变成了未完成。原因是 WorkBuddy 的状态字段是completed而 dsh 用- [x]表示完成转换工具默认只识别done字段。这个问题最终靠更新工具版本解决0.4.2 之后已经修复如果你用的还是旧版本可以在转换前用sed把 JSON 里的status: completed替换成status: done。我在这里写了个一行命令sed -i s/status: completed/status: done/g workbuddy_backup_20250501.json注意 macOS 上sed -i需要带即sed -i 否则会报错。这个细节容易卡住刚接触命令行的用户。替换后再跑一次转换任务状态就正常了。3.5 迁移后的插件配置数据进去只是第一步把日常流程顺起来还需要做一些插件配置。我先检查了dsh-archive插件是否生效dsh plugin status这个命令会列出当前 profile 下所有插件的状态。我注意到dsh-archive默认没有启用需要手动激活dsh plugin enable dsh-archive激活后我还用dsh-tag-batch做了一次全局标签规范化把之前转换时拆乱的标签重新合并。这个插件使用一个批处理文件里面写规则比如把TODO-/-写作重新映射成写作。我写完之后执行dsh plugin run dsh-tag-batch --config ./tag-rules.yaml跑完再检查标签云基本干净了。这一步建议放在验证完成之后再做否则规则处理到错误数据上还得回滚。4. 常见问题与排查技巧实录4.1 插件源添加失败或超时不少用户反馈执行dsh plugin --profile web add dshmarket出现连接失败或超时。首先要确认网络环境能够正常访问 dsh 的插件市场服务。如果企业内网有限制可以试试换一个网络环境。如果网络没问题再检查代理设置。dsh 命令行工具会读取系统代理但有些场景下内置的dsh plugin没有正确读取 HTTP_PROXY 环境变量。我的做法是在执行前显式导出代理变量比如export HTTP_PROXYhttp://127.0.0.1:8080 export HTTPS_PROXYhttp://127.0.0.1:8080不过这属于临时手段根本解法是确认 dsh 是否能正确识别你所在网络的代理信息。另外dsh 有多个市场源如果 dshmarket 这个源连接不佳可以换官方源dsh-community命令是dsh plugin --profile web add dsh-community我最后用了两个源dshmarket 用来装归档插件dsh-community 用来装官方维护的一些基础插件。两个源可以共存安装插件时通过源名/插件名区分不冲突。4.2 商店版 PowerShell 执行 dsh 报错这个问题最初是群里有位朋友问的他在 Windows 商店版 PowerShell 里运行dsh命令总是提示“无法加载或运行此脚本”或者报错缺少DLL。商店版 PowerShell即 PowerShell 7 的 Microsoft Store 安装版和传统 Windows PowerShell 5.1 不一样它的执行环境隔离更严格同时从商店版启动的终端经常没有继承系统 PATH 的完整环境变量。dsh 的安装路径可能没有被正确加入 PATH或者执行策略限制导致脚本无法运行。解决思路分三步先在普通 PowerShell 5.1管理员模式中执行一次dsh --version如果正常说明 dsh 安装本身没问题问题出在商店版终端的执行策略上。然后执行Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser允许本地脚本运行。最后把 dsh 安装目录手动加入 PATH如果是官方 exe 安装包目录一般在$env:LOCALAPPDATA\Programs\dsh如果用 winget 安装则在$env:ProgramFiles\dsh。加完后关闭商店版 PowerShell 重新打开再执行dsh --version验证。这个问题的本质是商店版 PowerShell 沙箱环境相对封闭很多人以为 dsh 坏了其实只是执行策略和 PATH 这两个基础配置没到位。我自己在 Windows 上迁移时没踩到但帮忙排查了好几次所以记下来供参考。4.3 转换后索引文件无法生成另一个高频问题运行 workbuddy-to-dsh 一切正常输出目录里却没有_dsh_index.json。我排查下来最常见的原因是输入 JSON 的顶层结构不对。WorkBuddy 不同版本的导出格式有差异有些版本导出的 JSON 外层包了一层{ data: [...] }而工具 0.3.x 版本只认{ notes: [...] }这种顶层结构。解决方法是先检查 JSON 顶层有哪些键再用jq提取jq .data // .notes workbuddy_backup_20250501.json normalized.json然后再把normalized.json喂给 workbuddy-to-dsh。如果仍然没有索引可以加--debug参数运行工具会打印出解析中断位置那个地方往往就是问题字段所在。有次我的日志停在了某个 base64 图片字段上检查后发现是导出的附件编码不完整重新导出一次就好了。4.4 迁移后桌面版加载缓慢迁移到 dsh 桌面版后第一次打开项目如果笔记数量上了千会明显卡几秒这个正常。dsh 需要解析所有文档并构建全文索引。如果卡的时间超过十几秒可能是某些文档里包含损坏的字符或超大 base64 图片块。我的解决办法是先用命令行执行一次预解析dsh scan ~/dsh-projects/my-notes这条命令会在不打开桌面版的情况下强制刷新索引同时打印警告信息比如哪篇文档格式异常。修掉异常文档后再打开桌面版基本就顺了。这里再提醒一下dsh scan会按照当前约束规则整理文档如果你还没配置好标签规则建议先跳过否则可能把文档顺序打乱。4.5 我的几条经验与避坑建议整个迁移过程下来最大的体会是转换工具只是负责把数据“倒”进新格式真正的整理工作还是要自己做。workbuddy-to-dsh 能自动完成字段映射和目录生成但标签清洗、附件重命名、时间统一这些决定数据质量的事情工具的自动化程度有限需要额外花时间。我的建议是迁移前先在 WorkBuddy 里做一次数据整理把垃圾标签、重复任务清干净再导出转换这样迁移后的 dsh 项目从一开始就是干净的。另一个经验是不要用 dsh 的归档管理插件来替代数据检查。归档管理插件擅长的是给过时笔记打上归档标记、移到归档目录但如果原始数据里就有错误插件只是帮你放大错误。我迁移时先用 dsh-tag-batch 跑了一次批量标签整理结果发现几个标签名被拆得七零八落后来回头重新处理才发现是原始标签里有特殊字符。所以顺序应该是先清洗原始数据再转换再装插件扩充功能别颠倒。最后就是养成定期导出的习惯。迁移完成后我把 WorkBuddy 原数据收在了一个冷备份目录并给 dsh 项目设了每天自动快照。毕竟工具可以换数据不能丢。如果你正卡在某个转换报错上多看看日志输出或者把报错片段丢到群里问基本都能解决。上面这些坑我都实际踩过按顺序排查一般十几分钟就能搞定。
阅读完成 · 觉得有帮助?