<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>mahui.me</title><description>Ma Hui 的个人网站：文章与独立作品。</description><link>https://mahui.me/</link><item><title>把 TLS 证书装进二维码——没有 CA 会为局域网里的一台 Mac 作保</title><link>https://mahui.me/blog/lynsi-certificate-in-qr/</link><guid isPermaLink="true">https://mahui.me/blog/lynsi-certificate-in-qr/</guid><description>灵犀的手机端和 Mac 端走 TLS 1.3,但证书链在这个场景里根本不存在。解法是让配对二维码直接携带证书本体,手机从此只信这一张。这篇讲三个决定:选 P-256 而不是 RSA、证书在进程内生成而不是调 openssl(以及不这么做时沙盒里发生了什么)、还有二维码为什么可以随便拍照。</description><pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate></item><item><title>TLS 之上还差一道门——以及两个把我骗了的验证脚本</title><link>https://mahui.me/blog/lynsi-handshake-gate/</link><guid isPermaLink="true">https://mahui.me/blog/lynsi-handshake-gate/</guid><description>TLS 建立的是私密信道,但它不回答「对面是谁」。灵犀的 Mac 端曾经在 TCP 一通就处理所有帧——不配对也能写它的剪贴板。这篇讲握手门的设计:未认证的连接只许发 hello、五秒不发就断、一个字节都不回;拒绝的爆炸半径怎么控制;挂断为什么需要一条专门的消息;以及验证脚本自己先后踩的两个坑——每个都让测试结果和真相完全相反。</description><pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate></item><item><title>256 个字,没有申诉入口——鸿蒙受限权限被驳回之后</title><link>https://mahui.me/blog/lynsi-harmony-acl-rejection/</link><guid isPermaLink="true">https://mahui.me/blog/lynsi-harmony-acl-rejection/</guid><description>灵犀申请了两个鸿蒙受限权限,READ_PASTEBOARD 过了,READ_IMAGEVIDEO 被驳回:「场景不符合权限使用要求」。复盘下来驳回是合理的——功能明明是备份,所有文案却写着「浏览」。这篇讲重新申请的全过程:按审核的判断顺序花掉 256 个字、正面回应 PhotoViewPicker 的替代建议、以及最重要的一条——申请材料里的每句承诺,代码里都得真的兑现。</description><pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate></item><item><title>对手是免费的官方应用——灵犀的付费墙怎么划</title><link>https://mahui.me/blog/lynsi-pricing-against-free/</link><guid isPermaLink="true">https://mahui.me/blog/lynsi-pricing-against-free/</guid><description>灵犀的直接竞品是华为官方的星河互联:免费,而且是官方。这篇讲付费边界怎么定:官方免费的能力一律免费,墙只立在官方没有的差异化上;投屏和视频流播为什么共用一个每天 10 分钟的池、额度为什么按天而不按会话;相册保存怎么从免费层改判成 Pro;以及三个被否决的方案——每个都差点做进去。</description><pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Mac 上点不动的分段控件——Catalyst 不会把点击投递进 List 的 section header</title><link>https://mahui.me/blog/flick-catalyst-section-header-hit-testing/</link><guid isPermaLink="true">https://mahui.me/blog/flick-catalyst-section-header-hit-testing/</guid><description>Flick 的范围选择器有个排序控件，在 iPhone 上一直好好的，装到 Mac 上却完全点不动。它渲染正常、编译无警告、代码两端共用一份，唯一的差别是点击到不了它。根因是它被放在了 List 的 Section header 里。</description><pubDate>Thu, 06 Aug 2026 00:00:00 GMT</pubDate></item><item><title>不能读源码的协议实现——把 mosh 从抓包里重新推导一遍</title><link>https://mahui.me/blog/shellby-mosh-clean-room/</link><guid isPermaLink="true">https://mahui.me/blog/shellby-mosh-clean-room/</guid><description>官方 mosh 是 GPLv3,Shellby 是闭源商业 App,不能读也不能抄。于是依据论文加自行抓包重新推导 SSP 协议:字段号全部靠实测,猜错一个就能把 mosh-server 直接搞崩;而且同一套协议要在 Swift 和 Dart 上逐字节对齐。</description><pubDate>Thu, 06 Aug 2026 00:00:00 GMT</pubDate></item><item><title>mosh 卡得要死,我差点怪罪自己刚做的架构取舍</title><link>https://mahui.me/blog/shellby-mosh-rtt-misdiagnosis/</link><guid isPermaLink="true">https://mahui.me/blog/shellby-mosh-rtt-misdiagnosis/</guid><description>Shellby 自研的 mosh 兼容传输上线后卡到不可用。我刚做过「停等状态同步」这个明确会牺牲吞吐的取舍,第一嫌疑人自然是它。但有一个指标不对——它把架构洗清了,真凶是一个回填错的时间戳,让服务端主动节流到 100ms 一个包。</description><pubDate>Thu, 06 Aug 2026 00:00:00 GMT</pubDate></item><item><title>你到底打了多久——把练习时长做成确定、防篡改、可复现</title><link>https://mahui.me/blog/keydo-deterministic-timing/</link><guid isPermaLink="true">https://mahui.me/blog/keydo-deterministic-timing/</guid><description>键道 KeyDo 复盘：练习时长原来用 Date.now() 的 end - start，挂机、切 tab、墙钟回拨全算进去了。改成累加「相邻击键之间被接受的间隔」，超 60 秒的间隔整段丢弃；再叠上输入法守卫、单调时钟、幂等结算，让这个数字既准又不被刷。</description><pubDate>Fri, 17 Jul 2026 00:00:00 GMT</pubDate></item><item><title>离线也能玩，联网不丢分——幂等 outbox 加一条 Worker 边界流水线</title><link>https://mahui.me/blog/keydo-offline-sync/</link><guid isPermaLink="true">https://mahui.me/blog/keydo-offline-sync/</guid><description>键道 KeyDo 复盘：成绩上报原来是 fire-and-forget，离线或失败就丢；公开 API 没有体积上限、来源校验和限流。这次做了 PWA 离线、双端幂等的成绩同步 outbox、以及一条「顺序即防护层次」的 Worker 请求边界流水线。</description><pubDate>Fri, 17 Jul 2026 00:00:00 GMT</pubDate></item><item><title>只同步权威源，派生态各端自己重建——AI 对话的跨栈同步</title><link>https://mahui.me/blog/shellby-derived-sync-transcript/</link><guid isPermaLink="true">https://mahui.me/blog/shellby-derived-sync-transcript/</guid><description>Shellby 复盘：把 AI 对话历史在 Apple 与 Flutter 双栈间同步。一个对话既有原始消息、又有步骤转录，但只有原始消息该同步——步骤是派生态，在每端由消息重建。外加一个「鸿蒙收不到」的版本字段坑。</description><pubDate>Fri, 17 Jul 2026 00:00:00 GMT</pubDate></item><item><title>命令片段库：把「点按即执行」改成「先查看再执行」</title><link>https://mahui.me/blog/shellby-snippet-library/</link><guid isPermaLink="true">https://mahui.me/blog/shellby-snippet-library/</guid><description>Shellby 复盘：终端顶部做了个命令工具条，点一下就发。上线后判定这个交互不安全，整体重构成「先查看再执行」的片段库。以及跨六端做这个功能踩的坑——移动端终端没有菜单注入口子、macOS 自绘右键菜单被系统置灰、全屏程序里不能乱注入。</description><pubDate>Fri, 17 Jul 2026 00:00:00 GMT</pubDate></item><item><title>没有服务端合并、没有账号，存档还能多设备收敛——G-Counter 加 CAS</title><link>https://mahui.me/blog/keydo-cas-cloud-save/</link><guid isPermaLink="true">https://mahui.me/blog/keydo-cas-cloud-save/</guid><description>键道 KeyDo 复盘：匿名、无登录、多设备各自离线练习，怎么保证存档最终一致又不丢更新。答案是把责任切开——Worker 只做带版本号的原子存取（CAS），前端做一个满足交换律、结合律、幂等律的确定性合并。</description><pubDate>Thu, 16 Jul 2026 00:00:00 GMT</pubDate></item><item><title>排行榜显示你的城市，却不知道你在哪——匿名地区标签</title><link>https://mahui.me/blog/keydo-city-rankings/</link><guid isPermaLink="true">https://mahui.me/blog/keydo-city-rankings/</guid><description>键道 KeyDo 复盘：给匿名排行榜加城市级地区标签，前提是不收集精确位置、不接第三方 IP 定位、业务库里绝不落 IP。只读 Cloudflare 边缘注入的国家/省/市字段、逐级降级、库层用 CHECK 约束把关，外加只让完整一局进榜、稳定名次靠三段 COUNT。</description><pubDate>Thu, 16 Jul 2026 00:00:00 GMT</pubDate></item><item><title>解析不出命令名，就别放行——命令解析是 AI Agent 的安全边界</title><link>https://mahui.me/blog/shellby-command-parsing-security/</link><guid isPermaLink="true">https://mahui.me/blog/shellby-command-parsing-security/</guid><description>Shellby 复盘：AI Agent 执行命令前按只读/变更/破坏分级，判定全靠「从命令行里解析出真实命令名」。而 sudo 选项、su 提权、环境赋值前缀、引号里的竖线，每一个都能骗过朴素解析。这篇讲为什么解析器本身就是安全边界，以及解析不出来时的正确默认是「拒绝」。</description><pubDate>Thu, 16 Jul 2026 00:00:00 GMT</pubDate></item><item><title>一套同步协议，两个技术栈——以及一个被 zlib 逼改的契约</title><link>https://mahui.me/blog/shellby-cross-stack-sync/</link><guid isPermaLink="true">https://mahui.me/blog/shellby-cross-stack-sync/</guid><description>Shellby 复盘：六端 SSH 客户端要跨生态同步（Apple 是 SwiftData、Flutter 是 drift），走用户自带的第三方存储、无服务器、端到端加密。难点是让「同一份数据两端同步后一致」，而实现期一个 zlib 细节把「密文逐字节相等」这个契约直接推翻了。</description><pubDate>Thu, 16 Jul 2026 00:00:00 GMT</pubDate></item><item><title>一段可以随便拍照的配对码——因为口令不在里面</title><link>https://mahui.me/blog/shellby-qr-pairing/</link><guid isPermaLink="true">https://mahui.me/blog/shellby-qr-pairing/</guid><description>Shellby 复盘：新设备接入跨栈同步要手输一堆敏感配置。做成一段口令加密的配对码、渲成二维码扫一下就好。关键设计是口令不进码、只当解密钥，于是配对码被拍照截图也无用；外加鸿蒙二维码白屏与桌面选图解码两个跨端坑。</description><pubDate>Thu, 16 Jul 2026 00:00:00 GMT</pubDate></item><item><title>让阿里云 OSS 真的当 S3 用——「S3 兼容」不是契约</title><link>https://mahui.me/blog/shellby-s3-compatible-oss/</link><guid isPermaLink="true">https://mahui.me/blog/shellby-s3-compatible-oss/</guid><description>Shellby 复盘：同步支持用户自带 S3 存储，一个用户填了阿里云 OSS 就同步失败。顺着 403 空响应体一路挖到寻址、条件写、连接被关四个坑，每一个都是「S3 兼容 ≠ S3」的一个侧面。</description><pubDate>Thu, 16 Jul 2026 00:00:00 GMT</pubDate></item><item><title>删了又活过来——一个会自己写回数据库的对象</title><link>https://mahui.me/blog/shellby-delete-resurrection/</link><guid isPermaLink="true">https://mahui.me/blog/shellby-delete-resurrection/</guid><description>Shellby 复盘：给 AI 会话加逐条删除，删完却又冒出来。凶手是会话自带的自动持久化回调——abort 触发最后一次状态变化、把已删记录 upsert 回去，还经 CloudKit 复活到所有设备。修复是一行，但位置是关键。</description><pubDate>Mon, 13 Jul 2026 00:00:00 GMT</pubDate></item><item><title>「尝试重新启动」不是「撤销」——不经 shell 的重启与崩溃恢复账本</title><link>https://mahui.me/blog/pier-safe-restart-recovery/</link><guid isPermaLink="true">https://mahui.me/blog/pier-safe-restart-recovery/</guid><description>Pier 3.0 复盘：停掉一个 dev server 后想再启动回来，看着简单，坑很深。为什么按钮叫「尝试重新启动」而不是「撤销」、为什么重启绝不能过 shell、以及一个能容忍自身崩溃和账本损坏的恢复设计。</description><pubDate>Sun, 12 Jul 2026 00:00:00 GMT</pubDate></item><item><title>宁可漏报，不可误杀——一个 fail-closed 的清理分级引擎</title><link>https://mahui.me/blog/pier-fail-closed-classification/</link><guid isPermaLink="true">https://mahui.me/blog/pier-fail-closed-classification/</guid><description>Pier 3.0 复盘：一键清理只包含「绿色」项，而一个进程要进绿色，得同时越过一整排硬护栏。讲讲确定性规则怎么设计、为什么绿色的默认是「不合格」、以及一份把这些规则钉成发布门槛的「安全不变量」清单。</description><pubDate>Sat, 11 Jul 2026 00:00:00 GMT</pubDate></item><item><title>停一个随时在变的进程——清理动作里的 TOCTOU 与连续检查点</title><link>https://mahui.me/blog/pier-safe-stop-toctou/</link><guid isPermaLink="true">https://mahui.me/blog/pier-safe-stop-toctou/</guid><description>Pier 3.0 复盘：绿色判定用的是诊断那一刻的快照，可从用户点下清理到信号真正发出，进程可能长出新连接、新子进程。讲讲怎么用「连续检查点 + 2 秒证据时限 + 发信号前复验内核启动时间」把这个检查与执行之间的窗口收到最小。</description><pubDate>Sat, 11 Jul 2026 00:00:00 GMT</pubDate></item><item><title>从资源监视器到「收尾助手」——当安全成为产品本体</title><link>https://mahui.me/blog/pier-cleanup-safety-first/</link><guid isPermaLink="true">https://mahui.me/blog/pier-cleanup-safety-first/</guid><description>Pier 3.0 复盘：把定位从「开发者资源监视器」转向「AI 编程后的本地收尾助手」。基本单位从端口/进程变成项目/会话，核心问题变成「我的 AI 工具留下了什么、哪些能安全停掉」。以及为什么面向非专业开发者的清理工具，安全不是卖点、是产品本体。</description><pubDate>Fri, 10 Jul 2026 00:00:00 GMT</pubDate></item><item><title>双语站的 &lt;head&gt; 里到底该放什么——canonical、hreflang 与结构化数据</title><link>https://mahui.me/blog/astro-bilingual-seo-head/</link><guid isPermaLink="true">https://mahui.me/blog/astro-bilingual-seo-head/</guid><description>给一个中英双语 Astro 站补齐 SEO head。重点是 hreflang 组的正确性（自引用 + 互指 + x-default，只指对方语言是错的）、没有译文的文章不该发 hreflang，以及文章页和首页各自该发哪种 JSON-LD。</description><pubDate>Thu, 09 Jul 2026 00:00:00 GMT</pubDate></item><item><title>不接生图服务，用 headless Chrome 给站点做 OG 分享图</title><link>https://mahui.me/blog/og-image-headless-chrome/</link><guid isPermaLink="true">https://mahui.me/blog/og-image-headless-chrome/</guid><description>需要一张 1200×630 的社交分享图。不开设计软件、不接第三方 OG 服务、不上动态生成——用站点自己的 CSS 变量写一个 HTML，headless Chrome 截一张图。以及为什么先做静态默认图、把按篇动态生成留到真需要时。</description><pubDate>Thu, 09 Jul 2026 00:00:00 GMT</pubDate></item><item><title>一个密钥五台 Mac，名额怎么才不会悄悄漏光</title><link>https://mahui.me/blog/pier-device-seats/</link><guid isPermaLink="true">https://mahui.me/blog/pier-device-seats/</guid><description>Pier 复盘：买断许可证限 5 台设备激活，但「注销」如果只清本地，服务端的名额永远占着，用户换几次机就撞墙来找你人工释放。修法是注销必须服务端释放名额，且失败时宁可不放、也绝不悄悄泄漏。</description><pubDate>Thu, 09 Jul 2026 00:00:00 GMT</pubDate></item><item><title>一个人的站群怎么做 SEO——同源 sitemap、域名资源与一条 308 陷阱</title><link>https://mahui.me/blog/subdomain-seo-architecture/</link><guid isPermaLink="true">https://mahui.me/blog/subdomain-seo-architecture/</guid><description>主站加六个产品子域名，sitemap 只覆盖主站。为什么一份 sitemap 管不了整个站群、Search Console 该建域名资源还是逐站验证、以及 Cloudflare Pages 上一条把每个条目都变成重定向的 .html 陷阱。</description><pubDate>Thu, 09 Jul 2026 00:00:00 GMT</pubDate></item><item><title>公证通过，双击即死——一个 entitlement 的线上事故</title><link>https://mahui.me/blog/pier-notarization-blind-spot/</link><guid isPermaLink="true">https://mahui.me/blog/pier-notarization-blind-spot/</guid><description>Pier 2.0.0 复盘：为了消掉一个 keychain 授权弹窗，带上了 restricted entitlement；公证照常通过，用户双击直接被 AMFI 杀掉。发布当晚回退出 2.0.1。</description><pubDate>Wed, 08 Jul 2026 00:00:00 GMT</pubDate></item><item><title>Pier 2.0 开始收费——价格由你定</title><link>https://mahui.me/blog/pier-pay-what-you-want/</link><guid isPermaLink="true">https://mahui.me/blog/pier-pay-what-you-want/</guid><description>免费推广期结束，Pier 改为 pay what you want：$0.99 起、建议 $6.99，一次性买断。讲讲一个单人开发者怎么划付费线、怎么定价、怎么给老用户留退路。</description><pubDate>Wed, 08 Jul 2026 00:00:00 GMT</pubDate></item><item><title>终端里的两处乱码——vim 粘贴卡死与远程中文变问号</title><link>https://mahui.me/blog/shellby-terminal-encoding/</link><guid isPermaLink="true">https://mahui.me/blog/shellby-terminal-encoding/</guid><description>Shellby 复盘：一个是粘贴到 vim 后按键全部错乱，根因是并发写 SSH 通道乱了顺序；一个是远程 macOS 上中文全成转义乱码，根因是 sshd 会话默认没有 LANG。两个 bug 都在「字节到达远端的路上」出问题，但一个是顺序、一个是环境。</description><pubDate>Wed, 08 Jul 2026 00:00:00 GMT</pubDate></item><item><title>键道 KeyDo——一个 CRT 街机风的打字道场</title><link>https://mahui.me/blog/keydo-launch/</link><guid isPermaLink="true">https://mahui.me/blog/keydo-launch/</guid><description>复古街机风的网页打字练习游戏：四种修炼模式、剑道段位、全球排行榜，纯前端离线可玩。讲讲它怎么做、以及一堆技术选择背后的取舍。</description><pubDate>Tue, 07 Jul 2026 00:00:00 GMT</pubDate></item><item><title>三份订阅，一个端点——开源了 LLM-Bridge</title><link>https://mahui.me/blog/llm-bridge-launch/</link><guid isPermaLink="true">https://mahui.me/blog/llm-bridge-launch/</guid><description>把 Claude Code、Codex、Antigravity 三个订阅统一到一个 OpenAI 兼容 API 后面。讲讲它做什么，以及刻意不做什么。</description><pubDate>Mon, 06 Jul 2026 00:00:00 GMT</pubDate></item><item><title>让 AI 开个会——开源了 Open Council</title><link>https://mahui.me/blog/open-council-launch/</link><guid isPermaLink="true">https://mahui.me/blog/open-council-launch/</guid><description>一个本地多模型辩论编排系统：让几个 AI 模型围绕同一问题辩论、互评、算出共识度，产出比单模型更可靠的答案。讲讲它怎么工作，以及适合用在哪。</description><pubDate>Mon, 06 Jul 2026 00:00:00 GMT</pubDate></item><item><title>客户端算的成绩，凭什么信——排行榜的服务端底线</title><link>https://mahui.me/blog/keydo-leaderboard-anti-cheat/</link><guid isPermaLink="true">https://mahui.me/blog/keydo-leaderboard-anti-cheat/</guid><description>键道 KeyDo 复盘：WPM 是浏览器里算出来的，全球排行榜怎么防止有人随手 POST 一个 9999。上限校验、每人每模式一条、SQL 里判最佳。</description><pubDate>Sun, 05 Jul 2026 00:00:00 GMT</pubDate></item><item><title>搜到了，却跳不过去：一条消息的两个身份</title><link>https://mahui.me/blog/vibetrail-search-anchor/</link><guid isPermaLink="true">https://mahui.me/blog/vibetrail-search-anchor/</guid><description>搜索按物理行定位，时间线按逻辑消息渲染——折叠操作把旧身份丢了，跳转就静默失灵。</description><pubDate>Sun, 05 Jul 2026 00:00:00 GMT</pubDate></item><item><title>在别人的终端里开一扇门：VibeTrail resume 的四次降级</title><link>https://mahui.me/blog/vibetrail-resume-degrade/</link><guid isPermaLink="true">https://mahui.me/blog/vibetrail-resume-degrade/</guid><description>AppleScript 崩溃、TCC 静默拒绝、死点击探案——macOS 自动化的权限暗礁，和最后那条一直摆在眼前的路。</description><pubDate>Sat, 04 Jul 2026 00:00:00 GMT</pubDate></item><item><title>建站记：这个网站是怎么搭的</title><link>https://mahui.me/blog/hello-world/</link><guid isPermaLink="true">https://mahui.me/blog/hello-world/</guid><description>技术选型、目录结构和部署方式，一篇讲完。</description><pubDate>Fri, 03 Jul 2026 00:00:00 GMT</pubDate></item><item><title>在 React 里跑一个命令式游戏循环——单词雨</title><link>https://mahui.me/blog/keydo-falling-words-loop/</link><guid isPermaLink="true">https://mahui.me/blog/keydo-falling-words-loop/</guid><description>键道 KeyDo 复盘：单词从天而降，requestAnimationFrame 每帧推进物理。React 每帧 setState 会卡死，状态得放 ref，渲染只靠一个空 tick 触发。</description><pubDate>Fri, 03 Jul 2026 00:00:00 GMT</pubDate></item><item><title>让 AI 在你的服务器上敲命令——Shellby 的三级审批门与五道护栏</title><link>https://mahui.me/blog/shellby-ai-agent-safety/</link><guid isPermaLink="true">https://mahui.me/blog/shellby-ai-agent-safety/</guid><description>Shellby 复盘：一个能自主执行命令的 AI Agent，最难的部分不是让它干活，是不让它闯祸。</description><pubDate>Fri, 03 Jul 2026 00:00:00 GMT</pubDate></item><item><title>让 AI Agent 的上下文不随步数膨胀——缓存断点、历史折叠与流式首字</title><link>https://mahui.me/blog/shellby-agent-context/</link><guid isPermaLink="true">https://mahui.me/blog/shellby-agent-context/</guid><description>Shellby 复盘：一个自主执行命令的 Agent，每多跑一步就把累积历史重发一遍，token 和首字延迟随步数线性爬升。三招压下去——Anthropic prompt caching 断点、单调固化的历史折叠、SSE 流式，且三者正交可叠加。</description><pubDate>Thu, 02 Jul 2026 00:00:00 GMT</pubDate></item><item><title>凭证不能上云——Shellby 的双轨同步</title><link>https://mahui.me/blog/shellby-dual-track-sync/</link><guid isPermaLink="true">https://mahui.me/blog/shellby-dual-track-sync/</guid><description>Shellby 复盘：让 SSH 客户端多端同步，最硬的约束是「密码和私钥绝不能明文进云端」。</description><pubDate>Thu, 02 Jul 2026 00:00:00 GMT</pubDate></item><item><title>把 ripgrep 链接进应用：VibeTrail 的无索引全文搜索</title><link>https://mahui.me/blog/vibetrail-ripgrep/</link><guid isPermaLink="true">https://mahui.me/blog/vibetrail-ripgrep/</guid><description>不建数据库、不做索引，直接把 grep 引擎编进 Rust 应用。</description><pubDate>Thu, 02 Jul 2026 00:00:00 GMT</pubDate></item><item><title>一个音频文件都不用的打字音效</title><link>https://mahui.me/blog/keydo-web-audio-sfx/</link><guid isPermaLink="true">https://mahui.me/blog/keydo-web-audio-sfx/</guid><description>键道 KeyDo 复盘：命中、失误、消灭、升级、游戏结束——全套 8-bit 音效，零音频资源，全靠 Web Audio 的振荡器实时合成。</description><pubDate>Wed, 01 Jul 2026 00:00:00 GMT</pubDate></item><item><title>不装 agent，一条命令采全服务器指标——Shellby 的监控</title><link>https://mahui.me/blog/shellby-server-monitoring/</link><guid isPermaLink="true">https://mahui.me/blog/shellby-server-monitoring/</guid><description>Shellby 复盘：没有采集端，纯 SSH 采 CPU/内存/磁盘/负载，把五类指标打包成一条命令。</description><pubDate>Wed, 01 Jul 2026 00:00:00 GMT</pubDate></item><item><title>隧道只有一种——Shellby 的端口转发</title><link>https://mahui.me/blog/shellby-port-forwarding/</link><guid isPermaLink="true">https://mahui.me/blog/shellby-port-forwarding/</guid><description>Shellby 复盘：本地转发、远程转发、动态 SOCKS、多跳跳板，四种形态，一个统一的隧道模型，外加一个 NIO 的坑。</description><pubDate>Tue, 30 Jun 2026 00:00:00 GMT</pubDate></item><item><title>ref 存真相，快照交给 React——一个逐字符打字引擎</title><link>https://mahui.me/blog/keydo-typing-engine/</link><guid isPermaLink="true">https://mahui.me/blog/keydo-typing-engine/</guid><description>键道 KeyDo 复盘：打字是高频键盘事件，直接塞进 React 状态会被 StrictMode 和异步 setState 坑到。真实状态放 ref，改完提交一份快照渲染。</description><pubDate>Sun, 28 Jun 2026 00:00:00 GMT</pubDate></item><item><title>一条看起来还活着的死连接——Shellby 的心跳令牌</title><link>https://mahui.me/blog/shellby-liveness-token/</link><guid isPermaLink="true">https://mahui.me/blog/shellby-liveness-token/</guid><description>Shellby 复盘：SSH 连接静默挂起时，「命令能返回」根本不代表连接还活着。</description><pubDate>Sun, 28 Jun 2026 00:00:00 GMT</pubDate></item><item><title>400 万个文件教我的事：Diskly 扫描器性能复盘</title><link>https://mahui.me/blog/diskly-four-million-files/</link><guid isPermaLink="true">https://mahui.me/blog/diskly-four-million-files/</guid><description>75 秒到 2.2 秒、6.46TB 的虚报、一行改动省 150MB、多开线程反而更慢——所有直觉都要过数字这一关。</description><pubDate>Sat, 27 Jun 2026 00:00:00 GMT</pubDate></item><item><title>一套 SwiftUI 代码，三端不同的手——Shellby 的多会话适配</title><link>https://mahui.me/blog/shellby-cross-platform/</link><guid isPermaLink="true">https://mahui.me/blog/shellby-cross-platform/</guid><description>Shellby 复盘：命令广播、分屏、⌘W——一套代码要同时伺候 Mac 的键盘、iPad 的多任务、iPhone 的单手。</description><pubDate>Fri, 26 Jun 2026 00:00:00 GMT</pubDate></item><item><title>让 macOS 不再每次连接都弹钥匙串授权——一次 Keychain 选型</title><link>https://mahui.me/blog/shellby-keychain-popups/</link><guid isPermaLink="true">https://mahui.me/blog/shellby-keychain-popups/</guid><description>Shellby 复盘：同一段存密码的代码，在 macOS 上每次连接都弹授权窗，换一种钥匙串就好了。</description><pubDate>Wed, 24 Jun 2026 00:00:00 GMT</pubDate></item><item><title>一个 reasoning_effort，翻译给三种后端</title><link>https://mahui.me/blog/llm-bridge-reasoning-effort/</link><guid isPermaLink="true">https://mahui.me/blog/llm-bridge-reasoning-effort/</guid><description>LLM-Bridge 复盘：OpenAI 给了一个统一的 reasoning_effort 字段，可三家后端接受深度的方式完全不同——SDK 选项、config 覆盖、模型名里编码。</description><pubDate>Tue, 23 Jun 2026 00:00:00 GMT</pubDate></item><item><title>不走 App Store：macOS 应用的签名、公证与自更新</title><link>https://mahui.me/blog/mac-app-distribution/</link><guid isPermaLink="true">https://mahui.me/blog/mac-app-distribution/</guid><description>Pier 和 Diskly 的独立分发实践：Developer ID、notarytool、Sparkle、Homebrew tap。</description><pubDate>Sat, 20 Jun 2026 00:00:00 GMT</pubDate></item><item><title>砍掉 OAuth，只留两种协议——一次接入收敛的取舍</title><link>https://mahui.me/blog/open-council-api-convergence/</link><guid isPermaLink="true">https://mahui.me/blog/open-council-api-convergence/</guid><description>Open Council 复盘：从 CLI / OAuth / 订阅 / 中间层的一张宽接入矩阵，收敛到只走 anthropic + openai 两种标准 API。为什么做减法，减法怎么减得诚实。</description><pubDate>Thu, 18 Jun 2026 00:00:00 GMT</pubDate></item><item><title>一个功能的生与死：Pier 每进程网速的四次重写</title><link>https://mahui.me/blog/pier-network-monitor-postmortem/</link><guid isPermaLink="true">https://mahui.me/blog/pier-network-monitor-postmortem/</guid><description>Pier 复盘：块缓冲、CRLF 字素、spin-loop 的 nettop、必崩的私有框架——以及怎么算清一笔「删功能」的账。</description><pubDate>Sun, 14 Jun 2026 00:00:00 GMT</pubDate></item><item><title>扫描时分组卡片一直闪——三层非确定性和一个 epoch 分箱</title><link>https://mahui.me/blog/flick-group-stability/</link><guid isPermaLink="true">https://mahui.me/blog/flick-group-stability/</guid><description>Flick 复盘：分析边跑边出结果，分组页的卡片却在循环里出现、消失、再出现。凶手是叠了三层的非确定性，加上一个会随时间线漂移的窗口锚点。修法是让「同一批照片」在每次重建里都算出逐位相同的分组。</description><pubDate>Fri, 12 Jun 2026 00:00:00 GMT</pubDate></item><item><title>不搭一行后端的许可证系统</title><link>https://mahui.me/blog/pier-no-backend-license/</link><guid isPermaLink="true">https://mahui.me/blog/pier-no-backend-license/</guid><description>Pier 复盘：一次性买断、5 台设备、可吊销退款——整套许可证系统客户端不到 200 行 Swift，零服务器、零嵌入密钥。关键在状态存哪、校验失败时信谁。</description><pubDate>Fri, 12 Jun 2026 00:00:00 GMT</pubDate></item><item><title>为一次登录做两套 SSH 栈——Shellby 的后端抉择</title><link>https://mahui.me/blog/shellby-two-ssh-backends/</link><guid isPermaLink="true">https://mahui.me/blog/shellby-two-ssh-backends/</guid><description>Shellby 复盘：iOS 上没有系统 SSH 库，纯 Swift 还是 C，两条路我都走了一遍。</description><pubDate>Fri, 12 Jun 2026 00:00:00 GMT</pubDate></item><item><title>App 假死三次，同一个凶手：别阻塞 Swift 协作线程池</title><link>https://mahui.me/blog/flick-cooperative-pool/</link><guid isPermaLink="true">https://mahui.me/blog/flick-cooperative-pool/</guid><description>Flick 复盘：4 次 compute start、0 次 compute done——协作式调度的契约，以及违反它的三种姿势。</description><pubDate>Wed, 10 Jun 2026 00:00:00 GMT</pubDate></item><item><title>菜单栏上的一颗红点——LaunchAgent 的被动监控</title><link>https://mahui.me/blog/pier-launchagent-badge/</link><guid isPermaLink="true">https://mahui.me/blog/pier-launchagent-badge/</guid><description>Pier 复盘：LaunchAgent 挂了从来不会通知你。plist 文件当真相、launchctl 回填状态、退出码非零亮红点，每 5 分钟刷一次——监控的价值在于你不看它的时候它也在看。</description><pubDate>Tue, 09 Jun 2026 00:00:00 GMT</pubDate></item><item><title>子进程的三条不变量——别把 CLI 跑成僵尸</title><link>https://mahui.me/blog/llm-bridge-subprocess-invariants/</link><guid isPermaLink="true">https://mahui.me/blog/llm-bridge-subprocess-invariants/</guid><description>LLM-Bridge 复盘：网关的活儿本质是「安全地 shell out 别人的 CLI」。stdin、stderr、finally kill 三条不变量，少一条就漏进程或死锁。</description><pubDate>Mon, 08 Jun 2026 00:00:00 GMT</pubDate></item><item><title>lsof 只告诉你 node，不告诉你是哪个项目</title><link>https://mahui.me/blog/pier-port-fingerprint/</link><guid isPermaLink="true">https://mahui.me/blog/pier-port-fingerprint/</guid><description>Pier 复盘：端口列表里全是 node、python、com.docker.backend。用完整 argv 指纹识别 40 种开发服务、proc_pidinfo 拿工作目录、docker ps 反查容器名——三条信息拼出「这个端口到底是谁」。</description><pubDate>Sat, 06 Jun 2026 00:00:00 GMT</pubDate></item><item><title>不上传一张照片：Flick 的本地相似照片检测</title><link>https://mahui.me/blog/on-device-photo-similarity/</link><guid isPermaLink="true">https://mahui.me/blog/on-device-photo-similarity/</guid><description>用 Vision 特征向量、Laplacian 方差和 SQLite 缓存，在设备端完成相册分析。</description><pubDate>Fri, 05 Jun 2026 00:00:00 GMT</pubDate></item><item><title>让数据库约束当哨兵：三个被约束「抓现行」的 bug</title><link>https://mahui.me/blog/yuwei-constraints-as-tripwires/</link><guid isPermaLink="true">https://mahui.me/blog/yuwei-constraints-as-tripwires/</guid><description>余位复盘：23514、23P01 和一批幽灵座位——约束不只是防线，还是最诚实的报警器。</description><pubDate>Thu, 28 May 2026 00:00:00 GMT</pubDate></item><item><title>辩论太长喂不进去——综合前的一次压缩</title><link>https://mahui.me/blog/open-council-presynthesis-compression/</link><guid isPermaLink="true">https://mahui.me/blog/open-council-presynthesis-compression/</guid><description>Open Council 复盘：多模型 × 多轮辩论产生的文本会撑爆主席的上下文。核心保全、外围截断、代码块绝不动，以及一个「先上确定性、把 LLM 摘要留到二期」的诚实取舍。</description><pubDate>Fri, 22 May 2026 00:00:00 GMT</pubDate></item><item><title>三重防护杜绝超售：一个排座系统的并发控制</title><link>https://mahui.me/blog/prevent-overselling/</link><guid isPermaLink="true">https://mahui.me/blog/prevent-overselling/</guid><description>余位的库存安全设计：行锁、乐观锁、数据库约束，缺一不可。</description><pubDate>Sat, 16 May 2026 00:00:00 GMT</pubDate></item><item><title>一个 OpenAI 端点，后面三种完全不同的进程</title><link>https://mahui.me/blog/llm-bridge-provider-adapters/</link><guid isPermaLink="true">https://mahui.me/blog/llm-bridge-provider-adapters/</guid><description>LLM-Bridge 复盘：对外是一种整齐的 OpenAI 格式，对内是 SDK 消息流、行分隔 JSON、纯文本三头野兽。归一化都发生在适配层里。</description><pubDate>Mon, 11 May 2026 00:00:00 GMT</pubDate></item><item><title>所有中文关键词都是死代码——路由、角色与一个正则坑</title><link>https://mahui.me/blog/open-council-routing-roles/</link><guid isPermaLink="true">https://mahui.me/blog/open-council-routing-roles/</guid><description>Open Council 复盘：怎么判断一个问题该辩几轮、该派谁上、给模型分什么角色。从一个「\b 让全部中文路由词失效」的经典正则坑讲起。</description><pubDate>Thu, 30 Apr 2026 00:00:00 GMT</pubDate></item><item><title>抽 token 是条死路——个人 AI 网关的合规红线</title><link>https://mahui.me/blog/llm-bridge-no-token-extraction/</link><guid isPermaLink="true">https://mahui.me/blog/llm-bridge-no-token-extraction/</guid><description>LLM-Bridge 复盘：从 CLI 里抠 OAuth token 直连后端，是最短的路，也是最先死的路。为什么最后全部退回官方 harness。</description><pubDate>Tue, 14 Apr 2026 00:00:00 GMT</pubDate></item><item><title>共识度 0.82 是怎么算出来的——多模型互评的量化</title><link>https://mahui.me/blog/open-council-consensus/</link><guid isPermaLink="true">https://mahui.me/blog/open-council-consensus/</guid><description>Open Council 复盘：让几个模型互相打分，再把打分变成一个 0-1 的共识度。一半来自打分离散度，一半来自排序一致性，还有一个差点让辩论永远停不下来的坑。</description><pubDate>Wed, 08 Apr 2026 00:00:00 GMT</pubDate></item></channel></rss>