【AI前沿】App+1 | 把笔记软件「装进」浏览器:SilverBullet.md
App+1 | 把笔记软件「装进」浏览器:SilverBullet.md主作者关注Cheech少数派作者There is a time for reciting poems and a time for fists.Cheech关注Cheech少数派作者There is a time for reciting poems and a time for fists.联合作者关注Cheech少数派作者There is a time for reciting poems and a time for fists.Cheech关注Cheech少数派作者There is a time for reciting poems and a time for fists.昨天 17:30我试过的笔记软件可能比记过的笔记都多——这样说或许有些夸张,但自 2019 年Roam Research进入大众视野,各种支持双链笔记的PKM软件有如过江之鲫。多年来,我也辗转于各类方案、各种组合。我尝试过一些命令行工具(如nb、zk),也用过经典编辑器中的的笔记插件(如Org-roam,vimwiki),还一度回归到 Obsidian 这样的专用软件。回顾历程,我的核心需求始终不变:所有数据须由个人掌控、所有笔记应以纯文本文件的形式来存储。因一种通用的笔记格式和一个完全受控的笔记库,使不同软件间的协作成为可能。随着智能体 AI 的兴起,这样的选择亦凸显其优势来。然而,有时我也会怀念用纸笔记录的时代,随手可读,拿起就写,没有负担。在 Obsidian 还没有发布移动客户端的时候,我曾将笔记发布在Quartz这样的静态网站上方便自己查阅。而在不同设备、平台间同步笔记与软件的设置,有时也令人颇感厌烦。那有没有什么办法能省却这些不便呢?认识SilverBullet.mdOn almost anything someone does in the computer business, you can go back in the literature and prove someone had done it earlier.—— Ken Olsen事实证明,你苦恼中的某个问题,可能早已有人解决。四年前,Zef Hemel开始了SilverBullet.md这个开源项目。与其他 PKM 软件最大的不同在于,它支持自托管,其客户端是一个本地优先的渐进式网页应用程序(progressive web app/PWA)。如果你点进 SilverBullet 的官网,你会发现整个网站就是一个笔记应用的只读实例,你可以在上面体验 SilverBullet 除编辑外的所有功能。自托管更好地保障了用户的数字所有权;而在人人携带智能手机的今天,作为 PWA 的笔记软件让用户打开浏览器便可使用,无需再操心客户端的重复安装与配置。在介绍 SilverBullet 的更多特点前,先谈谈它的部署方式。安装SilverBulletSilverBullet 提供一个单独的二进制文件,但更推荐用Docker来安装。你可以先在自己本地的电脑上熟悉整个流程,之后再到虚拟专用服务器(Virtual Private Server/VPS)上进行部署。整个流程大致如下:购买 VPS 和域名。主流供应商大都支持国内的支付渠道,以我个人为例,每年在这上面的花费为百元左右。除开 SilverBullet,你可尝试将自己订阅中的服务替换为其他的开源解决方案,好充分利用服务器的空余资源。在购买的 VPS 上使用 docker/podman 部署 SilverBullet。然后将购买的域名托管至 Cloudflare,并添加 A 记录将域名(或子域名)指向VPS的地址。再在 VPS 上使用 Caddy 或类似工具进行反向代理。这样,你就可以通过自己的域名访问部署好的 SilverBullet 服务。上述部署方式并非唯一。在官网的安装指南中还提及了其他方法(如使用Cloudflare Zero Trust)。其中,最简单的方法是注册PikaPods,它提供一键架设开源应用的付费服务,但你可以使用其赠送的免费额度体验 SilverBullet 数月。部署后访问相应网址,你会看到这样一个登录的界面。使用compose.yml中设定好的用户名/密码以登录。体验SilverBullet登录后,你会进入到笔记库的主页。(默认的主页文件为index.md,你可通过compose.yml中的SB_INDEX_PAGE变量进行设置。)方便起见,以官网的主页为例SilverBullet 的界面如上所示,分为顶栏和编辑区两个部分。顶栏的左侧为笔记标题,右侧为一行可自定义的按钮。其中,最重要的是Page Picker和Command Palette这两个按钮:Page Picker:也可通过按键Ctrl-k触发(MacOS 上为Cmd-k),用于打开或新建笔记。回车打开选中的笔记,Shift + 回车则会新建相应标题的笔记。使用 Page Picker 搜索带对应标签的笔记Inbox/TIL表示在 Inbox 文件夹下新建名为 TIL 的笔记。Command Palette: 可通过按键Ctrl/Cmd-/触发。命令的右侧会显示已有的按键绑定。执行过的命令在排序上会更加靠前。使用 Command Palette 搜索删除当前笔记的命令SilverBullet 中的每一页笔记都是一个常规的 markdown 文件。(后面你会发现,连软件的设置也是md文件。)这些文件会保存在你部署时设置的文件夹中。(通常是一个名为 space 的目录。如果你想迁移现有笔记至 SilverBullet,将相关文件放入该目录下即可。)若你想让其他软件共用 SilverBullet 的笔记库,你仍可使用如syncthing/git 之类的工具对该目录进行同步或拉取。当你使用 SilverBullet 时,所有笔记会自动保存。若当前笔记未保存,笔记标题会变为灰色。修改标题相当于重命名你的 md 文件,所有与该文件相关的链接也会自动更新。当你处于离线状态时,顶栏的背景则会变为淡黄色。此时,SilverBullet 会将内容保存在本地,等待上线后重新同步至服务器。顶栏之下就是 SilverBullet 的编辑区域。在页面底部,与其他双链笔记类似,SilverBullet 会列出Linked Mentions,即别的页面中引用过当前笔记的所有位置。现在,你已经对 SilverBullet 有所了解,下面我将介绍一些它的主要功能。笔记编辑SilverBullet 和 Obsidian 均使用CodeMirror作为底层的编辑器,因而两者在编辑体验上类似,都尽可能地将 markdown 的编辑和渲染糅合在一起。我个人觉得有比 markdown 更适合笔记的文件格式——因各家软件为了补足功能而开发了太多 markdown 的方言,致使一份笔记在不同编辑器中可能出现不一致的表现。无论如何,markdown 已成为许多平台默认的文档格式,SilverBullet 未能免俗,其使用的 markdown 在CommonMark的基础上亦添加了许多扩展:前辅文 / Frontmatter与 Obsidian 类似,SilverBullet 支持通过页面顶部的 frontmatter 来为笔记添加额外的元数据。比如你可以在 frontmatter 中设置aliases来为笔记增加别名。你可以使用斜杠命令(Slash Command)中提供的快捷方式来创建一个空的 frontmatter。在编辑区域按下/,触发命令后通过自动补全中的提示选择frontmatter若要为笔记中的个别内容添加属性,你可以使用Attribute,格式为[attributeName: value]。若要添加多个属性,你可以这样写:* Item [attr1: foo][attr2: bar]绝对路径链接 / Wikilink理所当然,SilverBullet 中的wikilink与其他笔记软件中的没有多大不同。它支持自动补全,支持使用形如[[link|description]]的格式定义链接显示的文字。你可以通过形如[[note#heading]]的格式指向笔记中的某个标题。此外,你还可以使用如[[note@postion]]的链接来指向笔记中的某个位置。举例来说,[[note@L10C42]]将指向某则笔记中的第 10 行第 42 列。[[note@n]]则会指向笔记中的第 n 个字符。由于笔记频繁增删,手动使用@+ 位置索引的方式并不可靠,通常只出现在自动生成的 Linked Mentions 中。作为补足,SilverBullet 还支持锚链接。你可以在笔记中的某个区域后添加一个$anchor,然后再在另一篇笔记中通过[[$anchor]]来指向这块区域。需要注意的是,你的整个笔记库中不可出现重复命名的 anchor。内容嵌入 / TransclusionTransclusion主要用于在当前笔记中内嵌其他笔记的内容。由于嵌入的是笔记本身而非一个副本,笔记的更新就意味着嵌入内容的更新。使用 transclution 只需在上面提到的那些链接前加一个!,即形如![[link]]的格式。行内标签在 SilverBullet 中,你可以使用#tag给整篇笔记添加标签,也可使用同样的格式为笔记中的某个段落,列表中的某个项目,甚至代码块添加标签。两个例子:为段落添加标签:Paragraph #paragraph-tag-example为列表项添加标签:* Item #item-tag-example标签在 SilverBullet 中极为重要,我将在后文中展开介绍。任务列表SilverBullet支持使用形如* [ ] example task的格式定义待办事项。你可使用斜杠命令/todo来创建。任务项的状态支持自定义。LaTeXSilverBullet 可通过插件Math来使用KaTeX渲染行内($…$)或块级($$…$$)的数学公式。插件的安装方式很简单,将在后文中的「软件扩展」一节中介绍。Mermaid 图表Mermaid 允许你用简单的语法来描述图表结构。SilverBullet 中也可通过安装相应的插件,在笔记中渲染 Mermaid 图表。在笔记页上渲染复杂图表Space Lua除上述扩展外,SilverBullet 还支持提示框、脚注、HTML 标签等功能。但在所有扩展中,Space Lua最为重要,SilverBullet 中的许多进阶功能都用它来实现。简言之,Space Lua 是 Zef Hemel 实现的一个 Lua 方言,在 SilverBullet 中,使用它的地方主要有两处:Space Lua 代码块:在space-lua代码块中定义的全局变量或函数,在你整个笔记库的任何地方均可调用。在后文「软件设置」一节中你会发现,配置 SilverBullet 的选项其实就是在space-lua代码块中使用一些内置的API。你可以使用斜杠命令/space-lua快速生成一个空的 Space Lua 代码块Space Lua 表达式当你在笔记中插入格式为${expression}的内容时 ,SilverBullet 会通过对expression求值,动态地在笔记中生成内容。比如,这行笔记:The Answer to the Ultimate Question of Life, the Universe, and Everything is ${theAnswer}将被渲染为:当然,Space Lua 表达式还有更实用的例子。这就引出了 SilverBullet 中另一个重要的功能:集成查询。集成查询 / Integrated Query若你用过 Obsidian 中的dataview插件,你可能对 SilverBullet 的集成查询不会感到太过陌生。它使用一种类似 SQL/LINQ的查询语