2026-06-02 13:00:00
最早接触 [[Vimium]] 是在学习 Vim 编辑器之后,那种能用键盘完全控制浏览器的感觉确实让人着迷。不用频繁移手到鼠标,链接跳转、页面滚动、标签切换全用键盘搞定,效率提升的体验是实实在在的。用了几年 Vimium 之后,我开始接触到 [[Surfingkeys]],起初以为不过是另一个同类扩展,但深入用下来才发现这两者的差距远比我想象的大。

对于长期使用 [[Vim]] 的人来说,键盘操作的肌肉记忆已经根深蒂固。在编辑器里习惯了 hjkl 导航,切换到浏览器还要去抓鼠标总觉得很割裂。更重要的是,对于程序员、研究者或者任何需要长时间使用浏览器查阅资料的人,频繁移手到鼠标会带来明显的效率损失,甚至是手腕疲劳。
Vimium 在这个领域确立了基础范式:用 f 键激活链接提示、hjkl 滚动页面、J/K 切换标签页、o/O 打开链接等等。这套设计简洁而高效,是很多 Vim 用户的第一个浏览器键盘扩展。不过,随着使用深入,你会发现 Vimium 的局限性也相当明显:配置能力有限、不支持自定义 JavaScript、在某些页面上会失效、搜索功能比较基础。这时候 Surfingkeys 就显示出它的价值了。
Surfingkeys 是一款同样基于 Vim 键位设计理念的浏览器扩展,支持 Chrome、Firefox 和 Safari。它的作者从 2015 年开始开发,目前仍在持续维护更新,在 GitHub 上有超过 13000 个星标。和 Vimium 相比,Surfingkeys 走的是功能更丰富、可定制性更强的路线,可以把它理解为浏览器键盘控制领域的”Neovim”,而 Vimium 则更像是轻量的”原版 Vim”。
核心上,两者都提供了类似的基础操作:用字母键激活页面上的链接、键盘滚动页面、标签页管理等。但 Surfingkeys 在这个基础上走得更远——它允许用户直接用 JavaScript 编写自定义快捷键逻辑,内置了一个独立的 Vim 编辑模式,甚至有自己的 PDF 查看支持和多引擎搜索系统。
Vimium 的配置主要通过它的设置页面完成,支持自定义搜索引擎和重新映射键位,但能做的事情相对有限。Surfingkeys 则提供了一个完整的 JavaScript 配置接口,你可以在配置文件里写任意 JS 代码来定义行为。这意味着你可以创建复杂的按键序列,根据当前网站动态调整键位,甚至调用浏览器 API 做更高级的操作。
举个实际例子:我在 Surfingkeys 的配置里写了几个针对特定网站的快捷键,比如在 [[GitHub]] 上快速跳到文件树、在 Twitter/X 上快速点赞等。这种程度的定制在 Vimium 里根本无法实现。
Surfingkeys 有一个非常实用的功能:在任何网页的文本输入框里,按 Ctrl+i 可以弹出一个内置的 [[CodeMirror]] 编辑器,用完整的 Vim 模式来编写文本。这对于需要在网页上写长文本的人来说非常有价值。写评论、填表单、甚至在 GitHub 上编辑文件,都可以在这个编辑器里用 Vim 操作完成。Vimium 完全不提供这个功能。
按 o 或 O 调出 Surfingkeys 的搜索栏之后,你可以在多个搜索引擎之间快速切换。配置文件里可以添加任意数量的搜索引擎,每个都绑定一个短前缀。比如输入 g 关键词 用 [[Google]] 搜索,输入 y 关键词 在 [[YouTube]] 搜索,输入 gh 关键词 在 GitHub 搜索。这个系统比 Vimium 的搜索引擎支持灵活得多,而且不需要每次都切换默认搜索引擎。
Surfingkeys 实现了比 Vimium 更完整的视觉模式,按 v 进入视觉模式后,可以用 Vim 的文本对象(如 w、e、b)来精确选择文字,然后按 y 复制。在需要精确复制页面文字的场景里,这个功能非常好用,比手动拖选鼠标准确得多。
Vimium 在 PDF 页面基本无效,而 Surfingkeys 对 PDF 有原生支持,可以用键盘翻页、搜索内容、跳转页码。这对于经常阅读 PDF 文档的用户来说是个实实在在的优势。
上手 Surfingkeys 的第一步建议先用默认配置熟悉两周。它的默认键位和 Vimium 有不少重合,但也有差异,比如链接提示默认用 f 激活(跟 Vimium 相同),但标签页切换是 E/R(Vimium 是 J/K)。这些差异需要时间适应。
配置文件可以直接在扩展设置页面里编辑,格式是纯 JavaScript。官方文档有完整的 API 说明,常用的配置项包括:
api.map('newKey', 'oldKey') — 重新映射键位api.mapkey('key', 'description', function() { ... }) — 创建新的自定义快捷键api.addSearchAlias('prefix', 'name', 'searchUrl') — 添加搜索引擎有一点要注意:Surfingkeys 的键位激活逻辑偶尔会和某些单页应用的前端框架产生冲突,导致在某些网站的特定输入场景下快捷键失灵。这时候可以通过配置 sites 白名单或黑名单来处理。Vimium 也有类似问题,不过因为功能更简单,冲突概率相对低一些。
另外,如果你是从 Vimium 迁移过来的,可以在社区里找别人分享的仿 Vimium 配置,先让键位基本一致,然后再逐步加入 Surfingkeys 独有的功能。这样迁移成本会低很多,不用一次性重新学习所有键位。
用了 Vimium 几年再换到 Surfingkeys,感受最直接的提升是配置自由度带来的效率改善。Vimium 是一个非常好的入门工具,设计简洁、开箱即用、学习曲线低,对于刚开始探索键盘操控浏览器的人来说是更好的起点。但如果你已经把 Vimium 用熟了,想要更深度的定制、更强大的文本操作、或者让浏览器键盘体验更接近真实的 Vim 工作流,Surfingkeys 是值得花时间迁移的选择。
两者的核心差异不在于基础功能的好坏,而在于你愿意投入多少时间去配置和适应。Vimium 的 80% 功能几乎零配置就能用上,Surfingkeys 的 100% 功能需要你真正去读文档、写配置。如果你是那种会去给 Vim 写几百行配置的人,Surfingkeys 会让你觉得非常顺手。
2026-05-28 13:00:00
最近在 GitHub 上闲逛的时候,我发现了 [[李继刚]] 整理的一批 [[Claude Skills]],出于好奇就 clone 下来翻了翻仓库。打开目录一眼扫过去,几乎所有 Skill 输出的文档文件名都长得很特别,大致是这样的形式: 20260527162000==z--投资分析-ajinomoto-2802。这种带着长串数字时间戳、夹杂 == 和 – 分隔符的写法,一眼看上去既不像我熟悉的 [[Jekyll]] 那种 YYYY-MM-DD-title.md,也不像 [[Obsidian]] 里常见的中文标题直接做文件名,反而有种”工程化”过头的味道。
我最初的猜测是 [[Zettelkasten]] 命名法,毕竟时间戳作为唯一 ID、之后跟着标题,这是卢曼卡片盒笔记法的经典做法之一。但仔细比对了一下我之前看过的几种 Zettelkasten 工具,发现这种带 等于等于 SIGNATURE 中间字段的命名方式其实并不是 Zettelkasten 通用做法,搜了一圈之后才确认,这是 [[Emacs]] 生态下一个叫做 [[Denote]] 的笔记包所使用的文件命名规则。既然好奇心已经被勾起来了,那干脆就花点时间系统性地了解一下 Denote,顺便看看作为一个长期使用 Obsidian 的人,我能从它的设计里借鉴到什么。
回到最开始那个文件名 20260527162000==z--投资分析-ajinomoto-2802 ,如果不知道背后的命名规则,看起来就像是某种自动生成的临时缓存文件。但实际上,这个文件名里的每一段都承担着明确的语义。前面 14 位 20260527162000 是一个精确到秒的时间戳,等同于 ISO 8601 中 20260527T162000 这种写法的紧凑表达,代表这条笔记创建于 2026 年 5 月 27 日 16 点 20 分 00 秒。这串时间戳并不是给人看的,而是给文件本身一个不会重复、不会被改名影响的唯一标识符 (Identifier)。
接着是 等于等于 z 这一段,== 是 Denote 中专门用来分隔标识符与签名 (Signature) 的符号,而 z 则是这条笔记的签名内容。签名在 Denote 中是一个完全自由的字段,你可以用它来记录卡片在卢曼式 folgezettel 体系中的序号 (比如 1a、1a1、1a2),也可以用它表达上下文 (比如 work、home、project-a),甚至可以单纯地放一个版本号或者优先级标记。在李继刚的 Skill 输出里,z 看起来更像是某种约定俗成的分类前缀,具体语义需要看他自己的整理逻辑。
最后是 --投资分析-ajinomoto-2802 这一段,-- 是签名与标题之间的分隔符,后面跟的就是标题本身,通常会做 slugify 处理,把空格、标点都换成短横线。完整解析之后,这个文件名实际上等同于一句完整的描述: “这是一条创建于 2026 年 5 月 27 日 16:20 的笔记,签名为 z,标题为’投资分析 ajinomoto 2802’“。从无意义的字符串到结构化信息,只需要知道分隔符的含义就能 100% 还原,这正是 Denote 文件命名设计的核心要点。
[[Denote]] 是 [[Protesilaos Stavrou]] (社区里多数人简称他为 Prot) 开发的一个 Emacs 笔记管理包,首个公开版本发布于 2022 年,如今已经进入 [[GNU ELPA]] 仓库,可以通过 Emacs 自带的包管理器直接安装。Prot 同时也是 [[Modus Themes]] 、 [[Ef Themes]] 、 [[Logos]] 、 [[Tempel-Collection]] 等多个广为人知的 Emacs 包的作者,他的整个工具链有一以贯之的设计风格,那就是简洁、可读、尽量贴近 Emacs 原生能力,而不引入额外的运行时依赖。Denote 也完整继承了这种思路。
理解 Denote 的设计动机,需要先看看它出现之前的同类工具。在 Emacs 生态里,谈到笔记管理几乎绕不开 [[Org-roam]],它基于 [[Org-mode]] 构建,通过 sqlite 数据库维护笔记之间的链接、反链以及节点元信息,功能强大但也带来不少代价: 数据库可能损坏需要重建,大量笔记下索引会变慢,而且这些笔记的语义信息一旦离开 Org-roam 的数据库就难以复现,可移植性受到影响。Prot 的看法是,如果笔记的核心价值是长期保存和自由迁移,那么任何外部数据库都是潜在的负担,真正应该被信任的只有文件本身。
基于这个判断,Denote 把所有的关键元数据都压进了文件名,数据库被彻底拿掉了。一条笔记的标识符、标题、关键词、签名,统统出现在文件名中,文件内部还会同步一份 YAML 或 Org 前置元数据 (front matter) 作为冗余备份。这样的结果是,即使你不打开 Emacs,只用 ls、grep、find 这些 Unix 标准工具,也能完成查找、过滤、批量改名等绝大多数管理操作。哪怕将来彻底不再使用 Emacs,这些文件搬到 [[VS Code]]、Obsidian 或者任何文本编辑器里,信息也不会丢。
Denote 的标准文件名格式可以用一个模式来概括: IDENTIFIER == SIGNATURE–TITLE__KEYWORDS.EXTENSION。每一段都有自己的分隔符,而且这些分隔符是被精心挑选过的,既不容易和正常的标题、标签内容冲突,也方便用正则表达式做切分。
IDENTIFIER 部分使用 YYYYMMDDTHHMMSS 这种紧凑的 ISO 风格时间戳,创建之后就不再变动,即使你重命名文件、修改标题、调整关键词,这个 ID 也始终保持不变。这一点至关重要,因为 Denote 的链接机制完全是基于 ID 的: 一条笔记内部引用另一条笔记时,记录的不是文件名,而是 14 位时间戳。这就意味着标题随便改、关键词随便加,链接永远不会失效。我个人觉得这是 Denote 整套设计里最优雅的部分之一,因为很多笔记系统的”链接腐烂”问题本质上都是把人类可读的标题当成了机器可识别的 ID,而 Denote 干脆把这两者分开来。
SIGNATURE 部分是可选的,夹在 == 之间。前面已经提到,它可以承载任意语义,Prot 自己也强调这是给用户自由发挥的字段。一个很有意思的用法是模拟 Niklas Luhmann 真正的卡片盒编号体系,比如 1、1a、1a1、1a2、1b,通过字符顺序就能在文件浏览器里看到笔记之间的逻辑关系。这种”folgezettel”结构在数字化 Zettelkasten 工具里其实长期缺乏好的实现,因为大多数工具只关心双向链接而忽略了顺序关系,Denote 通过签名字段把这件事重新带回了视野。
TITLE 部分跟在 -- 之后,默认会被处理成全小写、用短横线连接的 slug。如果你的标题里有中文,Denote 会保留中文字符,只把空格和标点替换掉,所以李继刚那个例子里中文标题原样出现是完全合理的行为。KEYWORDS 部分跟在 __ 之后,多个关键词用下划线连接,比如 __emacs_productivity_zettelkasten。最后是文件扩展名,Denote 支持 .org、.md、.txt 三种主流文本格式,你可以在配置里指定默认使用哪一种,不同格式对应的前置元数据写法也会自动调整。
值得强调的是,这五个组件的顺序并不是写死的,Denote 提供了 denote-file-name-components-order 这个变量,允许你按需调整顺序。比如有人喜欢把签名放在最前面方便排序,有人则希望关键词紧跟在标识符后面方便扫视,这些都可以在自己的配置里调整。但无论顺序如何变化,各段之间的分隔符 (– 、 __ 、 == ) 是固定不变的,这保证了不同顺序的文件名仍然可以被同一套解析逻辑识别。
我在调研过程中发现一个常见的误解,就是把 Denote 等同于 [[Zettelkasten]],或者反过来认为 Denote 仅仅是 Zettelkasten 的 Emacs 实现之一。事实上两者关系更微妙: Denote 借鉴了 Zettelkasten 的一些核心理念 (比如唯一 ID、纯文本、原子化笔记、链接为主),但它本身并不强制你使用 Zettelkasten 方法论。
Zettelkasten 的精髓在于卡片之间的网络结构、每张卡片只表达一个想法、通过持续地建立连接来涌现知识,这是方法论层面的事情。Denote 提供的只是一组工具: 文件名生成、链接管理、反链显示、关键词过滤,至于你怎么组织内容,完全是个人选择。你可以用 Denote 写日记、做项目笔记、记会议纪要、整理引用文献,这些场景全部都不需要遵守 Zettelkasten 的任何规则。
但如果你确实想严肃地实践 Zettelkasten,Denote 提供的工具组合恰好非常合适。基于时间戳的唯一标识符天然适合做原子化笔记的 ID,签名字段可以承载卢曼式的层级编号,关键词字段对应 Zettelkasten 中的索引词,链接和反链则实现了卡片之间的网络结构。Prot 还专门开发了一个可选扩展 denote-sequence.el,专门用来管理 folgezettel 序列,对深度 Zettelkasten 用户来说是个加分项。
作为一个 Obsidian 重度用户,我自然会把 Denote 和 Obsidian 做对比。两者表面上看起来很像: 都是基于纯文本,都强调链接,都不锁定厂商,但深入到具体的使用体验,差异其实非常明显。
Obsidian 的核心是 wiki-link 风格的双向链接,你通过 [[笔记标题]] 来引用另一条笔记,链接的解析完全依赖于标题。这种方式人类可读、操作直观,但缺点也很清楚: 一旦你改了笔记标题,所有引用都需要同步更新,Obsidian 会自动帮你做这件事,但代价是它必须维护一份反向索引。Denote 走的是另一条路,链接的目标永远是 14 位时间戳 ID,标题只是用来展示的,改标题对链接没有任何影响。从健壮性角度看,Denote 的方式更稳妥,但从可读性角度看,Obsidian 的 [[wiki-link]] 更友好。
文件命名上,Obsidian 把命名权完全交给用户,可以用中文、英文、长句子、emoji,只要文件系统支持都行。Denote 则是命名权交给工具,你输入标题和关键词,工具按规则生成文件名。前者灵活但容易混乱,后者整齐但需要适应。我自己用 Obsidian 这么多年,文件命名上确实存在一些不一致,比如有的笔记用中文标题、有的用英文,有的是动词开头、有的是名词开头,真正想搜索的时候不得不依赖全文搜索而不是文件名。Denote 这种”工具兜底”的方式在长期管理上确实能避免很多混乱。
元数据上,Obsidian 把所有信息放在 YAML frontmatter 里,文件名只是个标题。Denote 则把标识符、签名、标题、关键词全部塞进文件名,frontmatter 只是备份。这意味着 Denote 的文件名比 Obsidian 的更”重”,但也带来一个好处: 只看文件列表就能掌握全部关键信息,不需要打开文件,也不需要任何外部工具的帮助。在脱离 Emacs 或 Obsidian 的环境下,比如在终端、在 [[rclone]] 同步过程中、在文件管理器里浏览,这种差异会变得很明显。
生态层面,Obsidian 拥有庞大的第三方插件市场,移动端、桌面端体验完善,新手上手成本极低。Denote 则深度绑定 Emacs,如果你不是 Emacs 用户,引入 Denote 的成本几乎等同于学习一个新的编辑器,这是它最大的门槛。所以对绝大多数人来说,Denote 并不是 Obsidian 的替代品,但它的设计思路完全值得借鉴。
调研到这里,我开始思考一个更实际的问题: 我能不能在不放弃 Obsidian 的前提下,把 Denote 那些好用的设计抽出来,应用到自己的工作流里。答案是大部分都能借鉴,而且并不需要太复杂的改造。
第一个可以借鉴的是文件名结构。我之前给 Obsidian 笔记起名比较随性,完全靠当时的心情和标题灵感。试着改用 Denote 风格的 ID--TITLE__TAGS.md 之后,我发现两个明显的好处: 一是按文件名排序就等同于按创建时间排序,不需要依赖 frontmatter 里的 create_time 字段; 二是在 [[git]] 历史里看 commit diff 时,文件名本身就携带了足够的上下文,不需要打开文件就能知道改的是哪一类笔记。当然如果你完全照搬 Denote 的命名规则,Obsidian 的双链解析会有点别扭,因为 [[ID--TITLE__TAGS]] 这种写法既长又难看,这时候可以借助 [[Obsidian]] 的 alias 字段,在 frontmatter 里把人类可读的标题作为别名,链接时仍然用 [[标题]] 即可。
第二个可以借鉴的是签名字段的概念。Obsidian 默认没有 SIGNATURE 这个层级,但你完全可以用文件名前缀或者 frontmatter 字段来模拟。比如我可以约定所有读书笔记前缀为 book-,所有日记前缀为 diary-,所有项目笔记前缀为 proj-,这就相当于一个简化版的 signature 系统。结合 Obsidian 的全局搜索和 Dataview 查询,这种前缀分类的检索效率非常高。
第三个可以借鉴的是”文件即数据库”的思路。Obsidian 本身就是基于纯文本的,但很多用户依赖大量插件来管理元数据,等于又把数据迁移回了某种”数据库”。Denote 的极简思路提醒我,任何依赖插件才能解读的信息,都是有失效风险的,真正可靠的信息应该写在文件名和 frontmatter 这种通用结构里。我打算把自己一些散在插件状态里的标签和分类,统一迁移到 frontmatter 里去。
第四个可以借鉴的是链接的稳定性。虽然 Obsidian 不支持基于 ID 的链接,但我们可以利用 Obsidian 的 aliases 字段来缓解标题改名带来的链接腐烂问题。把笔记之前用过的所有标题都加到 aliases 里,即使现在的主标题变了,通过别名也能正常链接,这在一定程度上接近了 Denote 的”ID 永远稳定”的效果。
把研究的结果落到决策层面,我自己的判断是: 如果你已经是 Emacs 用户,并且对笔记的长期可移植性、不依赖数据库、纯文本至上这些原则非常认同,Denote 几乎是当前最优雅的选择。它的代码风格清晰、文档质量极高 (Prot 写的 manual 在 Emacs 包里算得上一流)、社区也比较活跃,可以放心地长期使用。
但如果你是 Obsidian 用户、Notion 用户,或者完全没有 Emacs 经验,我不会建议你切换到 Denote。门槛不在 Denote 本身,而在 Emacs 这个底座,从快捷键到配置文件到调试方式,都是一整套需要时间投入的体系。更现实的做法是,把 Denote 当作一个设计案例来研究,从中提炼出适合自己工具链的部分。本文前面提到的几个借鉴思路,都不需要你真的去装 Emacs。
对于像李继刚那样使用 Denote 来组织 Skill 输出的场景,我觉得是一个非常合理的选择。AI 生成的笔记、卡片、文档天然需要一个唯一标识符 (避免重复)、一个可机器解析的元数据结构 (方便后续处理)、以及对未来工具变迁的鲁棒性 (不绑定特定平台),Denote 的命名规则恰好把这三件事一次性解决。我看完之后也开始思考是不是把自己的 [[Claude Code]] 输出、[[ChatGPT]] 对话归档也用这套规则整理起来,把 AI 时代产生的大量”中间态文本”变成可长期检索的资产。
研究完 Denote 之后,我最大的感受是,工具的价值不仅仅在于它能不能解决问题,更在于它的设计哲学能不能给你新的视角。我并不打算从 Obsidian 切换到 Denote,但 Denote 那种”信任文件名、不信任数据库”的思路,确实让我对自己当前的笔记管理方式做了一次反思。文件名里能放进去的信息,我之前是不是都用到了; 标题和 ID 的分离,我能不能借助 alias 字段实现; 跨工具的可移植性,我有没有低估它的长期价值。
回到那个最初引发好奇的文件名 20260527162000==z--投资分析-ajinomoto-2802,现在再看它,已经不再是一串”工程化过头”的随意字符,而是一份非常克制、非常自律的信息组织方式。每一段都承担明确的语义,每一段都为长期保存而设计,每一段都尽量减少对外部工具的依赖。这种克制本身就是一种值得学习的态度。
下一步我想做的事情是: 在自己的 Obsidian vault 里挑一个子目录,比如 [[Zettelkasten]] 这个文件夹,试着改用 Denote 风格的命名规则跑一段时间,看看长期下来的检索效率、链接稳定性、心智负担是不是真的有改善。如果效果确实好,也许会扩展到整个仓库。这种”借鉴而不照搬”的方式,大概是面对优秀工具时最务实的态度。
2026-05-23 13:00:00
最近我在 macOS 上重新整理终端工具链的时候,又一次认真看了 [[Ghostty]]。很多人第一次接触 Ghostty,会先被它的界面、速度或者作者背景吸引,但只要打开 Shell 跑一个 echo $TERM,很快就会看到一个更陌生的名字:xterm-ghostty。这个名字看起来像是传统 xterm 的变种,实际上它背后代表的是 Ghostty 对终端兼容性的一整套设计思路。很多人把它当成一个无关紧要的环境变量,但如果你经常使用 [[SSH]]、[[tmux]]、[[Vim]]、[[Neovim]]、[[less]] 或者各种 TUI 工具,理解 xterm-ghostty 会让你少踩很多坑。

这篇文章我就集中聊两件事:第一,Ghostty 到底是一款什么样的终端;第二,xterm-ghostty 到底是什么,它相比传统的 xterm、xterm-256color 又多了哪些能力,为什么 Ghostty 要专门为自己定义一个终端类型。
Ghostty 是 [[Mitchell Hashimoto]] 主导开发的开源终端模拟器,项目目标很明确,就是做一个现代的、跨平台的、面向开发者工作流的终端。它不是那种只强调“极简”的终端,也不是把大量功能堆成一个庞杂 GUI 的终端,而是尽量把渲染性能、终端兼容性、原生平台体验和现代特性放在一起做平衡。按照官方文档的定位,Ghostty 在 macOS 上提供原生体验,在 Linux 上也尽量贴近各自桌面环境的习惯,同时保持统一的终端行为。
我自己看 Ghostty 最顺眼的一点,是它没有把“现代化”理解成重做一套封闭工作流。很多新终端喜欢把命令历史、AI、会话管理、团队协作都做进产品里,结果是表面上功能很多,底层兼容性却经常拖后腿。Ghostty 走的是另外一条路:先把终端模拟器本身做好,再把标签页、分屏、Shell 集成、图形协议、快捷终端这些真正和终端本体相关的能力打磨到位。对我这种长期泡在命令行里的人来说,这种思路更踏实。
从体验上看,Ghostty 有几个很明显的特征。第一个是渲染流畅,它本身就是围绕现代图形渲染路径来构建的,滚动大段日志、跑持续刷新的命令或者长时间开多个分屏,窗口依然很跟手。第二个是原生能力足够完整,它内置标签页、分屏和 Quick Terminal,不需要像以前那样先在 [[iTerm2]]、[[Kitty]]、[[tmux]] 之间反复权衡。第三个是它的配置模型比较干净,文本配置足够直观,适合直接纳入 dotfiles 管理。
xterm-ghostty 本质上是 Ghostty 对外声明的终端类型,也就是 TERM 环境变量里的值。终端程序、[[Shell]]、[[ncurses]] 应用、全屏 TUI 程序并不会直接“认识”某个终端窗口长什么样,它们通常只会看 TERM,然后去 terminfo 数据库里查这个终端支持哪些控制序列、键盘事件、颜色能力、鼠标模式和光标控制方式。换句话说,TERM=xterm-ghostty 并不是装饰品,而是 Ghostty 告诉整个命令行生态:“请按这一份能力说明和我对话。”
很多人会疑惑,为什么不直接沿用 xterm-256color。原因很简单,历史上的 xterm-256color 是一个兼容性很强、但能力描述也相对保守的通用终端身份。只要 Ghostty 的行为超出了这个公共最小集合,比如支持更多扩展键位、更准确的真彩色能力、更现代的粘贴模式、鼠标事件或者同步更新语义,那么继续伪装成 xterm-256color 反而会让应用程序无法正确利用这些能力。Ghostty 用 xterm-ghostty 这个名字,本质上是在继承 xterm 家族兼容基础的同时,声明“我还有自己的增强能力”。
从命名上看,这个选择也很聪明。前缀保留 xterm,意味着它仍然站在最广泛兼容的 VT/xterm 生态上,不是另起炉灶;后缀加上 ghostty,表示这是 Ghostty 自己维护的一份终端定义。对多数类 Unix 工具来说,这种命名既熟悉又明确,兼容老工具的概率更高,也给新特性留下了清晰的扩展空间。
如果只看名字,xterm-ghostty 很容易被理解成“换皮的 xterm”。但我本地用 infocmp -x xterm-ghostty 看过 Ghostty 自带的 terminfo 定义之后,会发现它包含的内容其实相当完整,远不只是 256 色这么简单。结合 Ghostty 官方文档,可以把它的能力理解成下面几层。
xterm-ghostty 声明了 colors#256,同时还包含 Tc 和 setrgbf、setrgbb 这类真彩色相关能力。这意味着依赖 terminfo 的应用不只知道“这个终端至少支持 256 色”,还可以更可靠地判断它支持 24-bit true color。对于现代编辑器、语法高亮器、Git diff 工具和各种 Dashboard 来说,这一点非常关键。很多人平时觉得主题显示不对,只会去怀疑配色方案,实际上问题常常出在终端身份过于保守,导致程序主动降级输出。
Ghostty 之所以要把这件事写进自己的终端定义,是因为现代终端的显示能力早就不止 16 色或者 256 色。今天我们在终端里使用 Catppuccin、Tokyo Night、Gruvbox 或者各种自定义主题时,往往默认期待颜色过渡准确、暗部层次足够细腻、选中态和光标色也能正确显示。xterm-ghostty 的存在,就是让应用层不用猜,直接知道这些能力是可以依赖的。
另一个特别实用的点,是 xterm-ghostty 对扩展功能键和修饰键组合描述得更完整。通过 infocmp 可以看到它不仅覆盖普通的 F1-F12,还列出了 Shift、Alt、Ctrl 等组合后的大量变体,比如 kf13 到更高位的功能键序列,以及 Home、End、Insert、Delete、方向键配合修饰键时的不同编码。对于只写普通命令的用户来说,这些东西平时几乎感知不到,但对 [[Vim]]、[[Emacs]]、[[Helix]]、[[tmux]]、[[fzf]] 这类大量依赖快捷键的工具而言,这类定义越完整,键位识别就越稳定。
这也是为什么有时候你会遇到一种很奇怪的情况:本地终端里某个快捷键能用,一进远程主机就失灵,或者进了 tmux 之后组合键被吃掉。很多人会先怀疑是 Shell、tmux 或编辑器配置的问题,但根子常常在于远程机器根本不认识 xterm-ghostty,于是只能按更保守的方式理解输入。终端身份一旦退化,键盘能力也会跟着退化。
Ghostty 的 terminfo 里还包含了很多现代终端日常会用到的交互能力,比如 bracketed paste、焦点事件、鼠标追踪、备用屏幕切换、下划线样式、下划线颜色、同步更新一类的控制序列。对普通用户来说,这些术语不一定熟,但你每天其实都在享受它们带来的好处。举个最直接的例子,bracketed paste 能让 Shell 和编辑器知道“这是一整段粘贴进来的内容”,从而避免因为自动缩进、自动执行或者逐字符解释而引发意外。焦点事件会让某些程序在窗口切换时刷新状态,鼠标追踪会让终端里的选择、点击和滚动行为更自然。
尤其是同步更新能力,这是一类很容易被忽略,但对观感影响很大的细节。终端程序在快速刷新界面时,如果没有同步更新机制,就可能出现闪烁、撕裂或者中间态短暂可见的问题。支持这类能力之后,TUI 程序可以把一整批画面更新更一致地提交给终端。你平时会觉得某个终端“看起来更稳”,背后往往就是这些协议细节在起作用。
Ghostty 官方文档还明确列出了对外部协议和终端扩展的支持,比如 OSC 8 hyperlinks、图形协议、剪贴板相关 OSC 52 以及 shell integration 所依赖的一些语义。这里要注意一件事:并不是所有扩展特性都会完整体现在 terminfo 里,因为 terminfo 主要描述的是一套传统的终端能力接口,很多较新的协议是通过额外 escape sequence 实现的。但 Ghostty 既提供了自己的终端定义,也在文档里明确说明支持哪些扩展,这就让应用开发者既能通过传统方式探测基础能力,也能为高级场景做更有把握的适配。
对终端爱好者来说,这一点很有吸引力。你可以把 Ghostty 理解成一个尽量和传统 Unix 生态兼容,但又不拒绝现代终端创新的实现。它并没有为了新特性去抛弃旧世界,而是努力让两边对齐,这也是 xterm-ghostty 这个命名比单纯叫 ghostty 更有现实意义的原因。
如果你只在本机开终端跑命令,xterm-ghostty 基本不会给你制造麻烦。Ghostty 会自带对应的 terminfo 数据,本地程序通常都能正常识别,绝大多数时候你甚至不需要知道它的存在。真正容易出问题的场景,通常出现在跨机器连接之后,尤其是你通过 SSH 连接到一台比较旧的 Linux、BSD、路由器、容器或者公司内网服务器时。
在这些机器上,如果系统没有安装 xterm-ghostty 的 terminfo 条目,应用拿到 TERM=xterm-ghostty 之后就可能直接报错,比如最常见的 unknown terminal type,或者退化成不完整的显示和键盘行为。Ghostty 官方帮助文档也专门解释了这一点:本地没问题不代表远程环境一定认识这个名字,必要时需要把 Ghostty 提供的 terminfo 安装到远程机器上。
这件事在 2026 年依然很现实,因为终端本身更新得很快,但很多服务器环境极度保守。你本地已经在用一个支持真彩色、扩展键位和现代协议的新终端,远端可能还是一套几年没升级过的 ncurses 数据库。只要 TERM 值传过去而 terminfo 没跟上,兼容性问题就会立刻暴露出来。
如果远程机器提示不认识 xterm-ghostty,我通常优先走“安装 terminfo”这条路,而不是直接把 TERM 改成 xterm-256color。因为后一种做法虽然省事,但本质上是让 Ghostty 主动降级伪装,很多增强能力也就跟着消失了。官方文档给出的建议也类似:尽量在远程环境安装正确的 terminfo 定义,这样本地和远端对终端能力的理解是一致的。
如果你只是临时登录一台权限受限的机器,没法安装 terminfo,那么把 TERM 临时切成 xterm-256color 是一个可以接受的兜底方案。只是你要知道,这不是“正确配置完成了”,而是“为了兼容老系统先退一步”。一旦你发现颜色不对、快捷键异常、鼠标行为不一致或者 tmux 中部分功能失灵,就应该优先回头检查 terminfo,而不是在应用层做越来越多的补丁。
平时我还会保留一个习惯:出问题时直接看 echo $TERM,再配合 infocmp $TERM 或者远程检查 terminfo 是否存在。终端问题看起来都像是编辑器问题、tmux 问题或者 shell 问题,但如果从终端身份开始排查,很多时候能很快找到根源。
如果你想找的是一款现代、快速、又尽量不破坏传统命令行生态的终端,我觉得 Ghostty 很值得试。它的吸引力不只在于“快”或者“好看”,更在于它对底层兼容性足够认真。很多终端喜欢在营销层面强调新功能,但 Ghostty 连 TERM 和 terminfo 这种多数普通用户不会主动关注的细节都处理得很扎实,这反而让我更愿意长期用它。
而 xterm-ghostty 这个名字,看似不起眼,其实正是 Ghostty 技术取向的缩影。它既承认自己站在 xterm 这条漫长的兼容链条上,又明确把自己的现代能力表达出来。对开发者来说,这样的设计比“神秘地能用”更重要,因为只有能力被准确声明,工具链才能稳定协同。
Ghostty 是一个现代终端模拟器,而 xterm-ghostty 是它在 Unix 终端生态里的正式身份证。前者解决的是你每天实际看到和操作的体验问题,后者解决的是编辑器、Shell、TUI 程序和远程服务器应该如何正确理解它的问题。把这两件事放在一起看,Ghostty 的价值就不只是一个“新终端”,而是一种尽量不牺牲传统兼容性的现代化实现。
如果你最近正准备从 [[iTerm2]]、[[Warp]]、[[Kitty]] 或 [[Alacritty 终端]] 切换,我会建议你不仅去试试 Ghostty 的界面和速度,也顺手看一眼 echo $TERM。当你真正开始理解 xterm-ghostty,你会发现终端体验好不好,很多时候不是主题和字体决定的,而是这些平时不怎么显眼的底层协议和能力声明决定的。
2026-05-22 13:00:00
作为一个长期泡在终端里的开发者,我的工作流几乎完全是由命令行和各类快捷键支撑起来的。从早期的命令行自动补全,到后来各种基于大模型的命令行聊天助手,AI 在终端里的角色一直在发生改变。然而,大多数时候我依然觉得有些割裂。当我们需要 AI 帮我们重构一个复杂的跨文件模块、运行构建命令并根据报错自动迭代时,传统的聊天式工具就显得力不从心了。
我最近一直在深度使用 Google 推出的新一代命令行开发工具 [[Antigravity CLI]]。在实际体验了一段时间之后,我深刻地感受到,它不仅仅是又一个命令行 AI 助手,而是代表了一种全新的人机协同开发范式。今天我想和大家聊聊,为什么 Google 决定淘汰掉原有的 [[Gemini CLI]],并全面转向以智能代理为核心的 [[Antigravity CLI]],以及它是如何重塑我们的命令行开发体验的。

在探讨新工具之前,我们有必要先回看一眼已经被替代的 [[Gemini CLI]]。早期的 [[Gemini CLI]] 本质上是一个以聊天和命令补全为核心的终端助手。它的交互模式非常单一:用户输入一个问题或命令意图,大模型返回一段生成的 shell 命令或代码片段,然后用户通过复制粘贴或者手动确认来执行。这种单次对话的模式在面对简单查询时表现尚可,但在处理真实的软件工程任务时,它的局限性就暴露无遗。
当面临需要分析项目整体架构、修改多个相互关联的文件、运行本地测试并根据测试报错进行修复的场景时,传统的单次对话模式会让开发者陷入无休止的“提问、复制、运行、报错、再次提问”的循环中。频繁的上下文切换不仅极大地消耗了开发者的精力,也限制了 AI 在复杂任务中的输出质量。
这就是 Google 推出 [[Antigravity CLI]] 的根本动力。相较于前代产品,新工具实现了从单纯的“自然语言转命令行工具”到“自主规划与工具执行智能体”的跨越。它引入了主动式的规划循环,智能体在接收到任务指令后,不仅会生成解决方案,还会自主使用内置的读写文件、代码检索以及终端运行工具来步步逼近目标。这种代理自治的模式,让 AI 能够真正以一个协作者的身份深入到工程项目的内部。
要实现代理自治,让智能体在开发者的本地机器上自主执行各种操作,首先要解决的就是安全和效率两大痛点。为此,[[Antigravity CLI]] 带来了两项颠覆性的技术设计。
给一个 AI 智能体开放本地系统的命令执行权限是极其危险的。即使是再聪明的模型,也可能因为环境差异或理解幻觉而执行一些灾难性的命令,比如误删关键文件。为了从根本上消除这一风险,该工具在不同的操作系统上都集成了原生的内核级隔离技术。
在 Linux 系统上,它采用 nsjail 技术,结合命名空间和系统调用过滤限制网络与文件访问;在 macOS 上则利用 Seatbelt 机制通过内置沙箱来隔离文件与网络;在 Windows 下则基于 AppContainer 进行原生包隔离。这套沙箱机制默认对智能体执行的所有终端命令进行审查 and 限制,只允许其读写当前工作区的文件。这种设计既解放了智能体的执行力,又牢牢守住了开发者本地系统的安全底线。
在开发大型特性时,我们常常需要同时处理多个子任务,比如一边编写核心业务逻辑,一边为辅助函数补充单元测试,同时还要更新对应的文档。如果使用传统的命令行 AI,我们只能排队等候一个任务结束。
而 [[Antigravity CLI]] 的另一大亮点在于支持后台并行的子智能体管理。通过内置的会话派生机制,我们可以直接在提示词中指示它在后台启动一个新的子智能体分支去处理文档或测试。所有的后台运行状态都可以通过特定的面板集中监控,主会话则保持畅通,这极大地提升了多任务处理的连贯性。
在实际的开发使用中,熟练掌握一些进阶的命令行指令和状态控制,可以让这套智能体系统发挥出更大的威力。
当我们在处理自己非常熟悉的安全本地项目时,可以通过命令实时修改智能体的权限级别。输入特定斜杠指令可以唤出权限设置,系统通常提供三种策略:第一种是命令运行前必须人工逐一审计,第二种是由智能体根据命令的危险程度自主决定是否请示,第三种是允许智能体在当前会话中完全自治。这让我们可以在安全可控与高效率之间自由切换。
长时间的连续开发会在上下文窗口中累积大量的历史对话,这往往会导致智能体产生记忆混乱或废话增多。我的习惯是每当完成一个独立模块的开发或修复后,就使用清空命令重置上下文,让智能体带着干净的历史开始下一个任务。
此外,当面临一些实验性的重构想法时,分支功能也非常实用。它会指示智能体在底层的版本控制系统上拉出一个临时分支去进行破坏性修改和测试。如果最终效果不理想,可以直接丢弃该分支,完全不用担心污染主分支的代码。
从单纯的命令行问答外壳走向深度集成的沙箱智能代理,[[Antigravity CLI]] 的演进正是近年来 AI 辅助开发工具发展的一个缩影。它不仅极大地降低了开发者在日常构建和多文件重构中的重复劳动,更通过沙箱隔离为智能体在宿主机上的自动执行撑起了一把保护伞。
对于像我这样热爱终端环境的开发者来说,这种键盘友好、安全且支持高并发的工作流设计,无疑是将人机协同的生产力推向了一个新的高度。如果你也是命令行工具的拥趸,不妨在自己的终端里体验一下这种全新的代理开发范式,或许它能给你的开发日常带来不一样的启发。
2026-05-22 13:00:00
最近在关注 Google I/O 2026 的动态时,看到了一个让我颇感兴趣的发布——[[Antigravity CLI]],Google 官方宣布用它来取代已经积累了超过 10 万 GitHub Stars 的 [[Gemini CLI]]。这个时机有点微妙:个人版 Gemini CLI 用户必须在 2026 年 6 月 18 日前完成迁移,否则将失去模型访问权限。作为一个长期在终端里工作、也在持续关注 AI 编程工具演进的开发者,我觉得有必要认真研究一下这个新工具到底带来了什么改变。

