Skip to content

JacksonHe04/iMon

Repository files navigation

MOONLESS

Google OKF Notion Integration TypeScript Next.js pnpm workspaces License: MIT

简体中文 | English | 日本語 | 繁體中文


They told us to aim for the Moon. We did. We put everything up there— our notes, our thoughts, our years of work— on someone else's servers, in someone else's client, behind someone else's paywall.

Now the servers are slow. The seats cost more. And we're still up there, floating, wondering how to come home.



曾几何时,Moonshot 是一个令人热血沸腾的词。

肯尼迪在 1962 年说,我们选择登月,不是因为它容易,而是因为它困难。
后来,这个词被互联网公司借走了。
每一个 SaaS 产品发布会,都是一次 Moonshot。
每一个云端笔记工具,都是你"通往未来的第一步"。

于是我们把笔记搬上去了。把文档搬上去了。把知识搬上去了。
Notion、飞书、语雀——它们接住了我们,给了我们漂亮的界面,流畅的体验,和按月计费的席位。

然后有一天,你想把自己的东西拿回来。

你才发现:你上去容易,下来难。


MOONLESS 是从月球上开的那扇门——但回家不是一步就能走完的。

它由 三个核心模块 串成一条回家的路:

模块 职责 在哪
ESCAPE 把困在云端的内容拉回本地,写成 OKF Markdown moon-escape/bye-bye-notion 等)
MOON 拉回来的内容,需要一个本地"月球"来住和编辑 moon-app/
SHOT 本地知识要有用,需要检索 / RAG / Agent API moon-shot/

ESCAPE 是逃逸——从 Notion / 飞书 / 语雀 的轨道上挣脱;
MOON 是落脚——把知识安放在你自己的硬盘上,用浏览器编辑;
SHOT 是发射——让本地知识被 Agent 真正用起来,不再是沉睡的 .md。

三个模块都遵循同一份规范:Google OKF(Open Knowledge Format)
ESCAPE 写出 OKF,MOON 编辑 OKF,SHOT 消费 OKF。

你的知识,再也没有 monthly seat fee。



三个模块

🚀 ESCAPE —— 离开云端

moon-escape/ 把你在云端的工作空间流式拉到本地,落成符合 OKF 的 Markdown。 它本身又由两部分组成:

  • moon-escape/common/ —— 跨平台共享工具(路径解析、文件名清洗、冲突分配、frontmatter 读写、容错、统计),平台无关。
  • bye-bye-<platform>/ —— 每个云端平台一份独立实现:
平台 目录 状态
Notion bye-bye-notion/ ✅ 可用
Lark (飞书) bye-bye-lark/ 🚧 仅初始化
语雀 (Yuque) bye-bye-yuque/ 🚧 仅初始化

Notion 是目前唯一完整实现的平台——2025 多 Data Source、block_id inline page、p-queue 限流、预算路径表全部到位。Lark 与语雀共用 common/,等接入实现。

当前仓库的 moon-escape/ 装的是 bye-bye 这个根包,start / dry-run 实际执行的是 bye-bye-notion

🌕 MOON —— 本地编辑器

moon-app/ 是跑在你浏览器里的本地 OKF Web 编辑器。

  • File System Access API 选目录 + IndexedDB 句柄持久化 —— 选一次后续自动恢复
  • 三栏布局:左文件树 / 中 Tiptap 富文本 / 右 PageProperties
  • 11 字段 OKF 面板(OKF 6 + Notion 5),未知字段透传不丢
  • 相对路径双链跳转(Cmd/Ctrl + 点击)+ 全局搜索(Cmd/Ctrl + K,MiniSearch,中文 2-gram + 英文空格分词)
  • 5s debounce 自动保存 + Cmd/Ctrl+S 立即保存
  • 文件/文件夹 CRUD,-1 自动防冲突

需要 Chromium 内核浏览器;其他浏览器加载时会显示 unsupported 状态。

🎯 SHOT —— 知识引擎 / Agent API

moon-shot/ 是把本地 OKF 知识重新发射出去的引擎,让 Agent / RAG / 检索真正用得上。

Roadmap 上的能力:

  • Dense Vector Search (RAG) —— 对本地 Markdown 分块、做语义 embedding 检索
  • Sparse Full-Text Search —— MiniSearch 关键词召回
  • Spaces Map & Dependency Graph —— 用 Markdown 相对路径双链当图边,画出页面间的依赖关系
  • Agent API Services —— 对外暴露 JSON 端点:关键词/语义查询、上下文环检索、统计、星球图布局、摘要

moon-shot/okf/docs/ 里同时放着 Google OKF 规范OKF.md 原文 + OKF_CN.md 中文翻译)—— OKF 是贯穿三个模块的统一契约,ESCAPE 写它、MOON 编辑它、SHOT 消费它。


项目结构

moon-escape/                            # 根(pnpm workspace)
├── pnpm-workspace.yaml                 # packages: ['.', 'moon-app', 'moon-shot']
├── package.json                        # bye-bye 根包:start / dry-run / typecheck / web
│
├── moon-escape/                        # ━━━ ESCAPE 模块 ━━━
│   ├── common/                         #   跨平台共享工具(平台无关)
│   │   ├── paths.ts                    #     --export-dir / MOON_ESCAPE_EXPORT_DIR / ~/iNon/Wiki/
│   │   ├── sanitize.ts                 #     文件名清洗
│   │   ├── path-allocator.ts           #     冲突后缀分配(X.md → X-1.md)
│   │   ├── frontmatter.ts              #     YAML frontmatter 读写
│   │   ├── safe-call.ts                #     try/catch 容错包装
│   │   └── count-md.ts                 #     递归统计 .md 数量
│   ├── bye-bye-notion/                 #   ✅ Notion 拉取实现(核心)
│   │   ├── src/
│   │   │   ├── main.ts                 #     CLI → searchAll → 预算路径表 → 流式递归
│   │   │   ├── limiter.ts              #     p-queue 3 req/s + 429/5xx 退避重试
│   │   │   └── notion/                 #     Notion SDK 封装
│   │   │       ├── client.ts           #       dotenv + @notionhq/client
│   │   │       ├── search.ts           #       全量 searchAll(page + data_source)
│   │   │       ├── page.ts             #       retrievePage 元数据
│   │   │       ├── database.ts         #       2025 Model: data_source.retrieve + query
│   │   │       ├── blocks.ts           #       BFS 拉 blocks 树(maxDepth=20)
│   │   │       ├── ancestor.ts         #       block_id → page_id 祖先索引
│   │   │       ├── budget.ts           #       预算路径表(自上而下 BFS 解算最终 localPath)
│   │   │       └── markdown.ts         #       block tree → markdown(含 mention 重写)
│   │   ├── scripts/                    #     一次性诊断/校验脚本
│   │   └── docs/                       #     迁移设计 + Notion API 字段文档
│   ├── bye-bye-lark/                   #   🚧 飞书拉取(待实现)
│   └── bye-bye-yuque/                  #   🚧 语雀拉取(待实现)
│
├── moon-app/                           # ━━━ MOON 模块 ━━━
│   ├── src/
│   │   ├── app/page.tsx                #   三栏编排(文件树 / 编辑器 / PageProperties)
│   │   ├── components/                 #   editor (Tiptap) / file-tree / page-properties / search
│   │   ├── hooks/                      #   useDirectory / useFileTree / useAutoSave / useSearchIndex
│   │   └── lib/                        #   fs-access / frontmatter / markdown-serde / double-link / search-index / db
│   └── docs/                           #   设计文档 + TODOs
│
├── moon-shot/                          # ━━━ SHOT 模块 ━━━
│   ├── src/                            #   知识引擎与 Agent API 实现
│   ├── okf/                            #   Google OKF 规范 & 工具
│   │   ├── docs/                       #     OKF.md 原文 + OKF_CN.md 中文翻译
│   │   ├── scripts/                    #     OKF 校验/转换脚本
│   │   └── CLAUDE.md                   #     SHOT 自身的指引
│   └── README.md                       #   模块说明(Roadmap + Features)
│
├── docs/                               # 项目级文档
│   ├── README_EN.md                    #   英文 README
│   ├── README_JA.md                    #   日文 README
│   ├── README_ZH_TW.md                 #   繁体中文 README
│   └── superpowers/
│       ├── specs/                      #   Web 编辑器 v1/v2/v3 设计规格
│       └── plans/                      #   对应实施计划
│
├── AGENTS.md                           # → CLAUDE.md
└── CLAUDE.md                           # 项目指引:Notion 字段映射 + 拉取策略 + 三条铁律

