你的上下文数据资产,不该只躺在别人的机器上
把一天里跟 agent 说过的话再看一遍,听上去像给自己写日报,挺无聊的。
但你不看,它明天开口第一句还是「你好,请问你在做什么项目」。
与其每天重讲一遍,不如让干过的活落进一个你自己的库,每天汇聚一次,让下一个 agent 从那儿接着干

过去一年,我在 Claude Code、Codex、OpenCode 之间来回换,同一套约定写过三遍——这个 agent 的目录里一份,那个 agent 的配置里一份,还有一份在我自己脑子里。每次都以为这回终于定下来了,换个终端打开,又得重讲。
与此同时,另一件事也在发生:我们一起干完的活,散在各处。一部分留在会话记录里,一部分在临时文件里,还有一部分在某个服务商的数据库里——那份我看得见,但带不走。
这两件事看着一个是效率、一个是所有权,其实是同一件事的两头。
你每天都在和 agent 干活,收工的时候,只有对话框记得。
于是我开始写自己的知识库。最开始只是因为 Obsidian 同步不顺手,同时我想让数据留在自己手里,一堆 markdown 文件走天下,格式不被哪个软件绑死。写着写着,它长成了整个工作台,叫 udctl(原名 UnDercontrol)。

图1 · udctl 的 Explorer:任务和文件在同一棵树里。
一、agent 越来越多,记得住事的还是只有你
先说问题。如果你也在拿终端里的 agent 干活,大概率会撞上同样几件。
Claude Code、Codex、OpenCode、Gemini CLI、Cline……这两年终端里的 agent 一个接一个,冒出来的速度比人适应的速度快。
工具越多,下面这几个问题越难回答:
- 昨天让 agent 查出来的那个结论,现在在哪?
- 同一套约定我给三个 agent 各写过一遍,哪份是最新的?
- 这个月我和 agent 一起做完了什么,有没有一份清单?
- 换一台机器、换一个 agent,为什么上下文要从头讲一遍?
- 上周明明查清楚过一次,为什么今天还得再查一遍?
- 我干过的活躺在谁的数据库里,哪天不想用了,能整个带走吗?
倒数第二条最要命。重复劳动真正的代价不在多花的那半小时,而在于你第二次做的时候,完全不知道自己在重做。

图2 · 过去,agent 的记忆随会话一起结束。
二、不只是存起来:它想做的是五件事
先说清楚一件事:能写字的工具太多了,笔记 app、各种 wiki、一堆 Markdown 编辑器,不缺。
但它们大多停在同一个地方——给人看。存下来,排好版,然后就结束了。
我们更在意另一半:存下来的东西,agent 能不能直接读走、直接改回来,不用你复制粘贴一遍。
一句话概括 udctl:一个自托管、跑在你自己机器上的工作台。人和 agent 共用同一份数据,读的是同一串字节。
它想走完的链路是五步:一个容器装下 → 换哪个 agent 都读得到 → 每天汇聚一次 → 沉成长期记忆 → 落进一棵你能打开的目录树。

图3 · 人和 agent 共用一个容器:同一份卡、同一份笔记、同一串字节。
第一件事:看清你的 agent 在干什么
udctl 把 agent 当成一等公民来管。你能看到:
- 正在跑的会话,以及它们各自挂在哪张卡上
- 车队里注册了哪些 agent,各自带什么 skill
- 定时任务上一次跑成了没有
ud get sessions、ud get agents、ud get scheduled-jobs,三条命令。
它看的是工作面,不是账单。用量和成本这一层我们不做,而且不必做——agent 是用你自己的登录 shell、在你自己的机器上起的,用的是你自己那份订阅。没有第二套计费,也就没有第二套账要对。
第二件事:把散在各处的约定收拢成一份
真正难管的不是工具,是工具里那些约定。
同一条规矩,可能在三个 agent 的目录里各躺一份;调好的一套 skill,换个工具又得重写。udctl 把它们放进同一个库。把你那套代码评审的约定写成一个自己的 skill,叫 code-reviewer,那么同一句 ud describe skill code-reviewer,Claude Code 读到的、Codex 读到的、OpenCode 读到的,是同一串字节 —— 三个读的都是你服务端上那一份。
改一次,所有 agent 下次开工就都变了。
它想建立的是一层在各家 agent 之上的公共上下文:在一个地方写,在所有 agent 那里生效。

图4 · 跨 agent 复用:skill、约定、上下文收进 udctl,再回流给各个 agent。
第三件事:一张卡,不只是一条待办
在 udctl 里,任务是个通用容器。它可以是待办,也可以是一份文档、一次决策记录、一条会议纪要、一篇还没写完的稿子。
往下分三层:卡体是活文档,随时改;note 是只增不改的时间线,记录它怎么变成今天这样;comment 是短对话,人和 agent 都在里面说话。
编辑器只有一套——任务、笔记、账目、账户,所有能写字的地方用的是同一个 Markdown 编辑器。

