扔掉 Electron:一个人 + 一队 AI 代理,撸出双端原生 SSH 客户端 PixShell

摘要:2026 年了,为什么还有人用 Electron 写 SSH 客户端?PixShell 的作者给出了另一种答案:同一个 monorepo,macOS 端用 Swift + AppKit + SwiftTerm + SwiftNIO 手写 SFTP v3 协议,Windows 端用 C# WPF + WebView2 + SSH.NET,双端原生、零 Electron。功能上它几乎照着 FinalShell 抄了一遍作业(同屏目录同步、chmod、打包传输、一键迁移),又加上了 2026 年的新东西:MCP、Agent Bridge、AI 工具一键接管 SSH。更有意思的是——这个项目几乎是一个人带着几个 AI 编码代理写出来的。本文拆解它的功能定位、架构取舍、协议实现细节和那些藏在注释里的踩坑记录。 一个 SSH 客户端的"去 Electron 化"实验 打开 FinalShell、Termius、Tabby 的进程列表,你大概率会看到一堆 --type=renderer 的 Chromium 子进程。一个用来连服务器的工具,自己先吃掉 800MB 内存,这件事大家似乎已经习惯了。 PixShell(github.com/lyu0805/pixshell)的作者显然没习惯。这个项目的前身就是一个 Electron 应用——仓库里的蓝图文档还留着旧账:renderer 约 1.6 万行 + main 约 5700 行 JS。从 v0.1.1 开始,他做了一个相当激进的决定:推倒重来,双端全原生,同一个 monorepo 维护。 平台 UI 终端渲染 SSH/SFTP 栈 🍎 macOS Swift / AppKit SwiftTerm(原生渲染) SwiftNIO + 自研 SFTP v3 🪟 Windows C# / WPF WebView2 + xterm.js SSH.NET 注意这张表里最反直觉的一点:macOS 端没有用 xterm.js。Mac 的终端是 SwiftTerm 原生渲染的,只有 Windows 端因为 WPF 生态里没有像样的终端控件,才走了 WebView2 内嵌 xterm.js 这条路。作者在 README 里专门加了个警告框强调这件事——大概是被问烦了。 ...

July 30, 2026 · FXIO

Ubuntu WireGuard 虚拟局域网配置:从零搭建安全隧道

开场:一个让我抓狂的周五下午 上周五下午五点半,我准备下班,突然想起家里的 NAS 上有一份重要的项目文档,周末要用。 打开手机一看——家里的公网 IP 又变了。上个月刚配好的端口转发,白搞了。 我试过这些方案: frp 内网穿透:配置文件写了 50 行,还要维护服务端,每次改配置都要重启 ZeroTier:有时候连接稳定,有时候突然断线,像开盲盒 Tailscale:好用,但免费版只能 3 个用户,团队协作不够用 直到同事推荐了 WireGuard。 第一次用的时候我惊了——配置文件只有 8 行,连接速度快到我怀疑它是不是真的加密了。更离谱的是,它的代码量只有 OpenVPN 的 1/100,安全性反而更高。 这篇文章就解决一件事:怎么在 Ubuntu 上从零开始配置 WireGuard,搭建一个稳定、安全的虚拟局域网。 先搞清楚:WireGuard 到底是什么? 在动手之前,先花 2 分钟搞清楚 WireGuard 的核心思想,不然你会一直踩坑。 密钥对就是你的身份 WireGuard 的身份验证简单到让人怀疑人生:每个设备一对密钥(公钥+私钥)。 打个比方:你去银行办业务,柜员要验证你的身份。WireGuard 的验证方式就像这样: 公钥 = 你的身份证号(可以告诉任何人) 私钥 = 你的密码(打死不能泄露) 预共享密钥(可选)= 银行给你发的动态验证码(额外安全层) 关键区别:WireGuard 没有"服务器"和"客户端"的概念——所有节点都是平等的 peer。 这就像微信群:每个人都可以给其他人发消息,没有"群主"的概念(虽然技术上你可以指定一个节点作为中继)。 为什么这很重要? 点对点连接:设备之间直接通信,不经过中心节点,延迟更低 拓扑灵活:星型、网状、混合都可以,按需选择 单点故障风险低:一个节点挂了,其他节点不受影响 性能对比:WireGuard vs 传统 VPN 协议 代码量 握手延迟 吞吐量 配置复杂度 安全性 WireGuard ~4,000 行 <100ms 接近线速 ⭐ 极简 ✅ 现代加密 OpenVPN ~100,000 行 1-3s 中等 ⭐⭐⭐ 复杂 ✅ 成熟稳定 IPSec ~500,000 行 2-5s 中等 ⭐⭐⭐⭐ 很复杂 ✅ 企业级 结论:WireGuard 在性能和易用性上碾压传统方案,唯一缺点是生态还在发展中(但已经够用了)。 ...

July 26, 2026 · FXIO

实时监控神器:用 Python 打造 macOS 屏幕区域 OCR 笔记生成器 (screen_ocr.py)

摘要:还在手动暂停视频截字幕?还在边看直播边手打笔记?本文介绍的 screen_ocr.py 脚本,利用 macOS 原生 screencapture 与 Vision API,结合 Python 的 imagehash 库,实现了一个“框选即监控、变化即记录”的实时 OCR 笔记神器。特别适合视频字幕提取、在线会议记录及动态网页监控。 1. 工具简介:你的屏幕“速记员” 在日常开发与学习中,我们经常面临以下场景: 看网课/直播:老师讲得太快,来不及记笔记。 提取视频字幕:视频没有提供字幕文件,只能盯着画面看。 监控动态界面:某个网页或软件界面不断刷新数据,需要手动记录。 screen_ocr.py 专为解决这些痛点而生。它运行后,你只需在屏幕上框选出感兴趣的文字区域,它就会在后台“盯着”这块区域。一旦检测到画面内容变化(如字幕变了、数据刷新了),它会立即调用 macOS 原生的 OCR 引擎识别文字,并按时间顺序写入 Markdown 文件。 2. 核心功能解析 2.1 原生框选:screencapture -i 传统 Python 截图工具(如 pyautogui)通常无法精确框选区域,或者依赖庞大的 GUI 库(如 tkinter、PyQt)。screen_ocr.py 直接调用了 macOS 内置的 screencapture -i 命令。 体验:按下运行键,鼠标变成十字准星,跟平时用 Cmd+Shift+4 一模一样。 优势:零依赖、原生体验、支持 Retina 屏幕高清截图。 2.2 智能去抖:感知哈希 (pHash) 比对 如果每秒钟都调用 OCR,不仅浪费资源,还会产生大量重复文本(比如画面没变,但识别结果可能因为噪点略有不同)。 脚本引入了 imagehash 库,计算图片的 pHash (感知哈希)。 原理:将图片缩放、灰度化、DCT 变换后生成一个 64 位的指纹。 判定:只有当新旧两帧图片的汉明距离(Hamming Distance)大于 5 时,才认为画面发生了实质变化。 效果:完美过滤静止画面,仅在文字更新时触发识别。 2.3 极速识别:macOS Native Vision API 通过 ocrmac 库封装,直接调用 macOS 系统级的 VNRecognizeTextRequest。 ...

July 26, 2026 · FXIO

避坑与飞跃:在 M4 Pro Mac 上对视频关键帧进行 OCR 识别与内存去重实战