数据流

                ┌────────────────────────────────────┐
                │  Notion · Lark · Yuque (云端)       │
                └──────────────┬─────────────────────┘
                               │
                ┌──────────────▼─────────────────────┐
   🚀 ESCAPE   │  bye-bye-notion / bye-bye-lark / … │
   moon-escape │  searchAll → blocks → OKF markdown  │
                └──────────────┬─────────────────────┘
                               │  ~/iNon/Wiki/*.md  (YAML frontmatter + 父子目录)
                               │
                ┌──────────────▼─────────────────────┐
   🌕 MOON     │  moon-app (Tiptap + FS Access API) │
   moon-app    │  三栏布局 / 11 字段属性 / 全文搜索    │
                └──────────────┬─────────────────────┘
                               │  同一份本地 .md
                               │
                ┌──────────────▼─────────────────────┐
   🎯 SHOT     │  moon-shot (RAG + MiniSearch + …) │
   moon-shot   │  向量检索 / 关键词召回 / Agent API  │
                └────────────────────────────────────┘

三个模块共享同一份 OKF 契约:ESCAPE 写、MOON 编辑、SHOT 读。改一处,全局生效。


Features

🚀 ESCAPE(moon-escape/,当前以 Notion 为准)

  • 流式拉取,带 ID 幂等 —— 扫一个写一个,断网/崩了不丢,重跑按 notion_id 跳过已导子树
  • Notion 2025 model 完整支持 —— Database 容器 + 多 Data Source、block_id 父页面、扁平化自定义属性全部映射进 OKF YAML
  • 预算路径表(Budgeted Path Map) —— 子 page 未拉时,父 page 渲染时仍能用正确相对路径写出 ## Children 列表
  • 限流 + 退避 —— p-queue 3 req/s + Retry-After 解析 + 5xx 指数退避 + jitter
  • 跨平台复用层 —— moon-escape/common/ 把路径解析、文件名清洗、frontmatter 抽到平台无关,给 Lark / Yuque 留好复用空间

🌕 MOON(moon-app/

  • File System Access API 选目录 + IndexedDB 句柄持久化 —— 选一次后续自动恢复,权限失效有 reauth 按钮
  • 三栏布局 —— 左侧文件树 / 中间 Tiptap 富文本 / 右侧 PageProperties
  • PageProperties 面板 —— js-yaml 解析 OKF 11 字段(OKF 6 + Notion 5),未知字段透传不丢
  • Markdown 相对路径双链跳转 —— Cmd/Ctrl + 点击,编辑器外用 getFileHandleByPath 解析跨层路径
  • 全局搜索(MiniSearch + Cmd/Ctrl+K) —— 中文 2-gram + 英文空格分词,递归扫子目录
  • 5s debounce 自动保存 + 状态指示器 —— 互斥锁避免并发写、Cmd/Ctrl+S 立即保存
  • 文件/文件夹 CRUD —— 右键菜单新建/重命名/删除,文件名 -1 自动防冲突

🎯 SHOT(moon-shot/,Roadmap)

  • Dense Vector Search (RAG) —— 对本地 Markdown 分块、做语义 embedding 检索
  • Sparse Full-Text Search —— MiniSearch 关键词召回
  • Spaces Map & Dependency Graph —— 用 Markdown 相对路径双链当图边,构建页面间依赖图
  • Agent API Services —— 对外暴露 JSON 端点:关键词/语义查询、上下文环检索、统计、星球图布局、摘要

Quick Start

0. 安装

pnpm install

复制 .env.example 并粘贴 TOKEN。

1. 先预览拉取计划(不写盘)—— ESCAPE

pnpm dry-run --root <page-uuid> [--root <page-uuid>...]

只读 Notion,把子树以 markdown 树状清单打印到 stdout,不写任何文件。<page-uuid> 接受 32hex / 8-4-4-4-12 / notion.so URL 三种形式。

2. 真正拉取(流式写盘)—— ESCAPE

pnpm start --root <page-uuid>

每扫到一个 page/database 就立刻写盘,挂掉时已扫描的内容都在导出目录里。重跑时按 notion_id 跳过已导出的整棵子树——要强制重导某个子树,删掉对应的 .md 或目录即可。

可用脚本(一次 pnpm install 装好后):

命令 作用
pnpm start 启动 Notion 流式拉取(ESCAPE)
pnpm dry-run 只读预览,不写盘
pnpm typecheck tsc --noEmit(覆盖 src + bye-bye-notion/src + scripts)
pnpm build TypeScript 编译到 dist/
pnpm web 启 Web 编辑器(moon-appnext dev,即 MOON)
pnpm web:build 构建 Web 编辑器生产包

子包命令也可直接进 moon-app/pnpm dev / pnpm test,进 moon-shot/ 跑它自己的命令,pnpm workspaces 自动提升依赖。

3. 自定义导出目录(ESCAPE)

默认会把内容写到 ~/iNon/Wiki/(首次运行会自动创建)。如需改路径:

# 命令行 flag
pnpm start --root <id> --export-dir /path/to/wiki

# 或环境变量(适合 shell alias / CI)
MOON_ESCAPE_EXPORT_DIR=/path/to/wiki pnpm start --root <id>

# 路径里的 ~ 会被自动展开到 $HOME
pnpm start --root <id> --export-dir '~/Documents/wiki'

解析优先级:--export-dir flag → MOON_ESCAPE_EXPORT_DIR 环境变量 → ~/iNon/Wiki/ 默认值。

移动后重跑 pnpm start 会按 notion_id 自动复用,不会重写文件。

4. 在浏览器里编辑 —— MOON

pnpm web
# 打开 http://localhost:3000/

~/iNon/Wiki/ 目录 → 授权读写 → 左侧文件树 → 中间 Tiptap 富文本 → 右侧 PageProperties(11 字段卡)→ Cmd/Ctrl+S 立即保存 / 5s 后自动保存 / Cmd/Ctrl+K 全文搜索。

需要 Chromium 内核浏览器(File System Access API);其他浏览器会在加载时报 unsupported 状态。

5. 把本地知识接给 Agent —— SHOT

SHOT 当前处于 Roadmap 阶段,等 moon-shot/src/ 落地后即可:

pnpm --filter moon-shot dev   # 启动知识引擎 / Agent API

深入阅读

设计与规范

参考资源


代码检查与测试

# 根目录 TypeScript(覆盖 src + bye-bye-notion/src + bye-bye-notion/scripts)
pnpm typecheck

# MOON 编辑器单元测试(vitest + happy-dom + fake-indexeddb)
pnpm --filter moon-app test

# SHOT 模块的命令(roadmap 落地后陆续补齐)
pnpm --filter moon-shot test

# 一次性诊断(ESCAPE / Notion 端,tsx 已在 devDeps 中)
pnpm exec tsx bye-bye-notion/scripts/validate.ts             # 比对 4 个 root 子树 vs 本地 .md
pnpm exec tsx bye-bye-notion/scripts/verify-ids.ts           # 逐 .md 校验 notion_id
pnpm exec tsx bye-bye-notion/scripts/verify-ancestor-index.mts  # 验证 inline page 归位

包管理(pnpm workspaces)

项目使用 pnpm workspaces 管理 monorepo:

  • pnpm-workspace.yaml 声明 packages: ['.', 'moon-app', 'moon-shot']
  • 三个模块各自是独立包:ESCAPE 在根包、MOON 在 moon-app/、SHOT 在 moon-shot/
  • 共享根 pnpm-lock.yaml,依赖去重、install 更快
  • 子包命令统一用 pnpm --filter <pkg> <cmd> 或在子包目录直接跑
  • .pnpm-store/(如果用全局 store)已被 .gitignore 排除


We chose to go to the Moon. Now we choose to leave. Not with fanfare. Just quietly, with our notes tucked under one arm, walking back down.

About

It's Mine or Nothing. Moon Escape: Reclaim Our Second Brains, Embrace Google OKF, Slay Every SaaS With Your Own Hands — Join Us.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages