Files.md专注思考的私密空间Files.md 是一款简洁的 .md 文件应用为用户打造一个私密、安静的思考空间。用户可以用它存储生活中的一切如笔记、文档、项目、日记、习惯记录、待办清单和任务等所有内容都以纯 .md 文件形式保存采用本地优先策略对大语言模型LLM友好且完全私密不会将数据发送到服务器用户可以完全掌控本地文件同时拥有打开这些文件的软件。借助文件和自身智慧积累知识还能利用 LLM 扩展软件功能。纯文件和自主拥有的软件可以长久留存。试用与支持用户可以前往 [app.files.md](app.files.md) 试用目前处于测试版主站为 [files.md](files.md)。这个项目开发者已经开发了 5 年若用户认可它欢迎在 GitHub 上给予支持。特色功能简洁实用必要功能至上只保留必要功能适度的限制反而能激发创造力。免安装使用无需安装任何程序只需浏览器即可使用。离线可用支持离线操作数据始终存储在本地设备。免费开源代码完全开源极其简单一个人或 LLM 都能轻松理解整个项目。易于扩展代码库便于 LLM 根据用户需求进行扩展。便携性强无需构建系统直接打开 web/index.html 即可使用。同步选项本地优先数据不会离开用户的设备最大程度保障隐私。云文件夹同步支持 iCloud、Dropbox、Google Drive 等云存储服务无需运行服务器即可实现设备间同步。自建同步服务器使用自己的服务器通过一个 Go 二进制文件实现局域网内设备间的同步。托管同步服务器使用开发者管理的服务器通过 api.files.md 实现同步无需设置即可立即试用。使用方法打开应用建议使用 Chrome 浏览器访问 [app.files.md](app.files.md)点击地址栏右侧的 “Install files.md”选择本地文件夹以保存更改。偶尔使用 CmdShiftRMac或 CtrlShiftRWindows强制刷新页面以获取更新。快速记录打开聊天窗口发送消息选择保存位置也可稍后选择即可快速保存笔记、任务、日记记录和待办清单。深度思考通过连接不同的想法让它们相互关联、不断积累。在 web 应用中建立相关笔记之间的联系输入 [如同大脑中的神经元连接。花时间浏览笔记深入思考不同领域的笔记关联可能会产生新的见解。例如开发者曾基于大脑和软件开发相关笔记的联系撰写了一篇关于《软件开发中的认知负载》的文章。避免知识陷阱阅读和记笔记容易让用户误以为自己理解了内容但实际上可能只是停留在表面。过多的知识可能会成为障碍阻止用户去体验新事物。在添加新笔记之前思考新知识如何提升自己的判断力或扩展知识体系以及如何从新的角度看待世界。具体使用场景日记记录当用户有良好的感受时发送消息并点击 “To Journal”或者在消息末尾添加 jj 或 жж记录将被保存到 journal/YYYY.MM Month.md 文件中。任务管理在工作流程中当同事要求发送报告时及时在聊天中记录任务只添加小而可操作的任务项避免添加过于宽泛的任务如 “Plan a vacation”。对于稍后完成的任务点击 “To Later”。待办清单当朋友推荐书籍或用户发现缺少生活用品时将这些信息记录到聊天中然后移动到相应的待办清单如 Read.md、Watch.md、Shop.md 等。文件结构文件结构已预先定义但用户也可以根据自己的需求进行调整。具体结构如下聊天记录Chat.md笔记brain/Note.md 及其他 .md 文件待办清单Read.md、Watch.md、Shop.md、MyChecklist_.md日记journal/2024.08 August.md任务Later.md习惯记录habits/Ate consciously.md 及其他 .md 文件图片media/*支持 png、jpg、webp、gif 格式存档archive/*.md配置文件config.json用户可以在 [files.md/llms.txt](files.md/llms.txt) 查看文件结构方案并将其复制到 CLAUDE.md 或 AGENTS.md 中以便 AI 代理理解文件结构。快捷键快捷键操作[插入文件链接CmdK / CtrlK打开文件搜索窗口CmdN / CtrlN创建新文件CmdM / CtrlM移动文件CmdD / CtrlD删除文件CmdEnter / CtrlEnter打开聊天窗口CmdShiftEnter / CtrlShiftEnter切换聊天对话框Cmd[ / Ctrl[切换到上一个文件Cmd] / Ctrl]切换到下一个文件Cmd~ / Ctrl~切换侧边栏CmdB / CtrlB切换加粗格式CmdI / CtrlI切换斜体格式CmdY / CtrlY插入复选框Cmd/Ctrl 点击复制内联文本或打开链接CtrlCmdSpace插入表情符号Mac实用脚本所有脚本都位于 cmd 目录下可在文件目录中运行。使用前请先安装 Go。添加 Whoop 指标到日记go run /abs/path/to/files.md/cmd/whoop/whoop.go将维基链接转换为 Markdown 链接go run /abs/path/to/files.md/cmd/tomdlinks/tomdlinks.go支持 --dry-run 选项插入反向链接go run /abs/path/to/files.md/cmd/backlink/backlink.go支持 --dry-run 选项移动日记时间戳go run /abs/path/to/files.md/cmd/shifttime/shifttime.go项目文档部署到自己的服务器项目包含以下部分webWeb 应用PWAindex.html 为入口文件。web/lib前端库。cmd/server服务器入口。cmd/*/.md 文件的实用脚本。server/bot.go聊天机器人服务器。server/sync/同步 API 服务器代码。vendor后端库。tests端到端测试测试 Web 应用和服务器。贡献指南代码应易于初级开发者理解。每个拉取请求PR应尽量减少或简化代码而非添加代码。尽量避免引入不必要的依赖。代码应自给自足vendor 和 web/lib 文件夹包含在仓库中。在添加新功能时思考该功能是否真正有助于完成核心任务还是仅仅带来短暂的满足感。后端指南编写测试代码。方法名不使用 get* 前缀。避免使用 panic将错误作为业务逻辑的一部分处理。忽略错误时需添加注释说明原因。始终包装错误添加方法上下文。客户端代码不使用迭代器。优先使用真实实现或模拟实现而非模拟对象和存根。仅在避免导入名称冲突时重命名导入。前端指南修改库文件时使用 PATCHED 关键字。希望有一天能用自己的小型实现替换 CodeMirror。不使用构建系统确保 10 年后打开 web/index.html 仍能正常工作。注意锁检查和锁获取之间的 await 可能导致竞态条件。避免不稳定的端到端测试。术语表filename带扩展名的文件名如 “note.md”用作唯一标识。header去除扩展名并大写的文件名如 “Note”。body文件内容。dir用于存储特定类别笔记的目录如 “happiness”。userID聊天 ID主要用作用户 ID与机器人的私聊。ctime for file文件的数据块或元数据更改时间包括文件所有权、位置、文件类型和权限设置的更改时间。父文件夹重命名不影响移动或重命名文件会影响。用于跟踪文件位置变化。mtime for file文件内容的最后修改时间不受文件元数据如所有权、权限或重命名变化的影响用于同步。ctime for dir目录中添加或删除文件或子目录的时间类似于 mtime 加上文件重命名等 inode 更改。性能项目运行速度极快。例如互斥锁的锁定/解锁操作仅需 25 纳秒从 SSD 随机读取 4K 数据需要 150,000 纳秒1 毫秒等于 1,000,000 纳秒。架构决策记录ADRs2026 年 5 月 20 日添加 LaTeX 支持尽管增加了 20 多个字体文件但 LaTeX 基于文本对 LLM 友好文本和数学内容基本能满足需求。2026 年 5 月 6 日从 Today.md 迁移到 Chat.md用户调研显示用户对 “chat” 概念理解困难且 “open chat” 在机器人和 Web 应用中都有明确含义。2026 年 5 月 2 日hide-token 现在每次更改时同步运行之前有 100 毫秒的防抖导致链接和格式化文本逐个删除时出现抖动。2026 年 5 月 6 日将 Inbox.md 和 Today.md 合并为 Today.md“Inbox” 名称过于抽象与生产力相关且遵循 GTD 方法开发者追求平静和简单“Today” 更像是 “聊天中的日常页面”。2026 年 4 月 23 日从 API_HOST、APP_HOST 迁移到 API_URL、APP_URL在不同环境中配置中提供更多信息如所需的协议更好。2026 年 4 月 22 日机器人中的收件箱条目现在通过稳定的内容哈希去除 - [ ] 或 - [x] 标记的块的 fs.Hash识别而不是位置索引即使在条目之间添加、删除或完成其他条目按钮仍能指向正确的行。2026 年 5 月 6 日看到 “to inbox” 和 “to chat” 两个按钮/消息会让人感到精神负担直接将任务放入聊天更轻松。现在所有内容都放入收件箱收件箱中的每个项目都是 Markdown 待办清单项目。此外PWA 应用现在默认显示聊天任务非常方便。也许 “inbox” 这个词在心理上负担过重“chat” 听起来更好有待观察。2026 年 4 月 11 日虽然希望将链接存储为纯 Markdown 链接但视觉上希望像处理最小化的 [links] 一样工作。因此当光标在该行时隐藏 (...) 部分仅对 Markdown 文件链接隐藏。2026 年 4 月 11 日恢复标准 Markdown 链接希望知识库跨平台能在 GitHub 上正常工作。2026 年 4 月 5 日尝试将 web/* 内容移动到根文件夹以简化结构但这是个错误的决定应该有一个明确的目录作为服务器的公共文档根目录。2026 年 4 月 19 日切换到 [link] 格式的链接[link](full%20path) 语法过于复杂且不想处理路径更改问题。2025 年 9 月 21 日移除 WASM。曾遇到消息从 Inbox.txt 移除但未添加到文件的问题虽无法重现但发现代码复杂度高。JS - GowriteFile- Go 等待 JS 的 Promise - JS 中间有 Golang 运行时 - JSwriteFile- Go从 Promise 返回- 将结果发送回 JS且必须在单独的 goroutine 中执行因为 WASM 和 JS 在同一线程中运行。此外Golang 的 WASM 仍处于实验阶段组件过多且不确定性大。现在是时候用 JS 重新实现功能放弃这种复杂性。另外inbox.wasm 约 8MB希望应用体积更小。2025 年 7 月 11 日决定使用 OPFS 作为文件系统的初始驱动浏览器支持更好用户使用更方便。应用默认使用 OPFS 驱动用户需要时可通过打开本地目录将驱动替换为本地文件系统 API此时 DirHandle 将保存到 IndexedDB 并在每次使用时复用。2025 年 7 月 8 日根文件夹现在为 /而非空字符串。Web 应用中的所有文件通过路径识别而非 “dir” “filename”限制为一级嵌套。2026 年 4 月 11 日Dropbox 会更改新创建文件的一些元数据导致 ctime 改变。考虑迁移到 mtime 进行同步虽然无法通过 mtime 检测重命名但有单独的机制检测但 mtime 更可靠且同步不会因权限/所有权更改等触发。已迁移到 mtimemtime 用于基于内容的同步ctime 用于追加同步日志重命名/删除且可以从 .git/archive 恢复 mtime而 ctime 不行。2025 年 6 月 30 日决定将所有流程迁移到 Chat.md包括待办清单。但此流程无法处理多行任务可能需要同时支持文件和索引。有两种方法统一编码参数并使用带 IF 的相同命令处理程序或使用不同的命令处理程序处理聊天/文件移动。开发者选择了不同的命令处理程序。如果使用不同的命令移动到按钮配置会很复杂。也许可以在 “文件移动” 时将文件移回 Chat.md复用现有流程。目前看来效果不错chat.md 日志作为追加日志即使未完成某些流程如安排/移动内容也会保存在日志中可从应用继续操作。2026 年 5 月 6 日现在所有传入消息默认进入 Chat.md。之前消息会移动到 /chat 并成为任务这对于简单的待办清单很方便但对于其他用例不太方便。开发者意识到在会议中只需要一个简单的输入框将脑海中的想法随时记录下来无需立即处理后续可以回顾和整理。这些内容可以是任务、日记记录或文件。拥有一个简单易懂的默认流程更好即把所有消息都存入一个文件。2025 年 6 月 27 日聊天的默认模式现在是 “一个大文件”即只将所有消息存入一个文件。从最简单的流程开始避免给用户带来过多负担。如果选择完整模式需要提前创建目录以便 “to habits”、“to read/shop” 等功能正常工作。如果用户不需要这些目录可以删除且不会重新创建不像 “即时模式”所以不能在所有地方都使用即时策略。2025 年 6 月 26 日之前会提前创建所有必要的目录现在改为即时创建避免一开始就使知识库过于杂乱。2025 年 6 月 24 日同步时使用微秒跟踪文件更改。连续文件创建的时间间隔足够大从 5000μs 到 1000μs 不等。未选择纳秒是因为 JavaScript 在处理 int64 精度时有问题。后来发现 Linux 使用缓存的内核时间以 CONFIG_HZ 间隔更新通过 grep CONFIG_HZ /boot/config-$(uname -r) 查看开发者的值为 1000即 1ms。由于用户交互、网络延迟和磁盘 I/O 等原因大多数实际操作的时间间隔远大于 1ms只有在有效/原生循环中更新文件时可能会有问题。2025 年 6 月 16 日为使知识库跨平台禁止在文件名中使用如 :?* 等字符这些字符在某些环境如 Windows、PWA中不允许使用。2025 年 9 月 15 日希望在浏览器中实现类似机器人的功能但不想用 TypeScript 重写经过测试的代码因此使用了 WASM效果很好。2025 年 6 月 12 日使用 Telegram 机器人作为无干扰的只写入口访问知识库但它在欧盟/美国不太流行。开发者想到当缩小窗口大小时可以将 app.files.md 转换为聊天界面这将是手机上的默认行为。2025 年 6 月 4 日引入追加日志进行同步。无状态同步实现起来很棘手每次请求都要发送所有文件。由于只在服务器上进行重命名操作因此只跟踪重命名。2025 年 6 月 4 日对于仅内容同步无重命名/删除不在服务器上存储任何状态通过比较哈希和最后 ctime 进行同步。2024 年 11 月 11 日移除维基链接支持只使用纯 Markdown 链接确保知识库的互操作性。2024 年 10 月 26 日现在按用户顺序处理更新因为并发文件写入存在竞态条件还遇到消息处理顺序混乱的问题无法将其合并为一条消息。2024 年 10 月 6 日移除 fyne.io。起初开发者想找一个轻量级的替代 Electron 的方案fyne.io 似乎是理想选择。使用几天后实现了约 80% 的机器人功能开发者很满意。但要实现其余功能需要付出巨大努力涉及滚动、表情渲染、文本选择行为、链接支持等细节。未来还需要实现图像上传和 Markdown/HTML 渲染在这种非 WebView 工具包中实现会很痛苦。尽管开发者不喜欢在桌面应用中使用 Web 栈但似乎别无选择尝试使用 wails.io。2024 年 9 月 9 日使用依赖项管理将所有依赖项放入仓库不担心依赖项被阻止或移除仓库是自给自足的事实来源。2025 年 6 月 9 日使用细粒度锁在数据库、日记、用户配置中代替每个用户的全局锁避免瓶颈。工作者可能使用 ChatGPT 等第三方 API不想一直持有用户锁。后来添加了按用户顺序处理更新机器人本身不会导致竞态条件但机器人和工作者可能会因此应继续使用细粒度锁。2024 年 8 月 20 日每次访问时从配置文件中读取每个用户配置值不需要在 bot.Answer() 方法前后加载/保存整个配置。每次需要更改配置时重新读取避免写入过时数据。例如如果只在 bot.Answer() 之前加载一次配置bot.Answer() 可能会有显著的网络延迟如进行外部请求时延迟 2 秒在此期间 worker.MoveDueTasks() 可能会修改 userconfig.Schedule导致数据竞争机器人回复后写入过时数据开发者不希望丢失日程安排。2024 年 8 月 8 日尽早进行清理之前在 Path 方法中放弃清理是意外行为会破坏路径。应在收到数据后立即进行清理。大多数命令使用 md5 哈希这种情况下无需清理。2024 年 7 月 13 日使用 gofumpt 进行更严格的格式化gofumpt 接受 gofmt 接受的格式的子集减少格式化选项的选择更好。2024 年 7 月 13 日文件系统FS的结构应包含用户文件系统userFS名称以反映其用户命名空间的事实。2024 年 7 月 9 日“Note” 这个术语过于模糊尝试使用 “file” 术语不使用任何高级抽象如 “note”。2024 年 8 月 13 日放弃 AST 解析/渲染。通过 AST 处理有很多边缘情况代码过于复杂。Markdown 解析并不难可以用简单直接的代码实现。现在代码量减少了 3 倍理解起来也轻松很多。MD 到 HTML 的转换也采用了同样的方法。由于 Telegram 不支持所有 HTML 标签编写自己的 MD 到 HTML 转换器更容易。2024 年 7 月 8 日遵循宽容读取原则。解析时遇到乱码则跳过但遇到有效数据标志如 ###但数据本身无效时会触发 panic。待办事项在读写循环中保留乱码。2024 年 7 月 7 日使用 [https://github.com/rivo/uniseg](https://github.com/rivo/uniseg)。在 Go 中字符串是只读字节切片可以通过 for 循环或类型转换 []rune(str) 转换为 Unicode 代码点。然而多个代码点可能组合成一个用户感知的字符即 Unicode 规范中的 “字形簇”。例如白色圆圈 “⚪” 有两个符文但只有一个字形簇。2024 年 9 月 7 日Markdown 到 HTML 的转换。用户笔记中可能存在无效的 MarkdownTG API 无法直接发送无效的 Markdown。因此先转义 HTML再将用户的 Markdown 转换为 HTML最后通过 Telegram API 以 HTML 形式发送。2023 年 6 月 13 日文件哈希。在所有用户输入的地方都应使用 fs.hash否则会得到长文件名TG 会返回 INVALID_DATA 错误回调数据最大 64 字节。2023 年 6 月 13 日引入 db.go必须对 Redis 进行抽象否则难以编写测试。2023 年 3 月 13 日db.go 包不存储用户 ID开发者经常单独使用它是否真的需要这样做也许会在不使用用户 ID 的情况下使用它如全局机器人统计。后来将用户 ID 移到类中也许以后会在用户范围之外使用这个类但先着眼于未来。2023 年 6 月 13 日不能在 fs.Put 中对文件名进行大写处理因为可能是用户在机器人外部创建的文件即文件名可能是小写的。