太久没写代码,重拾 Neovim 时发现不仅肌肉记忆有些生疏,而且因为插件生态的“疯狂内卷”,原来的配置报出了一连串的错误。于是和 AI 结结实实地“折腾”了一番,完成了一次 Neovim 架构的现代化升级。
这篇博客是我和 AI 聊天复盘的摘要记录,方便以后如果又断档了,可以快速接上思路。
1. 认知转换:从“极客生存手册”到“现代 IDE” # 在重新梳理快捷键和工作流时,AI 敏锐地指出我之前的旧文档思维还停留在原生 Vim 时代。而我现在的配置,其实已经是一个极其现代化的 IDE,工具其实在主动配合直觉:
搜索与查找:从敲命令退化到了全屏互动(全面拥抱 fzf-lua,支持代码预览和悬浮窗)。 精准跳转:不再依赖盲按 j/k 或者原生的标记,而是依靠视觉反馈的 Leap (s 瞬移) 和 Flash (S 语法树节点选择)。 多文件管理:用 Grapple (<leader>ma 打标, <leader>n 轮切) 替代了需要心智负担的数字 Buffer 管理,只把核心文件钉在书签里。 大纲与排错:用 Trouble 和 Aerial 侧边栏替代了底部的纯文本 Quickfix 列表。 2. 踩坑纪实:Treesitter 0.10+ 断代大迁移 # 这次遇到了 Neovim 社区目前最大的一个“断层更新”巨坑。因为我使用了 Neovim 0.12.0,核心 API 的变化导致了连环爆炸:
每日 LLM 健康检查报告显示 10 台摄像头中有 8 台当天崩溃次数达到数百次。 追查下去,根因是两台婴儿监控摄像头、一个 go2rtc 重连窗口,以及一次 vaapi 级联崩溃——没有一个环节是直接显而易见的。以下是完整的排查与修复过程。
问题是如何发现的 # 我在搭建一个每日家庭健康代理——一个定时脚本,查询所有家庭服务(Frigate、Home Assistant、Paperless、arr 媒体栈),然后将数据交给本地 LLM 分析。核心思路是:不再手动逐个检查仪表盘,而是每天早上收到一份摘要,自动标出异常项。
Frigate 的检查项查询 /api/stats,提取每台摄像头的崩溃次数。某天早上,报告返回了这样的数据:
1 2 3 4 5 6 nanit_adelia: 2228 次崩溃 nanit_leonard: 2228 次崩溃 backyard: 847 次崩溃 front_door: 391 次崩溃 side_a: 203 次崩溃 ... 如果没有健康检查,我根本不会注意到——Frigate 容器本身从未重启,Web UI 上各摄像头仍然显示"在线",也没有任何告警弹出。
根因:崩溃级联 # 顺着日志往前追,每天上午 9 点的事件链如下:
在 WSL 中运行 Claude Code 时,很容易错过它等待输入的时刻——尤其是当你切换到其他窗口的时候。本文记录了我搭建的通知系统:当 Claude 停止响应或请求权限时,会弹出 Windows 气泡通知,点击通知可直接聚焦到对应的 WezTerm 面板。
工作原理 # Claude Code 在 ~/.claude/settings.json 中提供了钩子(hooks)系统,其中两个事件特别有用:
Stop — Claude 完成一次响应、等待用户输入时触发。钩子载荷包含 last_assistant_message、cwd 和 transcript_path。 PermissionRequest — Claude 需要批准才能运行某个工具(Bash 命令、文件写入等)时触发。载荷包含 tool_name 和 tool_input。 两个钩子均以异步方式(async: true)运行 shell 命令,不会阻塞 Claude。
1 2 3 4 5 6 { "hooks": { "PermissionRequest": [{ "hooks": [{ "type": "command", "command": "bash ~/.claude/notify-permission.sh", "async": true }] }], "Stop": [{ "hooks": [{ "type": "command", "command": "bash ~/.claude/notify-stop.sh", "async": true }] }] } } 脚本说明 # ~/.claude/notify-stop.sh # 从钩子的标准输入 JSON 中提取标题、消息正文和 cwd,然后启动 PowerShell 发送通知:
将 Frigate 默认的 SSD MobileNet 检测器替换为 YOLOv9t(tiny),通过 OpenVINO 运行在 Intel N97 的核显上。涵盖模型导出、正确的 Frigate 配置,以及一个会导致 100% 误报的关键坑。
环境 # 服务器: Intel N97(Debian 13),8 路摄像头 Frigate: 0.17,Docker 运行 检测器: OpenVINO GPU(/dev/dri/renderD128) 原模型: SSD MobileNet v2(内置,300×300) 新模型: YOLOv9t ONNX(320×320,8.3 MB) 为什么换 YOLOv9t? # Frigate OpenVINO 镜像自带的 SSD MobileNet v2 速度快、资源占用低,但对画面边缘目标和部分遮挡目标的识别能力较弱。YOLOv9t(tiny)在精度上有明显提升,计算量却相差不大——在 320×320 输入、N97 核显约 18ms 推理速度下,跑 8 路摄像头完全够用。
在 Debian 服务器(Intel N97)上部署 Frigate NVR,替代传统 NVR 的检测功能。 涵盖 Docker Compose、go2rtc 流配置、硬件加速、HA 集成、推送通知及基于区域的告警。 VLAN 间流量经由主路由器(UCG Ultra)转发。
硬件与背景 # 服务器: Intel N97 迷你主机(debian.lan,10.0.10.11),Debian 13 摄像头: 8 台 Reolink PoE 摄像头(摄像头 VLAN,10.0.40.0/24),2 台 Nanit 婴儿监控器(IoT VLAN,10.0.20.0/24) 现有 NVR: 保留运行,负责持续录像;Frigate 专注于检测和事件片段 Home Assistant: 位于 IoT VLAN(10.0.20.10),已运行 MQTT Broker 存储设计 # 录像存储在 NAS 专用共享目录,避免占用本地 NVMe。
如何将本地讲座/课程视频(没有 TMDB/TVDB 收录的)在 Plex 中整理成结构清晰的电视节目,并通过 Plex API 写入自定义描述文字。
示例是 Jonathan Biss 的 Exploring Beethoven’s Piano Sonatas——Curtis 音乐学院与 Coursera 合作的 5 部分课程,存储在 Synology NAS 上。
问题 # Plex 默认的 metadata 爬虫依赖 TMDB 或 TVDB。没有收录的本地讲座视频要么显示成一堆无封面的乱列表,要么被错误匹配到不相关的节目。
解决方案:将课程当作**电视节目(TV Show)**处理,使用 Plex 的 Personal Media Shows 代理,再通过 Plex API 推送自定义 metadata。
第一步:按 Season/Episode 结构整理文件 # Plex 的 TV Show 扫描器要求文件名包含 SxxExx:
本文是一份完整的操作手册,介绍如何通过 paperless-ai 和本地运行的 Ollama 为 paperless-ngx 集成 AI 自动标签和分类功能。整套方案使用本地大语言模型读取文档文本,自动填充元数据字段——包括标题、文档类型、标签、联系人、日期以及自定义字段。
硬件与架构 # NAS(群晖 DS1621+,10.0.10.10):在 5656 端口运行 paperless-ngx 台式 PC:Windows,安装了 WSL2、Docker Desktop,配备 RTX 4090 目标:使用本地 LLM 实现 AI 自动打标/分类,零云端依赖 核心架构决策是拉取模式(pull model):paperless-ai 运行在 WSL2 的 Docker 容器中,轮询 paperless-ngx API 寻找带有 ai-pending 标签的文档,调用 Ollama 处理后将元数据写回。对于不是 24 小时开机的台式机而言,这是最正确的方案——NAS 保存待处理队列,台式机开机后自动消费。
1 2 3 4 5 6 7 paperless-ngx (NAS) ↑ ↓ (REST API) paperless-ai (WSL2 Docker) ↑ ↓ (HTTP) Ollama (Windows 原生) ↑ RTX 4090 (GPU) Ollama 以原生方式运行在 Windows 上(而非 WSL 内),以获得最佳 GPU 访问性能。在 WSL2 的 Docker 容器内,通过特殊主机名 host.docker.internal 访问 Ollama。
将近十年积累的个人文档从 Google Drive 文件夹体系迁移到 Paperless-ngx 的完整记录。 涵盖分类体系设计、从 Google Takeout 批量导入、ML 分类器训练,以及日常收件箱工作流。
为什么要迁移 # 过去多年,我的"文档管理"是一棵手工维护的 Google Drive 文件夹树:
1 2 3 4 5 6 7 8 9 10 10 - 文书材料/ 10 - 证件材料/身份证件/ 30 - 移民文档/ 30 - Tax Filing/ 40 - Finance/ 50 - 车辆注册/ 60 - 住房买房/ 80 - Medical/ 20 - 家装住房信息/ 80 - 旅行计划/ 归档时还算顺手,但检索很痛苦。想找"2022 年的保险表格",要翻六个文件夹,还得猜当时的命名。 Paperless-ngx 提供全文检索、OCR、以及会从你自己的标注中学习的 ML 分类器—— 对于横跨移民手续、税务申报、房产合同、医疗记录的文档库来说,这是本质性的提升。
在 Synology NAS 上配置 AirPrint 的操作手册,让 iOS/macOS 设备可以通过局域网打印到 USB 或网络打印机。使用 Docker CUPS 容器和 Synology 内置的 avahi(mDNS)守护进程实现服务发现。
架构 # 1 2 3 4 5 6 7 8 9 10 11 iPhone │ mDNS 发现 (_ipp._tcp) ▼ Synology avahi-daemon(eth4,端口 5353) │ 从 /etc/avahi/services/ 读取服务文件 │ CUPS Docker 容器(host 网络模式,端口 631) │ 生成 /etc/avahi/services/AirPrint-*.service │ 将打印任务代理到打印机 ▼ 打印机(如 socket://10.0.20.50:9100) 关键设计决策:
将家庭相册从 Synology Photos 迁移到自托管 Immich 实例的个人操作手册。 涵盖批量上传、Google Takeout 导入,以及通过 Synology PostgreSQL 数据库重建相册。
环境说明 # 来源:运行 Synology Photos 的 Synology NAS(多用户) 目标:同一 NAS 上自托管的 Immich 上传工具:immich-go v0.31+ 客户端:Windows 上的 WSL2,SSH 访问 NAS 相册脚本:自定义 Python(migrate_albums.py),使用 Immich REST API 第一阶段:照片上传 # 策略 # 每位用户有两个来源: