Ken Chen 的个人主页 - Microsoft Internet Explorer
善者同心
共筑美好网络
文章
KEN CHEN来自工作台 · 个人项目

· 阅读约 9 分钟 · 文章

用 Claude 和 Codex 打造我自己的 Todoist

一个可以随着我的生活调整的任务管理器。

做这个个人项目,是因为我想要一个完全按自己想法定制的任务管理器。

Todoist 是我的起点。我的项目、任务和完成历史都在那里,我也喜欢它熟悉的工作流程:快速记下一件事,在“今日”中找到它,再放进合适的项目。我想保留这样的节奏,同时自己掌握应用的运行方式。

这意味着我可以修改界面、增加功能,并为个人和家庭任务制定自己的规则。谁可以看到一个项目?谁可以完成被指派的家务?重复任务应该如何处理?有了自己的代码,我就能自己决定,并随着需求变化继续调整。

Claude 和 Codex 让这个想法变得可行。我给它取名 KenDo。

第一次尝试用 Sol 6 开发,界面很丑,问题也不少。后来我换到了 Opus 5.5。几乎没有增加多少提示,它就做出了我想要的、可以称作 1:1 复刻 Todoist 界面的效果。

KenDo 现在已经上线,核心任务流程和家庭协作都已就绪。我的 Todoist 数据也完成了迁移和验证。如今,我有了一个熟悉的任务管理器,而且能够自己修改它的功能和规则。

打开 KenDo

从已部署应用截取的新版 KenDo 今日界面

当前的今日视图。截图中的项目名称已收起。

熟悉的工作流程,也为家庭生活留出空间

Todoist 为任务录入、项目、分区和今日视图提供了参考。家庭工作空间则需要额外的规则:共享任务归谁负责?孩子是否可以完成被指派的家务,却不能编辑项目?工作空间所有者是否可以查看私人项目?

在开始实现前,我把这些决定写进了一份详细的产品需求文档,涵盖任务模型、角色、视图、安全性和交付阶段。Codex 有了明确的实现说明,我也可以据此检查结果。

购物清单、家庭仪表盘、提醒和协作都在需求中。一部分已经实现,另一部分还在待办列表里。

从 Sol 6 到 Opus 5.5

Sol 6 版本有了任务应用的大致形状,但界面不好看,应用也有不少问题。这是它的“即将到来”视图:

作者提供的截图:Sol 6 开发的最初版即将到来界面

改版前:最初截图中的 Sol 6 版本。

Opus 5.5 只需要少量额外提示,就重新做出了 Todoist 的外观和使用感受。我不必针对界面的每个部分反复写一长串指令。

换用 Opus 5.5 后的即将到来界面,截图来自已部署的 KenDo

改版后:当前的即将到来视图。两张截图的日期和视口尺寸不同。

仓库里已经有一份详细的 PRD,所以重做界面时有这些上下文可用。让我印象深刻的是,它几乎不需要更多指导。

我仍然需要检查行为、权限和边界情况。KenDo 也有自己的家庭功能,以及尚未完成的待办事项。

让两个助手共同推进一个项目

开发过程中我同时使用了 Claude 和 Codex,迁移则使用 Codex。仓库里的文件把不同会话之间的工作连接起来。

CLAUDE.md 记录项目约定,架构说明解释设计决定,CHECKPOINT.md 记录已经上线的内容、通过的检查以及剩余工作。迁移另有一份进度日志。每次会话都可以读取这些文件,不必依赖埋在之前聊天里的某个决定。

9 月,我加入了早期任务视图、周历、报表、项目、性能改进和 API。10 月 2 日,我围绕 Todoist 风格的流程重建了核心,随后补上加固和项目归档。家庭工作空间和协作功能在 10 月 3 日落地。

界面重做以后,重复任务、同步、错误处理、无障碍和归档项目规则仍需要继续完善。

让它真正好用的小交互

重复操作最容易让我注意到多余的点击:录入任务、找到任务、推迟到明天,然后完成它。快速添加支持这样的输入:

Buy milk tomorrow 6pm #Home @errands p1

KenDo 会把输入解析成标题、时间安排、项目、标签和优先级。共享指派使用 +Name,把 @ 留给标签。它还支持键盘快捷键、命令面板、子任务,以及项目列表或看板视图。