摘要:在处理视频关键帧文本/字幕提取时,我们常常面临“多帧重复”与“识别效率低”两大痛点。本文记录了从传统 PaddleOCR 方案切到 macOS Native Vision API 的全过程,并通过 Python 实现了内存级模糊去重与灵活的批量导出。在 M4 Pro 芯片加持下,识别速度直升至每秒 10+ 张! 1. 背景与痛点 在视频内容分析、字幕提取或文档视频化等场景中,我们通常需要将视频按帧导出为图片并识别其中的文本。然而,这一过程有两个核心痛点: 画面重复率极高:相邻的关键帧往往包含完全相同或极其相似的文本,直接输出会导致结果大量冗余。 传统 OCR 引擎偏重:像 PaddleOCR 这类业界顶级的开源方案,在 NVIDIA 显卡或 x86 CPU 上表现优异,但在 Apple Silicon(如 M4 Pro)上运行时,由于需要经过 Python 运行时与跨平台计算图调度,单图识别耗时较长(100~300ms/帧),处理大批量图片时风扇直吹、资源占用较高。 2. 方案对比:PaddleOCR vs macOS Native Vision 为了在 Mac 上获得最佳效率,我们对比了两种技术路线: 维度 PaddleOCR (Python) macOS Native Vision API (ocrmac) 底层硬件支持 主走 CPU 多线程推理 / MPS 支持有限 深度适配 Apple Neural Engine (NPU) + Metal 单图识别速度 ~100 - 300 ms / 帧 ~50 - 100 ms / 帧(每秒 10+ 张) 资源与内存占用 需加载完整神经网络权重与 Python 运行库 直接调系统驻留服务,占用微乎其微 初始化开销 首次运行需下载 100MB+ 模型模型并做连通性检测 零下载、零模型开销,开箱即用 最佳适用场景 复杂工业票据、表格结构化解析、跨平台部署 macOS 平台下的视频关键帧、截图、常规文本快速提取 结论:在 macOS 环境下处理视频字幕与常规截图,原生 Vision API 凭借对 NPU 的极致调度,性能堪称“降维打击”。 ...

July 25, 2026 · FXIO

PostgreSQL 16 → 18 官方升级实践(Ubuntu 24.04)

一次真实的升级记录。 从 Ubuntu 默认 Cluster 管理模式,迁移到 PostgreSQL 官方推荐目录结构。 全程使用 pg_upgrade,保留所有数据库,最终实现: PostgreSQL 18 官方数据目录 systemd 管理 MacBook 远程访问 完整踩坑记录 一、为什么升级? 原环境: 项目 版本 Ubuntu 24.04 PostgreSQL 16.14 数据目录 /srv/data/db/postgres/16/main 希望升级到: PostgreSQL 18.4 PostgreSQL 18 vs 16 关键改进 特性 PostgreSQL 16 PostgreSQL 18 增量备份 ❌ 仅全量 ✅ pg_basebackup 支持增量,备份时间减少 50%+ 逻辑复制 基础支持 ✅ 支持序列和大对象复制 并行查询 有限并行 ✅ 更多场景支持并行(VACUUM、CREATE INDEX) JSON 处理 JSONB 基础 ✅ JSON_TABLE 增强,复杂查询更高效 SSD 优化 无特殊处理 ✅ 强制 I/O 调度优化(见下文) 连接池 需外部工具 ✅ 内置连接池改进 SSD 专项优化(重要) PostgreSQL 18 对 NVMe/SSD 做了底层优化,这是升级的核心理由: ...

July 25, 2026 · FXIO

家用 PostgreSQL 调优实战:从默认配置到性能翻倍

一台 16GB 内存的家用服务器,PostgreSQL 跑起来总觉得慢,改配置又怕改坏——这篇文章用真实的配置文件逐项拆解,告诉你哪些参数值得动,动多少合适。 开场:一次"改坏"的调优经历 上周帮朋友调一台家用服务器上的 PostgreSQL,他信誓旦旦说"我照着网上的教程改了 shared_buffers 到 8GB,结果数据库直接起不来了"。我一看配置——16GB 的机器,shared_buffers 给了 8GB,再加上操作系统缓存、其他服务,内存直接 OOM。 这种故事在家庭服务器圈子里太常见了。PostgreSQL 的 postgresql.conf 有几百个参数,但真正需要动的也就十来个。今天我们用一台真实的家用机器配置,逐项拆解。 硬件家底:你的机器够干多大的活 先看看今天的实验对象: 项目 配置 CPU 12th Gen Intel i5-1240P(12核16线程) 内存 16GB 磁盘 SSD 系统 Ubuntu 24.04 LTS PG 版本 PostgreSQL 16 16GB 内存、SSD、12 代酷睿——这是典型的家用 NAS 或者小型工作站配置。够用,但没有太多余量可以挥霍。 第一梯队:内存分配三兄弟 PostgreSQL 的性能调优,80% 就是调内存分配。搞明白三个参数,基本就入门了。 shared_buffers — 数据库的"工作台" shared_buffers = 2GB 这是 PostgreSQL 自己用来缓存数据页的内存。你可以把它想象成厨师的工作台——台面越大,能同时摊开的食材越多,不用反复跑冰箱拿东西。 经验法则:物理内存的 25%。16GB 的机器给 2GB 是合理的。给太大(比如 8GB),操作系统缓存会被挤掉,反而变慢;给太小,频繁读磁盘,性能拉胯。 验证方法: SELECT pg_size_pretty(pg_database_size(current_database())) AS db_size, pg_size_pretty(pg_total_relation_size('projects')) AS table_size; 如果你的数据库总量小于 shared_buffers,那说明数据全在缓存里,调大没意义。 ...

