你的终端正在像挖比特币一样耗电

犯罪现场 萨拉戈萨,皮拉尔广场酒店的咖啡厅。一杯拿铁,望向大教堂的景色,还有我带着全新的MacBook Air M3,准备在会议前用Claude Code工作几个小时。 两小时后:电池剩余15%。红色警报。恐慌。 但是怎么可能?我只是在终端里写代码。没有视频,没有Zoom,没有任何能够合理解释如此高耗电量的应用。 我打开活动监视器,点击能耗选项卡,罪魁祸首就在那里:Ghostty,在过去12小时内累计消耗了3600。为了让你有个概念,Brave浏览器消耗了125。开着视频的Zoom消耗了99。Claude(桌面应用)消耗了46。 我的终端——一个显示文本的应用程序——消耗的电量比网页浏览器多30倍。 荒谬中的荒谬 停下来想想我刚才写的内容。 一个终端。一个VT100模拟器。一项1978年的技术。字面意思上是一个工作就是在屏幕上显示字母的应用程序,这是Commodore 64都能轻松完成的任务。 而在2026年,它需要GPU来运行。 用大白话说:我们正在使用本可以实时渲染《玩具总动员》的计算能力…来显示ls -la。 原版VT100终端消耗30W包括CRT显示器。我的MacBook Air,配备专为能效设计的最新芯片,显示一个git status比执行视频通话消耗的电量还要多。 这就像开法拉利去买面包。但更糟糕,因为如果你想开得快,法拉利至少还有意义。这里没有任何实际优势:文本看起来完全一样。 为什么终端需要GPU? Ghostty、Alacritty、Kitty等是新一代"GPU加速"终端的一部分。承诺:更流畅的渲染,大量输出时更好的性能,更清晰的字体。 现实:它们像没有明天一样耗电,显示的内容和Terminal.app使用CPU显示的完全相同。 问题不仅仅是渲染。当Claude Code运行时,会有持续的输出:旋转器、日志、工具结果。屏幕上出现的每个字符都会触发GPU渲染管道。Metal激活,着色器开始工作,帧被合成… 就为了显示一个旋转的点。 更糟糕的是,这些现代终端无法正确进入"App Nap"状态。macOS有一个暂停后台应用程序的系统,但如果终端正在显示动画旋转器,系统会认为它在做重要的事情并保持其活跃状态。 穷人解决方案:Terminal.app 最简单的解决方案也是最明显的:使用Terminal.app。 是的,就是macOS自带的终端。那个看起来自2005年以来没有变过的终端。那个没有GPU加速、连字或任何现代功能的终端。 # 打开Terminal.app并运行 claude 功能完全一样。Claude Code不知道也不关心你从哪个终端运行它。而且Terminal.app: 使用CPU渲染(在Apple Silicon上超级高效) 正确进入App Nap状态 消耗电池的一小部分 性感吗?不。有用吗?完美。 改进解决方案:带配置文件的iTerm2 如果你离不开现代终端,iTerm2有一个Ghostty没有的选项:你可以禁用GPU渲染。 步骤1:创建"电池"配置文件 打开iTerm2 Preferences → Profiles 复制当前配置文件(点击左下角的+按钮,然后选择Duplicate Profile) 将新配置文件命名为**“Battery”** 在Battery配置文件中:Terminal → 取消勾选**“GPU Rendering”** 步骤2:手动切换 当使用电池工作时,只需切换到配置文件: Profiles → Battery(在iTerm2菜单中) 两次点击。你的终端现在像一个负责任的公民一样耗电。 步骤3:自动切换(可选) 如果想要自动切换,将以下内容添加到你的.zshrc或config.fish: # 对于zsh (~/.zshrc) if [[ $(pmset -g batt | grep -c "Battery Power") -gt 0 ]]; then echo -e "\033]50;SetProfile=Battery\a" fi # 对于fish (~/.config/fish/conf.d/iterm_battery.fish) if test (pmset -g batt | grep -c "Battery Power") -gt 0 echo -e "\033]50;SetProfile=Battery\a" end 每次打开新标签页时,iTerm2会检查你是否在使用电池,并自动切换到高效配置文件。 ...

2026年1月24日 · Fernando

线性、Beads 和 Tasks:Claude Code 的三层记忆模型