归档可以收起已结束的项目,同时保留其中的内容。归档项目从日常视图中消失,可以恢复,在归档期间为只读。这个规则同样适用于从旧浏览器标签页发起的写入。

应用架构

KenDo 使用 Next.js 16、React 19、TypeScript 和 Tailwind CSS 4,部署在 Vercel。Supabase 提供身份认证、PostgreSQL 和实时事件。TanStack Query 管理浏览器缓存,Zod 验证输入,Drizzle 定义带类型的数据库结构。

KenDo 架构:服务端快照、浏览器缓存、经过认证的数据库访问、REST API 和实时刷新路径

浏览器更新界面,PostgreSQL 落实权限,实时事件触发快照刷新。

共享工作空间快照

早期版本会为每个页面分别获取数据。现在,经过认证的应用布局加载一份工作空间快照,并初始化一个 TanStack Query 缓存条目。

今日、即将到来、项目、筛选和搜索都从这份快照中得出结果。它包含个人任务,以及用户有权访问的家庭项目。报表会单独加载完成历史。

共享选择器让各个视图保持一致,也可以独立测试。REST API 为外部客户端复用同一套逻辑。

乐观写入与 RLS

浏览器通过 Zod 验证输入,乐观更新 TanStack Query 缓存,再使用当前登录用户的会话向 Supabase 写入。如果写入失败,就显示错误并重新获取数据。

PostgreSQL 行级安全(RLS)决定是否允许写入。界面隐藏不可用的操作,数据库策略负责执行限制。

涉及多行的操作,例如完成父任务及其尚未完成的后代任务,会使用以调用者权限运行的数据库函数。Drizzle 用于结构定义和迁移,运行时查询则使用经过认证的 Supabase 客户端。

实时协作

其他家庭成员修改数据时,Supabase 实时事件会触发经过防抖的快照刷新。写入控制机制会协调刷新与尚未完成的乐观写入。

数据库触发器生成活动记录和应用内通知,让网页应用与 REST API 的行为保持一致。客户端不能自行插入活动记录。

快照方案适合当前的应用。更大的工作空间可能需要不同的加载策略。

日期与家庭权限

“我计划周二做这件事”和“这件事必须在周五前完成”并不是一回事。KenDo 分开管理计划日期与截止日期。时间戳以 UTC 存储;今日和逾期计算使用用户资料中时区的日历日期。只有日期的截止时间仍然保持为日期。

完成重复任务时,会记录一次完成事件,并把计划推进到下一次。任务仍然保留,报表也保存它的历史。

孩子和访客只能看到自己被加入的项目。孩子可以完成被指派的任务,但没有一般编辑权限。私人项目即使对家庭工作空间所有者也仍然私密。

数据模型、策略、触发器和界面都必须遵循这些规则。

迁移任务,是第二个项目

界面已经很熟悉了,迁移数据却需要更多工作。

我把迁移放在独立工作空间中,保持 Todoist 只读,并备份原有的 KenDo 数据。任务标题只是其中一部分:日期、父子关系、重复规则、评论和完成历史都必须一起迁入。

已完成的迁移流水线:只读导出、目标备份、映射、事务导入与独立验证

迁移在 2026 年 10 月 3 日完成,并通过独立验证。保留了附件元数据和链接,但没有传输文件本身。

Python 导出程序会跟随分页游标,重试暂时性故障,并在去除部分凭证字段后保存原始响应页。完成历史按 80 天的窗口请求。应用的本地环境指向本地 Supabase,因此迁移明确指定了托管数据库。

第一次导出并不完整。后续历史查询又找回了 578 个较早完成的任务。合并后的来源包含 230 个未完成任务和 1,358 个已完成任务,以及 6 个标签和 13 条评论。KenDo 中已经存在的对应项目得到了复用,保留了当前名称和设置。

一次尝试发送约 3 MB 的导入 SQL,在任何应用数据写入前就遇到了 HTTP 413 响应。我改为在受限 schema 中分批暂存数据,再在一个事务里完成应用写入与检查。