July 24, 2026 · FXIO

Chromatic · 色彩主题实验室

<!DOCTYPE html> Chromatic · 色彩主题实验室 克莱因蓝 勃艮第红 马尔斯绿 蒂芙尼蓝 申布伦黄 🌙 深色模式 Chromatic · 色彩叙事 ...

July 24, 2026 · FXIO

PostgreSQL 百万级数据实战:查询计划与索引策略全解析

上一篇聊了家用 PostgreSQL 的配置调优,这篇来点硬的——100 万条数据,PostgreSQL 的查询计划选择会发生什么变化?索引策略又该怎么调? 开场:当 30 条变成 100 万条 上篇博客里,我们的 projects 表只有 30 条数据。COUNT 一下 0.97ms,排序一下 0.54ms,快得飞起。但你心里清楚——30 条数据,任何数据库都不会慢。 真正的考验是:数据量上来之后,你的索引还管用吗?优化器还会乖乖走 Index Scan 吗? 今天我们用 100 万条真实数据,把 PostgreSQL 的查询计划拆个底朝天。 实验环境 项目 配置 CPU 12th Gen Intel i5-1240P(12核16线程) 内存 16GB 磁盘 SSD PG 版本 PostgreSQL 16 数据量 1,000,000 行 数据大小 174 MB 索引大小 74 MB 总大小 248 MB 100 万行,248MB——不大不小,刚好是很多真实项目的规模。 插入性能:100 万条要多久 1,000,000 条批量插入: 12.7 秒 平均每秒约 7.8 万条。用的是逐批 10000 条的 INSERT ... VALUES 拼接方式,没有用 COPY。如果用 COPY FROM STDIN,速度还能再快 2-3 倍。 ...

July 24, 2026 · FXIO

深度学习实战——从标注到部署的完整闭环