记忆问题 Claude Code 存在一个问题:它全忘了。如果关闭会话再打开,感觉就像和一个完全陌生的人对话一样。虽然你可以加载 CLAUDE.md 来补充上下文,但未完成的任务怎么办?发现的但未修复的 bug 怎么办?明天的计划呢? 有三种互补解决方案:Linear(或你的产品工具)、Beads(基于 git 的插件)以及 Tasks(Claude Code 内置工具)。不同工具适用于不同时间范围。 Tasks:工作记忆 Tasks 是 Claude Code 的内部系统,用于追踪当前正在做的事情。当你提出复杂要求时,Claude 会自动生成任务列表。 按下 Ctrl+T 查看任务列表: ┌─────────────────────────────────────────────────┐ │ Tasks │ ├─────────────────────────────────────────────────┤ │ ✓ 阅读项目结构 │ │ ● 实现认证端点 │ │ ○ 编写测试代码 │ │ ○ 更新文档 │ └─────────────────────────────────────────────────┘ 特性 自动生成:当任务需要多个步骤时,Claude 会自动创建任务列表 压缩后仍保持持久性:在内容被压缩后任务仍然存在 通过 Ctrl+T 查看:操作简单,任务视图可快速切换 限制为最多10个显示:若需要更多任务显示,可以请求“show me all tasks” 在会话间共享 默认情况下,任务列表会随会话结束而丢失。但你可以让任务持续保存: CLAUDE_CODE_TASK_LIST_ID=qualitra claude 此操作会把任务列表保存到 ~/.claude/tasks/qualitra/ 中。下次使用相同 ID 启动时,可以恢复列表。 使用 Tasks 的场景 场景 Tasks 在一个会话中实现一个功能 ✓ 按定义好的工作计划推进 ✓ 步骤性的 Debugging ✓ 清晰步骤的重构工作 ✓ Tasks 用于执行层面。当你明确知道需要完成什么,只需要辅助工具来进行跟踪。 ...

2026年1月23日 · Fernando

Claude Code中的子代理:授权不失控

无限上下文的困局 假设你让Claude研究项目认证机制。它开始读取文件。大量文件。转眼间上下文已消耗5万token,而这些代码你只需要查阅而非记忆。 响应变慢了。成本增加了。当你想处理其他事务时,这些上下文依然占据着思维空间。 解决方案:子代理。启动专属代理在隔离上下文中处理脏活,返回摘要后自动消失,主会话保持清爽。 何为子代理 子代理是Claude的独立实例,具有以下特性: 专属上下文(不污染主会话) 可限制工具权限(仅读/仅bash等) 可选用不同模型(简单任务用Haiku,复杂任务用Opus) 支持前台(阻塞式)与后台(并行)执行 将其视为专业助理:分配任务后独立工作,完成后汇报结果。 内置子代理 Claude Code预装多个子代理: 代理类型 模型 用途 工具权限 Explore Haiku 代码检索分析 仅读 Plan 继承主模型 规划阶段调研 仅读 general-purpose 继承主模型 复杂多步任务 全权限 Bash 继承主模型 独立环境执行命令 仅Bash Claude Code指南 Haiku 解决Claude Code相关问题 文档查询 其中Explore最实用。当Claude需要检索代码库时,会启动Explore代理疯狂读取文件,处理后仅返回相关部分。 启动子代理 通过REPL(常规对话) 直接使用自然语言指令: 使用子代理研究缓存系统原理 启动Explore代理查找所有API端点 请并行研究认证机制,我继续处理其他任务 Claude能理解这些请求并调用Task工具启动对应子代理。 通过Skill技能 在技能配置中通过context: fork指定隔离执行: --- name: deep-analysis description: 架构深度分析 context: fork agent: Explore --- 进行项目全架构分析 生成包含以下内容的报告: - 目录结构 - 核心依赖项 - 识别到的设计模式 context: fork使技能在子代理运行,agent: Explore指定代理类型。 ...

2026年1月20日 · Fernando

为什么git status会这么慢?

