<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
            <title type="text">徐洲更的第二大脑</title>
    <updated>2026-05-29T15:08:40+08:00</updated>
        <id>http://xuzhougeng.com</id>
        <link rel="alternate" type="text/html" href="http://xuzhougeng.com" />
        <link rel="self" type="application/atom+xml" href="http://xuzhougeng.com/atom.xml" />
    <rights>Copyright © 2026, 徐洲更的第二大脑</rights>
    <generator uri="https://halo.run/" version="1.6.0">Halo</generator>
            <entry>
                <title><![CDATA[我正在创造一款豆包手机级别的 Windows 终端]]></title>
                <link rel="alternate" type="text/html" href="http://xuzhougeng.com/archives/building-an-ai-native-terminal-for-windows" />
                <id>tag:http://xuzhougeng.com,2026-05-13:building-an-ai-native-terminal-for-windows</id>
                <published>2026-05-13T16:41:37+08:00</published>
                <updated>2026-05-29T15:08:40+08:00</updated>
                <author>
                    <name>徐洲更</name>
                    <uri>http://xuzhougeng.com</uri>
                </author>
                <content type="html">
                        <![CDATA[<h1 id="%E6%88%91%E6%AD%A3%E5%9C%A8%E5%88%9B%E9%80%A0%E4%B8%80%E6%AC%BE%E8%B1%86%E5%8C%85%E6%89%8B%E6%9C%BA%E7%BA%A7%E5%88%AB%E7%9A%84-windows-%E7%BB%88%E7%AB%AF" tabindex="-1">我正在创造一款豆包手机级别的 Windows 终端</h1><p>这几天我一直在想豆包手机助手这件事。它真正让我震动的地方，不是“手机上多了一个 AI”，而是 AI 开始从一个聊天框，走进了普通用户最重要的数字入口。过去我们理解 AI 助手，很多时候还是问答逻辑：你问一句，它答一句；你让它写文案，它给你一段文字；你让它解释问题，它给你一个建议。但豆包手机助手展示出来的方向不是这样，它想做的是进入手机系统，理解屏幕内容，调用不同 App，然后替用户把任务真正做完。</p><p>公开资料里，豆包手机助手是在豆包 App 的基础上，和手机厂商在操作系统层面合作的 AI 助手软件。2025 年 12 月，字节跳动豆包团队发布了豆包手机助手技术预览版，并通过与中兴合作的 nubia M153 工程样机供开发者和科技爱好者体验；豆包方面也强调没有自研手机计划，而是通过生态合作把手机助手整合到不同品牌机型中。这个信息很关键，因为它说明豆包手机真正想争夺的不是一台硬件，而是“手机入口”本身。(<a href="https://www.ithome.com/0/901/473.htm" title="豆包发布手机助手技术预览版正与多家手机厂商洽谈合作 - IT之家" target="_blank">IT之家</a>)</p><p>从功能上看，豆包手机助手的能力也很典型。它可以通过语音、侧边 AI 键或耳机唤醒；在任意界面里，用户可以就当前屏幕内容直接向它提问；它还打通了系统原生相册，用户可以通过语音对图片下达修图指令，比如删除人物、清理杂物。更重要的是，它能根据用户指令在多款应用之间自动跳转，完成查票订票、商品下单、批量下载文件、多软件物流进度查询等任务。换句话说，它不是在手机里多放了一个 AI App，而是让 AI 站到了手机这个入口上，开始调度手机里的其他 App。(<a href="https://www.ithome.com/0/901/473.htm" title="豆包发布手机助手技术预览版正与多家手机厂商洽谈合作 - IT之家" target="_blank">IT之家</a>)</p><p>新华财经的实测也能看出这种变化。测试里，用户说“在 B 站搜索并播放某频道最新视频”，豆包手机助手可以自动打开 B 站、搜索频道并播放视频；用户要求查询“下周三上午从成都前往杭州的四川航空最便宜机票”，它也能打开旅行 App、填写出发地和目的地、选择日期并筛选航班。这里最重要的不是“它会不会搜视频”或者“它会不会查机票”，而是 AI 从建议者变成了执行者。传统助手会告诉你怎么做，而豆包手机助手开始替你进入 App，把步骤串起来。([新华网][2])</p><p>这件事让我想到 WispTerm。普通用户的数字入口是手机，那程序员的数字入口是什么？我现在越来越确定，答案不是浏览器，也不完全是 IDE，而是终端。浏览器连接的是信息世界，IDE 主要承载的是代码编辑，但终端连接的是系统本身。程序员启动项目、安装依赖、运行测试、查看日志、连接服务器、进入容器、部署服务、修改配置、排查故障，最后几乎都要回到终端。终端不是一个黑色窗口，它是程序员进入系统、服务器和运行现场的入口。</p><p>所以我看到豆包手机助手的时候，脑子里冒出来的不是“我也要做一个手机 AI”，而是另一个判断：如果豆包手机助手代表的是 AI 接管普通用户的手机入口，那么 WispTerm 要做的，就是让 AI 接管程序员的终端入口。这里的“接管”不是无边界地乱执行命令，而是在用户授权和权限控制下，让 AI 能够观察终端、理解上下文、提出计划、执行命令、读取结果，并继续推进任务。</p><p>这就是我说“我正在创造一款豆包手机级别的 Windows 终端”的原因。这个“级别”不是指商业规模，也不是说 WispTerm 现在已经拥有豆包手机助手那样完整的消费级体验，而是指产品范式。豆包手机助手的范式是：AI 不再停留在聊天框里，而是进入手机系统，理解屏幕，操作 App，串联任务。WispTerm 的范式则是：AI 不再停留在终端旁边的聊天框里，而是进入终端现场，理解会话，操作 shell，调度服务器。</p><p>WispTerm 本身是一个 Windows 终端，用 Zig 编写，基于 libghostty-vt 做终端模拟。在已有能力上，它已经不只是一个普通命令行窗口：它有 tabs 和 splits，有文件浏览和 Markdown/text 预览，有内置 WebView2 浏览器面板，有 AI Chat session，有远程访问能力，也支持 Kitty Graphics 图片协议。这些能力叠在一起，构成的不是一个孤立终端，而是一个程序员工作空间。([GitHub][3])</p><p>从 v0.19.0 开始，我真正想推进的，是让这个工作空间变成 agent 可以调度的现场。WispTerm v0.19.0 的 release 里，AI Chat 已经可以作为 agent 运行：它支持 OpenAI-compatible tool calling，可以在多轮循环中观察终端、执行本地 PowerShell，也可以向已经打开的 SSH session 注入命令。它还有 Ask 和 Full 两种权限模式，Ask 模式会在聊天里等待用户批准，Full 模式才会直接运行工具。([GitHub][4])</p><p>这一步的意义很大。传统 AI 终端大多还是“AI 帮你生成命令”。你遇到问题，把报错贴给 AI；AI 给你一段命令；你复制到终端里运行；运行完再把结果贴回去。这个过程当然有用，但 AI 仍然站在工作流外面。它并不知道你现在开了几个终端，不知道哪个是本地 PowerShell，哪个是远程 SSH，也不知道哪个窗口正在跑日志，哪个窗口已经进入了项目目录。它只是根据你搬运过去的信息进行判断。</p><p>我想做的 WispTerm 不一样。我希望 AI 直接活在终端里，能看到当前有哪些终端会话，能读取终端快照，能判断自己应该操作哪个 session。比如我已经打开了本地 PowerShell，也连上了几台服务器，其中一个 tab 在看日志，另一个 split 在跑构建命令。这个时候我问：“帮我看看服务为什么没起来。”AI 不应该只是告诉我“你可以运行 systemctl status”，而是应该先识别当前有哪些 session，再判断目标服务器是哪一个，然后提出要执行哪些只读检查命令。等我确认以后，它在对应的 SSH session 里执行命令，读取输出，再继续分析下一步。</p><p>这就对应了豆包手机助手的“同屏理解”。豆包手机助手可以看见你当前手机屏幕上发生了什么，WispTerm 的 agent 则应该能看见终端里发生了什么。豆包手机助手不需要用户把屏幕内容复制出来再问，WispTerm 的 agent 也不应该依赖用户不断复制终端输出。AI 只有看见现场，才能真正进入工作流；否则它只是一个站在旁边等你喂上下文的顾问。</p><p>豆包手机助手还有一个关键能力，是跨 App 操作。用户不需要自己在多个 App 之间跳来跳去，AI 可以按照任务需要打开不同应用，填写信息，筛选结果，把多个步骤串起来。对应到程序员世界，WispTerm 要做的不是跨 App，而是跨 tab、跨 split、跨 shell、跨 SSH session、跨服务器。程序员的真实工作现场本来就不是一个窗口，而是一组终端会话：本地、WSL、测试服务器、生产服务器、日志窗口、构建窗口、部署窗口，这些共同组成了程序员的工作流。</p><p>这里也能看出 WispTerm 和小龙虾、OpenClaw，或者我之前想做的 agent-control 的区别。小龙虾这类工具也可以跑在服务器上，也可以操控服务器；agent-control 的思路也成立，就是在不同服务器上分别运行一个 agent，然后通过一个 Web 控制台统一调度。但这种模式本质上是“每个环境一个 agent”。你要控制 A 服务器，就在 A 上部署 agent；你要控制 B 服务器，就在 B 上部署 agent；服务器越多，需要管理的 agent 也越多。</p><p>WispTerm 现在走的是另一条路。我不想在每台服务器上都放一个 agent，而是让一个 agent 活在我的终端里，调度我已经打开的所有终端会话。这个逻辑其实和豆包手机助手很像：豆包不是给每个 App 都装一个 AI，而是在手机这个入口上，让 AI 去操作不同 App；WispTerm 也不是给每台服务器都装一个 agent，而是在终端这个入口上，让 AI 去调度不同 shell 和 SSH session。前者是服务器视角，后者是程序员工作流视角。</p><p>这个视角差异非常重要。服务器 agent 关心的是某台机器上能执行什么，而终端 agent 关心的是程序员现在打开了哪些现场。程序员平时本来就是通过终端来组织工作的：我已经连上服务器了，我已经打开日志了，我已经进入项目目录了，我已经有了本地环境、远程环境、测试环境和生产环境。既然这些现场已经聚合在终端里，那最自然的方式不是另起一个 Web 控制台，而是让 AI 直接进入这个终端控制台。</p><p>当然，豆包手机助手也提醒了我另一件事：只要 AI 进入核心入口，安全和权限就不再是附属问题，而是产品本身的一部分。新华财经实测提到，豆包手机助手有事前、事中、事后的授权机制：执行具体功能前会询问用户，执行过程中会展示操作进度，用户可以手动接管、停止任务或补充需求；遇到支付密码、隐私信息修改等高风险操作时，系统会提示用户接管。([新华网][2])</p><p>终端里的风险比手机更直接。手机助手误点一个 App，最多是下错单、发错消息、触发平台风控；终端 agent 如果没有边界，可能会删文件、改配置、重启服务、部署生产环境，甚至影响远程服务器。所以 WispTerm 不能只强调“AI 能执行命令”，更要强调“AI 受控地执行命令”。它必须知道当前 session 是本地还是远程，必须知道自己操作的是测试环境还是生产环境，必须区分只读检查和修改性操作，必须在高风险命令前请求确认。</p><p>这也是为什么 v0.19.1 里那些看似细节的改动很重要。release 里提到，AI Chat 在 agent 工作时更容易控制：消息气泡支持复制，transcript 和输入框支持选择，界面上有可见的 stop 按钮，可以取消正在进行的请求；同时，AI 工具快照会从 UI 线程捕获活动终端列表，让 agent tools 能正确看到已有终端和 SSH sessions，取消操作也会尽可能停止正在运行的 PowerShell 命令。([GitHub][4])</p><p>这些不是普通 UI 优化，而是 agent 产品的基本安全能力。一个真正能干活的终端 agent，必须随时能停，必须让用户知道它在干什么，必须能被用户接管。否则它越聪明，风险越大。AI 进入终端以后，产品的核心问题不再是“模型会不会回答”，而是“它能不能可靠地观察、谨慎地执行、清楚地反馈、随时被中断”。</p><p>从这个角度看，豆包手机助手和 WispTerm 的关系非常清楚。豆包手机助手面对普通用户，WispTerm 面对程序员；豆包接管的是手机屏幕，WispTerm 接管的是终端会话；豆包跨的是 App，WispTerm 跨的是 shell、SSH、WSL、服务器和项目目录；豆包要理解的是用户生活里的任务，WispTerm 要理解的是程序员工作里的任务。两者的共同点是，它们都不是把 AI 当成一个外置聊天框，而是让 AI 进入最核心的操作入口。</p><p>所以“豆包手机级别的 Windows 终端”这个说法，对我来说不是一句夸张的口号。它真正表达的是一个产品方向：AI 原生的终端，不应该只是多一个聊天 tab，也不应该只是帮我生成几条命令。它应该能够观察我已经打开的工作现场，理解不同 session 的上下文，在我授权之后执行任务，并根据终端返回的结果继续推进。过去终端是人操作机器的界面，未来终端也可以变成 AI 理解和操作程序员工作现场的控制平面。</p><p>WispTerm 现在还处在很早期，但方向已经很清楚。第一步，让 AI 能看见终端。第二步，让 AI 能理解终端。第三步，让 AI 能在权限控制下执行命令。第四步，让 AI 能调度多个 SSH session。第五步，让 AI 能区分本地、远程、测试、生产。最后，让 AI 从一个聊天助手，变成程序员工作现场里的执行代理。</p><p>普通用户用手机连接数字生活，程序员用终端连接整个系统。当 AI 接管手机，普通用户的交互方式会改变；当 AI 接管终端，程序员的工作方式也会改变。豆包手机助手让我看到的是，AI 真正的产品革命，不是模型多聪明，而是它有没有进入用户真正的入口。对普通用户来说，这个入口是手机；对程序员来说，这个入口就是终端。</p><p>这就是我正在做的 WispTerm：一款豆包手机级别的 Windows 终端。不是把 ChatGPT 塞进终端，不是做一个命令补全插件，也不是每台服务器上部署一个 agent，而是让一个活在终端里的 agent，观察、理解、调度我已经打开的所有工作现场。豆包手机想做的是 AI 帮普通人操作手机，而 WispTerm 想做的是 AI 帮程序员操作终端。</p><p>[2]: <a href="https://www.news.cn/tech/20251226/a25b822dd8c545e2b238baa9b37910a1/c.html" target="_blank">https://www.news.cn/tech/20251226/a25b822dd8c545e2b238baa9b37910a1/c.html</a> &quot;<br />[3]: <a href="https://github.com/xuzhougeng/wispterm" target="_blank">https://github.com/xuzhougeng/wispterm</a> “GitHub - xuzhougeng/wispterm: Windows renderer for libghostty-vt · GitHub”<br />[4]: <a href="https://github.com/xuzhougeng/wispterm/releases" target="_blank">https://github.com/xuzhougeng/wispterm/releases</a> “Releases · xuzhougeng/wispterm · GitHub”</p>]]>
                </content>
            </entry>
            <entry>
                <title><![CDATA[我把sealso的容器管理做成了SKILL]]></title>
                <link rel="alternate" type="text/html" href="http://xuzhougeng.com/archives/skill-for-sealos" />
                <id>tag:http://xuzhougeng.com,2026-05-10:skill-for-sealos</id>
                <published>2026-05-10T11:31:04+08:00</published>
                <updated>2026-05-10T11:31:04+08:00</updated>
                <author>
                    <name>徐洲更</name>
                    <uri>http://xuzhougeng.com</uri>
                </author>
                <content type="html">
                        <![CDATA[<p>因为最近在开发一个项目，需要用到 Sealos 进行项目部署。由于项目开发比较频繁，需要不断地对镜像进行改动并投递到 Sealos。</p><p>之前一般的操作是等项目开发完后再去 Sealos 更改，变动不是太大，每次更新一次就好。但近期因为需要频繁变动去调试，就觉得这个过程有点重复化了。我就去看他的文档，看到它有一个 MCP 服务，想去试试。结果发现 MCP 服务并不存在，根据客服说法还在开发中。</p><p>不过他们提供了另一条路子，就是一个本地命令行工具。有命令行那就简单了，命令行可谓是 AI 时代最好的入口。</p><pre><code class="language-">wget https://github.com/labring/sealos/releases/download/v5.1.1/sealos_5.1.1_linux_amd64.tar.gztar xf  sealos_5.1.1_linux_amd64.tar.gzmv sealos ~/.local/bin</code></pre><p>所以我就把我的基本操作整理成了这个 Sealos 技能，并打包到了 GitHub 上。那么如何使用呢？</p><p>第一步：去个人中心获取 kubeconfig 文件，下载到本地，或者复制保存到某个文件</p><p><img src="/upload/2026/05/image.png" alt="image" /></p><p>第二步，用codex安装我的技能</p><pre><code class="language-">使用 skill-installer 安装  https://github.com/xuzhougeng/skills/tree/main/skills/sealos-remote-deploy</code></pre><p>然后，我用下面这段话就行了。</p><pre><code class="language-">重新docker build 然后更新我的sealos上线 配置文件在家目录下的kube开头的</code></pre><p><img src="/upload/2026/05/image-1778383834901.png" alt="image-1778383834901" /></p>]]>
                </content>
            </entry>
            <entry>
                <title><![CDATA[【Coding Crew】写了一个自进化的agent]]></title>
                <link rel="alternate" type="text/html" href="http://xuzhougeng.com/archives/codingcrew写了一个自进化的agent" />
                <id>tag:http://xuzhougeng.com,2026-05-09:codingcrew写了一个自进化的agent</id>
                <published>2026-05-09T19:34:45+08:00</published>
                <updated>2026-05-10T10:29:39+08:00</updated>
                <author>
                    <name>徐洲更</name>
                    <uri>http://xuzhougeng.com</uri>
                </author>
                <content type="html">
                        <![CDATA[<p>安装cc-agent</p><pre><code class="language-bash">mkdir -p ~/cc-agent &amp;&amp; cd ~/cc-agentcurl -LO https://github.com/xuzhougeng/agent-control/releases/latest/download/cc-agent-linux-amd64mv cc-agent-linux-amd64 cc-agentchmod +x cc-agent./cc-agent -version  </code></pre><p>使用deepseek配置</p><pre><code class="language-bash"># DeepSeek key (cheapest to start; swap providers later)echo &#39;sk-xxxxxxxx&#39; &gt; ~/.cc-agent-key &amp;&amp; chmod 600 ~/.cc-agent-keyCC_AGENT_API_KEY=&quot;$(cat ~/.cc-agent-key)&quot; \CC_AGENT_BASE_URL=&quot;https://api.deepseek.com&quot; \./cc-agent -provider deepseek -model deepseek-chat \           -cwd ~/cc-agent/yard \           -skills-dir ~/cc-agent/skills.d \           -memory ~/cc-agent/sessions.db</code></pre><p>使用方法很简单，就是对话</p><pre><code class="language-bash">you&gt; what&#39;s the kernel version on this box?▶ bash {command=uname -r}✓ exit_code=0  6.6.87.2-microsoft-standard-WSL2Kernel version: 6.6.87.2-microsoft-standard-WSL2</code></pre><p>对于一些危险命令，会有提示，让你解决</p><pre><code class="language-bash">you&gt; 用 rm -rf 删除 ~/cc-agent/yard 下所有文件[approval] rm -rf ~/cc-agent/yard  (reason: recursive rm)approve? [y/N]</code></pre><p>对于一些比较的操作，你可以让他沉淀下来。</p>]]>
                </content>
            </entry>
            <entry>
                <title><![CDATA[学会提问：在 AI 时代如何正确提问]]></title>
                <link rel="alternate" type="text/html" href="http://xuzhougeng.com/archives/how-to-ask-questions-in-the-age-of-ai" />
                <id>tag:http://xuzhougeng.com,2026-05-03:how-to-ask-questions-in-the-age-of-ai</id>
                <published>2026-05-03T10:59:20+08:00</published>
                <updated>2026-05-03T10:59:20+08:00</updated>
                <author>
                    <name>徐洲更</name>
                    <uri>http://xuzhougeng.com</uri>
                </author>
                <content type="html">
                        <![CDATA[<h1 id="%E5%AD%A6%E4%BC%9A%E6%8F%90%E9%97%AE%EF%BC%9A%E5%9C%A8-ai-%E6%97%B6%E4%BB%A3%E5%A6%82%E4%BD%95%E6%AD%A3%E7%A1%AE%E6%8F%90%E9%97%AE" tabindex="-1">学会提问：在 AI 时代如何正确提问</h1><h2 id="%E8%B5%B7%E5%9B%A0" tabindex="-1">起因</h2><p>很早以前，GitHub 上就有一篇很经典的文章，叫《提问的智慧》（<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way%EF%BC%89%E3%80%82" target="_blank">https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way）。</a></p><p>这篇文章我很早就看过。刚开始看的时候，觉得它有点“程序员社区规训”的味道，说话很直接，甚至有些不客气。但后来自己写教程、做课程、在群里答疑，以及被别人问问题问多了之后，我越来越觉得，它讲的其实是一个很基础的问题：</p><p>很多人不会提问。</p><p>这句话听起来可能有点冒犯。因为提问看起来是一个人人都有的能力，只要会打字，就能把问题发出去。</p><p>但实际情况是，很多人只是把一句话丢出来，并没有真正提出一个可以被回答的问题。</p><p>比如：</p><pre><code class="language-text">这个报错怎么解决？</code></pre><pre><code class="language-text">为什么连不上？</code></pre><pre><code class="language-text">有人会用这个工具吗？</code></pre><pre><code class="language-text">小龙虾怎么安装？</code></pre><p>这类问题不是不能问，而是信息量太少。看到这种问题的人，并不知道你想做什么，不知道你用了什么环境，不知道你已经尝试了什么，也不知道你卡在了哪一步。</p><p>换句话说，你不是在提问，你是在让别人替你猜上下文。</p><h2 id="%E6%8F%90%E9%97%AE%E8%83%BD%E5%8A%9B%E7%9A%84%E7%8E%B0%E7%8A%B6" tabindex="-1">提问能力的现状</h2><p>我发现很多人其实并不会提问。</p><p>这个现象在 AI 出现之后更加明显。以前你不会提问，可能只是群里没人理你。现在你不会提问，AI 也会回答你，而且还会回答得很像那么回事。</p><p>这就更麻烦了。</p><p>因为 AI 不会总是拒绝你。很多时候，它会顺着你的错误问题继续往下推，最后给出一个看似完整、但方向完全跑偏的答案。</p><p>比如前段时间遇到一个问题：Claude Code 启动之后一直卡在：</p><pre><code class="language-text">Checking connectivity...</code></pre><p>如果用户只问：</p><pre><code class="language-text">Claude Code 为什么连不上？</code></pre><p>那么很自然的排查方向是网络。</p><p>我们会看 DNS 能不能解析，看 443 端口能不能连，看 TLS 握手是否超时，看服务器出口网络是否有问题，看代理是否配置，看环境变量有没有冲突。</p><p>这些排查都没错。</p><p>但后面发现，用户真正想做的事情并不是“连接 Claude 官方服务”。</p><p>他真正想做的是：在服务器上使用 Claude Code 这个工具，但模型服务走 MiniMax、DeepSeek、Gemini，或者某个国内 API 转发服务。</p><p>这就不是同一个问题了。</p><p>前一个问题是：</p><pre><code class="language-text">为什么我的服务器连不上 Claude 官方服务？</code></pre><p>后一个问题是：</p><pre><code class="language-text">我能不能让 Claude Code 接入第三方模型服务？如果能，Base URL、Token、模型名和协议兼容性应该怎么配置？</code></pre><p>表面上看，它们都叫“连不上”。但实际排查路径完全不同。</p><p>如果你不把真实目标说出来，别人只能按照默认场景排查。最后就会出现一个很常见的情况：技术分析很完整，但解决的是错误的问题。</p><h2 id="%E6%88%91%E4%BB%A5%E5%89%8D%E6%98%AF%E6%80%8E%E4%B9%88%E5%AD%A6%E4%BC%9A%E6%8F%90%E9%97%AE%E7%9A%84" tabindex="-1">我以前是怎么学会提问的</h2><p>我不是一开始就会提问。</p><p>我的生物信息学技能基本上是自学出来的。刚开始学的时候，也会遇到各种问题，也会想着去群里问别人。但后来慢慢发现，大部分问题其实在问别人之前，都可以先自己查一轮。</p><p>那个时候还没有现在这么强的 AI，遇到问题主要靠搜索。</p><p>我一般会先把报错复制出来，然后做几件事：</p><ol><li>去掉自己机器上的路径和无关信息；</li><li>提取关键报错；</li><li>换不同关键词搜索；</li><li>中文搜不到就换英文；</li><li>只搜报错不行，就搜工具名、函数名、参数名；</li><li>官方文档、GitHub issue、博客、论坛一起看；</li><li>最后把多个来源的线索拼起来。</li></ol><p>很多问题不是一个页面就能解决的。</p><p>有时候一个 GitHub issue 只告诉你这是版本问题，另一个帖子告诉你某个参数变了，官方文档告诉你新版行为已经调整，最后你还要自己跑几个命令验证。</p><p>这个过程很慢，但它训练了一个能力：看到一个问题时，不是马上问“谁能帮我”，而是先想“这个问题的本质是什么”。</p><p>它到底是网络问题、权限问题、路径问题、版本问题、参数问题，还是我对工具的理解从一开始就是错的？</p><p>这才是提问能力的基础。</p><p>提问不是把困惑发出去。</p><p>提问是先把混乱的问题拆成别人能理解、自己也能验证的结构。</p><h2 id="%E6%88%91%E4%B8%8D%E4%BC%9A%E4%BC%98%E5%85%88%E6%B1%82%E5%8A%A9%E5%88%AB%E4%BA%BA" tabindex="-1">我不会优先求助别人</h2><p>我遇到问题时，一般不会优先求助别人。</p><p>不是因为我不需要别人帮助，而是因为我觉得，大部分问题在问别人之前，至少应该先问一遍自己。</p><p>以前我会先用百度、Google、Bing。</p><p>现在会加上 ChatGPT、DeepSeek、豆包、Kimi、Gemini 等 AI 工具。</p><p>但是核心逻辑没变：不要只依赖一个信息源。</p><p>搜索引擎会搜到过时内容。AI 会一本正经地胡说。论坛答案可能只适用于某个版本。官方文档也可能写得不完整。</p><p>所以真正重要的不是“我会用哪个工具”，而是我能不能从多个来源里面交叉验证，逐步逼近真实原因。</p><p>这也是为什么我觉得检索能力很重要。</p><p>很多人把搜索理解成“输入关键词，点开第一个结果”。但真正有效的搜索不是这样。它更像是一个不断缩小范围的过程。</p><p>比如一开始搜：</p><pre><code class="language-text">connection timeout</code></pre><p>太宽了。</p><p>然后根据报错细节改成：</p><pre><code class="language-text">socket timeout 110</code></pre><p>再结合工具和场景：</p><pre><code class="language-text">python requests socket timeout 110 proxy</code></pre><p>再结合网络环境：</p><pre><code class="language-text">linux server https tls handshake timeout proxy</code></pre><p>每一次搜索，都是在缩小问题空间。</p><p>你不是在找“标准答案”，你是在找线索。</p><h2 id="ai-%E6%97%B6%E4%BB%A3%EF%BC%8C%E6%8F%90%E9%97%AE%E5%8F%8D%E8%80%8C%E6%9B%B4%E9%87%8D%E8%A6%81" tabindex="-1">AI 时代，提问反而更重要</h2><p>现在很多人觉得，有了 AI 之后，就不需要学会提问了。</p><p>我觉得恰好相反。</p><p>AI 让提问能力变得更重要。</p><p>以前你问得不好，别人可能直接不回。这个反馈很明显。</p><p>但 AI 不一样。你问得不好，它也会回你。你给它一个模糊问题，它就给你一个模糊答案。你给它一个错误方向，它就沿着错误方向帮你展开。</p><p>这就像你在错误的路线上开了自动驾驶。</p><p>开得越快，离目标越远。</p><p>所以 AI 时代的问题不是“没有答案”，而是“答案太容易出现了”。</p><p>你需要判断的是：这个答案到底在解决什么问题？</p><p>还是以 Claude Code 为例。</p><p>如果你问：</p><pre><code class="language-text">Claude Code 一直 Checking connectivity 是为什么？</code></pre><p>AI 大概率会从网络、DNS、TLS、代理、证书、官方服务状态这些方向帮你分析。</p><p>这没有问题。</p><p>但如果你的真实目标是：</p><pre><code class="language-text">我想用 Claude Code 接入第三方模型服务，而不是连接 Claude 官方服务。</code></pre><p>那么你应该一开始就说清楚。</p><p>更好的问法是：</p><pre><code class="language-text">我想在服务器上使用 Claude Code，但不打算连接 Claude 官方服务，而是想接入 DeepSeek / MiniMax / Gemini 或某个兼容 API 的转发服务。现在启动时卡在 Checking connectivity。我想判断这是官方连通性检查失败，还是代理问题，还是第三方 endpoint 和 Claude Code 的协议不兼容。我应该检查哪些环境变量、Base URL、Token、模型名和网络请求？</code></pre><p>这个问题就清楚多了。</p><p>因为它提供了目标、上下文、现象、猜测方向和希望得到的帮助。</p><p>AI 才能沿着正确路径回答。</p><h2 id="%E4%B8%8D%E4%BC%9A%E6%8F%90%E9%97%AE%EF%BC%8C%E5%B0%B1%E5%88%AB%E6%80%A5%E7%9D%80%E7%8E%A9%E9%AB%98%E5%BA%A6%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7" tabindex="-1">不会提问，就别急着玩高度自动化工具</h2><p>这里顺便说一下现在很多人喜欢玩的高度自动化工具。</p><p>比如各种 Agent、Claude Code、Harness，或者我这里开玩笑说的“小龙虾”。</p><p>这些工具本身当然有价值。它们能帮你自动拆任务、调工具、跑命令、改代码、写文件。</p><p>但问题是：越是自动化的工具，越要求使用者有判断力。</p><p>如果你连这个工具是什么、解决什么问题、依赖什么服务、配置入口在哪里、失败时应该看哪一层都不知道，只是因为别人说它厉害就开始用，那么它并不会让你更强。</p><p>它只会更快地放大你的误判。</p><p>比如你问：</p><pre><code class="language-text">小龙虾怎么安装？</code></pre><p>这个问题本身不是不能问。但如果你连“小龙虾”是什么都不知道，只是看到别人用，就想先装上再说，那就有点危险。</p><p>这类工具不是普通软件。它们往往会替你执行很多动作。</p><p>你理解它，它是效率工具。</p><p>你不理解它，它就是黑箱。</p><p>以前你手动操作，错一步可能马上能看出来。现在你让 Agent 自动跑，它可能一口气错十步，而且每一步都看起来很自信。</p><p>所以我的建议是：先理解基本原理，再使用自动化工具。</p><p>不会提问，不会验证，不会设定边界，就不要急着把复杂任务交给自动化系统。</p><p>工具再强，也只是放大器，不是你的大脑。</p><h2 id="%E4%B8%80%E4%B8%AA%E5%A5%BD%E9%97%AE%E9%A2%98%E5%BA%94%E8%AF%A5%E5%8C%85%E5%90%AB%E4%BB%80%E4%B9%88" tabindex="-1">一个好问题应该包含什么</h2><p>我觉得一个技术问题，至少应该包含下面几类信息。</p><h3 id="1.-%E7%9B%AE%E6%A0%87" tabindex="-1">1. 目标</h3><p>你想实现什么？</p><p>不是你看到什么报错，而是你最后想达到什么状态。</p><p>例如：</p><pre><code class="language-text">我想让 Claude Code 在服务器上接入第三方模型服务。</code></pre><p>而不是：</p><pre><code class="language-text">为什么连不上？</code></pre><h3 id="2.-%E7%8E%AF%E5%A2%83" tabindex="-1">2. 环境</h3><p>你在什么环境下操作？</p><p>例如：</p><pre><code class="language-text">Ubuntu 24.04Claude Code 2.1.122远程服务器当前没有设置 HTTP_PROXY / HTTPS_PROXY</code></pre><p>环境信息可以帮助别人排除大量无关猜测。</p><h3 id="3.-%E7%8E%B0%E8%B1%A1" tabindex="-1">3. 现象</h3><p>具体发生了什么？</p><p>例如：</p><pre><code class="language-text">启动后卡在 Checking connectivity...curl 到 api.anthropic.com 时 DNS 能解析，443 能连接，但 TLS handshake 超时。</code></pre><p>不要只说“不行”。</p><p>“不行”不是信息。</p><h3 id="4.-%E5%B7%B2%E7%BB%8F%E5%B0%9D%E8%AF%95%E8%BF%87%E4%BB%80%E4%B9%88" tabindex="-1">4. 已经尝试过什么</h3><p>你做过哪些排查？</p><p>例如：</p><pre><code class="language-text">已经测试过 DNS。已经测试过 curl。已经检查过环境变量。没有发现 ANTHROPIC_BASE_URL。</code></pre><p>这可以避免别人让你重复做一遍你已经做过的事情。</p><h3 id="5.-%E4%BD%A0%E7%9A%84%E6%80%80%E7%96%91" tabindex="-1">5. 你的怀疑</h3><p>你认为问题可能在哪？</p><p>例如：</p><pre><code class="language-text">我不确定这是服务器出口网络问题，还是 Claude Code 启动阶段必须访问官方服务，还是第三方 API 不兼容。</code></pre><p>这一步很重要。</p><p>它能告诉别人你的思考路径，也能让别人判断你是不是已经问到了关键层。</p><h3 id="6.-%E5%B8%8C%E6%9C%9B%E5%BE%97%E5%88%B0%E7%9A%84%E5%B8%AE%E5%8A%A9" tabindex="-1">6. 希望得到的帮助</h3><p>你希望别人帮你做什么？</p><p>例如：</p><pre><code class="language-text">请帮我判断排查方向，并给出下一步验证命令。</code></pre><p>而不是：</p><pre><code class="language-text">帮我看看。</code></pre><p>“帮我看看”是最难回答的一种问题。</p><h2 id="%E6%9B%B4%E5%A5%BD%E7%9A%84%E6%8F%90%E9%97%AE%E6%A8%A1%E6%9D%BF" tabindex="-1">更好的提问模板</h2><p>如果要给一个通用模板，我会写成这样：</p><pre><code class="language-text">我想实现的目标是：……当前环境是：……我现在遇到的现象是：……完整报错或关键日志如下：……我已经尝试过：1. ……2. ……3. ……我目前怀疑可能是：1. ……2. ……我希望你帮我判断：1. 这个问题更可能出在哪一层？2. 下一步应该怎么验证？3. 有没有我忽略的关键上下文？</code></pre><p>这个模板不复杂，但非常有用。</p><p>它强迫你先整理自己的问题。</p><p>很多时候，你把这个模板填完，问题已经解决一半了。</p><h2 id="%E4%B8%80%E9%97%AE%E4%B8%80%E5%8F%8D%E6%80%9D" tabindex="-1">一问一反思</h2><p>提问能力不是天生的。</p><p>它可以训练。</p><p>现在 AI 最大的价值之一，就是它提供了一个非常方便的训练对象。</p><p>你可以用“一问一反思”的方式训练自己。</p><p>比如你问了一个问题，AI 给出的答案很泛。</p><p>不要马上怪 AI。</p><p>先反思：</p><pre><code class="language-text">我是不是没有说清楚目标？</code></pre><pre><code class="language-text">我是不是只描述了现象，没有描述背景？</code></pre><pre><code class="language-text">我是不是没有说自己已经尝试过什么？</code></pre><pre><code class="language-text">我是不是把真正想解决的问题藏起来了？</code></pre><pre><code class="language-text">AI 现在回答的是不是我真正关心的问题？</code></pre><p>然后重新改写问题，再问一次。</p><p>这个过程不是在训练 AI，而是在训练你自己。</p><p>你会逐渐发现，问题越具体，答案越可用。</p><p>上下文越清楚，AI 越不容易跑偏。</p><p>判断边界越明确，回答越接近你真正想要的东西。</p><h2 id="%E6%80%BB%E7%BB%93" tabindex="-1">总结</h2><p>学会提问，本质上是学会思考。</p><p>提问不是把一句“为什么不行”发出去。</p><p>提问是把一个混乱的问题，拆成目标、环境、现象、尝试、怀疑和诉求。</p><p>没有 AI 的时候，我们靠搜索引擎、文档、论坛和 GitHub issue 来训练这个能力。</p><p>有了 AI 之后，这个能力不但没有过时，反而更重要。</p><p>因为 AI 会回答你，但它不一定知道你真正想问什么。</p><p>如果你问错方向，它也会认真地帮你走错路。</p><p>所以，遇到问题时，我建议先做三件事：</p><ol><li>先问自己：我真正想实现什么？</li><li>再问搜索引擎和 AI：已有资料里有没有线索？</li><li>最后再问别人：带着上下文、尝试过程和明确诉求去问。</li></ol><p>很多时候，得不到正确答案，不是因为别人不会答，也不是因为 AI 不够强。</p><p>而是问题一开始就没有问对。</p><p>问清目标，答案才会对路。</p>]]>
                </content>
            </entry>
            <entry>
                <title><![CDATA[我开发了一个新的文献阅读工具]]></title>
                <link rel="alternate" type="text/html" href="http://xuzhougeng.com/archives/a-new-literature-reading-tool-i-developed" />
                <id>tag:http://xuzhougeng.com,2026-03-18:a-new-literature-reading-tool-i-developed</id>
                <published>2026-03-18T12:37:56+08:00</published>
                <updated>2026-03-24T15:30:44+08:00</updated>
                <author>
                    <name>徐洲更</name>
                    <uri>http://xuzhougeng.com</uri>
                </author>
                <content type="html">
                        <![CDATA[<p>很早之前我听我朋友说了一个科研体系，叫做“科研论”《钟澄》。它里面提到一个非常重要的事情，就是将文献图片全都打包入库。这样在后续做科研的时候，你可以非常快速地筛选出跟你相关领域的 Fig 1、Fig 2、Fig 3、Fig 4 怎么做。这样的话，你去做科研的时候就不会一头雾水，像个无头苍蝇一样。</p><p>这个系统的核心是截图，一开始想的是用 AI 自动进行图片的截取，但是发现 AI 截的图总是有问题。所以我索性算了吧，还是自己截图。一天看一篇文献，你就截一篇文献图，又不会死。毕竟跟领域相关的也没有那么多文章，无非就是截十张图而已，也无所谓的，压力也不大。主要是管理上确实有问题。钟澄老师是用一个Word文档管理的，虽然简陋但是有效。我想这个东西能不能给它体系化？所以之前一直在想这方面工具的开发。</p><p>所以说，我重新开发了这套阅读工具。<a href="https://github.com/xuzhougeng/citebox" target="_blank">citebox</a></p><p>它的核心是这样子：你登录之后呢，就可以上传文献。</p><p><img src="/upload/2026/03/image.png" alt="image" /></p><p>上传完之后，我们可以手动对PDF进行截图（基于pdf.js）你拆完之后，文章里的所有图片你就会入库了。</p><p><img src="/upload/2026/03/image-1773808375695.png" alt="image-1773808375695" /></p><p>当然，我可以自己搞了一个自动截图算法，在配置里面配置下就行，因为服务器比较弱，模型也不是特别好，很多时候不如直接手工方便。</p><p><img src="/upload/2026/03/image-1774336719519.png" alt="image-1774336719519" /></p><p>入库完之后有什么用呢？我们提供两套思路：</p><ol><li>对文章本身进行标签和分组。文章本身是可以标签和分组的。</li><li>对图片进行标签化。我们觉得文章里面最重要的就是图片，因为很多时候文章作者是按照图片去讲他的一个故事的。所以说我们给图片设计了专门的一套标签系统。</li></ol><p>同时呢，我们也设计了两套笔记系统：</p><ol><li>文献本身的笔记</li><li>图片本身的笔记</li></ol><p>这两个笔记都单独作为体系的。</p><p>然后有个关键是我们做了一套 AI 的解读系统，因为现在大模型越来越强嘛，一个工具没有 AI 肯定是不行的。所以想着，那怎么加 AI 工具呢？我们加两套：</p><ol><li>给图片本身的解读。一个图片你看不懂，AI 应该帮你解读一下。</li><li>Tag 建议。你这个图片不知道打什么 Tag，打 Tag 就很难了。那么你可以让 AI 给你做个建议，这也没问题。</li></ol><p><img src="/upload/2026/03/image-1774337080975.png" alt="image-1774337080975" /></p><p>同时我们还提供了文献图文交互式的一个解读。因为我们把文献里面的所有图片都给它拆分出来。这样拆分出来之后，我们就把图片作为一个上传内容传入给 AI。然后 AI 在回答的时候把图片也输出来。这样的话，我们可以生成一个图文并茂式的文献。</p><p>因为我用的是wolai，所以我还加了一个保存到wolai的功能，只不过有一个问题就是wolai的图片上传的API不知道怎么配置，所以效果不是特别的好。</p><p><img src="/upload/2026/03/image-1774337105902.png" alt="image-1774337105902" /><br /><img src="/upload/2026/03/image-1774337141913.png" alt="image-1774337141913" /></p><p>此外，最近我还加入了一个小功能，配色库，也就是支持对大图里面进行小图截图，截图完之后，就会给整理出6个配色，保存。</p><p><img src="/upload/2026/03/image-1774336896925.png" alt="image-1774336896925" /></p><p>同时，因为最近微信开放了 Claude Bot 这个接口，允许个人用户接入。我也给自己的客户端搞了这样一个接入，使用也非常简单：</p><p><img src="/upload/2026/03/image-1774337368858.png" alt="image-1774337368858" /></p><p>只需要打开你的微信进行扫码绑定即可。如果你无法绑定，说明你的版本比较低，建议升级你的微信到最新版本。</p><p><img src="/upload/2026/03/b792d08fb058b900eda29598198e8019.jpg" alt="b792d08fb058b900eda29598198e8019" /></p><p>这工具很简单，我是用 Go 来做的一个后端开发，前端是无框架的原生html/js/css。编译之后，不到 7MB 的样子。</p><p><img src="/upload/2026/03/image-1774337210456.png" alt="image-1774337210456" /></p><p>它前端用但是 WebView。WebView 是目前 Windows 10、Windows 11 以上它自带的一个功能。同时还支持MacOS，因为我交了苹果的开发税，所以我有苹果的认证。因此安装的时候相对来说比较简单，不会因为由于来自于“不明开发者”而被拦截。</p>]]>
                </content>
            </entry>
            <entry>
                <title><![CDATA[Windows 下 SSH config 权限错误：原因与解决方案]]></title>
                <link rel="alternate" type="text/html" href="http://xuzhougeng.com/archives/windows-ssh-config-permission-error-cause-and-solution" />
                <id>tag:http://xuzhougeng.com,2026-02-25:windows-ssh-config-permission-error-cause-and-solution</id>
                <published>2026-02-25T09:29:10+08:00</published>
                <updated>2026-02-25T09:29:33+08:00</updated>
                <author>
                    <name>徐洲更</name>
                    <uri>http://xuzhougeng.com</uri>
                </author>
                <content type="html">
                        <![CDATA[<blockquote><p>Cursor生成，我负责校对。</p></blockquote><h2 id="%E9%94%99%E8%AF%AF%E7%8E%B0%E8%B1%A1" tabindex="-1">错误现象</h2><p>执行 <code>ssh -G &lt;Host&gt;</code> 或正常 SSH 连接时出现：</p><pre><code class="language-">Bad permissions. Try removing permissions for user: UNKNOWN\UNKNOWN (S-1-5-21-906514677-3100084438-2507395604-3740986366) on file C:/Users/xxx/.ssh/config.Bad owner or permissions on C:\Users\xxx/.ssh/config</code></pre><h2 id="%E5%8E%9F%E5%9B%A0%E5%88%86%E6%9E%90" tabindex="-1">原因分析</h2><ol><li><p><strong>OpenSSH 的权限检查</strong><br />Windows 版 OpenSSH 会校验 <code>~/.ssh/config</code> 的 ACL，要求该文件<strong>只能</strong>被当前用户（以及 SYSTEM、Administrators 等系统账户）访问。若存在其他用户或未知账户的权限，会直接报错。</p></li><li><p><strong>“UNKNOWN\UNKNOWN” 与 SID</strong><br />错误中的 <code>S-1-5-21-906514677-3100084438-2507395604-3740986366</code> 是一个<strong>安全标识符（SID）</strong>。当该 SID 对应的本地账户已被删除或来自另一台机器（例如从旧电脑迁移了用户配置），系统无法解析出用户名，就会显示为 <code>UNKNOWN\UNKNOWN</code>。</p></li><li><p><strong>典型来源</strong></p><ul><li>用户配置文件从旧机器迁移或复制</li><li>重装系统后沿用旧的 <code>.ssh</code> 目录</li><li>域/本地账户变更导致旧 SID 残留在 ACL 中</li></ul><p>只要该 SID 仍在 <code>config</code> 的 ACL 里且具有读/写等权限，OpenSSH 就会认为“其他用户可访问”，从而拒绝使用该配置。</p></li></ol><h2 id="%E8%A7%A3%E5%86%B3%E6%80%9D%E8%B7%AF" tabindex="-1">解决思路</h2><p>从 <code>~/.ssh/config</code> 的 ACL 中<strong>移除该未知/孤儿 SID 的访问项</strong>，只保留当前用户（及必要的系统账户），并保证当前用户至少对 <code>config</code> 有读权限。</p><h2 id="%E8%A7%A3%E5%86%B3%E6%AD%A5%E9%AA%A4" tabindex="-1">解决步骤</h2><h3 id="1.-%E7%A1%AE%E8%AE%A4%E9%97%AE%E9%A2%98" tabindex="-1">1. 确认问题</h3><p>查看当前 ACL 和错误信息：</p><pre><code class="language-powershell"># 查看 config 的 ACLicacls &quot;$env:USERPROFILE\.ssh\config&quot;# 触发错误（会提示具体 SID）ssh -G CPU2</code></pre><p>若输出中存在错误里提示的 SID（如 <code>S-1-5-21-906514677-...</code>）且对应 <code>UNKNOWN</code>，则按下面步骤处理。</p><h3 id="2.-%E5%AF%BC%E5%87%BA%E5%BD%93%E5%89%8D-acl" tabindex="-1">2. 导出当前 ACL</h3><p>在 PowerShell 中执行：</p><pre><code class="language-powershell">icacls &quot;$env:USERPROFILE\.ssh\config&quot; /save &quot;$env:USERPROFILE\.ssh\config_acl.txt&quot;</code></pre><h3 id="3.-%E7%BC%96%E8%BE%91-acl-%E6%96%87%E4%BB%B6%EF%BC%8C%E5%8E%BB%E6%8E%89%E9%97%AE%E9%A2%98-sid" tabindex="-1">3. 编辑 ACL 文件，去掉问题 SID</h3><p><code>config_acl.txt</code> 为 UTF-16 编码，用脚本去掉对应 SID 的 ACE（将下面 <code>S-1-5-21-...</code> 换成你错误信息里的 SID）：</p><pre><code class="language-powershell">$path = &quot;$env:USERPROFILE\.ssh\config_acl.txt&quot;$text = [System.IO.File]::ReadAllText($path, [Text.Encoding]::Unicode)$badSid = &quot;(A;;0x1301ff;;;S-1-5-21-906514677-3100084438-2507395604-3740986366)&quot;  # 改为你的 SID$text = $text.Replace($badSid, &quot;&quot;)[System.IO.File]::WriteAllText($path, $text, [Text.Encoding]::Unicode)</code></pre><p>若不确定 SDDL 格式，可先打开 <code>config_acl.txt</code>，搜索该 SID 所在整段 <code>(A;;...;;;S-1-5-21-...)</code> 并整段删除后保存为 UTF-16。</p><h3 id="4.-%E4%BB%A5%E7%AE%A1%E7%90%86%E5%91%98%E6%9D%83%E9%99%90%E6%81%A2%E5%A4%8D-acl" tabindex="-1">4. 以管理员权限恢复 ACL</h3><p><strong>必须以管理员身份打开 PowerShell</strong>，然后执行：</p><pre><code class="language-powershell">Set-Location &quot;$env:USERPROFILE\.ssh&quot;icacls . /restore &quot;$env:USERPROFILE\.ssh\config_acl.txt&quot;</code></pre><p><code>/restore</code> 会按 ACL 文件中的条目重新应用权限，因此需提升权限。</p><h3 id="5.-%E9%AA%8C%E8%AF%81" tabindex="-1">5. 验证</h3><pre><code class="language-powershell"># 再次查看 ACL，确认问题 SID 已消失icacls &quot;$env:USERPROFILE\.ssh\config&quot;# 应能正常输出配置，不再报错ssh -G CPU2</code></pre><p>正常时，<code>config</code> 上应只剩例如 <code>NT AUTHORITY\SYSTEM</code>、<code>BUILTIN\Administrators</code> 和你的用户名（如 <code>DESKTOP-xxx\你的用户名</code>），且你的用户至少有读权限。</p><h2 id="%E5%8F%AF%E9%80%89%EF%BC%9A%E8%8B%A5%E6%9C%AC%E6%9C%BA%E6%9C%89%E7%AE%A1%E7%90%86%E5%91%98%E6%9D%83%E9%99%90%E4%B8%94%E7%86%9F%E6%82%89-icacls" tabindex="-1">可选：若本机有管理员权限且熟悉 icacls</h2><p>也可在<strong>管理员 PowerShell</strong> 中直接尝试移除该 SID（将 <code>S-1-5-21-...</code> 换成实际 SID）：</p><pre><code class="language-powershell">icacls &quot;$env:USERPROFILE\.ssh\config&quot; /remove &quot;S-1-5-21-906514677-3100084438-2507395604-3740986366&quot;</code></pre><p>若提示“无法解析/找不到主体”，说明系统已不认识该账户，此时用上面的“导出 → 编辑 → 恢复”方式更可靠。</p><h2 id="%E5%B0%8F%E7%BB%93" tabindex="-1">小结</h2><table><thead><tr><th>项目</th><th>说明</th></tr></thead><tbody><tr><td><strong>现象</strong></td><td><code>Bad owner or permissions on .../.ssh/config</code>，并提示 <code>UNKNOWN\UNKNOWN</code> 及一长串 SID</td></tr><tr><td><strong>原因</strong></td><td>config 的 ACL 中存在已失效/跨机器的 SID，OpenSSH 认为存在“其他用户”权限</td></tr><tr><td><strong>本质</strong></td><td>清理该 SID 在 <code>~/.ssh/config</code> 上的访问项，只保留当前用户和系统必要账户</td></tr><tr><td><strong>要点</strong></td><td>修改 ACL 需管理员权限；编辑导出文件时注意 UTF-16 与 SDDL 格式</td></tr></tbody></table><p>按上述步骤操作后，SSH 会正常读取 <code>~/.ssh/config</code>，<code>ssh -G</code> 与日常连接即可恢复使用。</p>]]>
                </content>
            </entry>
            <entry>
                <title><![CDATA[开发了一个随时随地控制服务器claude code的工具]]></title>
                <link rel="alternate" type="text/html" href="http://xuzhougeng.com/archives/claude-code-interface" />
                <id>tag:http://xuzhougeng.com,2026-02-11:claude-code-interface</id>
                <published>2026-02-11T16:09:24+08:00</published>
                <updated>2026-02-13T20:45:49+08:00</updated>
                <author>
                    <name>徐洲更</name>
                    <uri>http://xuzhougeng.com</uri>
                </author>
                <content type="html">
                        <![CDATA[<p>OpenClaw最近爆火出圈，每当人别人问有没有部署的时候，我都在一个问题，你打算做什么？因为本质上，我只需要一个服务器连接Claude Code就能实现OpenClaw的绝大部分功能了。</p><p>有一个功能我是特别喜欢，那就是 OpenClaw 可以通过不同的终端发送指令，而这是 Claude Code 目前所不能实现的。</p><p>比方说，我有多个服务器，每个服务器都运行着 Claude Code。</p><p>这些服务器运行完之后通常需要手动确认，但如果我当时刚好不在服务器旁边，操作起来就会比较麻烦。所以我想，有没有可能我自己搞一个网页终端？这样我就可以通过网页终端随时获取当前状态，并进行确认工作。</p><p>之所以有这个需求，是因为：</p><ol><li>OpenClaw 的权限特别大，操作不当可能会把服务器搞乱。</li><li>Claude Code 比较谨慎，权限控制相对严格，需要频繁点击确认。</li></ol><p>如果我有这样一个网页工具，能帮我随时随地确认状态，就完全符合我的需求了，甚至不再需要 OpenClaw。</p><p>我跟 ChatGPT 进行了交流，向它输入了流程思路，咨询大概需要什么工具以及具体的实现方法。</p><p>最后我决定使用 Go 语言作为后端，主要基于以下考虑：</p><ol><li>部署简单：Go 可以直接编译成二进制文件，资源占用非常小，直接分发到服务器上即可。</li><li>项目需求：这个项目总体比较简单，后端只需要监控我的 Terminal（终端），前端负责网页展示。相比之下，Python 众多的第三方库在本项目中并非必需。</li></ol><p>至于前端部分，因为逻辑比较简单，我没有使用任何框架，只是进行了原生的 Native 开发。</p><p>经过跟 Cursor 的交流，我们制定了以下开发流程：</p><ol><li>计划阶段：使用 GPT 5.2 (Extra High) 进行整体规划</li><li>编程操作：使用 GPT 5.3 CodeX Extra High)进行核心代码编写</li><li>模型优化：中间穿插使用了 Opus 4.6 模型</li></ol><p>大概经过这十几次 Commit，我们最终完成了代码。开发过程中，发现其中比较复杂的部分在于如何渲染终端和前端页面样式的可视化，难点主要是如何更适合手机端操作。</p><p>我最初的一些想法都在后续的反复开发中不断进行了重构。目前整体设计还是相对比较简洁的，因为 UI 比较简单，绝大部分功能都是通过 API 实现的，所以后面衔接其他程序也会相对容易一些。</p><p>代码开源在 GitHub 上，<a href="https://github.com/xuzhougeng/agent-control" target="_blank">https://github.com/xuzhougeng/agent-control</a></p><p>接下来介绍如何去部署这个工作：</p><p>首先我们需要从 GitHub 上克隆这个项目，然后对其进行编译。</p><pre><code class="language-Go">git clone https://github.com/xuzhougeng/agent-controlcd agent-controlcd cc-controlCGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o cc-control ./cmd/cc-controlcd ../cc-agentCGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o cc-agent ./cmd/cc-agent</code></pre><p>这个项目分为两个部分：其中一个部分是需要一个公网 IP 的服务器，因为我的服务器主要集中在境内，所以我们可以购买一个国内的服务器。</p><p>这里选择购买一个腾讯云服务器，不需要域名，只需要IP即可。</p><p><img src="/upload/2026/02/image.png" alt="image" /></p><p>服务器购买后，我们需要打开防火墙，在里面添加 443 端口。</p><p>之所以需要增加 443 端口，是因为如果使用 HTTP 端口，传输过程就是明文的。这样很有可能导致服务器暴露在外面，尤其是涉及敏感服务器时会非常危险。毕竟我们的权限还是比较大的，所以一定要通过 HTTPS 协议进行传输。</p><p><img src="/upload/2026/02/image-1770797207565.png" alt="image-1770797207565" /></p><p>然后根据服务器的 IP 地址、用户名和密码登录到服务器上。接着在服务器上做如下的配置操作：</p><p>第一步：建立相关的文件夹并赋予其权限</p><pre><code class="language-Bash">sudo mkdir -p /opt/cc-controlsudo chown ubuntu:ubuntu /opt/cc-control</code></pre><p>无域名时无法使用 Let’s Encrypt，可用自签名证书在 Nginx 上启用 TLS，传输仍加密；浏览器和 agent 需接受自签名（浏览器手动信任，agent 用 <code>-tls-skip-verify</code>）。</p><blockquote><p>下面的1.2.3.4得改成实际的IP地址</p></blockquote><pre><code class="language-Bash">mkdir -p /opt/cc-control/tlscd /opt/cc-control/tlscat &gt; openssl.cnf &lt;&lt; &#39;EOF2&#39;[req]distinguished_name = req_distinguished_namereq_extensions = v3_reqprompt = no[req_distinguished_name]CN = cc-control[v3_req]subjectAltName = @alt[alt]IP.1 = 1.2.3.4EOF2openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \  -keyout key.pem -out cert.pem -config openssl.cnf -extensions v3_req</code></pre><p>接着我们需要安装 Nginx</p><pre><code class="language-Bash">sudo apt install nginx</code></pre><p>增加配置文件 /etc/nginx/conf.d/cc.conf</p><pre><code class="language-nginx">server {    listen 443 ssl http2 default_server;    listen [::]:443 ssl http2 default_server;    server_name _;    ssl_certificate     /opt/cc-control/tls/cert.pem;    ssl_certificate_key /opt/cc-control/tls/key.pem;    location /ws/ {        proxy_pass http://127.0.0.1:18080;        proxy_http_version 1.1;        proxy_set_header Upgrade $http_upgrade;        proxy_set_header Connection &quot;upgrade&quot;;        proxy_set_header Host $host;        proxy_set_header X-Real-IP $remote_addr;        proxy_read_timeout 3600s;        proxy_send_timeout 3600s;    }    location / {        proxy_pass http://127.0.0.1:18080;        proxy_set_header Host $host;        proxy_set_header X-Real-IP $remote_addr;    }}</code></pre><p>重启nginx服务</p><pre><code class="language-Bash">sudo nginx -t sudo systemctl reload nginx</code></pre><p>在服务器这部分操作结束后，我们需要回到本地，将我们编译的代码进行上传。</p><pre><code class="language-Bash">scp cc-control ubuntu@106.54.201.18:/opt/cc-control/scp -r ../ui ubuntu@106.54.201.18:/opt/cc-control/ui</code></pre><p>然后是非常关键的一步，需要生成两个 token，分别是 AGENT_TOKEN 和 UI_TOKEN：</p><ol><li><p>AGENT_TOKEN</p><p>负责本地 agent 与服务器端进行连接（Service Network）。</p></li><li><p>UI_TOKEN</p><p>相当于一个密码。当别人访问页面时，在没有授权的情况下无法直接查看，需要输入这个密码才能够查看你的网页。</p></li></ol><pre><code class="language-Bash">ADMIN_TOKEN=$(openssl rand -hex 32)echo &quot;ADMIN_TOKEN=$ADMIN_TOKEN&quot;</code></pre><p>增加一个服务文件，<code>/etc/systemd/system/cc-control.service</code>，这样可以保证开机或重启之后，它会自动启动。</p><p>不然的话，可能服务器会重启，或者程序在某种情况下不小心中断了。如果它不能重连的话，处理起来就比较麻烦，你还得专门打开服务器去配置它，而设置为服务之后，它就会在这些情况下自动重启。</p><pre><code class="language-Ini">[Unit]Description=CC Control PlaneAfter=network.target[Service]Type=simpleUser=ccGroup=ccWorkingDirectory=/opt/cc-controlExecStart=/opt/cc-control/cc-control \  -addr 127.0.0.1:18080 \  -ui-dir /opt/cc-control/ui \  -agent-token ${AGENT_TOKEN} \  -ui-token ${UI_TOKEN} \  -audit-path /opt/cc-control/audit.jsonl \  -offline-after-sec 30EnvironmentFile=/opt/cc-control/.envRestart=alwaysRestartSec=3[Install]WantedBy=multi-user.target</code></pre><p>需要注意的是，这里面涉及到一个环境文件<code>/opt/cc-control/.env</code>，里面的 token 都是我们刚才生成的。</p><pre><code class="language-Bash">ADMIN_TOKEN=&lt;your-admin-token&gt;# optional: persist tokens across restartsTOKEN_DB=/opt/cc-control/tokens.db</code></pre><p>为了安全，我们继续新建一个不允许被登录的账号。同时，把刚才环境变量的权限改一改，进一步增加安全性，然后重启该服务。</p><pre><code class="language-Bash">sudo useradd -r -s /sbin/nologin ccsudo chown -R cc:cc /opt/cc-controlsudo chmod 600 /opt/cc-control/.envsudo systemctl daemon-reloadsudo systemctl enable --now cc-control</code></pre><p>等这些配置完成后，我们就可以打开浏览器访问我们的网站了。</p><p>由于 TLS 或者说 HTTP 协议（也就是 SSL 证书）是我们自签名的，浏览器会提示该连接不安全。但这没有关系，只需按照以下步骤操作：</p><ol><li>在浏览器提示界面选择“高级”</li><li>点击“继续访问”即可进入网站</li></ol><p>手机端访问时也会出现同样的情况，无需担心。</p><p><img src="/upload/2026/02/image-1770797247465.png" alt="image-1770797247465" /></p><p>接下来登录 /admin页面，我们要生成 Tenant ID和Token。</p><p><img src="/upload/2026/02/image-1770986480708.png" alt="image-1770986480708" /></p><p>接下来登录这个tenant页面，我们要生成 UI Token 和 Agent Token</p><p><img src="/upload/2026/02/image-1770986733519.png" alt="image-1770986733519" /></p><p>接着我们需要填写里面的 UI Token，也就是我们刚才生成的。不然的话，我们是看不到连接服务的。当然，现在连上去也看不到服务，毕竟我们本地agent都还没有连上去。</p><p><img src="/upload/2026/02/image-1770797259218.png" alt="image-1770797259218" /></p><p>然后需要启动本地端的 agent 了。</p><ol><li>IP 地址：我们现在写的是 1234，你得改成我们实际的 IP 地址</li><li>Agent Token：也一样，也要改成实际的 Agent Token</li></ol><p>当然，服务器上必须安装 Claude 并配置 Claude 的相关信息，这部分内容就不在这里过多介绍了。</p><pre><code class="language-Bash">cc-agent \  -control-url wss://1.2.3.4/ws/agent \  -tls-skip-verify \  -agent-token &quot;$AGENT_TOKEN&quot; \  -server-id srv-gpu-01 \  -allow-root /home/deploy/repos \  -claude-path /usr/local/bin/claude</code></pre><p>实际效果如下：</p><p><img src="/upload/2026/02/image-1770797278994.png" alt="image-1770797278994" /></p>]]>
                </content>
            </entry>
            <entry>
                <title><![CDATA[基于免费的Cloudflare搭建单细胞可视化网站]]></title>
                <link rel="alternate" type="text/html" href="http://xuzhougeng.com/archives/building-single-cell-visualization-website-with-free-cloudflare" />
                <id>tag:http://xuzhougeng.com,2026-01-18:building-single-cell-visualization-website-with-free-cloudflare</id>
                <published>2026-01-18T19:59:32+08:00</published>
                <updated>2026-01-20T21:37:08+08:00</updated>
                <author>
                    <name>徐洲更</name>
                    <uri>http://xuzhougeng.com</uri>
                </author>
                <content type="html">
                        <![CDATA[<p>这一篇是在<a href="http://xuzhougeng.com/archives/refactoring-of-published-single-cell-databases-by-atlasmap" target="_blank">AtlasMap重构已发表的单细胞数据库</a>的基础上，使用Cloudflare提供的page和worker功能进行前后端分离搭建。</p><h2 id="%E5%A6%82%E6%9E%9C%E4%BD%A0%E7%9A%84%E5%90%8E%E5%8F%B0%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%8F%AF%E4%BB%A5%E5%85%AC%E7%BD%91%E8%AE%BF%E9%97%AE" tabindex="-1">如果你的后台服务器可以公网访问</h2><p>在frontend生成用于发布的静态文件，这里你需要设置你的后台服务器。</p><pre><code class="language-bash">UPSTREAM_ORIGIN=http://your.backend.server npm run build:cloudflare</code></pre><p>此时会在frontend目录下生成两个子目录:</p><ul><li>dist: 静态资源站点</li><li>functionns : 基于worker实现方向代理</li></ul><p>使用cloudflare wrangler命令进行部署。这一步需要你的注册一个Cloudflare的账号</p><pre><code class="language-bash"># 1) 登录npx wrangler login# 2) （可选）创建 Pages 项目npx wrangler pages project create &lt;PROJECT_NAME&gt;# 3) 部署：在项目根目录执行（根目录要有 functions/）npx wrangler pages deploy dist --project-name &lt;PROJECT_NAME&gt;</code></pre><p>注: 后台服务器 nginx 转发设置保持不变，参考<a href="http://xuzhougeng.com/archives/refactoring-of-published-single-cell-databases-by-atlasmap" target="_blank">AtlasMap重构已发表的单细胞数据库</a>里的后端配置部分。</p><p>此时，他会提供一个跟项目关联的域名给你，类似于 <a href="https://plantcellatlas.pages.dev" target="_blank">https://plantcellatlas.pages.dev</a> , 当然你也可以选择使用CNAME设置自定义域名。</p><p><img src="/upload/2026/01/image-1768737508340.png" alt="image-1768737508340" /></p><h2 id="%E5%A6%82%E6%9E%9C%E4%BD%A0%E7%9A%84%E5%90%8E%E5%8F%B0%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%A4%84%E4%BA%8E%E5%86%85%E7%BD%91" tabindex="-1">如果你的后台服务器处于内网</h2><p>借助于赛博活菩萨Cloudflare提供tunnel服务。</p><p>目标：<strong>无需公网服务器/公网 IP</strong>（后端在内网/NAT/校园网），实现<strong>前后端分离部署</strong>：</p><ul><li>前端：Cloudflare Pages 托管静态站点</li><li>后端：任意一台可出网的机器上运行 <code>server/bin/server</code>（只需本机可监听端口）</li><li>连接：用 Cloudflare Tunnel 把后端暴露到一个 Cloudflare 子域名；前端通过 Pages Functions 同源代理 <code>/api/*</code>、<code>/d/*</code> 到该子域名（浏览器侧无 CORS 问题）</li></ul><p>注: 后端主机必须能连通到Cloudflare tunnel服务, 参考<a href="https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/troubleshoot-tunnels/connectivity-prechecks/" target="_blank">Connectivity pre-checks</a>, 即，如果内网服务器被屏蔽这类服务，或者无法访问外网，无法使用改方案。</p><h3 id="%E5%90%8E%E7%AB%AF%EF%BC%9A%E5%90%AF%E5%8A%A8%E6%9C%8D%E5%8A%A1%EF%BC%88%E5%86%85%E7%BD%91%E6%9C%BA%E5%99%A8%E5%8D%B3%E5%8F%AF%EF%BC%89" tabindex="-1">后端：启动服务（内网机器即可）</h3><p>后端数据准备与 <code>server.yaml</code> 配置同其它方式一致，然后在后端机器上启动：</p><pre><code class="language-bash">server/bin/server -config &quot;data/server.yaml&quot;</code></pre><p>默认后端监听 <code>:8080</code>（以实际配置为准）。<strong>不需要</strong>给这台机器配置公网 IP，也不需要额外的 nginx 反代（Tunnel 会负责入口）。</p><h3 id="%E5%90%8E%E7%AB%AF%EF%BC%9A%E5%88%9B%E5%BB%BA%E5%B9%B6%E8%BF%90%E8%A1%8C-cloudflare-tunnel" tabindex="-1">后端：创建并运行 Cloudflare Tunnel</h3><p>从Github上下载cloudflared</p><pre><code class="language-bash">wget https://github.com/cloudflare/cloudflared/releases/download/2026.1.1/cloudflared-linux-amd64mv cloudflared-linux-amd64 cloudflaredchmod +x cloudflared</code></pre><p>参考<a href="https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/do-more-with-tunnels/local-management/create-local-tunnel/" target="_blank">Create a locally-managed tunnel</a></p><p>安装完成后，登录并创建 Tunnel, 此时会弹出一个网页，要求你选择一个 Cloudflare 托管域名下的子域名作为上游入口</p><pre><code class="language-bash">cloudflared tunnel login</code></pre><p>创建一个隧道，名字自取，这里我写的是atlasmap</p><pre><code class="language-bash">cloudflared tunnel create atlasmap</code></pre><p>后续步骤中的<code>&lt;USER&gt;</code>, <code>TUNNEL_ID</code> 和  <code>HOST_DOMAIN</code> 是需要根据实际结果进行修改。</p><p>创建 <code>cloudflared</code> 配置文件（示例路径 <code>~/.cloudflared/config.yml</code>）：</p><pre><code class="language-yaml">tunnel: atlasmapcredentials-file: /home/&lt;USER&gt;/.cloudflared/&lt;TUNNEL_ID&gt;.jsoningress:  - hostname: &lt;HOST_DOMAIN&gt;    service: http://127.0.0.1:8080  - service: http_status:404</code></pre><p>建立DNS记录（非常重要，也可以在Cloudflare dashboard中DNS里面手动创建）</p><pre><code class="language-bash">cloudflared tunnel route dns atlasmap &lt;HOST_DOMAIN&gt;</code></pre><p>启动 Tunnel：</p><pre><code class="language-bash">cloudflared tunnel run atlasmap</code></pre><p>日志信息只要不出现ERR都算运行正常。</p><p>可选：将 Tunnel 配置为 systemd 服务，保证重启后自启动（按 cloudflared 官方文档即可）。</p><h3 id="%E5%89%8D%E7%AB%AF%EF%BC%9A%E6%9E%84%E5%BB%BA-cloudflare-pages-%E4%BA%A7%E7%89%A9%EF%BC%88%E5%8C%85%E5%90%AB-functions-%E4%BB%A3%E7%90%86%EF%BC%89" tabindex="-1">前端：构建 Cloudflare Pages 产物（包含 Functions 代理）</h3><p>本项目已提供 Pages Functions 的同源代理实现：部署到 Pages 后，<code>/api/*</code> 与 <code>/d/*</code> 会被转发到 <code>UPSTREAM_ORIGIN</code> 指定的上游。</p><p>在 <code>frontend/</code> 目录构建（把上游指向刚才的 Tunnel 子域名）：</p><pre><code class="language-bash">cd frontendUPSTREAM_ORIGIN=&lt;HOST_DOMAIN&gt; npm run build:cloudflare</code></pre><p>构建完成后会生成：</p><ul><li><code>frontend/dist/</code>：静态站点</li><li><code>frontend/functions/</code>：Pages Functions（同源反代 <code>/api/*</code>、<code>/d/*</code>）</li></ul><h3 id="%E9%83%A8%E7%BD%B2%E5%88%B0-cloudflare-pages" tabindex="-1">部署到 Cloudflare Pages</h3><p>用 wrangler 一键发布</p><pre><code class="language-bash">cd frontendnpx wrangler loginnpx wrangler pages project create &lt;PROJECT_NAME&gt;npx wrangler pages deploy dist --project-name &lt;PROJECT_NAME&gt;</code></pre><h3 id="%E9%AA%8C%E8%AF%81%E4%B8%8E%E6%8E%92%E9%94%99" tabindex="-1">验证与排错</h3><ul><li>访问 Pages 域名（例如 <code>https://&lt;PROJECT&gt;.pages.dev</code>）</li><li>打开浏览器 Network：确认请求打到同源的 <code>/api/...</code>、<code>/d/...</code>（由 Pages Functions 转发到 <code>https://api.example.com</code>）</li><li>如果接口返回 502/超时：<ul><li>确认后端机器上 <code>server</code> 正在运行，且本机可访问 <code>http://127.0.0.1:8080/health</code>（或你配置的健康检查）</li><li>确认 <code>cloudflared tunnel run ...</code> 正在运行，且 <code>api.example.com</code> 已在 Cloudflare DNS 中生效</li><li>确认 <code>UPSTREAM_ORIGIN</code> 使用 <code>https://api.example.com</code>（Tunnel 默认提供 HTTPS 入口）</li></ul></li></ul>]]>
                </content>
            </entry>
            <entry>
                <title><![CDATA[AtlasMap重构已发表的单细胞数据库]]></title>
                <link rel="alternate" type="text/html" href="http://xuzhougeng.com/archives/refactoring-of-published-single-cell-databases-by-atlasmap" />
                <id>tag:http://xuzhougeng.com,2026-01-18:refactoring-of-published-single-cell-databases-by-atlasmap</id>
                <published>2026-01-18T12:34:12+08:00</published>
                <updated>2026-01-18T12:34:12+08:00</updated>
                <author>
                    <name>徐洲更</name>
                    <uri>http://xuzhougeng.com</uri>
                </author>
                <content type="html">
                        <![CDATA[<p>我觉得单细胞文章发表之后，最好是搭配一个对应的网页方便用户查看数据。毕竟我看到你的文章后，第一个想法可能就是我关注的基因是不是在你的数据集中也有某种特征，而不是我要去数据库上下载你的数据，然后在本地进行处理，最后只为了看个表达量。</p><p>因此，我在2019参与发表拟南芥的根的单细胞中就提供了对应网站，当现在已经过去了快6年了，依旧每天都会几个人来看。</p><p>我觉得目前发表的很多单细胞文章之所以不提供对应的工作，其中一个很大原因就是按照目前现成工具部署到一个能够被访问的公网服务器上，一年下来是要不少钱的。我找了一圈，也就是USCS Cell Browser是低资源的，他处理完之后就是一个静态页面，直接用NGINX托管就行。但是有一个小小的问题，就是他是通过用户的浏览器渲染，当细胞数比较多的时候，可能会有点卡顿。</p><p>当然也可能是我调研不够全，还没有找到合适的软件，我借助目前比较强大的人工智能辅助编程，开发了一个新的工具，可以在非常低资源的情况下进行部署，0.2个CPU，128M内存，可能一天不需要1块钱，就能给自己工作增加一个曝光点。</p><p>目前项目开源代码在<a href="https://github.com/xuzhougeng/atlasmap-sc" target="_blank">https://github.com/xuzhougeng/atlasmap-sc</a>。</p><p>以课题组之前发表的，被我托管在shiny-server的数据为例，目标是统一托管在<a href="https://explorer.plantcellatlas.com" target="_blank">https://explorer.plantcellatlas.com</a> 。</p><p>我有一台比较高性能的服务器，但是域名是固定的，假设是http://www.example.com，我们可以将其作为计算中心，负责返回前端静态页面的API请求。</p><p>在高性能的服务器上，我们做如下的操作</p><p>第一步，克隆项目并安装环境</p><pre><code class="language-Bash">git clone https://github.com/xuzhougeng/atlasmap-sc.gitcd atlasmap-sc# 配置Python环境cd preprocessinguv pip install  .cd ..# 配置go环境 cd servergo build -o bin/server ./cmd/server</code></pre><p>第二步，运行atlasmap-preproces做数据预处理</p><pre><code class="language-Bash">uv run atlasmap-preprocess run -i rootatlas.h5ad -o data/ath_root -a -z 11 uv run atlasmap-preprocess run -i shootatlas.h5ad -o data/ath_shoot -a -z 11 uv run atlasmap-preprocess run -i marchantia_census.h5ad -o data/mp_census -a -z 11 </code></pre><p>第三步，配置data/sever.yaml</p><pre><code class="language-YAML">server:  port: 8080   cors_origins:    - &quot;http://localhost:3000&quot;    - &quot;http://localhost:5173&quot;  # Custom title displayed in the header (optional, defaults to &quot;SOMA-Tiles&quot;)  title: &quot;Cell 1K&quot;# Multi-dataset format:data:  ath_root:    zarr_path: &quot;data/ath_root/zarr/bins.zarr&quot;  ath_shoot:    zarr_path: &quot;data/ath_shoot/zarr/bins.zarr&quot;  mp_census:    zarr_path: &quot;data/mp_census/zarr/bins.zarr&quot;cache:  tile_size_mb: 512  tile_ttl_minutes: 10render:  tile_size: 256  default_colormap: viridis</code></pre><p>启动后台</p><pre><code class="language-Bash">server/bin/server -config &quot;data/server.yaml&quot;</code></pre><p>第四步，配置后台的nginx，将前端请求反向代理到前端的到go服务器上，并用<code>ngins -s reload</code>重新加载</p><pre><code class="language-nginx">server {    # .... other    # /api (no trailing slash) -&gt; /api/    location = /api { return 301 /api/; }    location /api/ {        proxy_pass http://127.0.0.1:8080/api/;        proxy_set_header Host $host;        proxy_set_header X-Real-IP $remote_addr;        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;        proxy_set_header X-Forwarded-Proto $scheme;        proxy_read_timeout 300s;    }    # /d (no trailing slash) -&gt; /d/    location = /d { return 301 /d/; }    location /d/ {        proxy_pass http://127.0.0.1:8080/d/;        proxy_set_header Host $host;        proxy_set_header X-Real-IP $remote_addr;        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;        proxy_set_header X-Forwarded-Proto $scheme;        proxy_read_timeout 300s;    }    # 可选：健康检查直通    location /health {        proxy_pass http://127.0.0.1:8080/health;    }    # ... other}</code></pre><p>配置前端：</p><p>我用的是环界云<a href="https://cloud.sealos.io/" target="_blank">https://cloud.sealos.io/</a>提供谷歌云，直接用配置好的镜像：<code>hoptoper/atlasmap-frontend:latest</code>， 最低配置，一天不到5毛钱。</p><p><img src="/upload/2026/01/image-1768710646096.png" alt="image-1768710646096" /></p><p>通过CNAME的方式实现自定义域名。</p><p><img src="/upload/2026/01/image-1768710668398.png" alt="image-1768710668398" /></p><p>保存的时候，提示你应该如何到域名服务上设置CNAME解析，这里面的值就是你需要复制过去的。</p><p><img src="/upload/2026/01/image-1768710678018.png" alt="image-1768710678018" /></p><p>高级配置中，设置环境变量 BACKEND_HOST， BACKEND_PORT, 对应后台服务器NGINX配置的server_name 和listen。</p><p><img src="/upload/2026/01/image-1768710696507.png" alt="image-1768710696507" /></p><p>启动等待一会就可以了，就可以通过域名<a href="https://explorer.plantcellatlas.com/" target="_blank">https://explorer.plantcellatlas.com/</a>访问了，终于实现了我的单细胞数据统一化展示了。</p>]]>
                </content>
            </entry>
            <entry>
                <title><![CDATA[AHK关掉恼人的微信电脑语音视频电话弹窗]]></title>
                <link rel="alternate" type="text/html" href="http://xuzhougeng.com/archives/close-wechat-notification-using-ahk" />
                <id>tag:http://xuzhougeng.com,2026-01-06:close-wechat-notification-using-ahk</id>
                <published>2026-01-06T08:54:08+08:00</published>
                <updated>2026-01-06T08:54:08+08:00</updated>
                <author>
                    <name>徐洲更</name>
                    <uri>http://xuzhougeng.com</uri>
                </author>
                <content type="html">
                        <![CDATA[<p>我发现微信电脑端（测试的时候是4.1.6.46）有一个很讨厌的问题，就是一旦别人视频或者语音电话给你，你的的右下角就会有一个弹窗，而且离谱的时候，我在设置中，根本关不掉。</p><p><img src="/upload/2026/01/image.png" alt="image" /></p><p>当然这里书都关不掉指的是，我查了各种资料，做了包括不限于如下的操作</p><ul><li>找windows10里的信息通知（没找到）</li><li>消息列表中设置仅限闹钟</li><li>windows防火墙限制微信的UDP</li></ul><p>最后借助AI的力量，用最传统的方法，实时监控电脑，一旦看到弹窗给它瞬间隐藏。</p><p>第一步，安装AHK，这是他的官方站点https://www.autohotkey.com/ （记得之前用这个软件还是为DNF连招）</p><p>第二步，新建一个脚本，命名为 <code>wechat_call_popup_kill.ahk</code>,  粘贴如下的代码，并保存。</p><pre><code class="language-ahk">#Requires AutoHotkey v2.0#SingleInstance ForceSetTimer BlockWeChatCallPopup, 80DetectHiddenWindows false; 你的来电小窗尺寸（允许一点点误差）global TARGET_W := 472global TARGET_H := 170global TOL_W := 30global TOL_H := 30; 右下角容差（像素）global EDGE_PAD := 120BlockWeChatCallPopup() {    for hwnd in WinGetList(&quot;ahk_exe Weixin.exe&quot;) {        try {            if (WinGetClass(&quot;ahk_id &quot; hwnd) != &quot;Qt51514QWindowIcon&quot;)                continue            WinGetPos &amp;x, &amp;y, &amp;w, &amp;h, &quot;ahk_id &quot; hwnd            ; 尺寸匹配（来电小窗）            if (Abs(w - TARGET_W) &gt; TOL_W || Abs(h - TARGET_H) &gt; TOL_H)                continue            ; 位置匹配（贴近主屏右下角工作区）            mon := MonitorGetPrimary()            MonitorGetWorkArea mon, &amp;L, &amp;T, &amp;R, &amp;B            rightGap  := R - (x + w)            bottomGap := B - (y + h)            if (rightGap &gt; EDGE_PAD || bottomGap &gt; EDGE_PAD)                continue            ; 最稳：隐藏（避免 WinClose 无效/闪烁）            WinHide &quot;ahk_id &quot; hwnd            ; 如果你更希望“直接关掉窗口”，用下面替换 WinHide：            ; PostMessage 0x0010, 0, 0, , &quot;ahk_id &quot; hwnd   ; WM_CLOSE        }    }}</code></pre><p>第三步，双击运行。启动后，别人打电话给你，手机端依旧会有提示，电脑端只会一闪而过。</p><p>此外还可以设置开机自动运行。 使用快捷键Win + R → 输入 shell:startup → 回车 ，将脚本放进去。</p><p><img src="/upload/2026/01/image-1767660703050.png" alt="image-1767660703050" /></p>]]>
                </content>
            </entry>
            <entry>
                <title><![CDATA[Github添加Claude作为助手]]></title>
                <link rel="alternate" type="text/html" href="http://xuzhougeng.com/archives/add-claude-app-in-github" />
                <id>tag:http://xuzhougeng.com,2025-12-19:add-claude-app-in-github</id>
                <published>2025-12-19T22:24:45+08:00</published>
                <updated>2025-12-19T22:26:20+08:00</updated>
                <author>
                    <name>徐洲更</name>
                    <uri>http://xuzhougeng.com</uri>
                </author>
                <content type="html">
                        <![CDATA[<p>Claude Code中有一项是 <code>/instal-github-app</code>, 作用就是让Claude Code出现在你的github仓库中作为issue和PR的处理助手。</p><p>如下是操作流程</p><ol><li>使用 <code>gh auth login</code> 注册当前的设备</li><li>到 <a href="https://github.com/apps/claude" target="_blank">https://github.com/apps/claude</a>安装Claude应用</li><li>在Cluade Code 中，运行<code>/instal-github-app</code>, 选择需要安装的功能</li><li>在Claude Code弹出页面中进行授权，粘贴Prompt</li><li>在弹出的github PR页面合并新增的action的PR</li><li>后续在Issue和PR中，就可以使用 <code>@claude</code> 处理简单的任务代码debug和reivew（默认只有repo的所有者能够调用）</li></ol><p>注意，必须要注册Claude的账号，因此无法使用中转站的方式。</p>]]>
                </content>
            </entry>
            <entry>
                <title><![CDATA[尝鲜了Z-image模型]]></title>
                <link rel="alternate" type="text/html" href="http://xuzhougeng.com/archives/quick-view-on-z-image" />
                <id>tag:http://xuzhougeng.com,2025-11-29:quick-view-on-z-image</id>
                <published>2025-11-29T22:23:37+08:00</published>
                <updated>2025-11-29T22:23:37+08:00</updated>
                <author>
                    <name>徐洲更</name>
                    <uri>http://xuzhougeng.com</uri>
                </author>
                <content type="html">
                        <![CDATA[<p>阿里最近推出了一个6B的生图模型，叫做造相(Z-Image),6B参数，模型文件32.9G，经过我测试，刚好可以跑在24G显存的4090 GPU上，以及我的32G内存内存的M1 Pro（实际用了25.6G）</p><p><img src="/upload/2025/11/image-1764425632521.png" alt="image-1764425632521" /></p><p>因为用的深度学习框架pytorch可以运行在全平台上，所以如下代码实际上可以在macOS, Linux, Windows上运行。我们配置环境用的是uv，目前python生态里非常优秀的环境管理工具。</p><p>使用uv建立一个新的环境</p><pre><code class="language-Bash"># 如果系统没有安装uv，需要先装uvcurl -LsSf https://astral.sh/uv/install.sh | shuv venv -p 3.12source .venv/bin/activate</code></pre><p>安装torch,这一步的命令要看平台了，详见 <a href="https://pytorch.org/get-started/locally/" target="_blank">https://pytorch.org/get-started/locally/</a></p><pre><code class="language-"># Windows cuda 130的uv pip install torch torchvision --index-url https://download.pytorch.org/whl/cu130# macosuv pip install torch torchvision</code></pre><p>安装diffusers</p><pre><code class="language-bash"># 安装diffusers和transformersuv pip install git+https://github.com/huggingface/diffusersuv pip install transformers</code></pre><p>为了提高模型下载速度，我们用的是modelscope，这样子走的就是国内的站点</p><pre><code class="language-bash">uv pip install modelscopemodelscope download --model &#39;Tongyi-MAI/Z-Image-Turbo&#39; --local_dir &#39;Z-Image-Turbo&#39;</code></pre><p>下载的模型位于当前目录下，后续运行的时候需要指定路径，不然会出错。</p><p>安装成功后，我们运行如下的代码进行测序。如果是macOS，记得把下面的cuda改成mps，否则会报错。</p><pre><code class="language-Python">import torchfrom diffusers import ZImagePipeline# 1. Load the pipeline# Use bfloat16 for optimal performance on supported GPUspipe = ZImagePipeline.from_pretrained(    &quot;./Z-Image-Turbo&quot;,    torch_dtype=torch.bfloat16,    low_cpu_mem_usage=False,)pipe.to(&quot;cuda&quot;)# [Optional] Attention Backend# Diffusers uses SDPA by default. Switch to Flash Attention for better efficiency if supported:# pipe.transformer.set_attention_backend(&quot;flash&quot;)    # Enable Flash-Attention-2# pipe.transformer.set_attention_backend(&quot;_flash_3&quot;) # Enable Flash-Attention-3# [Optional] Model Compilation# Compiling the DiT model accelerates inference, but the first run will take longer to compile.# pipe.transformer.compile()# [Optional] CPU Offloading# Enable CPU offloading for memory-constrained devices.# pipe.enable_model_cpu_offload()prompt = &quot;Young Chinese woman in red Hanfu, intricate embroidery. Impeccable makeup, red floral forehead pattern. Elaborate high bun, golden phoenix headdress, red flowers, beads. Holds round folding fan with lady, trees, bird. Neon lightning-bolt lamp (⚡️), bright yellow glow, above extended left palm. Soft-lit outdoor night background, silhouetted tiered pagoda (西安大雁塔), blurred colorful distant lights.&quot;import timestart_time = time.time()# 2. Generate Imageimage = pipe(    prompt=prompt,    height=1024,    width=1024,    num_inference_steps=9,  # This actually results in 8 DiT forwards    guidance_scale=0.0,     # Guidance should be 0 for the Turbo models    generator=torch.Generator(&quot;cuda&quot;).manual_seed(42),).images[0]# 记录结束时间并计算耗时end_time = time.time()elapsed_time = end_time - start_timeprint(f&#39;消耗时间: {elapsed_time}&#39;)image.save(&quot;example.png&quot;)</code></pre><p>经过我测试，相同的我的M1 Mac需要大概率200秒生成一张图，Windows 的4090需要大概160秒，速度也还行吧。但是，如果是NVIDIA RTX PRO 6000，则需要3秒，一下子差异就有了。因此如果想要体验的话，我建议直接去用在线的站点，毕竟在线用也就只需要10秒而已，还不需要自己配置环境。</p><p>PS: 加载模型也需要时间的，模型文件大小是33G，如果不是固态硬盘，可能还需要画个几分钟。</p><p>官方提供的在线站点:</p><ul><li>huggingface: <a href="https://huggingface.co/spaces/Tongyi-MAI/Z-Image-Turbo" target="_blank">https://huggingface.co/spaces/Tongyi-MAI/Z-Image-Turbo</a></li><li>modelspace: <a href="https://www.modelscope.cn/aigc/imageGeneration?tab=advanced&amp;versionId=469191&amp;modelType=Checkpoint&amp;sdVersion=Z_IMAGE_TURBO&amp;modelUrl=modelscope%3A%2F%2FTongyi-MAI%2FZ-Image-Turbo%3Frevision%3Dmaster" target="_blank">https://www.modelscope.cn/aigc/imageGeneration?tab=advanced&amp;versionId=469191&amp;modelType=Checkpoint&amp;sdVersion=Z_IMAGE_TURBO&amp;modelUrl=modelscope%3A%2F%2FTongyi-MAI%2FZ-Image-Turbo%3Frevision%3Dmaster</a></li></ul><p>下图是我自己测试的效果，用的prompt是：“一个生物信息学家，正在努力的赶项目，前面有三个屏幕（左，右是竖屏），桌边是冰美式，脚下是吃掉的麦当劳”</p><p><img src="/upload/2025/11/image-1764426037769.png" alt="image-1764426037769" /></p><p>同样的提示词交给谷歌的生图模式就没有问题，起码冰美式和竖屏都对了。</p><p><img src="/upload/2025/11/image-1764426117168.png" alt="image-1764426117168" /></p>]]>
                </content>
            </entry>
            <entry>
                <title><![CDATA[我卸载了沉浸式翻译，安装了KISS和Ries]]></title>
                <link rel="alternate" type="text/html" href="http://xuzhougeng.com/archives/recommend-on-kiss-and-ries-for-english-learning" />
                <id>tag:http://xuzhougeng.com,2025-11-29:recommend-on-kiss-and-ries-for-english-learning</id>
                <published>2025-11-29T18:25:39+08:00</published>
                <updated>2025-11-29T18:27:08+08:00</updated>
                <author>
                    <name>徐洲更</name>
                    <uri>http://xuzhougeng.com</uri>
                </author>
                <content type="html">
                        <![CDATA[<blockquote><p>本文段落中的英文为Ries自动替换</p></blockquote><p>我应该是沉浸式翻译的老用户，购买过了两年的年度 subscription(订阅)服务。 因为 用起来效果确实挺不错的，上面是英文,下面是对照的中文，相比于全部翻译成中文，我还能有机会了解下我不懂的单词。</p><p><img src="/upload/2025/11/image-1764411786173.png" alt="image-1764411786173" /></p><p>但是用着用着，我就感觉自己的英语水平咋开始倒退了，仔细一想，我发现我在使用的时候几乎看的全是中文那部分，就跟看外语电影，只要有字幕，我肯定就开始盯着屏幕的下方了。</p><p>虽然，我相信随着科技的进步，我们都不需要专门学习英语，只要开着App，然后你说一句，它翻译一句，同时 translate(翻译) 对方说的话（现在应该已经能实现了）。 不过，我个人是觉得翻译本身就是一种信息的不完全的 conversion(转换)，比如说，你将唐诗翻译成英文，就可能失去了原来的那种意境。 所以，我个人还是觉得有必要继续加强下自己。</p><p>我想到的第一个方法就是能够在网页里面自动高亮我不熟悉的单词，这个我用到KISS插件，它里面可以配置highlight(高亮)。</p><p><img src="/upload/2025/11/image-1764411803512.png" alt="image-1764411803512" /></p><p>于是你就能在平时用浏览器看东西的时候，不知不觉的强化对一些陌生单词的记忆，毕竟好歹经过那么多年的教育，大部分的句子都是能读懂，只是少部分单词可能不认识，需要多次接触才能够熟悉。</p><p><img src="/upload/2025/11/image-1764411818259.png" alt="image-1764411818259" /></p><p>后来，我又发现了一个新的工具，叫做Rise。它的思路就是在你平时阅读材料做替换，大概是下面这个效果。基本上一个段落里面就会替换一两处，确保你不会读不下去，又能够接触新的单词。KISS的好处在于读英文材料的时候，帮我高亮我不记得单词，Rise就能够在我读中文的时候，也增加我一些生词的接触机会。</p><p>Rise是懂营销的，新用户首日是五折，抓住了我们捡便宜的心理。不过，最近刚好是黑五打折，有一个离谱的四折活动，我就以199买了一个ultra会员，感觉赚到了（比沉浸式翻译的一年订阅便宜多了）。</p><p><img src="/upload/2025/11/image-1764411826649.png" alt="image-1764411826649" /></p><p>Anyway，如果你感兴趣的话，可以考虑通过我的邀请地址（邀请码是7QBI)，<a href="https://ries.ai?c=7QBI" target="_blank">https://ries.ai?c=7QBI</a>   购买，会有额外一个月的时长</p>]]>
                </content>
            </entry>
            <entry>
                <title><![CDATA[做了一个微信公众号Markdown编辑器-02]]></title>
                <link rel="alternate" type="text/html" href="http://xuzhougeng.com/archives/create-a-wx-markdown-editor-02" />
                <id>tag:http://xuzhougeng.com,2025-11-21:create-a-wx-markdown-editor-02</id>
                <published>2025-11-21T22:43:25+08:00</published>
                <updated>2025-11-22T10:37:33+08:00</updated>
                <author>
                    <name>徐洲更</name>
                    <uri>http://xuzhougeng.com</uri>
                </author>
                <content type="html">
                        <![CDATA[<p>前两天自己通过&quot;氛围编程&quot;手搓了一个满足自己需要的微信公众号编辑器，第一版本虽然能用，但是还是没有存在问题，当然问题还是出在图片上。也就是我自己站点的图片，微信公众号后台有一定概率拉取不到，而之前用的墨滴的自带的图床没有这个问题。</p><p>这个方法我的解决思路就是先把图片上传到微信公众后台，然后替换本地markdown里的内容。因此，我专门搞了一个设置页，用配置AppID和开发者密码，可以在微信公众号的后台获取。此外，还得设置IP白名单，这个实在是太严格了。</p><p><img src="/upload/2025/11/image-1763733455594.png" alt="image-1763733455594" /></p><p>我们先可以把远程的图片本地化</p><p><img src="/upload/2025/11/image-1763777947542.png" alt="image-1763777947542" /></p><p>然后上传到公众号就行，而且因为上传到了公众号，就有了防盗链系统，图片就成了下面的情况，一定程度上，让我们知道哪些图片是上传的，哪些是没有的</p><p><img src="/upload/2025/11/image-1763778028862.png" alt="image-1763778028862" /></p><p>虽然编辑器目前还是有很多bug，但至少目前发表公众号就方便多了。</p>]]>
                </content>
            </entry>
            <entry>
                <title><![CDATA[做了一个微信公众号Markdown编辑器]]></title>
                <link rel="alternate" type="text/html" href="http://xuzhougeng.com/archives/create-a-wx-markdown-editor" />
                <id>tag:http://xuzhougeng.com,2025-11-21:create-a-wx-markdown-editor</id>
                <published>2025-11-21T21:06:34+08:00</published>
                <updated>2025-11-21T21:06:34+08:00</updated>
                <author>
                    <name>徐洲更</name>
                    <uri>http://xuzhougeng.com</uri>
                </author>
                <content type="html">
                        <![CDATA[<p>我平时写东西一般来说都喜欢在我的Halo的后台写，然后到<a href="https://www.mdnice.com/" target="_blank">墨滴</a>上进行渲染，然后粘贴微信公众号的后台。</p><p><img src="/upload/2025/11/image.png" alt="image" /></p><p>整个流程里面有个最讨厌的是步骤就是图片，因为我的图片在Halo后台是相对路径，这就导致复制到墨滴后台，要么是自己一个个添加网站前缀，要么就是重新截图，很麻烦。</p><p>为了节约这点时间，我打算自己做一个本地的编辑器。当然主要原因是最近谷歌推出了Antigravity，里面的Gemini 3 Pro免费用。如下是我的项目的初始化的提示词:</p><blockquote><p>使用rust开发一个跨平台的基于markdown转成微信公众号的编辑器，样式需要内连。</p></blockquote><p>Gemini3 Pro 用的技术栈是 Tauri 和 React，Tauri 主要管“和电脑打交道”的那部分，比如文件操作、窗口管理之类的底层功能；React 就负责“你看到的那一层”，也就是界面、交互、按钮这些前端展示的东西。</p><p>基本上一轮跑下来，完成度大概就有 90% 了，界面如下，其中右上角的网址前缀是我后面迭代一轮得到的，也就是最需要的功能，这篇推文也就是通过这个方式来生成的。</p><p><img src="/upload/2025/11/image-1763729835947.png" alt="image-1763729835947" /></p><p>项目目前开源在在Github上，我通过GitHub action自动化打包了全平台安装包，见<a href="https://github.com/xuzhougeng/WxTyper/releases" target="_blank">releases</a>，至少我在Windows 11里面是能够直接通过exe安装，但是下载的时候会被认为是不安全文件，需要手动选择保存。</p>]]>
                </content>
            </entry>
            <entry>
                <title><![CDATA[在Shell中配置一个AI智能助手]]></title>
                <link rel="alternate" type="text/html" href="http://xuzhougeng.com/archives/config-ai-assistant-in-shell" />
                <id>tag:http://xuzhougeng.com,2025-09-14:config-ai-assistant-in-shell</id>
                <published>2025-09-14T10:10:45+08:00</published>
                <updated>2025-09-14T10:10:45+08:00</updated>
                <author>
                    <name>徐洲更</name>
                    <uri>http://xuzhougeng.com</uri>
                </author>
                <content type="html">
                        <![CDATA[<p>当前项目是受到Shell_GPT启发的，使用Rust开发的一个命令行工具，作用跟Shell_GPT几乎一样，就是可以让你命令行里面调用LLM。</p><p>相比于Shell_GPT，我搞的sgp_rs应该是可以直接下载二进制文件解压缩就能用的，所以安装代码如下, 以0.4.5版本为例。如果有最新的，从 <a href="https://github.com/xuzhougeng/sgpt-rs/releases/" target="_blank">https://github.com/xuzhougeng/sgpt-rs/releases/</a>下载。</p><pre><code class="language-bash">wget https://github.com/xuzhougeng/sgpt-rs/releases/download/v0.4.5/sgpt-v0.4.5-linux-musl-x86_64.tar.gztar xf sgpt-v0.4.5-linux-musl-x86_64.tar.gz</code></pre><p>接着把sgpt添加到环境变量中，或者在当前目录下用<code>./sgpt</code>的方式使用。</p><p>先使用我的fake模型评估是否安装成功</p><pre><code class="language-bash">sgpt --model fake &quot;Hello world&quot;</code></pre><p>为了真正的使用模型，编辑 ~/.config/sgpt_rs/.sgptrc 设置使用DeepSeek作为默认模型</p><pre><code class="language-yaml">API_BASE_URL=https://api.deepseek.comOPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxDEFAULT_MODEL=deepseek-chat</code></pre><p>也可以直接在环境变量或者在~/.zshrc, ~/.bashrc中配置</p><pre><code class="language-bash">export API_BASE_URL=https://api.deepseek.comexport OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxexport DEFAULT_MODEL=deepseek-chat</code></pre><p>大抵是支持所所有OpenAI接口兼容的模型，比如说轨迹流动的接口。</p><pre><code class="language-bash">export API_BASE_URL=https://api.siliconflow.cnexport OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxexport DEFAULT_MODEL=moonshotai/Kimi-K2-Instruct-0905</code></pre><p>也支持本地Ollama</p><pre><code class="language-bash"># 推荐写法：带 /v1（客户端会自动补齐 /v1，不带也可以）export API_BASE_URL=http://localhost:11434/v1# Ollama 不需要API_KEY, 随便写export OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx# 选择已拉取的模型，例如：llama3.1 / qwen2.5 / mistral 等export DEFAULT_MODEL=gpt-oss:120b</code></pre><p>如果你是服务器A上配置了Ollama，想让服务器B也能用。千万不要修改让Ollama的Host为0.0.0.0，因为Ollama无法设置API_KEY，很容易被其他人用。最好的方法你用Nignx转发。</p><pre><code class="language-bash">server {  listen 80;  server_name _;   # 或者写你的内网主机名/IP  # 基本认证  # （可选）内网 IP 白名单，更安全  allow 172.16.0.0/12;  allow 192.168.0.0/16;  deny all;  location / {    proxy_pass http://127.0.0.1:11434;    proxy_http_version 1.1;    proxy_set_header Host $host;    proxy_set_header X-Real-IP $remote_addr;    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;    proxy_set_header X-Forwarded-Proto $scheme;    # 对流式响应（SSE）很重要    proxy_buffering off;    proxy_read_timeout 3600s;    proxy_send_timeout 3600s;  }}</code></pre><p>然后其他服务器只需要修改 <code>export API_BASE_URL=http://你的Ollama的服务器:11434/v1</code>即可使用</p><p>对于我而言，sgpt的主要用户就是如下几个</p><p>第一，一些复杂的命令，我想不到起来，例如find查找一天内生成的文件</p><pre><code class="language-bash">sgpt -s &#39;find查找一天内生成的文件&#39;# 输出的结果find . -type f -mtime -1[E]xecute, [M]odify, [D]escribe, [A]bort:</code></pre><p>这里的E表示执行，M表示还不对，继续提示，D表示解释这个命令，A表示退出。</p><p>第二，就是不想复制信息到网页里，可以直接通过管道符合给sgpt，比如说</p><pre><code class="language-">cat install.sh  | sgpt &#39;这个脚本用途是什么?&#39;</code></pre><p>第三，直接生成脚本</p><pre><code class="language-">sgpt --code &#39;来一个shell脚本分析下最近的登录用户&#39; &gt; run.shbash run.sh</code></pre><p>当然实际上我还开发了很多有趣的功能，就后面慢慢介绍了</p>]]>
                </content>
            </entry>
            <entry>
                <title><![CDATA[使用银河录像店代充ChatGPT Plus]]></title>
                <link rel="alternate" type="text/html" href="http://xuzhougeng.com/archives/use-nf-video-to-top-up-chatgpt-plus" />
                <id>tag:http://xuzhougeng.com,2025-09-06:use-nf-video-to-top-up-chatgpt-plus</id>
                <published>2025-09-06T10:01:27+08:00</published>
                <updated>2025-09-06T12:50:26+08:00</updated>
                <author>
                    <name>徐洲更</name>
                    <uri>http://xuzhougeng.com</uri>
                </author>
                <content type="html">
                        <![CDATA[<p>之前我一直用的就是野卡充值我的ChatGPT Plus，然而因为不可抗力，它大概率是用不了了，因此目前的思路就是走代充。</p><p>通过银河录像局  <a href="https://nf.video/5iPel" target="_blank">https://nf.video/5iPel</a> （最后的 5iPel 是我的邀请码）注册一个账号，然后到首页代充的ChatGPT Plus代充。</p><p><img src="/upload/2025/09/image-1757123395417.png" alt="ChatGPT Plus代充" /></p><p>跳转到对应的购买页面，需要注意的是，这里的包年实际上，他还是一个月一个月给你充，只不过你现在是一次性付费了而已，所以我选择的是1个月。</p><p><img src="/upload/2025/09/image-1757123443266.png" alt="image-1757123443266" /></p><p>支付成功后有一个车票信息，你点击这个</p><p><img src="/upload/2025/09/image-1757123581647.png" alt="image-1757123581647" /></p><p>然后需要你绑定账号，就是你登录ChatGPT的账号</p><p><img src="/upload/2025/09/image-1757123610171.png" alt="image-1757123610171" /></p><p>接着，我们需要在登录ChatGPT后，通过<a href="https://chatgpt.com/api/auth/session" target="_blank">https://chatgpt.com/api/auth/session</a> 获取我们的认证信息，</p><p><img src="/upload/2025/09/image-1757123694794.png" alt="image-1757123694794" /></p><p>粘贴到图中，然后验证充值账号</p><p><img src="/upload/2025/09/image-1757123778001.png" alt="image-1757123778001" /></p><p>最后点击确认充值，大概需要等到3-5分钟。</p><p><img src="/upload/2025/09/image-1757123954614.png" alt="image-1757123954614" /></p><p>当然也有一定概率失败，那就只能自己填写账号信息让客服帮你处理了。</p><p><img src="/upload/2025/09/image-1757123932779.png" alt="image-1757123932779" /></p><p>成功的结算界面如下</p><p><img src="/upload/2025/09/image-1757134176660.png" alt="image-1757134176660" /></p>]]>
                </content>
            </entry>
            <entry>
                <title><![CDATA[通过代理使用Claude-Code]]></title>
                <link rel="alternate" type="text/html" href="http://xuzhougeng.com/archives/use-claude-code-by-proxy" />
                <id>tag:http://xuzhougeng.com,2025-09-05:use-claude-code-by-proxy</id>
                <published>2025-09-05T13:12:02+08:00</published>
                <updated>2026-01-06T09:12:23+08:00</updated>
                <author>
                    <name>徐洲更</name>
                    <uri>http://xuzhougeng.com</uri>
                </author>
                <content type="html">
                        <![CDATA[<p>之前使用API搞Claude-Code开发，但是发现太费钱了。后面又搞了订阅，但是20美刀不够用，100美刀又太贵，而且还担心封号。还好上有政策下有对策，总有转发的方案，目前我的主力方案就是<a href="https://www.aicodemirror.com/" target="_blank">https://www.aicodemirror.com/</a>。</p><p>在 <a href="https://www.aicodemirror.com/register?invitecode=A6DYDL" target="_blank">https://www.aicodemirror.com/register?invitecode=A6DYDL</a> 注册（A6DYDL是我的邀请码），然后到控制台<a href="https://www.aicodemirror.com/dashboard" target="_blank">https://www.aicodemirror.com/dashboard</a>，会有一个弹窗提示添加企业微信可以领取8元尝鲜券，进行试用。</p><p><img src="/upload/2025/09/image-1758290776779.png" alt="image-1758290776779" /></p><p>点击“API密钥”，然后创建API密钥</p><p><img src="/upload/2025/09/image-1757048971860.png" alt="image-1757048971860" /></p><p>需要注意，这个密钥你得复制一份到本地记事本存下，后面要用到。如果忘了，就重新建立一个。</p><p><img src="/upload/2025/09/image-1757044443658.png" alt="image-1757044443658" /></p><p>之后，使用aicoder提供的自动化安装脚本，安装npm</p><pre><code class="language-">curl -fsSL https://download.aicodemirror.com/env_deploy/env-install.sh | bash</code></pre><p><img src="/upload/2025/09/image-1757047884543.png" alt="image-1757047884543" /></p><p>安装之后，你应该可以看到npm是在你的家目录下了，比如说我的家目录就是 /home/xzg</p><pre><code class="language-bash">$ which npm/home/xzg/.nvm/versions/node/v22.19.0/bin/npm</code></pre><p>然后运行运行命令，安装官方claude-code</p><pre><code class="language-bash">npm install -g @anthropic-ai/claude-code</code></pre><p>接着使用如下脚本，配置环境，需要用到刚才获取的API_KYE</p><pre><code class="language-">curl -fsSL https://download.aicodemirror.com/env_deploy/env-deploy.sh | bash -s -- &quot;你的API_KEY&quot;</code></pre><p>如果因为环境没有jq，导致无法正确编辑 ~/.claude.json ，可以手动编辑。后续变更密钥后也可以自己手动改</p><pre><code class="language-">{  &quot;customApiKeyResponses&quot;: {    &quot;approved&quot;: [      &quot;你的API_KEY的最后20位&quot;    ]  }}</code></pre><p>可以自己手动在 .bashrc，.zshrc 添加如下的环境变量。</p><pre><code class="language-">export ANTHROPIC_BASE_URL=https://api.aicodemirror.com/api/claudecodeexport ANTHROPIC_API_KEY=刚才复制的你的密钥export ANTHROPIC_AUTH_TOKEN=&quot;&quot;</code></pre><p>使用claude打开后，会让配置主题这些，最后就会看到下图，其中API Base URL就是代理商的地址。</p><p><img src="/upload/2025/09/image-1757044729711.png" alt="image-1757044729711" /></p>]]>
                </content>
            </entry>
            <entry>
                <title><![CDATA[Juicer 1.6 数据处理流程详解]]></title>
                <link rel="alternate" type="text/html" href="http://xuzhougeng.com/archives/detailed-explanation-of-the-data-processing-flow-of-juicer-1-6" />
                <id>tag:http://xuzhougeng.com,2025-09-04:detailed-explanation-of-the-data-processing-flow-of-juicer-1-6</id>
                <published>2025-09-04T21:38:13+08:00</published>
                <updated>2025-09-04T21:38:13+08:00</updated>
                <author>
                    <name>徐洲更</name>
                    <uri>http://xuzhougeng.com</uri>
                </author>
                <content type="html">
                        <![CDATA[<h2 id="%E6%A6%82%E8%BF%B0" tabindex="-1">概述</h2><p>Juicer 是一个用于处理 Hi-C 测序数据的完整分析流程，从原始 FASTQ 文件到最终的接触矩阵（.hic 文件）。</p><p>安装方法如下</p><pre><code class="language-bash">wget https://github.com/aidenlab/juicer/archive/refs/tags/1.6.tar.gztar xf 1.6.tar.gzcd juicer-1.6ln -s $PWD/CPU scriptscd scripts/commonwget https://hicfiles.tc4ga.com/public/juicer/juicer_tools.1.9.9_jcuda.0.8.jarln -s juicer_tools.1.9.9_jcuda.0.8.jar  juicer_tools.jar</code></pre><h2 id="%E4%B8%BB%E8%A6%81%E5%A4%84%E7%90%86%E9%98%B6%E6%AE%B5" tabindex="-1">主要处理阶段</h2><h3 id="1.-%E6%AF%94%E5%AF%B9%E9%98%B6%E6%AE%B5-(alignment)" tabindex="-1">1. 比对阶段 (Alignment)</h3><p><strong>功能</strong>：将双端测序reads比对到参考基因组</p><ul><li>使用 BWA mem 进行比对</li><li>参数 <code>-SP5M</code> 专门针对 Hi-C 数据优化<ul><li><code>-SP</code>: 跳过配对救援，将read1和read2独立比对</li><li><code>-5</code>: 对于split reads，输出主要和补充比对</li><li><code>-M</code>: 将较短的split标记为次要比对</li></ul></li><li>输出：SAM 格式的比对文件</li></ul><h3 id="2.-%E5%B5%8C%E5%90%88reads%E5%A4%84%E7%90%86-(chimeric-reads-processing)" tabindex="-1">2. 嵌合reads处理 (Chimeric Reads Processing)</h3><p><strong>功能</strong>：识别和处理跨越多个基因组区域的reads</p><h4 id="%E4%BB%80%E4%B9%88%E6%98%AF%E5%B5%8C%E5%90%88reads" tabindex="-1">什么是嵌合reads</h4><p>在Hi-C实验中，一个DNA分子可能包含多个连接点：</p><pre><code class="language-">Read序列: [区域A]--[连接点]--[区域B]--[连接点]--[区域C]</code></pre><h4 id="%E5%A4%84%E7%90%86%E6%9C%BA%E5%88%B6" tabindex="-1">处理机制</h4><p><code>chimeric_blacklist.awk</code> 脚本将reads分为三类：</p><ul><li><strong>正常配对</strong> (<code>_norm.txt</code>)：标准的双端配对，两个reads各映射到单一位置</li><li><strong>异常配对</strong> (<code>_abnorm.sam</code>)：包含嵌合reads，有补充比对（SA tag）</li><li><strong>未映射</strong> (<code>_unmapped.sam</code>)：无法比对的低质量reads</li></ul><h4 id="%E7%94%9F%E7%89%A9%E5%AD%A6%E6%84%8F%E4%B9%89" tabindex="-1">生物学意义</h4><ul><li>反映多重染色质互作（A-B-C三者空间接近）</li><li>可能指示染色体重排或复杂的空间结构</li><li>提供额外的互作信息，提高数据利用率</li></ul><h3 id="3.-%E7%89%87%E6%AE%B5%E5%88%86%E9%85%8D-(fragment-assignment)" tabindex="-1">3. 片段分配 (Fragment Assignment)</h3><p><strong>功能</strong>：将reads分配到对应的限制性酶切片段</p><h4 id="%E4%BD%9C%E7%94%A8%E6%9C%BA%E5%88%B6" tabindex="-1">作用机制</h4><ul><li>使用 <code>fragment.pl</code> 根据酶切位点文件分配片段编号</li><li>为每个read pair添加片段信息（片段号和片段间距离）</li></ul><h4 id="%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F%E8%BD%AC%E6%8D%A2" tabindex="-1">数据格式转换</h4><p>分配前：</p><pre><code class="language-">readname chr1 pos1 chr2 pos2 strand1 strand2</code></pre><p>分配后：</p><pre><code class="language-">readname chr1 pos1 frag1 chr2 pos2 frag2 frag_distance</code></pre><h4 id="%E8%B4%A8%E9%87%8F%E6%8E%A7%E5%88%B6%E6%84%8F%E4%B9%89" tabindex="-1">质量控制意义</h4><p>片段分配用于区分：</p><ul><li><strong>有效配对</strong>：不同片段间的连接（真实互作）</li><li><strong>自连片段</strong> (dangling ends)：同一片段内的连接</li><li><strong>自环片段</strong> (self-circles)：片段自身环化</li><li><strong>重连片段</strong> (re-ligation)：相邻片段的非特异连接</li></ul><h4 id="dnase-hi-c%E7%89%B9%E6%AE%8A%E5%A4%84%E7%90%86" tabindex="-1">DNase-Hi-C特殊处理</h4><p>当使用 <code>site=&quot;none&quot;</code> 时，不进行实际片段分配，设置假片段值（0和1）</p><h3 id="4.-%E6%8E%92%E5%BA%8F-(sorting)" tabindex="-1">4. 排序 (Sorting)</h3><p><strong>功能</strong>：对处理后的数据进行多键排序</p><ul><li>排序顺序：染色体 → 片段 → 链方向 → 位置</li><li>使用临时目录处理大文件：<code>-T $tmpdir</code></li></ul><h3 id="5.-%E5%90%88%E5%B9%B6-(merge)" tabindex="-1">5. 合并 (Merge)</h3><p><strong>功能</strong>：将所有排序文件合并为单一文件</p><ul><li>输出：<code>merged_sort.txt</code></li><li>保持排序顺序，为去重做准备</li></ul><h3 id="6.-%E5%8E%BB%E9%87%8D%E5%A4%8D-(deduplication)" tabindex="-1">6. 去重复 (Deduplication)</h3><p><strong>功能</strong>：去除PCR扩增产生的重复reads</p><h4 id="%E5%A4%84%E7%90%86%E9%80%89%E9%A1%B9" tabindex="-1">处理选项</h4><ul><li>默认模式：使用&quot;wobble&quot;策略（允许位置轻微偏移）</li><li>精确模式（<code>-j</code>参数）：仅去除完全相同的重复</li></ul><h4 id="%E8%BE%93%E5%87%BA%E6%96%87%E4%BB%B6" tabindex="-1">输出文件</h4><ul><li><code>merged_nodups.txt</code>：去重后的有效配对</li><li><code>dups.txt</code>：被去除的重复reads</li><li><code>opt_dups.txt</code>：光学重复</li></ul><h3 id="7.-%E7%BB%9F%E8%AE%A1%E5%88%86%E6%9E%90-(statistics)" tabindex="-1">7. 统计分析 (Statistics)</h3><p><strong>功能</strong>：生成质量控制指标</p><h4 id="%E4%B8%BB%E8%A6%81%E7%BB%9F%E8%AE%A1%E5%86%85%E5%AE%B9" tabindex="-1">主要统计内容</h4><ul><li><strong>文库复杂度</strong>：评估文库多样性</li><li><strong>有效配对率</strong>：真实互作的比例</li><li><strong>片段内/间配对</strong>：评估消化和连接效率</li><li><strong>短程/长程互作</strong>：距离分布统计</li><li><strong>碰撞分析</strong>：处理异常和嵌合reads统计</li></ul><h3 id="8.-hic%E6%96%87%E4%BB%B6%E7%94%9F%E6%88%90-(hic-file-creation)" tabindex="-1">8. HiC文件生成 (HiC File Creation)</h3><p><strong>功能</strong>：创建二进制接触矩阵文件</p><h4 id="%E8%B4%A8%E9%87%8F%E7%89%88%E6%9C%AC" tabindex="-1">质量版本</h4><ul><li><strong>inter.hic</strong>：MAPQ ≥ 1（包含更多数据）</li><li><strong>inter_30.hic</strong>：MAPQ ≥ 30（高质量数据）</li></ul><h4 id="%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E" tabindex="-1">参数说明</h4><ul><li><code>-f</code>：包含片段信息（用于片段级分辨率）</li><li><code>-s</code>：统计文件路径</li><li><code>-g</code>：直方图输出</li><li><code>-q</code>：最小映射质量阈值</li></ul><h3 id="9.-%E5%90%8E%E5%A4%84%E7%90%86-(post-processing)" tabindex="-1">9. 后处理 (Post-processing)</h3><p><strong>功能</strong>：特征注释和高级分析</p><ul><li>调用 <code>juicer_postprocessing.sh</code></li><li>添加基因组注释</li><li>识别染色质环等特征</li></ul><h2 id="%E6%96%AD%E7%82%B9%E6%81%A2%E5%A4%8D%E6%9C%BA%E5%88%B6" tabindex="-1">断点恢复机制</h2><p>Juicer 支持从特定阶段恢复，避免重复计算：</p><h3 id="%E6%81%A2%E5%A4%8D%E9%98%B6%E6%AE%B5-(-s-%E5%8F%82%E6%95%B0)" tabindex="-1">恢复阶段 (-S 参数)</h3><ul><li><strong>merge</strong>：从合并步骤开始（比对已完成）</li><li><strong>dedup</strong>：从去重步骤开始（合并已完成）</li><li><strong>final</strong>：从生成HiC文件开始（去重已完成）</li><li><strong>postproc</strong>：仅执行后处理</li><li><strong>early</strong>：在统计后提前退出</li></ul><h2 id="%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E5%8F%8A%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88" tabindex="-1">常见问题及解决方案</h2><h3 id="1.-awk-%E5%85%BC%E5%AE%B9%E6%80%A7%E9%97%AE%E9%A2%98" tabindex="-1">1. AWK 兼容性问题</h3><p><strong>问题</strong>：<code>and() function never defined</code><br /><strong>原因</strong>：使用了 mawk 而非 gawk<br /><strong>解决</strong>：安装并使用 GNU awk (gawk)</p><h3 id="2.-%E7%BC%BA%E5%B0%91-juicer_tools" tabindex="-1">2. 缺少 juicer_tools</h3><p><strong>问题</strong>：<code>juicer_tools: No such file or directory</code><br /><strong>解决</strong>：下载 juicer_tools.jar 并创建执行脚本</p><h3 id="3.-%E9%AB%98%E5%B5%8C%E5%90%88reads%E7%8E%87" tabindex="-1">3. 高嵌合reads率</h3><p><strong>可能原因</strong>：</p><ul><li>过度消化（片段太小）</li><li>连接浓度过高</li><li>交联不充分<br /><strong>建议</strong>：优化实验条件，检查酶切和连接步骤</li></ul><h2 id="%E5%85%B3%E9%94%AE%E8%B4%A8%E9%87%8F%E6%8C%87%E6%A0%87" tabindex="-1">关键质量指标</h2><h3 id="%E8%89%AF%E5%A5%BD%E7%9A%84hi-c%E6%95%B0%E6%8D%AE%E5%BA%94%E5%85%B7%E5%A4%87" tabindex="-1">良好的Hi-C数据应具备</h3><ul><li>有效配对率 &gt; 60%</li><li>片段间配对率 &gt; 90%</li><li>长程互作（&gt;20kb）&gt; 40%</li><li>PCR重复率 &lt; 20%</li><li>嵌合reads率 &lt; 15%</li></ul><h3 id="%E8%B4%A8%E9%87%8F%E8%AF%84%E4%BC%B0%E8%A6%81%E7%82%B9" tabindex="-1">质量评估要点</h3><ol><li><strong>比对率</strong>：评估测序质量和基因组匹配度</li><li><strong>有效配对率</strong>：反映实验成功程度</li><li><strong>文库复杂度</strong>：评估数据多样性</li><li><strong>距离分布</strong>：验证是否符合预期的幂律分布</li><li><strong>片段大小分布</strong>：评估酶切效率</li></ol><h2 id="%E4%BC%98%E5%8C%96%E5%BB%BA%E8%AE%AE" tabindex="-1">优化建议</h2><h3 id="%E8%AE%A1%E7%AE%97%E8%B5%84%E6%BA%90" tabindex="-1">计算资源</h3><ul><li>使用多线程加速BWA比对（<code>-t</code> 参数）</li><li>预留足够的临时空间用于排序</li><li>内存需求：至少16GB用于 juicer_tools</li></ul><h3 id="%E6%95%B0%E6%8D%AE%E5%A4%84%E7%90%86" tabindex="-1">数据处理</h3><ul><li>保留中间文件便于问题排查</li><li>定期检查各阶段输出文件大小</li><li>使用 <code>-S</code> 参数从断点恢复，避免重复计算</li></ul><h2 id="%E6%96%87%E4%BB%B6%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84" tabindex="-1">文件组织结构</h2><pre><code class="language-">topDir/├── fastq/          # 原始测序文件├── splits/         # 中间处理文件│   ├── *.sam│   ├── *_norm.txt│   ├── *_abnorm.sam│   ├── *_unmapped.sam│   └── *.sort.txt├── aligned/        # 最终输出文件│   ├── merged_sort.txt│   ├── merged_nodups.txt│   ├── inter.txt│   ├── inter.hic│   └── inter_30.hic└── HIC_tmp/        # 临时文件目录</code></pre><h2 id="%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99" tabindex="-1">参考资料</h2><ul><li><a href="https://github.com/aidenlab/juicer" target="_blank">Juicer GitHub</a></li><li><a href="https://github.com/aidenlab/juicer/wiki" target="_blank">Juicer Wiki</a></li><li>Durand et al., 2016. Cell Systems%</li></ul>]]>
                </content>
            </entry>
            <entry>
                <title><![CDATA[使用Codex模仿shell_gpt]]></title>
                <link rel="alternate" type="text/html" href="http://xuzhougeng.com/archives/usecodextoimitateshellgpt" />
                <id>tag:http://xuzhougeng.com,2025-08-27:usecodextoimitateshellgpt</id>
                <published>2025-08-27T15:16:54+08:00</published>
                <updated>2025-08-27T15:16:54+08:00</updated>
                <author>
                    <name>徐洲更</name>
                    <uri>http://xuzhougeng.com</uri>
                </author>
                <content type="html">
                        <![CDATA[<blockquote><p>Agent的出现，导致每次任务的token消耗量都特别的大，所以Cursor我也不再订阅了，使用Claude-Code和Codex进行平时的开发。</p></blockquote><p>之前用OpenAI的codex进行项目开发，发现效果非常一般，但是GPT-5出来之后，改变了我的看法。</p><p>我的目标是用Rust写一个<a href="https://github.com/TheR1D/shell_gpt" target="_blank">shell_gpt</a>，这是生成的结果 <a href="https://github.com/xuzhougeng/sgpt-rs" target="_blank">https://github.com/xuzhougeng/sgpt-rs</a> ，确实完成了我的需求，大概就说了如下一些话</p><ol><li>阅读 shellgpt 项目，我计划使用Rust对该项目进行重构，请制定一个项目规划</li><li>仅支持原生 JSON 工具 ；  termimad（更终端友好）； 自行 reqwest 保持更灵活； 然后将规划写到Plan.md中</li><li>请继续搭建 Rust 项目骨架（目录结构与最小 main/CLI 参数）</li><li>yes  proceed with handler routing + config loader next</li><li>start on the reqwest-based LLM streaming client?</li><li>before you start, let me give your a basic information; API_BASE_URL=<a href="https://api.deepseek.com" target="_blank">https://api.deepseek.com</a>  OPENAI_API_KEY=sk-  DEFAULT_MODEL=deepseek-chat ; you should set this to env and use for following test; plase go on toto wire the client into the Default and Chat handlers next, using a simple text printer and START/STOP streaming ;</li><li>implement ChatSession persistence and use it in --chat/–repl next</li><li>first add usage into readme</li><li><a href="http://Plan.md" target="_blank">Plan.md</a> 根据进度表，我们现在是到了哪一步，下一步做什么？</li><li>需要的！</li><li>先把 --show-chat 做成更易读的格式, 开始开始接通 Shell/Code/Describe</li><li>我觉得需要接入termimad了</li><li>需要</li><li>需要</li><li>shell模式不太行，是不是还不能执行命令？</li><li><a href="http://Plan.md" target="_blank">Plan.md</a> 根据计划，我们现在到了哪一步？</li><li><ol><li>接入 DEFAULT_EXECUTE_SHELL_CMD 并完善 Shell 交互</li></ol></li><li>可以，完善README</li><li>需要的</li><li>请这样子做！</li><li>需要</li><li><a href="http://README.md" target="_blank">README.md</a> 区分版本，中文版本在README_zh.md 原来的版本是英文</li><li>增加一个.gitignore</li><li>staget this change and commit with git</li><li>add other file and commit</li><li>use git status check  and add file and commit with message</li><li>yes</li><li>我目前已经按照 <a href="http://Plan.md" target="_blank">Plan.md</a> 仿照 shell_gpt 开发了一部分的 sgpt_rs， 请问的项目支持 git diff | sgpt “Generate git commit message, for my changes” 使用方法吗？</li><li>$ tree -L 2 | sgpt-rs ‘描述下项目’<br />Error: LLM error: 422 Unprocessable Entity</li><li>无法通过build …（长错误日志）</li><li>在错误输出中附带更加明确的修复建议（如检测到 422 且包含 “tool_choice” 时提示 --no-functions）</li><li>我觉得参数 --no-functions 换成–functions 默认不用tools, 除非手动要求启动</li><li>当前的sgpt-rs项目如何读取变量，从 .sgptrc 文件吗？</li><li>修改读取路径为  ~/.config/sgpt_rs/.sgptrc</li><li>不仅仅是配置文件读取路径，应该是配置目录就是  ~/.config/sgpt_rs</li><li>需要的</li><li>i found use cargo build have many warnings , try to fix</li><li>following warnings: …（长 warning 输出）</li><li>sgpt的配置文件的路径哪个？</li><li>i have set ~/.config/sgpt_rs/.sgptrc, but Error: LLM error: 401 Unauthorized {“error”:{“message”:“Authentication Fails, Your api key: ****wjIA is invalid”,“type”:“authentication_error”,“param”:null,“code”:“invalid_request_error”}}<br />Hint: Set OPENAI_API_KEY or export it in your shell</li><li>use git to check change and stage and commmit</li></ol><p><a href="http://xn--Plan-494f35bv7le9qq20ave8azs0c.md" target="_blank">如下是他的计划Plan.md</a></p><h1 id="shellgpt-rust-%E9%87%8D%E6%9E%84%E8%A7%84%E5%88%92%EF%BC%88plan%EF%BC%89" tabindex="-1">ShellGPT Rust 重构规划（Plan）</h1><blockquote><p>决策确认（来自你的偏好）：</p><ul><li>工具调用：仅支持原生 JSON 工具（不再兼容 Python 函数类定义）。</li><li>Markdown 渲染：使用 termimad（更终端友好）。</li><li>LLM 客户端：基于 reqwest 自行实现（保持更高灵活性），不绑定 async-openai。</li></ul></blockquote><h2 id="1.-%E7%9B%AE%E6%A0%87%E4%B8%8E%E8%8C%83%E5%9B%B4" tabindex="-1">1. 目标与范围</h2><ul><li>目标：<ul><li>复刻现有 CLI 行为与输出（参数、互斥关系、REPL、Chat/Cache/Role 等），在性能、稳定性、跨平台（Linux/macOS/Windows）上显著提升。</li><li>可扩展：统一 LLM 适配、原生工具调用（JSON 工具）、可插拔渲染与打印。</li></ul></li><li>非目标：<ul><li>迁移或执行旧版 Python 函数生态；不破坏现有配置与用户数据（会话、缓存、角色）。</li></ul></li></ul><h2 id="2.-%E6%80%BB%E4%BD%93%E6%9E%B6%E6%9E%84" tabindex="-1">2. 总体架构</h2><ul><li>分层：<ul><li>CLI 层：参数解析、命令路由、互斥校验。</li><li>应用层：角色与消息拼装、模式处理器（默认/聊天/REPL/代码/命令）、打印器。</li><li>领域层：配置、请求缓存、会话存储、角色管理、原生 JSON 工具、OS/Shell 检测与执行。</li><li>LLM 适配层：OpenAI 兼容端点/LiteLLM/自托管端点统一抽象，使用 reqwest 实现流式解析。</li></ul></li><li>关键抽象：<ul><li>trait LlmClient：<code>chat_stream(messages, params) -&gt; impl Stream&lt;Item = Delta&gt;</code>，屏蔽供应商差异（tool_calls、增量/终止原因）。</li><li>trait Printer：<code>live_print(stream)</code>, <code>static_print(text)</code>；实现 Text 与 Markdown（termimad）。</li><li>Handler（基类）：生成 messages、驱动 LLM、打印输出；派生 Default/Chat/Repl/Code/Shell/DescribeShell。</li><li>Cache/ChatSession：请求级缓存、会话消息 JSON 存储与截断（保留首条 system）。</li></ul></li></ul><h2 id="3.-%E6%A8%A1%E5%9D%97%E6%98%A0%E5%B0%84%EF%BC%88python-%E2%86%92-rust%EF%BC%89" tabindex="-1">3. 模块映射（Python → Rust）</h2><ul><li>sgpt/app.py → <code>crate::cli</code>：clap 命令与 flags、入口 <code>main</code>、互斥与默认值。</li><li>handlers/* → <code>crate::handlers::{default, chat, repl, code, shell, describe}</code>。</li><li><a href="http://role.py" target="_blank">role.py</a> → <code>crate::role::{SystemRole, DefaultRoles, store}</code>。</li><li><a href="http://printer.py" target="_blank">printer.py</a> → <code>crate::printer::{TextPrinter, MarkdownPrinter(termimad)}</code>。</li><li><a href="http://config.py" target="_blank">config.py</a> → <code>crate::config::{loader, env_merge, defaults}</code>。</li><li><a href="http://cache.py" target="_blank">cache.py</a> → <code>crate::cache::{request_cache, chat_cache}</code>。</li><li><a href="http://function.py" target="_blank">function.py</a> + llm_functions → <code>crate::functions::{schema, registry, executor}</code>（原生 JSON 工具）。</li><li><a href="http://utils.py" target="_blank">utils.py</a> → <code>crate::utils::{editor, run_command, install_integration, version}</code>。</li><li><a href="http://integration.py" target="_blank">integration.py</a> → <code>crate::integration::{bash, zsh}</code>。</li></ul><h2 id="4.-%E6%8A%80%E6%9C%AF%E9%80%89%E5%9E%8B" tabindex="-1">4. 技术选型</h2><ul><li>CLI/REPL：clap v4 + rustyline/reedline（行编辑、历史、多行输入）。</li><li>异步/HTTP：tokio + reqwest（自实现 OpenAI 兼容 Chat Completions 流式接口，SSE 或 chunked）。</li><li>终端与颜色：crossterm + owo-colors。</li><li>Markdown 渲染：termimad（主题可调，匹配 CODE_THEME 近似语义）。</li><li>语法高亮：syntect（代码块高亮，主题近似映射）。</li><li>序列化：serde/serde_json。</li><li>路径与平台：directories + sysinfo。</li><li>错误：anyhow/thiserror。</li><li>测试：assert_cmd、insta（快照）、mockito（HTTP 模拟）、proptest（必要时）。</li></ul><h2 id="5.-cli-%E5%85%BC%E5%AE%B9%E7%9F%A9%E9%98%B5" tabindex="-1">5. CLI 兼容矩阵</h2><ul><li>全量还原参数与互斥：<ul><li>通用：<code>--model --temperature --top-p --md/--no-md --editor --cache/--no-cache --version</code>。</li><li>Assistance：<code>--shell/-s --interaction/--no-interaction --describe-shell/-d --code/-c --functions/--no-functions</code>。</li><li>Chat：<code>--chat --repl --show-chat --list-chats/-lc</code>。</li><li>Role：<code>--role --create-role --show-role --list-roles/-lr</code>。</li><li>隐藏：<code>--install-integration --install-functions</code>。</li></ul></li><li>行为一致性：<ul><li>Shell/Code 模式禁用 markdown；三者（shell/describe/code）互斥；REPL 支持 <code>&quot;&quot;&quot;</code> 多行；stdin 拼接含 <code>__sgpt__eof__</code> 协议。</li></ul></li></ul><h2 id="6.-%E9%85%8D%E7%BD%AE%E4%B8%8E%E6%95%B0%E6%8D%AE%E5%B8%83%E5%B1%80" tabindex="-1">6. 配置与数据布局</h2><ul><li>兼容路径：<code>~/.config/shell_gpt/.sgptrc</code>（优先 env 后配置文件）。</li><li>默认键与语义保持一致：<code>DEFAULT_MODEL, CACHE_PATH, CHAT_CACHE_PATH, CODE_THEME, ...</code>。</li><li>会话与请求缓存：JSON 文件；会话截断保留首条 system；缓存命中键与 Python 逻辑一致（忽略含 @FunctionCall 的结果）。</li></ul><h2 id="7.-llm-%E9%80%82%E9%85%8D%EF%BC%88reqwest-%E5%AE%9E%E7%8E%B0%EF%BC%89" tabindex="-1">7. LLM 适配（reqwest 实现）</h2><ul><li>协议：OpenAI Chat Completions 兼容（<code>/v1/chat/completions</code>），支持 <code>base_url</code> 与 <code>api_key</code>；<code>stream=true</code> 增量解析（SSE/分块）。</li><li>tool_calls：解析增量中的 <code>tool_calls</code>，在 finish_reason=tool_calls 事件时进入工具执行分支并继续对话。</li><li>超时/重试：继承 <code>REQUEST_TIMEOUT</code>，实现指数退避（可配置重试次数与 429/5xx 策略）。</li><li>LiteLLM：通过 <code>base_url</code> 适配（OpenAI 兼容模式），不引入额外依赖。</li></ul><h2 id="8.-%E5%8E%9F%E7%94%9F-json-%E5%B7%A5%E5%85%B7%EF%BC%88functions%EF%BC%89" tabindex="-1">8. 原生 JSON 工具（Functions）</h2><ul><li>目录：<code>~/.config/shell_gpt/functions</code>。</li><li>每个工具一个 JSON 文件，示例：<pre><code class="language-json">{  &quot;name&quot;: &quot;execute_shell_command&quot;,  &quot;description&quot;: &quot;Execute a shell command and return stdout/stderr.&quot;,  &quot;parameters&quot;: {    &quot;type&quot;: &quot;object&quot;,    &quot;properties&quot;: {      &quot;cmd&quot;: {&quot;type&quot;: &quot;string&quot;}    },    &quot;required&quot;: [&quot;cmd&quot;]  },  &quot;exec&quot;: {    &quot;program&quot;: &quot;/bin/sh&quot;,    &quot;args_template&quot;: [&quot;-c&quot;, &quot;{{cmd}}&quot;],    &quot;stdin&quot;: false,    &quot;timeout_sec&quot;: 60  }}</code></pre></li><li>约定：<ul><li><code>parameters</code> 使用 JSON Schema（draft-07 近似）供 LLM 工具调用描述。</li><li><code>exec</code> 描述执行方式：<ul><li><code>program</code> 可执行路径；<code>args_template</code> 支持 <code>{{param}}</code> 占位符替换；</li><li>若 <code>stdin=true</code> 则将完整参数 JSON 通过 stdin 传入；</li><li><code>timeout_sec</code> 超时终止并返回非零状态描述。</li></ul></li></ul></li><li>执行与安全：<ul><li>受 <code>OPENAI_USE_FUNCTIONS</code> 总开关控制；<code>SHOW_FUNCTIONS_OUTPUT</code> 控制是否原样回显输出块。</li><li>仅加载 JSON 工具（忽略 .py）；目录白名单限制，禁止递归外部路径。</li></ul></li></ul><h2 id="9.-%E4%BA%A4%E4%BA%92%E4%B8%8E-shell-%E9%9B%86%E6%88%90" tabindex="-1">9. 交互与 Shell 集成</h2><ul><li><code>--shell</code>：生成后进入 <code>[E]xecute / [M]odify / [D]escribe / [A]bort</code>（或 <code>--no-interaction</code> 直出）。</li><li>执行：按 OS/SHELL 构造命令（PowerShell/CMD/bash/zsh），与 Python 逻辑一致。</li><li>REPL：信息提示一致；<code>e/d</code> 特殊指令保留；历史可视化；termimad 渲染（在默认角色与 describe 模式）。</li><li>Shell integration：复用现有注入脚本（bash/zsh），Windows 后续 PowerShell Profile 支持。</li></ul><h2 id="10.-%E6%B5%8B%E8%AF%95%E4%B8%8E%E8%B4%A8%E9%87%8F%E4%BF%9D%E9%9A%9C" tabindex="-1">10. 测试与质量保障</h2><ul><li>单测：<ul><li>参数解析与互斥；消息构造；缓存/会话裁剪；JSON 工具解析与执行（mock 进程）。</li><li>配置加载/合并；OS/SHELL 路径分支。</li></ul></li><li>集成测：<ul><li>模拟 LLM 流（本地 HTTP mock，SSE/分块），校验 Printer 与增量输出。</li></ul></li><li>端到端：<ul><li>覆盖现有 Python 测试场景的等价用例（默认/代码/命令/聊天/REPL/角色/显示聊天等）。</li></ul></li><li>快照：<ul><li>termimad 渲染与文本颜色输出使用 insta 快照。</li></ul></li><li>CI：<ul><li>Linux/macOS/Windows 矩阵；fmt+clippy+test；最小化网络依赖（完全使用本地 mock）。</li></ul></li></ul><h2 id="11.-%E5%8F%91%E5%B8%83%E4%B8%8E%E4%BA%A4%E4%BB%98" tabindex="-1">11. 发布与交付</h2><ul><li>构建：<code>cargo build --release</code>；提供多平台产物（x86_64/aarch64）。</li><li>包装：Homebrew tap、Scoop、AUR、.deb/.rpm（分阶段推进）。</li><li>文档：README 与迁移指南（JSON 工具编写规范、示例库、常见问题）。</li><li>版本：0.x 快速迭代可用；达完全兼容后 1.0。</li></ul><h2 id="12.-%E8%BF%81%E7%A7%BB%E4%B8%8E%E5%85%BC%E5%AE%B9" tabindex="-1">12. 迁移与兼容</h2><ul><li>配置：首次启动检测 <code>.sgptrc</code>，保留现有键并补全缺省；仍优先 ENV。</li><li>角色/会话/缓存：无损继承现有 JSON 文件；路径可配置；结构不变。</li><li>参数与帮助：名称/互斥逻辑一致，帮助文案同步。</li><li>函数生态：新增 JSON 工具方案与脚手架，不再执行旧 .py 函数；提供迁移示例。</li></ul><h2 id="13.-%E9%87%8C%E7%A8%8B%E7%A2%91%E4%B8%8E%E6%97%B6%E9%97%B4%E7%BA%BF%EF%BC%88%E5%BB%BA%E8%AE%AE%EF%BC%89" tabindex="-1">13. 里程碑与时间线（建议）</h2><ul><li>M0 需求冻结与设计评审（0.5 周）<ul><li>产出：该 <a href="http://Plan.md" target="_blank">Plan.md</a> 确认、JSON 工具规范定稿、termimad 主题策略。</li></ul></li><li>M1 CLI 骨架 + 配置加载 + TextPrinter（1 周）<ul><li>clap 参数/互斥/帮助；.sgptrc/env 合并；版本输出；基础颜色输出。</li></ul></li><li>M2 LLM 适配 + 流式打印 + 默认模式（1 周）<ul><li>reqwest SSE/分块解析；DefaultHandler；请求缓存；超时/重试。</li></ul></li><li>M3 Chat/REPL/会话（1 周）<ul><li>ChatSession JSON 存储与裁剪；REPL（多行、e/d）；显示聊天与列表。</li></ul></li><li>M4 Shell/Code/Describe 模式 + 命令执行（1 周）<ul><li>Shell 执行器（多平台）；Describe 走 markdown；Code 模式禁 md。</li></ul></li><li>M5 原生 JSON 工具 V1 + 默认函数安装（1 周）<ul><li>JSON schema 校验、执行器；示例函数库与安装；tool_calls 分支闭环。</li></ul></li><li>M6 termimad 渲染完善 + 测试矩阵 + 打包（1 周）<ul><li>主题映射；端到端与快照；多平台产物。</li></ul></li><li>M7 文档/迁移指南/候选发布（0.5 周）<ul><li>README、示例、已知问题；RC 发版。</li></ul></li><li>总计：6–7 周（部分并行可压缩至 4–5 周）。</li></ul><h2 id="14.-%E9%A3%8E%E9%99%A9%E4%B8%8E%E5%AF%B9%E7%AD%96" tabindex="-1">14. 风险与对策</h2><ul><li>Markdown 实时渲染卡顿：termimad 增量更新；必要时降级静态打印。</li><li>Windows 兼容：尽早纳入 CI；优先验证 PowerShell/CMD 执行路径。</li><li>LLM 兼容差异：对 LiteLLM/OpenAI 细节通过 HTTP mock 收敛；保留可配置字段透传。</li><li>JSON 工具误用与安全：目录白名单；默认关闭执行；超时与返回码处理；输出可选回显。</li></ul><hr /><h3 id="%E9%99%84%EF%BC%9Ajson-%E5%B7%A5%E5%85%B7%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5%EF%BC%88%E7%AE%80%E7%89%88%EF%BC%89" tabindex="-1">附：JSON 工具最佳实践（简版）</h3><ul><li>用最小参数面向任务；参数命名清晰，与模板占位符一致。</li><li>失败时输出结构化错误 JSON（<code>{&quot;error&quot;: {&quot;code&quot;: , &quot;message&quot;: }}</code>），便于 LLM 复述与纠偏。</li><li>避免副作用命令或明确在 description 中警示；必要时让 LLM 先描述再执行。</li></ul>]]>
                </content>
            </entry>
</feed>
