我的配置:Claude Code + Ghostty + worktrees 在 Mac 上的极致实践

我现在有三个运行中的 Claude Code 会话。一个在翻译博客文章,另一个在为 CLI 编写测试,还有一个在帮我调试数据流水线。每个会话都运行在独立的 worktree 中,每个会话都开启在 Ghostty 的一个 split 里,而我则通过 Cmd+Alt+方向键 在它们之间快速切换。 我几个月没打开过 iTerm2,几个星期没用过 tmux。现在几乎所有工作都集中在 Ghostty 的一个窗口里。 它是完美的配置吗?当然不是。但它是迄今为止让我最高效的配置?毫无疑问。 为什么选择 Ghostty,而不是别的终端? 一句话总结:Ghostty 和挖矿一样耗电。我详细讲过 GPU终端和电量消耗问题,这一问题并没有改善,这依然是它最大的缺点。如果我用的是电池,我会果断关掉 Ghostty,转而使用 Terminal.app。 但每当电脑插电源时——我80%的时间都会坐在 Studio Display 前的桌子上工作——Ghostty 赢下这场比赛的两个原因与外观美化完全无关: 1. 没有闪屏。 听起来没什么,但当你每天对着终端屏幕盯八个小时时,就完全不一样了。iTerm2 在快速滚动时会有轻微的闪屏;调整窗口大小时会出现显示滞后;切换标签页时会有轻微的画面闪烁。Terminal.app 这些问题更严重。而由于 Ghostty使用 GPU 渲染,它提供的视觉流畅度绝对不会让人眼睛疲劳。当 Claude Code 输出200多行日志时,你滑动查看有哪些问题时,一款没有闪屏的终端和一款有闪屏的终端,体验可以说完全不可同日而语。 2. 支持超大缓存。 我设置了 scrollback-limit = 50000,即每个终端窗口有 50,000 行历史记录。Claude Code 输出日志时非常详细:生成代码、解释代码、运行代码、显示结果,偶尔还会附上一堆自言自语式的冗长分析。对于 iTerm2 或 Terminal.app 默认有限的缓冲区来说,这种频率的日志输出很容易就会丢失早期的上下文。而在 Ghostty 中,我可以随心所欲地向上滚动,甚至找到两小时前的操作记录,非常可靠。 除此之外,它还支持默认分屏(通过按 Cmd+D 快速创建),内建下拉式 Quake 风格终端(`Ctrl+``),但这些只是锦上添花。无闪屏、不丢日志历史才是它的两大核心亮点。 我的工作窗口布局 当我需要同时处理多个独立任务时,我的 Ghostty 窗口通常如下: ┌──────────────────────────────────┬──────────────────────────────────┐ │ │ │ │ Claude Code (worktree A) │ Claude Code (worktree B) │ │ feature/nueva-validacion │ chore/traducciones │ │ │ │ │ │ │ ├──────────────────────────────────┴──────────────────────────────────┤ │ │ │ 主仓库(main)—— 测试、构建、git log │ │ │ └─────────────────────────────────────────────────────────────────────┘ 上方两个 splits,每个运行一个 worktree 和对应的代理。下方是 main 仓库,用于运行测试、查看变更和在代理完成任务后进行合并。 ...

2026年3月11日 · Fernando

五个 Claude Code Worktree 技巧,彻底改变你的工作流

几周前,我写了一篇关于 git worktrees 的文章 —— 讲解了它们是什么,怎么创建,以及为什么它们比多次克隆代码库更好。这些只是基础。 但仅仅掌握这些基础只是成功的一半。而 Claude Code 不仅仅是在 worktree 的基础上运行,它还原生支持 worktree,拥有专门的参数、自动隔离功能,与 tmux 的深度集成。了解 worktree 存在和理解 Claude Code 如何利用它们的巨大差异,就像拥有一辆车并知道它有运动模式一样。 Claude Code 的创始人 Boris Cherny 发布了五个关于充分利用 worktree 的技巧。我把这些技巧全都测试了一遍。有些真的是大大优化了我的工作流,省去了我从今年一月起一直在用的小修小补(ñapa)。下面一起来看看吧。 技巧 1:--worktree —— 一个参数搞定一个 worktree 在经典的 worktree 工作流程中,你需要进行以下这些操作: 1 2 3 git worktree add ../mi-proyecto-feature -b feature/algo cd ../mi-proyecto-feature claude 总共三步。虽然不算太复杂,但得想目录名、记住语法,然后还得导航到新目录。如果你一天做五次这个操作,时间一长确实会觉得心累。 Claude Code 将整个过程简化成了一步: 1 claude --worktree 就是这样。Claude 会创建一个临时 worktree,将目录命名为随机生成的名字,自动切换到该目录,并启动会话。当你结束作业后,worktree 会自动清理干净。 ...

2026年3月11日 · Fernando

git-cliff: 自动生成的变更日志(几乎不费力)

107 个提交。从第一天开始就是完美的约定式提交。Feat、fix、refactor、chore — 所有内容都完美标记。那么 CHANGELOG 呢?空的。不存在。一个"明天再写"的文件,已经拖了两个月。 如果这听起来很熟悉,你不是一个人。手动编写变更日志是奥林匹克级别的苦差事。不是说它难 — 而是它乏味、重复,总有更紧急的事情要做。这就是为什么 git-cliff 存在的原因。 什么是 git-cliff(30 秒版本) 这是一个用 Rust 编写的变更日志生成器,它读取你的 git 提交,根据约定式提交解析它们,然后输出按版本和类型分组的 CHANGELOG.md。没有奇怪的依赖,没有插件,没有黑魔法。一个二进制文件,一个配置文件,就完了。 简单来说:你给它你的提交,它返回你拖延了几个月的文件。 1 2 brew install git-cliff git cliff --output CHANGELOG.md 这两行字面上就是开始所需的全部。如果你的提交遵循 类型: 描述 约定,git-cliff 无需额外配置就能理解它们。 真实案例:8 个版本的回溯性变更日志 在 Tokamak(我的监控 Claude 配额的菜单栏应用)中,我正好遇到了这个问题:107 个完美提交和一个空白的 CHANGELOG。应用已经是 v1.3.0 版本,但只有一个开始时的 v0.1 标签。 计划很简单: 步骤 1:在每个版本的提交上创建回溯性标签。 1 2 3 4 5 git tag v0.2.0 32950f4 # Dashboard, biblioteca, achievements v1 git tag v0.3.0 9c56985 # Rename a Tokamak, 6 idiomas git tag v1.0.0 a283490 # App Store: sandbox, privacy manifest git tag v1.3.0 6248bac # HEAD: multi-provider, fetch pipeline # ... 以此类推 步骤 2:运行 git-cliff。 ...

2026年2月22日 · Fernando

Git Worktrees:如何让多个AI助手同时工作而不相互冲突

单一checkout的瓶颈 我正在开发一个macOS菜单栏应用。我有三个功能在待办清单中:一个消耗量的迷你图表、原生通知和一个桌面小组件。这三个功能都是独立的。我打算用Claude Code来完成这三个功能。 问题是:Claude Code在一个目录中工作。一个目录有一个分支。而git checkout就像一个单车道的环岛:一次只能通过一个。 如果我想同时推进这三个功能,我的传统选择是: Stash乒乓球:git stash,切换分支,工作,git stash pop,祈祷没有冲突。重复直到发疯或退休,看哪个先到。 克隆仓库三次:可以工作,但现在我有三个.git/副本,三个独立的历史记录,每个都要执行git fetch。浪费。 接受串行生活:一个功能接着一个功能。安全,可预测,但慢得像手动归并排序。 都不好。但有第四个选择,自2015年以来git就有了,但几乎没人使用。 Worktrees:你已经安装的解决方案 一个worktree是第二个工作目录,共享同一个.git仓库。没有副本,没有克隆,没有黑魔法。 比喻:你的仓库是一个图书馆。到目前为止你有一张桌子,只能打开一本书。worktree是放更多桌子。每张桌子都打开着不同的书,但都从同一个书架取书。 ~/code/miapp/ ← 桌子1 (main) .git/ ← 图书馆(只有一个) ~/code/miapp-sparkline/ ← 桌子2 (feature/sparkline) .git ← 文件,不是文件夹(指向图书馆的指针) ~/code/miapp-notificaciones/ ← 桌子3 (feature/notifications) .git ← 另一个指针 每个目录都是一个完整的checkout,包含所有文件。你可以在一个中编译,在另一个中运行测试,在第三个中让你的AI助手工作。同时进行。 创建只需一行命令 从你的主仓库: 1 2 git worktree add ../miapp-sparkline -b feature/sparkline git worktree add ../miapp-notificaciones -b feature/notifications 就这样。两个新目录,每个在自己的分支上,共享整个git数据库。不需要克隆,不需要配置远程,不需要复制历史记录。 它们共享什么,不共享什么 这很重要。worktrees共享整个仓库:提交、分支、标签、远程、钩子、配置。如果你在sparkline的worktree中做了一个提交,你可以立即从notifications的worktree中看到它,不需要fetch或任何操作,因为它们是同一个数据库。 它们不共享: 磁盘上的文件(每张桌子都有自己的工作副本) 暂存区(每个都有自己的git add) HEAD(每个指向自己的分支) 简单来说:“我正在处理什么"的状态对每个worktree是私有的。其他一切都是公共的。 ...

2026年2月16日 · Fernando

3900万个密钥在GitHub上泄露,下一个可能就是你的

5分钟。就这么长时间。 一个安全研究员故意在GitHub的公开仓库中发布了一个AWS访问密钥,作为实验。 5分钟后,就有人在用它挖加密货币了。 5分钟。 有机器人24/7扫描GitHub,专门寻找这种东西:暴露的凭证。而且它们很快。比你意识到自己搞砸了要快得多。 数字很可怕 据GitHub统计,2024年有3900万个密钥在公开仓库中泄露。比前一年增加了67%。 专门扫描这类问题的GitGuardian仅在公开仓库中就发现了2370万个新密钥。最糟糕的是:2022年检测到的70%密钥在2024年仍然有效。 两年后。仍然能用。等着有人使用它们。 不只是无名小卒 丰田在GitHub上暴露了AWS凭证,这些凭证可以访问他们的车辆远程信息处理系统。培生集团因为有人在配置文件中留下GitLab令牌而丢失数据。酒店管理公司Otelier因为Bitbucket上暴露的凭证,看着8TB的S3数据被盗。 这不只发生在实习生身上。财富500强企业也会中招。 经典借口:“这只是我的个人项目” 是啊,当然。 问题是那个个人项目使用了和生产环境相同的OpenAI API密钥。或者你的Telegram机器人令牌。或者你的测试数据库凭证,哦惊喜,里面有真实数据因为"这样测试更容易"。 然后有一天你不假思索地执行git push。或者因为想展示给某人看而把仓库从私有改为公开。或者GitHub出现bug临时暴露了私有仓库(这种事发生过)。 然后你发现AWS账单从20欧元变成了2000欧元。一夜之间。 “但我立刻删除了” 又一个经典。 Git是版本控制系统。它的工作就是记住发生的所有事情。删除提交不会从历史记录中删除密钥。强制推送不会从分支中删除它。绝对不会从已经复制它的机器人那里删除。 一旦密钥接触到公开仓库,就算是被泄露了。句号。必须轮换。 灾难金字塔 这是典型项目中密钥管理的演进过程: 级别1:地狱 1 2 3 # config.py AWS_KEY = "AKIAIOSFODNN7EXAMPLE" AWS_SECRET = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" 直接写在代码里。已提交。在生产环境中。别笑,这真的存在。 级别2:炼狱 1 2 3 # .env (据说在.gitignore中) AWS_KEY=AKIAIOSFODNN7EXAMPLE AWS_SECRET=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY 好一些,但那个.env最终会出现在备份中,在你通过Slack发送的压缩包中,在你卖掉的硬盘中… 级别3:边缘地带 1 2 # 系统环境变量中的密钥 export AWS_KEY=... 可以,但你把它们存在哪里?便利贴?桌面上的secrets.txt文件?给自己发的Slack消息? ...

2026年2月5日 · Fernando

为什么 git status 这么慢啊?

缓慢的觉醒 你已经在数据科学项目上工作了一段时间。有二十个 notebook,一些图片,还有那种三个月前看起来不错的典型文件夹结构。 你执行 git status 想看看改了什么,然后… 等待。继续等待。在等待的时候你开始怀疑是不是电脑卡死了还是在沉思什么。 剧透:它不是在沉思。它在痛苦。 问题有名有姓 Git 不慢。你的仓库慢。 当你执行 git status 时,git 需要做两件看起来简单但实际很复杂的事情: 扫描整个文件树 看看有什么变化 比较每个文件 与保存的版本 在普通仓库里这是瞬间完成的。但 Jupyter notebook 是伪装成文档的 JSON。而且不是普通的 JSON:是包含代码、输出、base64 编码图片、内核元数据,以及设计这个格式的人能想到的所有东西的 JSON。 一个带几张图表的"小" notebook 可能有几兆大小。乘以二十个 notebook,你就有了一个每次看它都在呻吟的仓库。 如果你还重命名了文件夹… git 会理解为"你删除了 50 个文件然后创建了 50 个新文件"。保证有趣。 解决方案 1:给你的仓库配个门卫 第一个解决方案优雅得让人恨不得早点知道。 叫做 FSMonitor,工作原理是:不让 git 每次都扫描整个仓库,而是操作系统告诉它哪些文件变了。 用人话说:就像在门口有个门卫告诉你"只有小王进来了",而不用每次都检查整个宾客名单。 激活方法: 1 2 git config core.fsmonitor true git config core.untrackedcache true 搞定。就这样。 激活后第一次执行 git status 还是会花同样(或更多)时间,因为要初始化缓存。但从第二次开始… 魔法。 ...

2026年1月19日 · Fernando