<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Granda | Ideas &amp; Code</title><link>https://granda.org/zh/</link><description>Recent content on Granda | Ideas &amp; Code</description><generator>Hugo</generator><language>zh</language><lastBuildDate>Fri, 13 Mar 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://granda.org/zh/index.xml" rel="self" type="application/rss+xml"/><item><title>你停着的特斯拉就是一个数据中心</title><link>https://granda.org/zh/2026/03/13/%E4%BD%A0%E5%81%9C%E7%9D%80%E7%9A%84%E7%89%B9%E6%96%AF%E6%8B%89%E5%B0%B1%E6%98%AF%E4%B8%80%E4%B8%AA%E6%95%B0%E6%8D%AE%E4%B8%AD%E5%BF%83/</link><pubDate>Fri, 13 Mar 2026 00:00:00 +0000</pubDate><guid>https://granda.org/zh/2026/03/13/%E4%BD%A0%E5%81%9C%E7%9D%80%E7%9A%84%E7%89%B9%E6%96%AF%E6%8B%89%E5%B0%B1%E6%98%AF%E4%B8%80%E4%B8%AA%E6%95%B0%E6%8D%AE%E4%B8%AD%E5%BF%83/</guid><description>&lt;p&gt;你的车95%的时间都停着不动。车里装着一块每秒能执行300到500万亿次运算的芯片，连接着冷却系统、电源转换装置和蜂窝无线电模块。它什么都不做。&lt;/p&gt;
&lt;p&gt;特斯拉和xAI想改变这一现状。3月11日，埃隆·马斯克&lt;a href="https://www.cnbc.com/2026/03/11/musk-unveils-joint-tesla-xai-project-macrohard.html"&gt;发布了&amp;quot;Macrohard&amp;quot;&lt;/a&gt;——内部代号Digital Optimus——这是一个将停驻的特斯拉变成个人AI智能体的联合项目。不是聊天机器人，而是能盯着你的屏幕、控制鼠标键盘、真正干活的智能体。&lt;/p&gt;
&lt;p&gt;这个名字是在明戳微软。官方声称该系统能够&amp;quot;模拟整个公司的职能&amp;quot;——有些夸大其词，但底层架构是真实的，硬件也已大规模部署到位。&lt;/p&gt;
&lt;h2 id="硬件早已就位"&gt;硬件早已就位&lt;/h2&gt;
&lt;p&gt;特斯拉在美国路上行驶的车辆中，大约有400到500万辆搭载了AI3（前身为HW3）或AI4芯片。AI3算力达到&lt;a href="https://x.com/convequity/status/1802008991314461176"&gt;144 TOPS&lt;/a&gt;，AI4达到&lt;a href="https://x.com/pbeisel/status/1950314514580459698"&gt;300-500 TOPS&lt;/a&gt;，预计2026年底推出的AI5则将跃升至&lt;a href="https://x.com/pbeisel/status/1950314514580459698"&gt;2,000-2,500 TOPS&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;这些不是通用CPU，而是专为神经网络推理打造的加速器——以低功耗、被动冷却的方式运行视觉模型来实现自动驾驶。同样的特性让它们既能处理行驶中的摄像头画面，也能在停车场运行AI模型。&lt;/p&gt;
&lt;p&gt;马斯克在特斯拉2025年第三季度财报电话会议上&lt;a href="https://www.tomshardware.com/tech-industry/elon-musk-says-idling-tesla-cars-could-create-massive-100-million-vehicle-strong-computer-for-ai-bored-vehicles-could-offer-100-gigawatts-of-distributed-compute-power"&gt;提出了这个构想&lt;/a&gt;：如果1亿辆车每辆具备1kW的推理能力，那就是1000亿瓦的分布式算力。冷却和电源转换系统已经集成在车辆中，无需另建数据中心。&lt;/p&gt;
&lt;h2 id="两台电脑不是一台"&gt;两台电脑，不是一台&lt;/h2&gt;
&lt;p&gt;大多数人以为特斯拉只有一台电脑，其实它有两台。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AI芯片&lt;/strong&gt;（AI3/AI4/AI5）是推理加速器，专为神经网络前向传播而生，是整个系统的大脑，负责运行决策所需的智能体模型。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;车载娱乐系统&lt;/strong&gt;则是一台&lt;a href="https://videocardz.com/newz/tesla-car-computer-features-zen-ryzen-embedded-apu-and-discrete-navi-23-gpu"&gt;完整的AMD Ryzen工作站&lt;/a&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AMD Ryzen嵌入式处理器，4核Zen+，主频3.8 GHz&lt;/li&gt;
&lt;li&gt;8 GB内存（Model 3/Y）或16 GB（Model S/X）&lt;/li&gt;
&lt;li&gt;AMD Navi 23独立GPU（RDNA 2架构）——10 TFLOPS，与PS5同系列架构&lt;/li&gt;
&lt;li&gt;128-256 GB存储&lt;/li&gt;
&lt;li&gt;液冷散热&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这可不是普通的车载音响，而是一台液冷Linux机器，配有独立GPU。特斯拉装上Navi 23是为了让你在中控屏上玩《赛博朋克2077》。但当车子停着、没人玩游戏时，这就是闲置算力。&lt;/p&gt;
&lt;p&gt;智能体不需要云端虚拟机——车子本身就是服务器。AI芯片运行模型，AMD系统在容器中运行无头浏览器，处理Gmail、Google Sheets、Slack等应用。液冷散热可应对整夜的持续工作负载，不会因过热而降频。&lt;/p&gt;
&lt;p&gt;离开车辆的只有发往目标网页应用的HTTPS流量——和你在笔记本上查邮件产生的流量没什么两样。你的数据不会流经特斯拉或xAI的服务器，推理在本地进行，工作空间也在本地。&lt;/p&gt;
&lt;h2 id="架构系统1与系统2"&gt;架构：系统1与系统2&lt;/h2&gt;
&lt;p&gt;Macrohard将推理分为两层：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;系统1（特斯拉AI芯片）&lt;/strong&gt;——快速、反应式处理。车载模型负责实时观察屏幕、控制鼠标移动和键盘输入，是直觉层，负责模式匹配、视觉解析和即时响应。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;系统2（xAI的Grok）&lt;/strong&gt;——高层推理。规划、多步骤决策和情境理解，当任务需要深度思考时在xAI云端运行。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;车辆在本地处理廉价、快速的推理，昂贵的推理则交给云端。这与FSD的混合架构如出一辙——车辆以毫秒级延迟在本地处理摄像头画面，而复杂的路线规划则可延迟到网络端处理。&lt;/p&gt;
&lt;p&gt;对于计算机操作任务，这意味着智能体可以在本地跟踪屏幕状态、处理常规交互，同时将&amp;quot;是否应该批准这张发票&amp;quot;或&amp;quot;如何回复这封邮件&amp;quot;这类判断交给Grok。&lt;/p&gt;
&lt;h2 id="不是聊天机器人而是工作者"&gt;不是聊天机器人，而是工作者&lt;/h2&gt;
&lt;p&gt;关键在于这个系统做什么。它不是在回答问题，而是在执行任务。&lt;/p&gt;
&lt;p&gt;当你的特斯拉停着时，Digital Optimus可以：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;处理邮件并起草回复&lt;/li&gt;
&lt;li&gt;填写电子表格&lt;/li&gt;
&lt;li&gt;操作网页应用&lt;/li&gt;
&lt;li&gt;完成多步骤工作流&lt;/li&gt;
&lt;li&gt;处理重复性数据录入&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;每辆车独立执行车主的任务，无需将单次推理调用分散到多辆车上——计算机操作任务天然具有高度并行性。一辆车，一个智能体，一项任务。规模来自车队数量，而非互联带宽。&lt;/p&gt;
&lt;p&gt;这一点很重要，因为计算机操作任务的延迟容忍度相当宽松。一个表单填写智能体每次操作花30秒依然有用——你不是在等实时响应，而是在把工作委托出去，让它趁你睡觉时运转。&lt;/p&gt;
&lt;h2 id="实际使用体验"&gt;实际使用体验&lt;/h2&gt;
&lt;p&gt;不谈架构图，来看看日常体验。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;特斯拉App是控制平面。&lt;/strong&gt;&amp;ldquo;智能体&amp;quot;标签页与现有的充电、气候、哨兵模式控件并列显示，你可以用它：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;排入任务&lt;/strong&gt;——&amp;ldquo;处理我的收件箱&amp;rdquo;、&amp;ldquo;核对上周的收据&amp;rdquo;，或设置&amp;quot;每天早上6点自动整理邮件&amp;quot;等周期性规则&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;关联账户&lt;/strong&gt;——为Gmail、Google Drive、Microsoft 365、Slack进行OAuth授权&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;设置限制&lt;/strong&gt;——最低电量阈值、仅WiFi模式、工作时间段&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;查看结果&lt;/strong&gt;——查看智能体的操作记录，批准或拒绝操作&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;你躺在床上，打开特斯拉App，输入&amp;quot;帮我提交上周出差的报销单&amp;rdquo;，点击提交，然后入睡。车停在车库，连着WiFi，电量80%，它接手这项任务。&lt;/p&gt;
&lt;p&gt;AI芯片加载智能体模型，AMD系统在容器中启动无头浏览器。智能体打开你的邮件，找到收据附件，导航到公司的报销工具，填好表单，附上收据，保存草稿等待你审核。&lt;/p&gt;
&lt;p&gt;早上，推送通知：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;智能体在停车期间完成了3项任务&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;收件箱整理：已处理42封邮件，7封需要你查看 → [查看]&lt;/li&gt;
&lt;li&gt;报销单：12张收据已分类，草稿待审 → [批准 / 修改]&lt;/li&gt;
&lt;li&gt;日历：2个冲突已解决，1个需要你处理 → [查看]&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;你点进每项任务。智能体展示了带截图的分步操作日志——就像在回看屏幕录像。你能看到它做了什么、为什么这么做、按什么顺序执行。你批准报销单，调整一封邮件草稿，解决日历冲突。八小时的智能体工作，只需三分钟审核。&lt;/p&gt;</description></item><item><title>将视觉QA作为CI流水线阶段</title><link>https://granda.org/zh/2026/02/06/%E5%B0%86%E8%A7%86%E8%A7%89qa%E4%BD%9C%E4%B8%BAci%E6%B5%81%E6%B0%B4%E7%BA%BF%E9%98%B6%E6%AE%B5/</link><pubDate>Fri, 06 Feb 2026 00:00:00 +0000</pubDate><guid>https://granda.org/zh/2026/02/06/%E5%B0%86%E8%A7%86%E8%A7%89qa%E4%BD%9C%E4%B8%BAci%E6%B5%81%E6%B0%B4%E7%BA%BF%E9%98%B6%E6%AE%B5/</guid><description>&lt;p&gt;上个月我合并了一个PR。代码审查看起来不错。测试通过了。然后我在手机上打开网站,侧边栏完全坏了。&lt;/p&gt;
&lt;p&gt;修复很简单——缺少一个媒体查询。一旦你真正查看移动视图,bug就很明显了。没人看。&lt;/p&gt;
&lt;p&gt;所以我添加了一个会看的流水线阶段。&lt;/p&gt;
&lt;p&gt;我打开一个GitHub issue,上面写着:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;实现手动输入选项以添加客户。点击时,打开一个宽幅滑出抽屉,其中包含创建新客户的表单。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;一次提交后,PR带着30多张截图到达,证明每个状态在每个视口下都能工作。零手动测试。唯一的努力是编写功能描述。&lt;/p&gt;
&lt;h2 id="概念"&gt;概念&lt;/h2&gt;
&lt;p&gt;每次推送到PR时,GitHub Actions工作流会:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;从PR分支启动Docker Compose堆栈(Django + Postgres)&lt;/li&gt;
&lt;li&gt;运行迁移并植入测试用户&lt;/li&gt;
&lt;li&gt;将本地URL交给带有Playwright MCP(无头Chromium)的Claude Code&lt;/li&gt;
&lt;li&gt;基于PR差异执行交互元素&lt;/li&gt;
&lt;li&gt;在三个视口截取每个状态&lt;/li&gt;
&lt;li&gt;将结果作为PR评论发布&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Claude Code控制浏览器。Docker Compose提供应用。GitHub Actions将它们联系在一起。审查者无需在本地运行任何东西就能看到功能证明。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-mermaid" data-lang="mermaid"&gt;%%{init: {&amp;#34;flowchart&amp;#34;: {&amp;#34;subGraphTitleMargin&amp;#34;: {&amp;#34;top&amp;#34;: 3, &amp;#34;bottom&amp;#34;: 10}}} }%%
graph TD
 A[&amp;#34;PR推送&amp;#34;] --&amp;gt; B

 subgraph GHA[&amp;#34;GitHub Actions Runner&amp;#34;]
 B[&amp;#34;Checkout + Docker Compose&amp;#34;] --&amp;gt; C[&amp;#34;迁移 + 种子数据&amp;#34;]
 C --&amp;gt; Agent

 subgraph Agent[&amp;#34;Claude Code + Playwright&amp;#34;]
 direction LR
 D[&amp;#34;读取PR差异&amp;#34;] --&amp;gt; E[&amp;#34;映射文件 → URLs&amp;#34;]
 E --&amp;gt; F[&amp;#34;登录 + 导航&amp;#34;]
 F --&amp;gt; G[&amp;#34;截图 ×3视口&amp;#34;]
 end
 end

 Agent --&amp;gt; H[&amp;#34;PR评论&amp;#34;]

 style GHA fill:transparent,stroke:#888
 style Agent fill:transparent,stroke:#888
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;工作流本身很直接:&lt;/p&gt;</description></item><item><title>Agent Trace 是为谁而设计的?</title><link>https://granda.org/zh/2026/01/30/agent-trace-%E6%98%AF%E4%B8%BA%E8%B0%81%E8%80%8C%E8%AE%BE%E8%AE%A1%E7%9A%84/</link><pubDate>Fri, 30 Jan 2026 00:00:00 +0000</pubDate><guid>https://granda.org/zh/2026/01/30/agent-trace-%E6%98%AF%E4%B8%BA%E8%B0%81%E8%80%8C%E8%AE%BE%E8%AE%A1%E7%9A%84/</guid><description>&lt;p&gt;Cursor 发布了 &lt;a href="https://github.com/cursor/agent-trace"&gt;Agent Trace&lt;/a&gt;,这是一个开放规范,用于追踪仓库中哪些代码是由 LLM 编写的。它记录模型、工具、对话和精确的行范围——所有内容都追加到项目中的 JSONL 文件中。&lt;/p&gt;
&lt;p&gt;推介词:&amp;ldquo;随着代理编写更多代码,理解什么来自 AI 而非人类变得很重要。&amp;rdquo;&lt;/p&gt;
&lt;p&gt;我花时间阅读了规范和参考实现。工程设计很扎实——清晰的架构、深思熟虑的可扩展性、良好的合作伙伴列表(Amp、Amplitude、Cloudflare、Cognition、Google、Vercel)。但我一直回到一个问题:你用这些数据&lt;em&gt;做&lt;/em&gt;什么?&lt;/p&gt;
&lt;h2 id="它捕获了什么"&gt;它捕获了什么&lt;/h2&gt;
&lt;p&gt;每次 LLM 编辑文件时,都会触发一个钩子并记录一条追踪:哪个模型、哪个工具、哪些行、哪个对话。参考实现处理来自 Cursor 和 Claude Code 的事件:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 来自参考钩子——事件通过 stdin 流入
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;appendTrace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;createTrace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ai&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;file_path&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;model&lt;/span&gt;: &lt;span class="kt"&gt;input.model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;rangePositions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;transcript&lt;/span&gt;: &lt;span class="kt"&gt;input.transcript_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;conversation_id&lt;/span&gt;: &lt;span class="kt"&gt;input.conversation_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;generation_id&lt;/span&gt;: &lt;span class="kt"&gt;input.generation_id&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;规范定义了四种贡献者类型——&lt;code&gt;human&lt;/code&gt;、&lt;code&gt;ai&lt;/code&gt;、&lt;code&gt;mixed&lt;/code&gt;、&lt;code&gt;unknown&lt;/code&gt;——并支持行级归属,使用内容哈希来追踪移动的代码。它是供应商中立的、VCS 无关的,并且可以通过命名空间元数据进行扩展。&lt;/p&gt;
&lt;p&gt;作为数据格式,它设计得很好。问题是它能实现什么。&lt;/p&gt;
&lt;h2 id="归属挑战"&gt;归属挑战&lt;/h2&gt;
&lt;p&gt;规范将作者身份建模为一种分类。但 LLM 辅助编码是一场对话。你描述你想要什么。LLM 生成一些东西。你编辑其中一半,拒绝一个函数,要求修订,接受第二次尝试,然后手动修复边缘情况。后来,另一个 LLM 重构了整个块。&lt;/p&gt;
&lt;p&gt;谁写了那段代码?人类和 LLM 作者身份之间的界限是模糊的,而且变得越来越模糊。大多数真实代码最终都会是 &lt;code&gt;mixed&lt;/code&gt;,如果几乎所有东西都是 &lt;code&gt;mixed&lt;/code&gt;,分类就没有告诉你太多信息。&lt;/p&gt;
&lt;p&gt;行级归属也有保质期问题。追踪说&amp;quot;Claude 在提交 &lt;code&gt;abc123&lt;/code&gt; 时写了第 10-50 行。&amp;ldquo;两次提交后,有人重新格式化了该块或从中提取了一个函数。规范的答案是通过 &lt;code&gt;git blame&lt;/code&gt; 链接,内容哈希可以帮助追踪移动的代码。但在使用 rebase 和 squash-merge 的工作流中,链条会断裂。这些是困难的问题——早期 RFC 应该提出的那种问题。&lt;/p&gt;
&lt;h2 id="缺失的行动"&gt;缺失的行动&lt;/h2&gt;
&lt;p&gt;规范明确否认了明显的用途:不用于代码所有权,不用于质量评估,不用于训练数据来源。它说&amp;quot;透明度&amp;rdquo;。但透明度是手段,不是目的。&lt;/p&gt;
&lt;p&gt;如果代码通过了审查和测试,因为 LLM 写的就有什么改变吗?如果它有 bug,无论如何你都会修复它。规范从未将归属与具体行动联系起来。数据进去了,但没有定义获取答案的方法。这就是差距——不是格式,而是用例。&lt;/p&gt;
&lt;h2 id="有趣的地方"&gt;有趣的地方&lt;/h2&gt;
&lt;p&gt;这是我认为 Agent Trace 实际指向的内容,即使规范还没有说出来。&lt;/p&gt;</description></item><item><title>懒惰开发者的富链接</title><link>https://granda.org/zh/2026/01/10/%E6%87%92%E6%83%B0%E5%BC%80%E5%8F%91%E8%80%85%E7%9A%84%E5%AF%8C%E9%93%BE%E6%8E%A5/</link><pubDate>Sat, 10 Jan 2026 00:00:00 +0000</pubDate><guid>https://granda.org/zh/2026/01/10/%E6%87%92%E6%83%B0%E5%BC%80%E5%8F%91%E8%80%85%E7%9A%84%E5%AF%8C%E9%93%BE%E6%8E%A5/</guid><description>&lt;p&gt;当我在Twitter或Slack上分享博客链接时,它显示为纯文本。没有预览图片。只有一个像&lt;a href="https://granda.org/en/2026/01/02/claude-code-on-the-go/"&gt;granda.org/en/2026/01/02/claude-code-on-the-go/&lt;/a&gt;这样的URL。&lt;/p&gt;
&lt;p&gt;我需要Open Graph图片。标准方法:为每篇文章手动创建一个1200x630的图片。这很繁琐。我让Claude自动化它。&lt;/p&gt;
&lt;div class="desktop-only"&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-mermaid" data-lang="mermaid"&gt;flowchart LR
 Push[git push] --&amp;gt; GHA[GitHub Actions]
 GHA --&amp;gt; Hugo[Hugo Server]
 GHA --&amp;gt; PW[Playwright]
 PW --&amp;gt;|screenshot| Hugo
 PW --&amp;gt; IMG[OG Image]
 IMG --&amp;gt; Commit[git commit]
 Commit --&amp;gt; Deploy[Deploy]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="mobile-only"&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-mermaid" data-lang="mermaid"&gt;flowchart TB
 Push[git push] --&amp;gt; GHA[GitHub Actions]
 GHA --&amp;gt; Hugo[Hugo Server]
 GHA --&amp;gt; PW[Playwright]
 PW --&amp;gt;|screenshot| Hugo
 PW --&amp;gt; IMG[OG Image]
 IMG --&amp;gt; Commit[git commit]
 Commit --&amp;gt; Deploy[Deploy]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="设置"&gt;设置&lt;/h2&gt;
&lt;p&gt;我向Claude说明了问题:文章需要社交预览图片,但我不想手动创建它们。截取文章内容的屏幕截图,将其保存为OG图片,自动更新前置元数据。&lt;/p&gt;
&lt;h2 id="claude构建了什么"&gt;Claude构建了什么&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;组件&lt;/th&gt;
 &lt;th&gt;用途&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;generate-og-image.js&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;用于截图文章的Playwright脚本&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;generate-og-images.yml&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;文章更改时触发的GitHub Action&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;baseof.html&lt;/code&gt;更改&lt;/td&gt;
 &lt;td&gt;条件性og:image元标签&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Playwright脚本启动无头Chrome,导航到文章,强制浅色模式,隐藏页眉和页脚,并以1200x630截图:&lt;/p&gt;</description></item><item><title>取消订阅</title><link>https://granda.org/zh/unsubscribe/</link><pubDate>Sat, 10 Jan 2026 00:00:00 +0000</pubDate><guid>https://granda.org/zh/unsubscribe/</guid><description>&lt;p id="unsubscribe-message"&gt;处理中...&lt;/p&gt;
&lt;script&gt;
(function() {
 const params = new URLSearchParams(window.location.search);
 const msg = document.getElementById('unsubscribe-message');

 if (params.get('success') === 'true') {
 msg.textContent = '您已成功取消订阅新闻通讯。';
 } else if (params.get('error') === 'missing') {
 msg.textContent = '错误:未提供取消订阅令牌。';
 } else if (params.get('error') === 'invalid') {
 msg.textContent = '错误:无效的取消订阅链接。';
 } else {
 msg.textContent = '错误:发生未知错误。';
 }
})();
&lt;/script&gt;</description></item><item><title>我的QA工程师是一个LLM</title><link>https://granda.org/zh/2026/01/09/%E6%88%91%E7%9A%84qa%E5%B7%A5%E7%A8%8B%E5%B8%88%E6%98%AF%E4%B8%80%E4%B8%AAllm/</link><pubDate>Fri, 09 Jan 2026 00:00:00 +0000</pubDate><guid>https://granda.org/zh/2026/01/09/%E6%88%91%E7%9A%84qa%E5%B7%A5%E7%A8%8B%E5%B8%88%E6%98%AF%E4%B8%80%E4%B8%AAllm/</guid><description>&lt;p&gt;Claude可以点击按钮。&lt;/p&gt;
&lt;p&gt;这听起来很简单,但它改变了我构建UI的方式。使用Playwright MCP,Claude不仅仅是编写代码——它打开浏览器,导航到localhost,并验证事物实际运行。它捕获我在代码审查中会错过的bug。&lt;/p&gt;
&lt;h2 id="设置"&gt;设置&lt;/h2&gt;
&lt;p&gt;Playwright MCP为Claude提供浏览器自动化。我用无头Chromium运行它:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;mcpServers&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;playwright&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;npx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;args&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;@anthropic-ai/mcp-server-playwright&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;--headless&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;现在Claude可以导航、点击、输入和截图。它看到用户看到的东西。&lt;/p&gt;
&lt;div class="desktop-only"&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-mermaid" data-lang="mermaid"&gt;flowchart LR
 Claude([Claude Code]) --&amp;gt;|browser_snapshot| PW[Playwright MCP]
 PW --&amp;gt; Browser[Headless Chrome]
 Browser --&amp;gt; App[localhost:1313]
 Browser -.-&amp;gt;|screenshot| Issue[(GitHub Issue)]
 Issue -.-&amp;gt;|visual history| PR[Pull Request]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="mobile-only"&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-mermaid" data-lang="mermaid"&gt;flowchart TB
 Claude([Claude Code]) --&amp;gt;|browser_snapshot| PW[Playwright MCP]
 PW --&amp;gt; Browser[Headless Chrome]
 Browser --&amp;gt; App[localhost:1313]
 Browser -.-&amp;gt;|screenshot| Issue[(GitHub Issue)]
 Issue -.-&amp;gt;|visual history| PR[Pull Request]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;流程: Claude Code → Playwright MCP → 浏览器 → 截图 → GitHub Issues → PR&lt;/em&gt;&lt;/p&gt;</description></item><item><title>用Claude构建我自己的新闻通讯</title><link>https://granda.org/zh/2026/01/07/%E7%94%A8claude%E6%9E%84%E5%BB%BA%E6%88%91%E8%87%AA%E5%B7%B1%E7%9A%84%E6%96%B0%E9%97%BB%E9%80%9A%E8%AE%AF/</link><pubDate>Wed, 07 Jan 2026 00:00:00 +0000</pubDate><guid>https://granda.org/zh/2026/01/07/%E7%94%A8claude%E6%9E%84%E5%BB%BA%E6%88%91%E8%87%AA%E5%B7%B1%E7%9A%84%E6%96%B0%E9%97%BB%E9%80%9A%E8%AE%AF/</guid><description>&lt;p&gt;Hacker News流量高峰的第二天。四万访客，没有办法再次联系他们。我需要一个新闻通讯注册表单。&lt;/p&gt;
&lt;p&gt;我看了Buttondown、Beehiiv、Substack、ConvertKit。都太复杂了。我只需要收集电子邮件。我不需要营销活动、分析或订阅者管理。而且我想拥有自己的数据。&lt;/p&gt;
&lt;p&gt;所以我让Claude来构建它。&lt;/p&gt;
&lt;div class="desktop-only"&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-mermaid" data-lang="mermaid"&gt;flowchart LR
 User([User]) --&amp;gt; Form[Newsletter Form]
 Form --&amp;gt;|POST /api/subscribe| Worker[Cloudflare Worker]
 Worker --&amp;gt; KV[(Cloudflare KV)]
 KV -.-&amp;gt;|Daily sync| GHA[GitHub Actions]
 GHA -.-&amp;gt; Repo[(subscribers.jsonl)]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="mobile-only"&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-mermaid" data-lang="mermaid"&gt;flowchart TB
 User([User]) --&amp;gt; Form[Newsletter Form]
 Form --&amp;gt;|POST /api/subscribe| Worker[Cloudflare Worker]
 Worker --&amp;gt; KV[(Cloudflare KV)]
 KV -.-&amp;gt;|Daily sync| GHA[GitHub Actions]
 GHA -.-&amp;gt; Repo[(subscribers.jsonl)]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="设置"&gt;设置&lt;/h2&gt;
&lt;p&gt;我通过环境变量给Claude提供了一个Cloudflare API令牌，并描述了我想要的东西：一个收集电子邮件并将其存储在我控制的地方的表单。&lt;/p&gt;
&lt;p&gt;不到30分钟后，我就有了一个可工作的新闻通讯。&lt;/p&gt;
&lt;h2 id="claude构建了什么"&gt;Claude构建了什么&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;组件&lt;/th&gt;
 &lt;th&gt;技术&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;表单&lt;/td&gt;
 &lt;td&gt;HTML + vanilla JS&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;后端&lt;/td&gt;
 &lt;td&gt;Cloudflare Worker&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;存储&lt;/td&gt;
 &lt;td&gt;Cloudflare KV&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;同步&lt;/td&gt;
 &lt;td&gt;GitHub Actions&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;表单是一个发送到&lt;code&gt;/api/subscribe&lt;/code&gt;的Hugo partial：&lt;/p&gt;</description></item><item><title>随时随地使用Claude Code</title><link>https://granda.org/zh/2026/01/02/%E9%9A%8F%E6%97%B6%E9%9A%8F%E5%9C%B0%E4%BD%BF%E7%94%A8claude-code/</link><pubDate>Fri, 02 Jan 2026 00:00:00 +0000</pubDate><guid>https://granda.org/zh/2026/01/02/%E9%9A%8F%E6%97%B6%E9%9A%8F%E5%9C%B0%E4%BD%BF%E7%94%A8claude-code/</guid><description>&lt;p&gt;我在手机上并行运行六个Claude Code代理。没有笔记本电脑,没有台式机——只有iOS上的Termius和云虚拟机。&lt;/p&gt;
&lt;h2 id="设置"&gt;设置&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-mermaid" data-lang="mermaid"&gt;flowchart LR
 A[Phone] --&amp;gt;|Termius + mosh| B[Tailscale VPN]
 B --&amp;gt; C[Vultr VM]
 C --&amp;gt; D[Claude Code]
 D --&amp;gt;|PreToolUse hook| E[Poke webhook]
 E --&amp;gt;|Push notification| A
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;流程是:启动任务,将手机放入口袋,当Claude需要输入时收到通知。从任何地方进行异步开发。&lt;/p&gt;
&lt;h2 id="基础设施"&gt;基础设施&lt;/h2&gt;
&lt;p&gt;硅谷的Vultr虚拟机:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Spec&lt;/th&gt;
 &lt;th&gt;Value&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Instance&lt;/td&gt;
 &lt;td&gt;vhf-8c-32gb&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Cost&lt;/td&gt;
 &lt;td&gt;$0.29/小时 (运行时约$7/天)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Access&lt;/td&gt;
 &lt;td&gt;仅Tailscale (无公共SSH)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;我只在工作时付费。两个脚本管理生命周期:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;vm-start &lt;span class="c1"&gt;# Start VM, wait for Tailscale, connect via mosh&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;vm-stop &lt;span class="c1"&gt;# Halt VM&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;我还有一个直接调用Vultr API的iOS快捷指令——在我甚至打开Termius之前就从手机启动虚拟机。&lt;/p&gt;
&lt;p&gt;虚拟机的公共IP没有SSH监听器。所有访问都通过Tailscale的私有网络。深度防御:云防火墙阻止除Tailscale协调之外的所有内容,本地nftables作为备份,fail2ban以防万一。&lt;/p&gt;
&lt;h2 id="移动终端"&gt;移动终端&lt;/h2&gt;
&lt;p&gt;Termius在iOS/Android上处理SSH和mosh。Mosh是关键——它能在网络切换中幸存。从WiFi切换到蜂窝网络,穿过信号盲区,让手机进入睡眠状态。连接持续存在。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mosh --ssh&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ssh -p 47892&amp;#34;&lt;/span&gt; mgranda@100.100.100.100
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一个问题:mosh不转发SSH代理。对于需要GitHub身份验证的git操作,我在tmux中使用常规SSH。&lt;/p&gt;
&lt;h2 id="会话持久性"&gt;会话持久性&lt;/h2&gt;
&lt;p&gt;Shell在登录时自动附加到tmux。关闭Termius,几小时后重新打开,一切都还在。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# In .zshrc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -z &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$TMUX&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; tmux attach -t main 2&amp;gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; tmux new -s main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;多个Claude代理在并行窗口中运行。&lt;code&gt;C-a c&lt;/code&gt;用于新窗口,&lt;code&gt;C-a n&lt;/code&gt;用于切换。在手机键盘上效果很好。&lt;/p&gt;</description></item><item><title>让AI来做</title><link>https://granda.org/zh/2025/12/28/%E8%AE%A9ai%E6%9D%A5%E5%81%9A/</link><pubDate>Sun, 28 Dec 2025 00:00:00 +0000</pubDate><guid>https://granda.org/zh/2025/12/28/%E8%AE%A9ai%E6%9D%A5%E5%81%9A/</guid><description>&lt;p&gt;我需要一台开发服务器：带SSH访问和开发工具的VM。我向Claude Code描述了我想要的，让它处理配置。&lt;/p&gt;
&lt;h2 id="提示"&gt;提示&lt;/h2&gt;
&lt;p&gt;我要求一台Vultr VM，配置8核和32GB内存，只能通过Tailscale访问，具有能在网络中断后恢复的持久会话。&lt;/p&gt;
&lt;h2 id="claude-code构建的内容"&gt;Claude Code构建的内容&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;1. 通过Vultr API配置VM&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;它创建了一个8核/32GB的Ubuntu实例，等待IP可用，然后以root身份SSH连接。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. 强化SSH&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-conf" data-lang="conf"&gt;Port 49152 # 随机高端口
PermitRootLogin no
PasswordAuthentication no
ListenAddress 100.x.x.x # 仅Tailscale接口
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;仅基于密钥的认证，仅在Tailscale接口上监听。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. 设置三层防火墙&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;UFW&lt;/strong&gt;：拒绝除Tailscale子网外的所有传入连接&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;fail2ban&lt;/strong&gt;：登录尝试失败后自动封禁IP&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vultr防火墙&lt;/strong&gt;：在虚拟化程序级别阻止所有连接&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;4. 安装启用了SSH的Tailscale&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -fsSL https://tailscale.com/install.sh &lt;span class="p"&gt;|&lt;/span&gt; sh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tailscale up --ssh --authkey&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$TAILSCALE_KEY&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这通过Tailscale的内置SSH服务器创建了第二条SSH路径，独立于OpenSSH。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. 安装开发栈&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Node.js（通过nvm）、Python（通过pyenv）、Docker和常用工具。配置Docker无需sudo运行。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;6. 使用tmux设置持久会话&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;一个启动脚本，自动重新连接到现有会话，这样网络中断就不会终止正在运行的进程。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;7. 创建本地管理脚本&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在我的笔记本电脑上创建&lt;code&gt;dev-start&lt;/code&gt;和&lt;code&gt;dev-stop&lt;/code&gt;脚本，通过Vultr API启动和停止VM。&lt;/p&gt;
&lt;h2 id="锁定"&gt;锁定&lt;/h2&gt;
&lt;p&gt;完成后，Claude Code通过尝试以root身份SSH连接来验证root登录是否已禁用。登录失败。fail2ban注意到失败的尝试并封禁了我们。&lt;/p&gt;
&lt;p&gt;Claude Code已将Tailscale SSH设置为备用路径。它使用&lt;code&gt;tailscale ssh&lt;/code&gt;重新进入并执行：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fail2ban-client &lt;span class="nb"&gt;set&lt;/span&gt; sshd unbanip 100.x.x.x
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="配置"&gt;配置&lt;/h2&gt;
&lt;p&gt;你需要：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Claude Code（或具有工具使用能力的类似AI）&lt;/li&gt;
&lt;li&gt;云提供商账户（Vultr、DigitalOcean、AWS等）&lt;/li&gt;
&lt;li&gt;Tailscale账户&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;将API密钥存储为环境变量并按名称引用它们（例如&lt;code&gt;$VULTR_API_KEY&lt;/code&gt;），这样机密就不会出现在对话中。&lt;/p&gt;</description></item><item><title>使用Claude和GitHub Actions自动翻译博客</title><link>https://granda.org/zh/2025/12/23/%E4%BD%BF%E7%94%A8claude%E5%92%8Cgithub-actions%E8%87%AA%E5%8A%A8%E7%BF%BB%E8%AF%91%E5%8D%9A%E5%AE%A2/</link><pubDate>Tue, 23 Dec 2025 00:00:00 +0000</pubDate><guid>https://granda.org/zh/2025/12/23/%E4%BD%BF%E7%94%A8claude%E5%92%8Cgithub-actions%E8%87%AA%E5%8A%A8%E7%BF%BB%E8%AF%91%E5%8D%9A%E5%AE%A2/</guid><description>&lt;p&gt;我写的每篇文章都会自动翻译。Claude处理翻译，将结果提交到main，翻译版本与原文一起部署。&lt;/p&gt;
&lt;h2 id="流程"&gt;流程&lt;/h2&gt;
&lt;p&gt;当英文内容合并到main时，翻译工作流在GitHub Actions中运行：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;branches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;main]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s1"&gt;&amp;#39;content/**/*.en.md&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre tabindex="0"&gt;&lt;code class="language-mermaid" data-lang="mermaid"&gt;flowchart LR
 B[合并到main] --&amp;gt; C[生成翻译]
 C --&amp;gt; D[提交到main]
 D --&amp;gt; E[所有语言一起部署到生产环境]
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="提示词"&gt;提示词&lt;/h2&gt;
&lt;p&gt;工作流使用&lt;a href="https://github.com/anthropics/claude-code-action"&gt;claude-code-action&lt;/a&gt;：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;For each .en.md file that was added or modified:
1. Read the English content
2. Create translations for these languages: es, nl, de, it, fr, ja, zh, ru, hi
3. Save each translation as filename.{lang}.md (e.g., hello-world.es.md)
4. Preserve the frontmatter structure exactly, but translate the title
5. Translate the body content naturally
6. Keep code blocks, URLs, file paths, and technical terms unchanged
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;一个提示词处理所有9种语言。&amp;ldquo;自然翻译&amp;quot;比&amp;quot;翻译这段文字&amp;quot;产生更流畅的输出。代码块和技术术语保持英文。&lt;/p&gt;</description></item><item><title>关于</title><link>https://granda.org/zh/about/</link><pubDate>Mon, 22 Dec 2025 00:00:00 +0000</pubDate><guid>https://granda.org/zh/about/</guid><description>&lt;h2 id="摘要"&gt;摘要&lt;/h2&gt;
&lt;p&gt;本文档提供了关于本博客作者的背景信息。&lt;/p&gt;
&lt;h2 id="1-背景"&gt;1. 背景&lt;/h2&gt;
&lt;p&gt;拥有15年经验的软件工程师,其中10年在该领域工作。
专注领域包括:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分布式系统&lt;/li&gt;
&lt;li&gt;后端开发和基础设施&lt;/li&gt;
&lt;li&gt;全栈和端到端产品开发&lt;/li&gt;
&lt;li&gt;用户界面设计&lt;/li&gt;
&lt;li&gt;构建安全可靠的系统&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="2-联系方式"&gt;2. 联系方式&lt;/h2&gt;
&lt;p&gt;很高兴与业内人士建立联系:
&lt;a href="https://x.com/mtt"&gt;@mtt&lt;/a&gt;&lt;/p&gt;</description></item><item><title>关于</title><link>https://granda.org/zh/authorship/</link><pubDate>Mon, 22 Dec 2025 00:00:00 +0000</pubDate><guid>https://granda.org/zh/authorship/</guid><description>&lt;h2 id="摘要"&gt;摘要&lt;/h2&gt;
&lt;p&gt;本文档描述了本博客所采用的写作方法论。&lt;/p&gt;
&lt;h2 id="1-引言"&gt;1. 引言&lt;/h2&gt;
&lt;p&gt;本博客主要在大型语言模型(LLMs)的协助下生成。作者提供方向、编辑和质量控制;机器提供初稿和翻译。&lt;/p&gt;
&lt;h2 id="2-理由"&gt;2. 理由&lt;/h2&gt;
&lt;p&gt;作者相信在AI辅助内容创作方面保持透明。与其掩盖所使用的工具,这一披露旨在:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;为读者设定适当的期望&lt;/li&gt;
&lt;li&gt;为围绕AI内容的诚实规范做出贡献&lt;/li&gt;
&lt;li&gt;承认现代写作的协作性质&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="3-这意味着什么"&gt;3. 这意味着什么&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;想法&lt;/strong&gt;: 源自人类&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;结构&lt;/strong&gt;: 协作式&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;文字&lt;/strong&gt;: 主要由AI生成,由人类审核&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;翻译&lt;/strong&gt;: 完全由AI生成(未经人类审核)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="4-质量保证"&gt;4. 质量保证&lt;/h2&gt;
&lt;p&gt;英文内容在发布前经过人工审核。翻译是自动生成的,可能包含错误或笨拙的措辞。作者对最终发布的英文内容负责。&lt;/p&gt;
&lt;h2 id="5-联系方式"&gt;5. 联系方式&lt;/h2&gt;
&lt;p&gt;关于本政策的问题或疑虑可以直接联系作者。&lt;/p&gt;</description></item><item><title>你好世界</title><link>https://granda.org/zh/2025/12/20/%E4%BD%A0%E5%A5%BD%E4%B8%96%E7%95%8C/</link><pubDate>Sat, 20 Dec 2025 00:00:00 +0000</pubDate><guid>https://granda.org/zh/2025/12/20/%E4%BD%A0%E5%A5%BD%E4%B8%96%E7%95%8C/</guid><description>&lt;p&gt;欢迎来到我的博客！这是我的第一篇文章。&lt;/p&gt;
&lt;p&gt;我会在这里分享想法、笔记和有趣的事情。&lt;/p&gt;</description></item></channel></rss>