Posts for: #Tech

Mac 远程桌面:看的是同一个画面

今天我在外面,远程连回我的电脑操作。同事经过,看到那台电脑居然没锁屏——屏幕亮着,鼠标自己在动,窗口一个个开。我才去了解了 Mac 远程桌面是怎么回事。

打开 Mac 的「屏幕共享」连上另一台 Mac,你看到的就是那台机器此刻的屏幕,和坐在它面前的人看到的完全一样。它当下显示什么,你这边就显示什么。我在外面操作,那台电脑的屏幕就同步显示我的每一步——同事看到的"没锁屏",就是我远程操作的实时画面。

你动鼠标,那台 Mac 屏幕上的鼠标也跟着动;你打字,字就落在它的屏幕上。坐在电脑前的人能实时看到你点了哪里、开了哪个窗口、敲了什么,像看直播。

控制权是两人共享的。你能动,坐在跟前的人也能动。要是同事这时顺手去推那台电脑的鼠标,就会和我远程的操作抢起来——光标在屏幕上跳来跳去,谁都使不顺。想配合,得有人先松手。

远程桌面连过去,是两个人共用同一块屏幕、同一套鼠标键盘。人没在跟前,用的还是那台真机。

eink 手机重装后的工具清单

昨天重装了 eink 手机。安装后希望装少而精的几个工具即可:

Telegram、Pocket Casts、Claude、Google Tasks、Brave、YouTube、微信读书、微信输入法、Slax Reader、Slax Note、Dropbox、Gemini、Spotify。

eval 是什么,sgai.md 怎么做

只要产品里嵌了 AI,就一定要做 evals。这是过去两个月在 sgai.md(新加坡 AI 战略观察站)上踩坑总结出来的判断。

eval 是什么

eval = 评估测试。给 AI 输出和数据完整性写的回归测试,但和单元测试不是一回事。

单元测试测的是「函数给定输入,输出是不是这个值」——确定性的。

eval 测的是「AI 这次生成的东西,和金标 / 规则相比,质量有没有掉」——非确定性的。

简单说:单元测试盯代码,eval 盯模型 + 数据。

eval 解决什么问题

任何依赖大模型的系统,都有三个天然漏洞。代码里写的单元测试管不到,人肉 review 一定漏。

模型会幻觉。 LLM 会编一个看起来合理但根本不存在的 URL、人名、事实。我自己在 sgai.md 上踩过——5 月初让 agent 给一批 voice 人物档案补「主导项目 / 公开引言」,agent 给两条记录写了根本不存在的 sourceUrl(一个伪造的 Fintech Festival 演讲者 ID,一个伪造的航空业报道)。URL 模式正确得肉眼分辨不出,靠用户事后报错才发现。

模型会退化。 升级模型(Claude 4.6 → 4.7)或改 prompt,输出可能变差。但你不会主动知道——除非有人发现产出明显烂了。等用户先发现就太晚了。

数据会漂移。 AI 生成的内容入库后,没人持续盯着完整性,漏字段、缺翻译、链接腐烂会慢慢累积。sgai.md 是中英日三语站,数据文件里每条 record 要求 title / titleEn / titleJa 三套字段必须同时给。我有一次只 commit 了中文,下一个 PR 想补英日——结果 EN/JA 页面立刻断裂。

[阅读全文]

Bitwarden CLI npm 包被投毒,AI 编码工具凭证成新目标

The Hacker News 报道了一起 npm 供应链攻击:Bitwarden CLI 的 npm 包(@bitwarden/cli)2026.4.0 版本被植入恶意代码,藏在包内的 bw1.js 文件里。

感染窗口从 4 月 22 日 ET 时间下午 5:57 到 7:30,约 1.5 小时,估计 334 次下载。被怀疑是更大规模 Checkmarx 供应链攻击的一部分,归因到 “Shai-Hulud: The Third Coming” 这一波。

攻击路径

攻击者拿下了 Bitwarden CI/CD 流水线里一个被入侵的 GitHub Action(checkmarx/ast-github-action),通过 preinstall 钩子在用户 npm install 时执行恶意代码。

据安全研究员 Adnan Khan 说,这可能是首次使用 npm Trusted Publishing 的包遭到入侵。