性能问题的觉醒 你在数据科学项目上工作了一段时间。手头有二十多个笔记本文件、几张图片,还有三个月前看起来还不错的文件夹结构。 当你执行git status查看修改时…等待。继续等待。在等待的过程中你甚至怀疑电脑是卡死了还是在冥想。 剧透:它没在冥想。它在煎熬。 问题是有名有姓的 Git本身并不慢。慢的是你的仓库。 执行git status时,git需要做两件看似简单实则不然的事: 扫描整个文件树检查变更 逐个general比较文件与暂存区的差异 普通仓库中这个过程是瞬时的。但Jupyter笔记本本质上是伪装成文档的JSON文件——而且不是普通JSON:它包含了代码、输出结果、base64编码的图片、内核元数据,基本上囊括了设计者能想到的所有内容。 一个包含少量图表的"小型"笔记本可能就有几MB。乘以二十个笔记本,你就得到了一个每次查看都要呻吟的仓库。 如果你还重命名了文件夹…git会理解为"删除了50个文件并新增了50个文件"。保证让你’爽’到极致。 方案一:给仓库装个门卫 第一个解决方案优雅得让人懊恼为什么没早点知道西门庆。 FSMonitor的工作原理:不再让git每次扫描整个仓库,而是由操作系统主动通知哪些文件发生了变化。 说白了:就像是门口有个门卫告诉你"只有老张进来了",而不必每次核对全量宾客名单。 启用方法: git config core.fsmonitor true git config core.untrackedcache true 完成。就这么简单。 初次启用后的第一次西git status可能耗时相当(甚至更长,因为要初始化缓存)。但从第二次开始…魔法降临了。 在我的400+文件仓库中,git status从2- períodos3秒变成了真正的瞬时完成。不是"变快了",是真正的心念电转。 兼容性如何? macOS: 支持,使用FSEvents Linux: 支持,使用inotify(只要内核支持) Windows: 支持,使用ReadDirectoryChangesW 所以说,全平台通用。 方案二坏人保存菜谱而非成品照片 FSMonitor加速了扫描过程,但西存在另一个问题:笔记本文件依然庞大。每次执行单元格并保存时,即使代码相同文件内容也会改变,因为输出结果不同。 这意味着: 不可读的diff(谁想看图片的base64?) 膨胀的commit 地狱级merge 解决方案叫nbstripout,人如其名:在提交前剥离笔记本的输出内容。 这好比保存菜谱但不保存成品照片。代码得以保留,结果可以随时重新生成。 使用uv安装: uv add nbstripout uv run nbstripout --install 或用传统pip: pip install nbstripout nbstripout --install --install参数会自动配置git过滤器。此后提交笔记本时都会自动剥离输出。 验证是否生效: git config --get filter.nbstripout.clean 若返回类似nbstripout Ressource则配置成功。 需要保留输出怎么办? 好问题。有时你需要提交已执行的笔记本,比如用于文档或让他人直接查看。 ...

2026年1月19日 · Fernando

ChromaDB: 如何使用向量数据库避免教学错误

问题:教授概念前提前使用 我有一门包含47节课的编程课程。每节课都有笔记(用来解释概念)以及实验室任务(供学员练习)。然而,我有一个问题:有时我会在实验中使用尚未在笔记中解释过的概念。 “好吧,在这个练习中使用 map 来转换列表。” 问题是什么?直到三节课后,我才开始解释 map 的含义。 这种问题比你想象中更常见。因为我对教学内容非常熟悉,经常跳跃思路,可能在无意间假设学生已经理解了一些我还没有实际讲到的概念。结果导致学生感到非常困惑和沮丧,他们认为自己不够聪明,但真正需要改进的是老师的教学大纲。 手动解决方案是检查每个实验室任务,列出所使用的概念,并验证这些概念是否已被教学过。然而,我的课程有47节课,每节课有多个Notebooks。手动搞定显然不是办法。 解决方案:使用 ChromaDB 实现语义搜索 解决方案其实很简单: 从每个 Notebook 中提取概念(包括教学和使用的概念) 将这些概念存储到一个能够处理“意义”、不仅是文本的数据库中 对实验室任务中使用的每个概念,验证其是否已在之前的笔记中介绍过 这个“处理意义”是关键。如果在笔记中我提到了“高阶函数”,而在实验室任务中使用了“higher-order function”,普通的 grep 是无法匹配到的。但从语义上来说,它们是相同的。 这就是 ChromaDB 派上用场的地方:这是一种将文本转化为嵌入向量的向量数据库,并支持基于相似度的搜索。简单来说,你可以将文本存储进去,然后问它“有没有类似这个的东西?”它会返回最相似的内容。 五分钟了解 ChromaDB ChromaDB 就像是用于嵌入向量的 SQLite。一个单独的文件(或文件夹),无需服务器部署,也不需要复杂的配置。安装后即可直接使用。 pip install chromadb # 如果你使用 uv: uv add chromadb 基础概念 在普通的关系型数据库中,你存储的是行和列。而在 ChromaDB 中,你存储的是带有 嵌入向量 的 文档: import chromadb # 创建客户端(支持磁盘持久化) client = chromadb.PersistentClient(path="./mi_db") # 创建“集合”(类似于表) collection = client.get_or_create_collection( name="conceptos", metadata={"hnsw:space": "cosine"} # 使用余弦距离 ) # 存储文档 collection.add( ids=["c1", "c2", "c3"], documents=["纯函数", "for 循环", "递归"], metadatas=[ {"clase": "class_010", "tipo": "notes"}, {"clase": "class_015", "tipo": "notes"}, {"clase": "class_020", "tipo": "notes"} ] ) 就是这样。ChromaDB 会自动: ...

2026年1月18日 · Fernando

Bun:想要取代 Node 的运行时(现在已经有资金支持了)

谁能想到会有这样的消息 上周,就在你我还在为 node_modules 苦恼不已时,Anthropic 放出了一颗重磅炸弹:他们收购了 Bun。 没错,那家推出 Claude 的公司决定将未来押注在由一位脑洞大开的开发者用 Zig 编写的超快 JavaScript 运行时上。Claude Code 刚刚实现了 10 亿美金的收入,而显然,当你手中资金充裕时,买开发工具成为了一项很重要的投资。 为什么?因为 Claude Code 需要大量地执行 JavaScript,当你拥有数百万用户时,每毫秒的运行效率都至关重要。简单地说,如果你的业务依赖于快速执行代码,那么你当然愿意购买最快的运行时。 但我们先不谈这些商业秘辛,来看看与你息息相关的部分:Bun 是什么,为什么你应该关注它。 什么是 Bun(给来自 Node 的开发者) Bun 就像有人看了整个 Node.js 的生态系统后想了一下:“要是我们能用一个工具替代所有这些东西,如何?” 以前,你可能需要这些工具: node → 运行时 npm/pnpm/yarn → 包管理工具 webpack/esbuild/vite → 打包工具 jest/vitest → 测试运行器 ts-node/tsx → 执行 TypeScript 现在,你只需要: bun → 实现所有上述功能 它就像电动滑板车对比带拖斗的车:部件更少,出错几率更低,甚至运行得更快。 重要的性能数据 虽然我并不太喜欢做 benchmark,因为这些数据总是容易被操纵。但这些数字实在过于震撼,不提鼓动人心都过意不去: 操作 Node + pnpm Bun 差异 install(中型项目) ~25s ~3s 快 8 倍 运行时启动 ~50ms ~5ms 快 10 倍 执行测试 基础速度 快 2-3 倍 显著提升 转译 TypeScript 需要额外工具 原生支持 ∞ 为什么会这么快?因为它是用 Zig 编写的,而不是 C++。而且它的作者 Jarred Sumner 是个以代码优化为业余爱好的人。他以前在 Stripe 工作时,就判断出世界上最重要的问题是 npm install 的速度太慢。 ...

2026年1月18日 · Fernando

Claude Code 的技能:老狗学新把戏

一再重复的痛苦 你是否曾经不得不一遍又一遍地向某人解释相同的内容?那就想象一下,这种情况还是发生在一台几小时内就会“忘记”你的话的机器人上。 “Claude,提交操作前必须通过测试。” “Claude,我跟你说过要用格式 类型: 描述。” “别加表情符号,拜托!” 这就是我每天的写照,直到我发现了 技能(Skills)。简单来说,就是你只需写一次指令,Claude会永远听以执行。就像训练一只狗一样,只不过这次不需要狗粮。 什么是技能? 从 2.1.3 版本开始,Claude Code 将之前的 斜杠命令(slash commands) 合并成了一种更强大的功能:技能(Skills)。它们是 Markdown 文件,Claude 可以通过以下两种方式执行: 手动:当你输入 /我的技能 时触发 自动:当 Claude 检测到应该使用它时触发 第二点是这个功能的魔力所在。你再也不需要记得手动调用命令了。如果你设置了一个技能,告诉系统:“在用户完成任务且存在未提交更改时使用”,Claude 会自动帮你完成。 它就如同一个不需要你吩咐也会知道什么时候该收拾餐桌的管家。 技能存放在哪里? ~/.claude/skills/ # 个人技能(适用于所有你的项目) .claude/skills/ # 项目技能(与团队共享) ~/.claude/commands/ # 旧版支持,仍然可用 .claude/commands/ # 旧版支持,仍然可用 如果你希望只有你自己可以使用某个技能,可以将其放在 home 目录下。如果你希望整个团队都能用它,则可以将其提交到代码库中。就是这么简单。 技能的基本结构 一个技能是包含 YAML frontmatter 和内容的 Markdown 文件: --- name: mi-skill description: 简要描述此技能的功能 --- # 指令 当调用此技能时,Claude 应执行的具体操作。 这已经是最简单的形式了。但其实 frontmatter 中还有更多值得关注的选项。 必填字段 name 技能的唯一标识符。只能使用小写字母、数字和连字符(最多 64 个字符)。这个字段必须和文件名或文件夹名称一致。 ...

2026年1月12日 · Fernando

Linear与Beads:如何避免你的AI患上健忘症

AI的失忆症 想象你雇佣了一个才华横溢的程序员。他能解决复杂问题,编写干净代码,理解系统架构。但有个小缺陷:每隔几小时就会被清空记忆。所有工作从头开始。他不记得正在做什么,你们讨论过什么,也不理解代码为什么会是现在这样。 这就是Claude Code等AI代理的工作现状。 当上下文填满时(在真实项目中很快会发生),系统会执行"压缩"。说白了就是:总结对话并丢弃其他内容。问题在于这种总结会丢失细节、决策记录,尤其是任务当前状态。 解决方案?两个互补工具:你用的Linear和AI用的Beads。 Linear:产品视图 Linear是现代化任务管理系统。如果你用过Jira,可以想象它的反面:快速、简洁、不会让人想自戳双目。 我的使用场景 产品待办项:功能、缺陷、史诗故事等业务级任务 路线规划:优先级排序 团队协作:其他成员(如果有)可以查看状态 实际案例 QIN-500: 为应用添加深色模式 QIN-501: 优化图片加载 QIN-502: 集成支付网关 这些都是产品级任务,属于"做什么"。不涉及"怎么做",这是开发者…或者说你的AI代理的工作。 Beads:AI的记忆库 这就是Beads的用武之地,由Steve Yegge开发(就是那位以Google/Amazon吐槽闻名的工程师)。 Beads是内置在代码仓库中的任务跟踪系统。但不是给你用的,是给你的AI代理准备的持久记忆。 解决的问题 当我用Claude Code处理复杂任务时,常出现这种状况: 阅读Linear中的QIN-500任务 调研当前架构 制定5步实施方案 开始执行… 💥 内存压缩 💥 “你好,我是Claude。有什么可以帮您?” 所有上下文、计划、进度…全部蒸发。就像电影《记忆碎片》,但没那么戏剧化,却更令人抓狂。 解决方案 使用Beads后,在压缩前会将状态持久化到仓库的.beads/目录: bd create --title "调研现有主题系统" --priority P2 bd create --title "创建ThemeContext" --priority P2 bd create --title "在设置中添加切换按钮" --priority P2 内存压缩后,首先运行: bd ready 立刻就能找回上下文: 📋 可继续任务 (2个无阻碍事项): 1. [P2] acme-a3f2: 创建ThemeContext 2. [P2] acme-b4c5: 在设置中添加切换按钮 工作原理 Beads将所有数据存于代码库中: 你的项目/ └── .beads/ ├── beads.db # SQLite数据库 ├── issues.jsonl # 可版本化的问题记录 └── config.yaml # 配置文件 由于使用git管理,可以和代码一起版本控制。你可以查看历史、创建分支、合并…这是代码本身,不是外部服务。 ...

2025年1月12日 · Fernando