核心问题:怎么让一个“不会看”的模型,学会识别工业零件表面的划痕? 质检员的 0.5 秒困境 想象你是一个质检员,面前是传送带上飞速流动的钢板。每秒几十张,你要在 0.5 秒内判断:这张有没有划痕?有没有夹杂物?有没有裂纹? 人眼做不到。但神经网络可以。 目标——用深度学习,把这双"眼睛"训练出来。从 CNN 的底层原理开始,经过 YOLO 目标检测实战、LabelMe 数据标注,到用 trace-cn 辅助写训练代码,最终走完**“标注→训练→推理”**的完整闭环。 CNN 基础:卷积神经网络到底在"看"什么? 从生物视觉到数学公式 CNN 的设计灵感来自人类视觉皮层。你看到一张照片,不是逐个像素分析的——你先看到边缘,再看到形状,最后组合出"这是一张脸"。CNN 干的是同样的事: 浅层卷积核提取边缘、纹理(“这里有条线”) 中层把边缘组合成形状(“这是个圆形”) 深层把形状组合成语义(“这是个齿轮”) 核心操作是卷积:一个小的权重矩阵(比如 3×3)在图像上滑动,每个位置做加权求和。一个 3×3 的卷积核只有 9 个参数,却能扫描整个图像——这就是参数共享的威力。全连接网络处理一张 224×224 的图片需要上亿参数,CNN 可能只需要几万。 为什么卷积核能提取特征? 假设你有一个检测水平边缘的卷积核: [[-1, -1, -1], [ 0, 0, 0], [ 1, 1, 1]] 当它滑过图像时,遇到"上暗下亮"的区域,输出值就很大;遇到均匀区域,输出接近零。所以卷积核本质上就是一个模式匹配器——每个核负责匹配一种特定的视觉模式。 池化层:压缩但不丢失 卷积之后通常接一个池化层(最常见的是 2×2 最大池化)。它做的事情很简单:把 2×2 区域里的最大值保留下来,其余扔掉。 为什么这么"浪费"?因为池化做了两件事: 降低计算量:特征图尺寸减半,参数量降到 25% 增加鲁棒性:目标稍微平移一点,最大池化的输出不变 这就像你看一个人,不需要记住他脸上每个像素的位置,只需要知道"眼睛在鼻子上面"这种相对关系。 训练的三驾马车:损失函数、学习率、早停 损失函数衡量模型预测和真实值的差距。不同任务用不同的损失: 分类用交叉熵(“你预测是猫,但其实是狗,惩罚!") 目标检测用 CIoU Loss(同时考虑框的重叠面积、中心距离、宽高比) 分割用 Dice Loss(对小目标特别敏感,比如医学影像里的肿瘤) 学习率控制每次更新参数的步长。太大了来回震荡,太小了原地踏步。实际训练中常用自适应学习率(如 Adam),它会根据梯度自动调整步长——梯度大就小步走,梯度小就大步跑。 ...

July 11, 2026 · FXIO

识别技术——让机器从"看见"到"读懂"

机器视觉采集到图像之后,怎么从中提取有意义的信息?识别技术给出了答案。 双十一仓库的条码失明事件 想象一下这个场景:双十一仓库高峰期,传送带上每秒飞过上百个包裹。你设计的条码识别系统突然大批量"失明"——不是算法不对,而是条码印得太浅、包裹朝向随机、曲面包装拉伸变形。客户在电话那头吼:“你们的系统废了!” 这是工业视觉工程师的日常。识别不是一个算法问题,而是一个工程问题。条形码识别、二维码识别、几何识别、大豆检测——用四个真实场景告诉我们:让机器"读懂"图像,远比"看见"它难得多。 条形码识别:工业世界的基础语言 条形码是工业自动化的"老前辈",从超市收银到物流分拣,无处不在。但你以为识别条码就是"扫一下"?太天真了。 课程用 DobotVisionStudio 搭建了一个食品包装盒识别系统,流程是: 图像采集 → 摄像头拍下包装盒 快速匹配 → 用模板定位条码区域 仿射变换 → 校正角度和位置 字符识别 → 读取包装上的文字信息 条码识别 → 解码条形码 脚本判断 → 对比字符与条码,判断是否匹配 听起来顺理成章,但坑在细节里。课程特别提到:有时候条形码根本识别不出来。为什么? 静区宽度不够:条码两侧的空白区域被压缩,解码器找不到起始位置。 码制没选对:系统默认只识别常见码制,如果遇到特殊编码,需要手动开启"所有码"选项。 定位不准:用快速匹配做模板时,矩形掩膜画得太小或太大都会翻车。 解决方案:调参数 + 试错。把静区宽度逐步调大,把码制选项全开,把匹配框精调到刚好包含条码。这没有银弹,只有耐心。 💡 经验之谈:条码识别的工程难度往往不在算法,而在"最后一公里"——印刷质量、安装角度、光照条件。这些才是现场调试工程师的噩梦。 二维码识别:比条码多一个维度 二维码识别的流程和条形码类似,但多了一个关键能力:抗变形。二维码可以贴在曲面、歪斜、甚至部分遮挡的物体上,依然能解码——靠的是 Reed-Solomon 纠错算法。 课程演示的完整流程: 快速匹配 → 定位二维码区域(创建模板 → 矩形掩膜 → 编辑模板) 仿射变换 → 校正透视变形(继承方式选"按区域") 二维码识别 → 绘制识别区域,解码内容 脚本编写 → 把结果存入变量,做后续逻辑判断 这里有个有趣的工程细节:仿射变换的继承方式选"按区域"而不是"按图像"。为什么?因为二维码可能出现在画面的任何位置,你需要让变换矩阵跟着定位结果走,而不是固定死。 课程还展示了脚本编写——把识别结果存入 strEWMSB 变量,输出 RESULT 作为判断依据。这体现了工业视觉的核心思想:识别只是第一步,判断和决策才是目的。 几何识别:从像素到精确测量 如果说条码/二维码解决的是"读"的问题,几何识别解决的是"量"的问题。 课程用 DobotVisionStudio 的测量工具,演示了如何测量: ...

July 4, 2026 · FXIO