导入
导入让你一次上传,就把已有的知识库整个搬进空间:claude.ai 和 ChatGPT 的导出包、MCP 记忆服务器(memory-server)、Claude 的项目与记忆,以及普通的 Markdown 和文本文件。格式按内容识别,而不看文件名,所以你不必事先手工准备什么——引擎会自己解析归档,并分门别类放进文件夹。
导入是导出的镜像:导出从磁盘读取作为事实来源的文件,导入则解析源数据,再走常规写入路径写出笔记。每条笔记进入空间的方式,和真人在编辑器里亲手创建它别无二致——同样有版本管理、溯源和索引。
能识别哪些格式
一份 Claude 或 ChatGPT 归档里通常同时装着好几类数据;凡是导入认得的,它都会识别出来并一并搬过去:
| 来源 | 导出包中的文件 | 会变成怎样的笔记 |
|---|---|---|
| Claude 对话 | conversations.json | 每段对话一条笔记,消息呈现为 ### Human/Assistant |
| ChatGPT 对话 | conversations.json(含分片形式 conversations-000.json…) | 每段对话一条笔记,按时间顺序的完整记录 |
| MCP 记忆 | memory.json(JSONL) | 每个实体一条笔记;关系 → [[wikilinks]] |
| Claude 项目 | projects.json 或 projects/<uuid>.json | 一个项目文件夹:文档 + 指令 |
| Claude 记忆 | memories.json | 账号记忆的每个块各一条笔记 |
| Claude 设计对话 | design_chats/<uuid>.json | 每段对话一条笔记 |
| Markdown / 文本 | .md、.txt | 一条笔记,文件正文即笔记正文 |
格式靠分析内容来判定(每家服务都会给出一个叫 conversations.json 的文件,所以文件名靠不住)。空消息,以及没有一段实质内容的对话,不会留下「孤儿」笔记——跳过了多少,会写在导入摘要里。归档里若混有无法识别的 JSON,它同样会作为 unsupported 计入摘要——数据的丢失始终摆在摘要里,而不会悄无声息地发生。
如何导入
导入位于空间设置的 Import 标签页(/s/<space>/management/import)中。每个选项各占一节:
- File——选择导出文件(
conversations.json、整个 ZIP 导出包,或memory.json)。单个.md/.txt文件走拖放导入(见下文),不经由这个对话框。 - Skip existing notes——重复导入时如何处理(见下文)。
- Memory entries——记忆实体往哪里放(见下文)。
耗时长的导入会作为持久任务运行:进度条带实时刷新的已写入笔记计数、当前阶段,以及一个 Cancel 按钮。你可以离开这个标签页再回来——导入会在后台继续跑,回来时你会重新看到进度,或是最终的摘要。
那个单独的上传对话框并非必需:把 .md 或 .txt 文件直接拖进应用窗口,它就成了一条笔记。拖到树里的某个文件夹上,笔记就落在那个文件夹里;拖进内容区,则落在当前打开笔记所在的文件夹,或者落在根目录。这是同一条导入流水线,只是多开了一个入口。
「Skip existing notes」选项
笔记的文件名是确定性的,且与来源的身份绑定。正因如此,重新导入同一份导出包会覆盖同一批文件,而不是繁殖出一堆重复——五十段都叫「Untitled」的对话也不会互相打架。
- 关闭(重复上传时的默认值——upsert)——已有笔记按路径覆盖,幂等。
- 开启——路径已存在的笔记会被跳过。这对应的场景是:「我把更新过的历史又导了一遍——别把我手工改好的东西覆盖掉。」
「Memory entries」选项
memory.json 里的实体可以送往三个去处之一:
- folder——放在导入根文件夹下,作为用户可见的普通笔记。
- space——放进空间隐藏的智能体记忆挂载点(
.notarium/memory):这些条目不出现在树、文档流和搜索里,但智能体能通过recall取到。 - skip——干脆不导入记忆。
space 选项放进的是该空间自己的智能体记忆。空间内部没有单独的 UI 界面来浏览这份记忆——智能体通过 recall 看到它。这是某一个具体空间的记忆,而不是全局的个人记忆域(后者在资源管理器树中以 Memory 透镜打开)——本次导入不会写到那里。
数据如何摆放
导入会在所选根目录下建出一棵可预期的文件夹树:
conversations/claude/ — Claude 对话
conversations/chatgpt/ — ChatGPT 对话
projects/<project>/ — Claude 项目(+ docs/、prompt-template.md)
memory/claude/ — Claude 账号记忆
memory/<entity-type>/ — memory.json 中的实体
design-chats/<project>/ — Claude 设计对话
日期作为数据保留下来
天真的导入会把整段历史都打上「今天」的日期,文档流于是把几百段对话堆成一堆。Notarium 的做法相反:把创建日期当作数据一路传下来——每条笔记的 frontmatter 里都会写入 created:,取值是那段对话真正发生的时间。文档流会把导入的历史铺回它们各自的真实日期上;而「导出 → 导入」这一来一回也保留日期,搬家不掉东西。
「Created」字段也可以在编辑器里手动改(就在笔记的元数据里)——比如做迁移时,或者要订正一条笔记的日期。最后修改时间(modified)则始终如实反映文件被编辑的时刻,改不了。
底层如何运作
导入的设计要经得起两件事:GB 级的归档,和半路断掉的连接。
- 流式处理。 上传边收边写入磁盘,ZIP 一个成员一个成员地解包,对话的 JSON 数组逐元素解析——一次只处理一段对话。峰值内存与归档大小无关,所以 600 MB 的导出包不会把服务器压垮。
- 持久任务。 主机有元数据库时(自托管的常态),导入默认走持久任务:上传先存进暂存区,再由后台工作进程在请求之外把笔记写出来。关掉标签页、连接断开、甚至服务器重启——进度都不会丢。
- 协作式调度。 批量导入不会独占服务器:写入会给交互请求让路,后台索引在流处理期间暂停、事后再补上。哪怕正在写入成千上万条笔记,搜索和导航依旧灵敏。
flowchart LR
src([归档 / 文件]) -->|上传| stage[磁盘上的暂存区]
stage -->|导入任务| worker[后台工作进程]
worker -->|写入路径| notes[(Markdown 笔记)]
worker -.->|进度| ui([Import 标签页])
主机上没有元数据库时(只有 AUTH_MODE=none 模式才会没有),就没有任务层:导入在单个请求内走同步的流式路径,核心相同,实时计数器照旧。进度和摘要看上去一模一样;唯一的差别是,这样的导入扛不过服务器重启。
边界
- 能取消,不能暂停。 任务可以(协作式地)取消,但不能暂停之后再恢复。
- 进度是不确定型的。 归档里有多少笔记事先无从得知,所以进度显示的是阶段和已写入笔记的实时计数,而不是百分比和剩余时间。
- 上传一旦中断就得重来。 持久性要等字节抵达之后才生效:大归档传到一半断了,就得从头再来。
- 二进制附件不会被导入。 附件里的文本会嵌进笔记正文,但二进制文件本身不会(和导出一样)。
- 导入落在空间根目录。 导入对话框不提供目标文件夹的选择——笔记进入根目录;用拖放时,根目录由落点区域决定。