恶意代码偷什么

  • 本地开发凭证:GitHub / npm tokens、.ssh 密钥、.env 文件、shell 历史
  • 云端密钥:GitHub Actions 环境变量、CI/CD secrets、多云凭证
  • AI 编码工具配置:Claude、Kiro、Cursor、Codex CLI、Aider 的认证配置
  • 自传播:偷到 GitHub token 后注入恶意 Actions workflow,用偷到的 npm 凭证向下游包发布恶意版本,蠕虫式扩散
  • 数据外泄走 AES-256-GCM 加密发到伪装域名 audit.checkmarx[.]cx,失败后以 GitHub commit 作为 fallback

有一个细节:如果系统 locale 是俄罗斯,恶意代码自动退出。这一行为与原始 Checkmarx 攻击不一致。

[阅读全文]

macOS 的 cron 和 launchd

今天在终端收到一封 cron 发来的邮件,说某个脚本 “Operation not permitted”。查下去是两个问题合在一起,顺手也把 cron 和 launchd 在 macOS 上的差别重新过了一遍。

先看今天这件事

我有三个用 cron 跑的定时任务:每小时 15 分把知识库备份到 git,每小时 20 分刷新知识库的向量索引,每天早 9 点跑一次健康检查。

有一天开始,前两个任务悄无声息失败。打开日志才看见:

/bin/bash: .../brain-git-backup.sh: Operation not permitted
/bin/bash: gbrain: command not found

第一个是权限拦截——脚本文件在 ~/Library/CloudStorage/Dropbox/ 里,macOS 的隐私系统(TCC)不让 cron 碰 iCloud、Dropbox 这种云端同步目录下的文件。

第二个是 PATH 问题。cron 跑的 bash 是个干净的非交互 shell,.zshrc 里配置的 PATH 不会加载,gbrain 找不到。

cron 和 launchd 是什么

两者都是"定时工具"——让系统在指定时间跑一段命令。

cron 是 Unix 时代的老工具,几十年历史,Linux、Mac 都有,写一行配置就能用。

launchd 是苹果自己做的调度系统,2005 年随 macOS 10.4 推出。现在苹果系统里所有后台服务,包括 cron 本身,都归 launchd 管。

[阅读全文]

让每个 AI 助手的对话都进我的记忆系统

我维护着一个叫 context 的个人上下文系统:一份中心 markdown,分发到 Claude Code、Codex CLI、Gemini CLI、OpenClaw 的配置路径里,保证同一个"我"在各个工具之间一致。

这个系统每天自动扫当天的对话,把我说过的偏好、决策、踩坑提炼到 OBSERVATIONS.md。问题是——它只懂 Claude Code 一家的 JSONL 格式。我同时还在用 Codex、Gemini、OpenCode,这些对话历史全都被扔在一边。

每家 AI 助手的对话都存在本地,但格式各家不同。Claude 用 JSONL,Codex 也用 JSONL 但 schema 不一样;Gemini 用整块 JSON;OpenCode 用 SQLite,message 和 part 分两张表;Cline 和 Cursor 藏在 VSCode 扩展的 globalStorage 里;Aider 干脆写在项目目录的 markdown 里。

自己从零逆向这些格式,不是我想干的活。

在 GitHub 上撞见 jhlee0409/claude-code-history-viewer,简称 CCHV。本意是个桌面历史查看器——七家 AI 助手的对话在一个界面里翻。我对桌面 app 本身不感兴趣,但它的 Rust 源码里有一个 providers/ 目录:七个文件,每家一个解析模块。每家的存储路径它替我找好了,每种格式的 schema 它替我逆向完了。

让 AI 把这部分代码翻成 Python,挪进 context 项目。

OOM 杀死 NetworkManager 事件记录

2026 年 4 月 19 日凌晨 00:06,luca-xm(RedmiBook Air 13,16GB 内存,4GB swap)上的 NetworkManager 意外退出,网络断开。