要理解 Antigravity CLI 的价值,首先得弄清楚 Gemini CLI 为什么走到了被替代这一步。Gemini CLI 诞生于 AI 助手的早期,那时候人们对 AI 编程工具的期待还停留在”能帮我写代码、能帮我解释函数”这个层面,一个对话框加上文件上下文,基本就够用了。
但随着时间推移,开发者们开始尝试更复杂的工作流:跨多个文件的大规模重构、同时推进多个独立任务、在 CI 流水线里嵌入自动化代理……Gemini CLI 底层是 Node.js,在这些场景下暴露出了性能瓶颈;而更根本的问题是,它的架构根本没为多智能体协作设计。代码库越来越臃肿,扩展也越来越难。所以与其打补丁,Google 选择了从头重建。
Antigravity CLI 的背后是一个更大的平台——Antigravity 2.0,这是 Google 重新定义的”智能体优先”开发环境,核心理念是把 AI 智能体从”回答问题的助手”升级为”主动参与开发的协作者”。CLI 只是这个平台的终端入口。
Antigravity CLI 用 Go 重写了整个二进制文件,命令从 gemini 变成了 agy。这个变化带来的不只是启动速度的提升,更重要的是并发模型的根本性改变。Go 的 goroutine 天然适合异步任务调度,这为下面要说的异步子智能体模式奠定了基础。
在实际使用中,agy 的冷启动明显比 Node.js 版本快,在 SSH 远程会话或资源受限的环境里感知尤为明显。对于需要频繁启动 CLI 的自动化脚本来说,这个差异会随着调用次数累积成相当可观的效率提升。
如果说 Antigravity CLI 有一个让我眼前一亮的特性,那一定是异步子智能体模式(Async Subagent Mode)。在 TUI 界面里,你可以用 /agent 命令启动一个后台智能体,它会在不阻塞主会话的情况下并行执行任务:
/agent refactor "Convert all callback-based handlers in @internal/api to use context.Context"
这意味着你可以同时跑多个独立的大型任务——一个在重构 API 层,另一个在整理测试文件,第三个在查找潜在的安全漏洞,你则继续在主会话里做其他工作。对于中大型代码库来说,这种并行化能力能显著压缩整体完成时间。当然,副作用是多个并行智能体会同时消耗 API 配额,在免费层用户那里需要注意别烧得太快。
工具设计得很务实,提供了三种明确定位的操作模式。交互式智能体模式(直接运行 agy)是完整的 TUI 界面,支持 @filename 和 @**/*.ts 这样的 glob 模式向上下文注入文件,适合日常的对话式开发。
无头脚本模式适合自动化集成:
agy -p "List all TODOs in this codebase" --output-format json
加上 --output-format json 后,输出可以直接被下游脚本解析,嵌进 CI/CD 流水线里毫无压力。
异步子智能体模式前面已经说过,是最有差异化的能力,适合那些”扔进去、等结果”的大型任务。
这个设计思路和我在用 [[Claude Code]] 时见到的 CLAUDE.md 非常相似。在项目根目录放一个 AGENTS.md 文件,里面用自然语言描述项目规范,智能体在每次启动时会自动读取并遵循:
Always use TypeScript. Prefer functional patterns over class-based ones.
Run `npm test` after every file modification.
更进一步,你还可以在 .agents/skills/ 目录下创建 Markdown 文件,它们会自动变成 TUI 里的 /slash 命令,相当于把常用的操作流程封装成了可复用的技能。全局技能则放在 ~/.gemini/antigravity-cli/skills/ 下跨项目复用。
Hooks 是 JSON 格式的生命周期拦截器,可以在工具调用前、文件编辑后或会话开始时触发自定义脚本。比如每次写完 Go 文件后自动运行 gofmt,或者在每次会话开始时加载最新的项目文档——这类需求过去要靠额外的包装脚本实现,现在内置支持了。
MCP(Model Context Protocol)服务器通过 mcp_config.json 配置,支持本地 stdio 和远程 HTTP 两种接入方式,和目前主流的 AI 工具生态对接没有障碍。
Antigravity CLI 不再局限于 Gemini 模型家族,内置支持了:
在 TUI 里用 /model 命令可以随时切换,这对需要根据任务类型选择最优模型的开发者来说很友好。
安装很简单,官方提供了一键脚本:
# macOS / Linux
curl -fsSL https://antigravity.google/cli/install.sh | bash
# Windows PowerShell
irm https://antigravity.google/cli/install.ps1 | iex
# 验证安装
agy --version
认证方面,桌面环境会自动打开浏览器完成 Google OAuth;SSH/无头环境会打印授权 URL 和一次性验证码,在本地完成授权后远程会话自动激活。也支持直接设置 API Key:
export ANTIGRAVITY_API_KEY=your_api_key_here
安装完成后,运行 agy inspect 可以查看当前加载的配置、技能、插件、Hooks 和已连接的 MCP 服务器,相当于一个配置状态的快速诊断命令。如果你原来是 Gemini CLI 用户,官方提供了迁移命令:
agy plugin import gemini
它会把旧版扩展转换为新的 Plugin 格式,同时保留原始文件备份,迁移过程相对安全。
从我目前的使用体验来看,这几个工具的定位其实各有侧重,很难说谁全面碾压谁。
Antigravity CLI 的核心优势在于异步并行子智能体和与 Antigravity 2.0 桌面端的无缝同步——你可以把一个终端会话直接推送到桌面 GUI 里继续处理,这种跨界面的上下文保留是独家的。对于需要批量处理大型任务、或者在 SSH 环境里重度工作的开发者,它有不可替代的价值。
[[Claude Code]] 在我这边用得最多的场景是需要深度推理的复杂任务。Opus 4.7 的推理能力、百万 token 上下文窗口、加上精细的用户审批工作流,在处理需要仔细思考的架构决策或微妙的 Bug 时更让人放心。
[[Cursor]] 则继续是日常快节奏开发的首选——IDE 集成太紧密了,补全速度快,对普通的功能开发来说效率最高。
我现在的模式基本是:日常功能开发用 Cursor,复杂推理任务用 Claude Code,需要并行跑多个大型重构任务时用 Antigravity CLI。三个工具并不互斥,反而能形成互补。
Antigravity CLI 的出现标志着 AI 终端工具从”单线程对话”向”多智能体并发编排”的明确转变。Google 用 Go 重写、引入异步子智能体、打通桌面端,这些选择都指向同一个判断:未来的开发工作流是多个智能体协作完成的,不是一个智能体串行执行的。
对于个人开发者来说,如果你现在还在用 Gemini CLI,迁移截止日期是 6 月 18 日,建议尽早完成迁移以免影响日常工作。如果你对多智能体并发这个方向感兴趣,Antigravity CLI 值得认真试用一段时间,特别是那个异步子智能体模式,一旦用顺了,回不去了。
2026-05-20 13:00:00
随着我频道录制的视频越攒越多,加上平时用相机拍摄的原始素材,存储问题开始变得越来越头疼。一个 4K 视频的原始素材少则几个 GB,多则上百 GB,几次拍摄下来一块移动硬盘就见底了。而且随着视频数量的增加,想快速找到某段素材或者回翻旧成片的成本越来越高。这种情况下,我开始认真考虑搭建一套本地存储方案,于是目光落到了[[零刻]] ME Pro 这台小型 NAS 主机上。

说起来这个问题其实积累了很久。之前拍视频的素材都临时存在移动硬盘里,拍完一期就整理一次,但随着时间推移,手头的移动硬盘越来越多,哪块盘存了哪段素材根本理不清楚。有几次要找几个月前某个项目的 B-roll 素材,翻了好几块硬盘才找到,实在太低效了。
另外一个更让我担心的问题是频道视频的存档。YouTube 上传的视频都经过了压缩,画质相比原始文件已经损失了不少,但我一直没有一个稳妥的地方把原始成片统一保管起来。万一哪天账号出现问题,或者视频被误删,手头还要有一份完整备份才放心。这种隐患一直悬在那里,直到我真正动手解决之前都让人不舒服。
这些问题都指向同一个方向:搭建一套可靠的本地存储,最好还能配合软件实现自动整理和备份。传统品牌 NAS 价格偏高,而且存储之外的计算能力有限,很难跑额外的服务。几番权衡之后,我把目光投向了国内的小主机品牌,最终锁定了[[零刻]]的 ME Pro。
[[零刻]](Beelink)是国内比较知名的迷你主机品牌,这几年在 NAS 方向推出了一些有意思的产品。ME Pro 是他们专门面向存储扩展场景设计的小主机,整体尺寸控制得很紧凑,但内部塞入了相当可观的存储接口。
| 项目 | 规格 |
|---|---|
| CPU | Intel N95 |
| 内存 | 12GB LPDDR5 |
| 硬盘位 | 上部 2× 3.5” HDD + 下部 3× M.2 2280 SSD |
| 最大存储 | HDD 2×20TB + SSD 3×4TB,理论约 52TB |
| 网口 | 1× 5GbE + 1× 2.5GbE |
| 视频输出 | HDMI 2.1 |
| USB | 前 1×USB-A 10Gbps / 后 2×USB-A 480Mbps + 1×USB-C 10Gbps |
| 系统 | 支持[[飞牛 fnOS]] |
| 价格 | 基础版 1848 元 / 商业版 1999 元(含 128GB SSD + 5 年会员) |
两个 3.5 寸硬盘位是这台机器最吸引我的地方。对于视频存储来说,机械硬盘的容量密度和价格比固态硬盘友好太多了,塞两块 8TB 或 16TB 的西数红盘,就能获得相当充裕的空间。三个 M.2 插槽可以用来装系统盘和高频访问的缓存,让整体读写性能更均衡。双网口的设计也很实用,5GbE 加上 2.5GbE,在局域网内传输大文件的速度不会成为瓶颈,尤其是未来如果升级到万兆交换机,5GbE 这个口直接接上去就好了。
我选择了商业版,1999 元包含一块 128GB 的 SSD 用作系统盘,以及五年的[[飞牛 fnOS]]会员。硬盘另外单独购买,选了两块 8TB 的西数红盘,在二手市场淘到了不错的价格。
机器到手打开包装,机身是金属一体机身,手感和质感比我想象中要好,不像某些小主机那样有明显的塑料感。涡轮风扇采用定向风道设计,噪音控制得还可以,放在书架上日常基本听不到。硬盘安装很简单,上盖一拧就开,两块 3.5 寸盘插进去接好数据线和电源线,盖上机器就完成了,完全不需要工具。
[[飞牛 fnOS]] 是国内专门为 NAS 和家庭服务器开发的操作系统,界面设计类似 [[Synology]] DSM,但在国内生态适配上做了很多工作。商业版附赠的会员可以解锁一些高级功能,比如更多的用户数和一些进阶的备份选项。
安装过程很顺畅,系统镜像预先写入附赠的 128GB SSD,插进 M.2 口然后开机,按照引导一步步来,大概 15 分钟左右就可以通过浏览器访问后台了。两块 8TB 硬盘在存储管理里组成了 RAID 1,这样任何一块盘损坏数据都不会丢失,代价是可用空间只有 8TB,对于我目前的需求已经绰绰有余。
系统搭好之后,第一件事就是把分散在各个移动硬盘里的素材集中迁移过来。通过局域网的 SMB 共享,ME Pro 直接挂载成网络驱动器,拖拽就能复制,5GbE 的速度让这个过程比我想象中快不少,一块 4TB 移动硬盘大概两个小时左右就能传完。
视频素材的目录结构我按照「年份/月份/项目名」的层级来组织,每个项目文件夹下面分别放原始素材、粗剪片段、成品文件以及缩略图,这样以后要找某个项目的任何素材都一目了然。[[飞牛 fnOS]]自带的文件管理界面可以直接在浏览器里预览视频,不用把文件下载下来就能快速确认内容,这个功能在翻找素材时省了不少时间。
频道视频的存档也按类似思路整理,每条视频单独一个文件夹,成品 MP4、字幕文件、封面图和相关素材放在一起。以后视频需要重新剪辑或者输出成其他格式,素材随时可以调出来,不用再担心丢失或者找不到的问题。
既然 ME Pro 本质上是一台 Intel N95 的小型 Linux 主机,在跑 NAS 之外顺带跑一些服务也是自然而然的选择。我在[[飞牛 fnOS]]里启用了 Docker,额外部署了几个常用服务:
ME Pro 的性能面对这些轻量级服务完全绰绰有余,平时 CPU 占用基本维持在很低的水平,即使同时在转码视频也没有出现明显卡顿。
搭建这套存储方案之后,视频素材管理的效率提升非常明显。以前要找素材靠记忆和运气,现在打开浏览器按目录搜索,几秒钟就能定位到。更重要的是,再也不用担心移动硬盘磕碰或者丢失导致数据消失,RAID 1 的冗余加上机器稳定的散热设计,让这套方案在可靠性上有了基本保障。
1999 元的商业版对于一套可以稳定运行的家用 NAS 方案来说性价比相当合理,尤其是对于有视频创作需求、同时又不想在存储管理上花太多时间折腾的人来说,是一个很值得考虑的选项。如果你也在面临素材越堆越多、找文件费时费力的问题,不妨认真考虑一下这个方向。