图5 · 卡体 / note / comment 三层,所有能写字的地方共用同一个编辑器。
第四件事:每天汇聚,和一个会删东西的管线
这一件得说准一点:下面这套做法是我们自己搭的,不是 udctl 开箱就有的功能。产品给的是容器和定时任务,做法是我们自己的。
我们那张账本卡上,每天落一条纪要。到第四天,旧的那条被移出近处,归档进当月那张月卡;要点压进一条「月度压缩」。
关键在那个移走的动作。没有它,所谓沉淀就只是越堆越多,堆到最后没人读——那跟什么都没留下,区别不大。
数是这样的:我自己这一本账本,2026 年 8 月完整 31 天,原始纪要 919,538 个字符;留在近处、每天被重读的月度压缩 13,506 个字符。原文一个字没丢,它在月卡里,要查的时候翻得到。

图6 · 每日纪要 → 第四天归档进月卡 → 压成月度压缩 → 耐久的事实进知识库卡。
第五件事:沉下来的东西,得落进一个打得开的目录
前面这些都要有地方放。在 udctl 里,每张卡、每个文件都挂在一条虚拟路径上——/content/blog、/ud/docs/architecture/、/agents/claude-cert-tutor/lessons/D1/——合起来就是一棵目录树。连内置的 skill 都在这棵树上,路径是 /system/skills/ud-cli/。
树上不只有卡。图片、PDF、docx、表格、csv、代码、drawio 图,还有 HTML,都能放进同一条路径下,和卡并排躺着。
HTML 这条值得单说:上传一个 .html,在应用里点开就是渲染好的那一页,不是一屏源码——样式照常,脚本也照常跑,旁边就是下载和全屏。我们自己那份讲虚拟路径的架构文档就是个 .html,一直躺在 /ud/docs/architecture/ 下,要看的时候点开。
这棵树还能整个落到磁盘上。ud init /Notes/ 把本地一个文件夹绑到某条虚拟路径,ud pull 把那条路径底下的卡和文件一起拉下来,子文件夹对子文件夹。卡落成 .md,文件名就是标题,frontmatter 只有一行 ud-id;文件就是文件本身。你的编辑器、你的 grep、你的 git,全都直接能用。

图7 · 同一棵树上并排躺着卡、图片和 .html,点开 .html 就是渲染好的页面。
三、这些字节,落在谁的盘上
做这个项目的时候,有一条线我们不打算越:你的工作记录,不该必须放在我们这儿。
你和 agent 的工作记录里藏着很多东西——你在做什么项目、卡在哪一步、客户是谁、钱怎么花的、你拿什么思路绕过去的。这些信息对你有价值,对别人一样有价值。
所以 udctl 是自托管的。装完之后,你的卡、笔记、纪要、账目,落在你自己机器上 ~/.ud-server/data 下的一个 SQLite 文件里。
首次启动连密码都不问,打开就是你的工作台。
有一件得说实话:每次调用模型,当次的上下文还是会发给模型厂商,这一步谁也省不掉。但留下来的那一份——卡、笔记、纪要——就在你自己机器上的那个文件里。
你的记录,归你自己。 这就是「自托管」三个字全部的意思。
四、哪些人用得上
符合下面任意一条,它可能对你有用:
- 每天靠终端里的 agent 干活,而且不止用一个
- 把约定写成过 skill,结果在三个工具的目录里各存了一份
- 手上一堆「上次好像解决过」的问题,但翻不回当时的记录
- 不想把工作记录、客户名字、账目放进第三方的数据库
- 想让明天开工的那个 agent,已经知道今天这个干到哪了
五、怎么开始:三种装法
上手成本不高,三种方式任选。
方式一:一行命令
npm i -g @oatnil/ud-server && ud-server
装六秒,起一秒,浏览器打开就能用,数据库自己建好。
方式二:Docker——前后端在同一个镜像里,一条命令:
docker run -d -p 3000:8080 \
-e HOST_DOMAIN=http://localhost:3000 \
-e JWT_SECRET=change-me-to-a-random-string \
-e ADMIN_EMAIL=admin@example.com \
-e ADMIN_PASSWORD=changeme \
-v undercontrol-data:/app/data \
lintao0o0/undercontrol:latest
打开 http://localhost:3000,用你上面填的那组邮箱密码登录,数据默认落在 SQLite 里。适合丢在家里那台小机器上常驻。
方式三:只装 CLI——npm i -g @oatnil/ud,装完 ud 和 udctl 两个命令都在。agent 在终端里用的就是它。
写在最后
前面那条纪要管线是我们自己搭的,你多半会搭成另一个样子。要是不知道从哪起步,最小的那一版是这样:每天收工前,让 agent 把今天干了什么写成一条 note,挂在同一张卡上。
就这一步,先做一周。等你嫌那张卡太长了,再去想归档和压缩的事。
项目地址: https://udctl.com