日期转换使用 KenDo 自己的日期库和重复任务逻辑。检查覆盖只有日期的任务、带时间的任务、悉尼夏令时切换、优先级和子任务关系。正式提交前,先执行了一次完整事务演练并回滚。

完成历史需要格外仔细。已完成任务与单次完成事件是不同的记录,重复任务尤其如此。导入保留了 2,550 条实际完成事件,最早追溯到 2015 年 1 月 27 日;对缺少事件历史的任务,还补充了 81 条已完成状态记录。最终生成了 2,631 行完成历史,以及 1,867 条完成与取消完成的活动记录。

我也明确记录了迁移的边界。按照要求,已删除或不可访问的任务及其可获取历史留在本地备份中。附件元数据和可用链接得到了保留,其中包括一个尚未完成上传、没有下载 URL 的附件。两个较早完成的任务需要调整写入顺序,因此更新了它们的更新时间戳,原始时间戳仍保存在备份中。一个历史标签没有颜色元数据,所以使用了 KenDo 的默认颜色。

最终的独立检查比对了 6,107 条导入记录和 71,057 个字段。原有的 32 条记录全部保持不变,包括复用的项目和 3 个 Inbox 测试任务。重复运行后的回滚检查没有产生重复记录。导入没有创建通知,暂存 schema 也已删除。

导入的任务数量是 1,588。KenDo 中总共有 1,591 个任务,因为保留了那 3 个测试任务。这个区别很小,却正是我希望迁移报告解释清楚的细节。

迁移会话耗时 40 分 43 秒,这个时间记录在完成画面中。应用本身是在多次会话中开发的;这个计时只属于迁移。

迁移完成截图的英文版,展示导入任务数量和 40 分 43 秒的会话计时

迁移完成画面,中文终端输出已翻译成英文。打开完整尺寸截图。

验证与剩余工作

10 月 3 日的检查点记录了 404 个通过的单元与集成测试、81 个通过的 pgTAP 数据库测试,以及 22 个通过的 Playwright 测试,其中包括 4 个实时协作场景。验证命令还覆盖类型检查、代码检查和生产构建。

邮件发送、推送通知和定时提醒暂缓实现。邀请通过共享链接完成,通知显示在应用内。购物模式和家庭仪表盘仍有待开发。

迁移已经完成,产品仍有待办事项。如今,我在 KenDo 里拥有了想要的界面和原来的任务数据,接下来还要搭建家庭仪表盘和购物流程。

为什么我认为 Todoist 这类应用会逐渐淡出

我的预测是:像 Todoist 这样的独立任务应用,会逐渐淡出聚光灯。随着 AI 让定制软件更容易开发,助手接管更多日常交互,我认为通用任务管理应用作为独立产品存在的理由会减少。

KenDo 让我具体看到了这种可能。我可以重新做出熟悉的流程,再加入适合自己家庭的规则。标准任务应用必须为广泛的用户做取舍,个人应用则可以遵循一个人的选择。随着开发和修改这些工具越来越容易,我预计更多人会选择围绕自身需求打造的软件。精美的列表、看板或日历,将越来越难成为说服用户留下的主要理由。

我们与任务互动的方式也在改变。Todoist 已经提供了用于语音录入任务的 Ramble,以及可以读取、创建和更新任务及项目的 Claude 连接器。在我看来,这些功能是转变的早期信号。如果助手能够通过对话记录任务、找到合适的项目,并协助安排一周,就少了很多打开专门任务应用的理由。数据仍然需要一个存放的地方,但应用可能成为在幕后工作的服务。

迁移这些数据也可能变得更容易。我的迁移会话用了 40 分 43 秒,保留了多年来可以访问的任务历史,也完成了备份、映射与验证。这只是一次经历,却让我预期:随着工具进步,系统之间的迁移阻力会减少。多年积累的历史,可能不再是留在某个应用中的那么强的理由。

KenDo 中那些困难的部分,也解释了为什么我认为这种变化会是渐进的。重复任务、时区处理、权限、同步和恢复,都需要持续维护。随着测试、托管和维护工具改善,我预计小团队和个人能够承担更多这样的工作。成熟的任务应用将面临压力,需要提供人们难以轻易自行组装的价值。有的可能演变成服务助手的基础设施,有的则可能逐渐离开人们的日常。

探索 KenDo