时间线

  • 4 月 18 日全天,NetworkManager 日志显示 WiFi 连接在 CONNECTED_SITE 和 CONNECTED_GLOBAL 之间反复切换,但均自动恢复,属正常行为
  • 4 月 19 日 00:06:13,内核触发 OOM Killer
  • OOM Killer 选中 unattended-upgr(PID 392258,属于 apt-daily.service),该进程占用 13.6GB 匿名内存(anon-rss: 13601484kB)
  • 此时 swap 已耗尽(Free swap = 0kB)
  • 进程被杀后,D-Bus 连接断裂(Unexpected error response from GetNameOwner(): Connection terminated)
  • NetworkManager 收到 SIGTERM,正常退出
  • 4 月 20 日 08:43,系统重启后 NetworkManager 恢复正常

根因

apt-daily.service 自动执行系统更新时,unattended-upgr 进程内存泄漏或异常膨胀至 13.6GB,耗尽系统全部可用内存和 swap。OOM Killer 介入后引发 D-Bus 连接中断,NetworkManager 作为 D-Bus 依赖方被连带终止。NetworkManager 本身无异常。

[阅读全文]

GBrain 双机部署实录

一台常开的台式 / 常驻机负责跑重活,一台笔记本带在身边随写随记。两台机器共用一个 GBrain,写在哪台都能在另一台搜到。

下面是我把这套装起来的实际过程,包括踩到的坑。环境是两台 Mac:M2(常开)和 M4(日常,有开有关),GitHub 账号 wulujia,笔记放 Dropbox。

架构

三层,分工明确。

Brain 仓库 = markdown 文件,源头。放 ~/Dropbox/brain/,Dropbox 负责实时同步文件,GitHub private repo 负责版本备份。

gbrain 工具 = 读 markdown、灌进索引的 CLI。每台机器独立从 GitHub clone 到非 Dropbox 路径,各自 bun link。不要让 Dropbox 同步工具源码,node_modules 跨机会掐架。

索引 = PGLite(嵌入式 Postgres),默认引擎,放 ~/.gbrain/。每台机器一份独立本地索引。markdown 是真相,索引坏了重建。

M4(日常机)从零装起

1. 装 gbrain 工具

git clone https://github.com/garrytan/gbrain.git
cd gbrain && bun install && bun link

2. OPENAI_API_KEY

到 platform.openai.com 建个 project key,丢 zshrc:

echo 'export OPENAI_API_KEY="sk-proj-..."' >> ~/.zshrc
source ~/.zshrc

注意变量名全大写 OPENAI_API_KEY。一个字母错了 OpenAI SDK 读不到,跑出来一堆 401。

[阅读全文]

GBrain 入门:给 AI agent 一个长期记忆

跟 AI 聊天有个长期的问题。每次新对话它都从零开始。聊过的想法、见过的人、读过的文章,下次对话完全空白。

GBrain 解决的就是这件事。

它是什么

AI agent 是大脑,GBrain 是它的记忆。

更准确一点:GBrain 是一堆 markdown 文件加一个搜索引擎。跟 AI 聊天时,它自己决定把什么存进去、什么取出来。存的是文本文件,可以打开看、改、备份。

这一点很重要。市面上很多 AI 记忆功能是黑盒,坏了查不出原因,也导不出来。GBrain 的记忆就是你自己的文件,放在 Git 仓库里,agent 关掉记忆也还在。

它怎么工作

三个核心动作

捕获。你跟 agent 说"今天跟老王聊了一下 SaaS 定价",一个叫 signal-detector 的技能在后台自动抽取:“老王"是人,“SaaS 定价"是话题。后台并行跑,对话照常进行。

回答前查大脑。下次问"老王最近在想什么”,agent 先搜 GBrain,翻出上次的记录,带着上下文回答。跳过这一步的 agent 等于失忆。

睡觉时整理。装上 autopilot,凌晨 agent 自动扫白天所有对话,给新出现的人建档、补社交资料、修引用。早上起来大脑比昨晚厚。

页面长什么样

每个人、每件事在 GBrain 里就是一个 markdown 文件。结构很简单:上半部写当前结论,下半部写时间线。

比如"老王"这一页。

上半:老王是某某公司 CEO,擅长 SaaS 定价,2026 年 3 月开始考虑出海日本。

下半:

  • 2025-01-10 邮件里第一次提到
  • 2025-08-22 聊过定价策略
  • 2026-03-05 说要出海日本

上半随时重写。下半只加不删,是证据链。好处是:问一个问题,agent 直接读上半部就知道答案,不用每次把所有历史再推理一遍。

怎么装

前提是装了 bun。然后两行:

git clone https://github.com/garrytan/gbrain.git && cd gbrain && bun install && bun link
gbrain init

默认用嵌入式 Postgres,零配置。接到 Claude Desktop 或 Claude Code 之后,正常聊天它就正常往里存。Gemini CLI、Codex 也能接,都走 MCP 协议。

[阅读全文]

给自己和家人装个龙虾助理

最近打听小龙虾的朋友有点多,所以我干脆写篇短文,把文科背景朋友们最经常问的问题,做个粗浅的回答。

第一步:我需要什么?

找一台独立的旧电脑。

建议用一台不用的旧电脑专门跑它。原因有两个:

一是稳定。你大概率会希望这个助理 24 小时在线——半夜收到重要邮件能帮你处理,每天早上自动发一份新闻摘要,你不在的时候也能替你盯着事情。用日常办公的电脑跑,合上盖子就断了。

二是安全。这个助理会接触你的邮件、日历、文件,给它一台独立的机器,跟你的工作环境隔开,万一配置出了问题,也不影响你日常用的东西。

五六年前的笔记本就够,Mac、Windows、Linux 都行。

没有旧电脑怎么办?

• 树莓派,几百块钱,功耗极低,放在角落里一直跑

• 云服务器(VPS),每月几十到一百多块,不用管硬件

• Mac mini,如果你本来就想买一台——这是极其豪华的配置

在中国能用吗?OpenClaw 本身没有限制。但它需要调用 AI 服务(比如 Claude、GPT),如果网络访问不了这些服务,需要想办法解决,或者选用国内能访问的 AI 模型。

注意,这里强烈建议:用独立设备,跟你的工作电脑分开。

───

第二步:要花钱吗?

OpenClaw 开源,费用来自 AI 模型——就像请了一个助理,AI 模型是助理的大脑。

我最直接的建议:用你能用得起的最贵、最好、最聪明的模型。

模型笨,相当于助理笨,你要个笨助理干嘛?以及,笨助理更容易被网页里藏的恶意指令操控,如果被骗了,一次损失,估计就够付这辈子的模型账单了。

AI 模型的能力差距非常大。便宜的模型能聊天,但理解力、判断力、可靠性都差不少。你既然花时间把助理搭起来了,别在最关键的大脑上省钱。一个聪明的助理能帮你省的时间,远超模型费用。

轻度使用(每天聊几轮,偶尔帮忙查东西),一个月大概几美元到十几美元。重度使用会更多。

如果你有一些 AI 的订阅,可以请懂技术的朋友看看,说不定无需额外付费就能使用。

第三步:装上它

安装过程需要有人帮你在电脑的终端里输入几条命令。不复杂,但如果你从来没用过终端,建议找个懂技术的朋友帮忙,十分钟就能搞定。

装好之后,OpenClaw 会自带一个网页聊天界面,打开浏览器就能跟它说话。

但更多人是想在手机上随时跟它聊,可以把它连到一个聊天工具。海外用户推荐 Telegram(配置最简单)或 WhatsApp。

中国用户怎么办?Telegram 和 WhatsApp 在国内不能直接用。几个替代方案:

• 飞书(Lark)——OpenClaw 支持飞书机器人,国内直接可用,适合个人和团队

• 网页界面——装好就自带,不依赖任何第三方聊天工具,打开浏览器就能用

第四步:搞清楚它能帮你做什么?

从聊天开始。

刚装好的时候,先就当它是一个聊天对象。问它问题,让它帮你查资料、翻译、写邮件草稿、整理想法。用几天,找找感觉。

然后逐步给它更多权限。

当你觉得它靠谱了,可以开始授权更多能力——读你的邮件、管你的日历、帮你搜索网页、定时执行任务。

具体怎么授权?直接问它就行。跟它说"我想让你能帮我读邮件"或者"我想让你每天早上给我发一份新闻",它会告诉你需要做什么配置。这些配置通常就是几步操作,它会一步步带你完成。

它有记忆。你告诉它的事情,它会记住。下次你再跟它聊,不用从头说起。

每个能力都可以单独开关。一个一个加,逐步建立信任。

下一步:给家人也配一个

不需要再买电脑。同一台机器上可以跑好几个独立的 AI 助理,每个人一个。

每个人的助理完全独立:

[阅读全文]