<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title><![CDATA[Eric Guo's blog.cloud-mes.com]]></title>
  <link href="https://blog.cloud-mes.com/atom.xml" rel="self"/>
  <link href="https://blog.cloud-mes.com/"/>
  <updated>2026-04-13T16:36:33+08:00</updated>
  <id>https://blog.cloud-mes.com/</id>
  <author>
    <name><![CDATA[Eric Guo]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
    <entry>
      




<title type="html"><![CDATA[How to fix Bun v1.3.12 based opencode got Killed: 9 after bun turbo build]]></title>
<link href="https://blog.cloud-mes.com/2026/04/12/how-to-fix-bun-v1-dot-3-12-based-opencode-got-killed-9-after-bun-turbo-build/"/>
<updated>2026-04-12T14:50:00+08:00</updated>
<id>https://blog.cloud-mes.com/2026/04/12/how-to-fix-bun-v1-dot-3-12-based-opencode-got-killed-9-after-bun-turbo-build</id>
<category term="Bun" />

      <content type="html"><![CDATA[<p data-sourcepos="1:1-1:33">New bun 1.3.12 release but I got:</p>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div></pre></td><td class='main  text'><pre><div class='line'><span></span>$ ./opencode --version
</div><div class='line'>Killed: 9
</div></pre></td></table></div></figure>
<p data-sourcepos="8:1-8:61">In fact, the binary was fine. The <strong data-sourcepos="8:35-8:52">code signature</strong> was not.</p>
<h2 data-sourcepos="10:1-10:12">Diagnosis</h2>
<p data-sourcepos="12:1-12:56">A quick check with <code data-sourcepos="12:20-12:29">codesign</code> revealed the real culprit:</p>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div></pre></td><td class='main  text'><pre><div class='line'><span></span>$ codesign -vv ./opencode
</div><div class='line'>./opencode: invalid or unsupported format for signature
</div><div class='line'>In architecture: arm64
</div></pre></td></table></div></figure>
<p data-sourcepos="20:1-20:241">On Apple Silicon, macOS enforces code signing strictly. A malformed or corrupt <code data-sourcepos="20:80-20:98">LC_CODE_SIGNATURE</code> load command will cause the kernel to terminate the process immediately with <code data-sourcepos="20:177-20:185">SIGKILL</code> (<code data-sourcepos="20:188-20:198">Killed: 9</code>)—before a single line of your code runs.</p>
<p data-sourcepos="22:1-22:63">You can confirm the signature load command exists with <code data-sourcepos="22:56-22:62">otool</code>:</p>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div></pre></td><td class='main  bash'><pre><div class='line'><span></span>$<span class="w"> </span>otool<span class="w"> </span>-l<span class="w"> </span>./opencode<span class="w"> </span><span class="p">|</span><span class="w"> </span>grep<span class="w"> </span>LC_CODE_SIGNATURE
</div><div class='line'><span class="w">      </span>cmd<span class="w"> </span>LC_CODE_SIGNATURE
</div></pre></td></table></div></figure>
<h2 data-sourcepos="29:1-29:10">The Fix</h2>
<p data-sourcepos="31:1-31:73">Remove the broken signature and replace it with a local ad-hoc signature:</p>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div></pre></td><td class='main  bash'><pre><div class='line'><span></span>codesign<span class="w"> </span>--remove-signature<span class="w"> </span>./opencode
</div><div class='line'>codesign<span class="w"> </span>--sign<span class="w"> </span>-<span class="w"> </span>--force<span class="w"> </span>./opencode
</div></pre></td></table></div></figure>
<p data-sourcepos="38:1-38:12">Then verify:</p>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div><div data-line='4' class='line-number'></div><div data-line='5' class='line-number'></div><div data-line='6' class='line-number'></div></pre></td><td class='main  text'><pre><div class='line'><span></span>$ codesign -vv ./opencode
</div><div class='line'>./opencode: valid on disk
</div><div class='line'>./opencode: satisfies its Designated Requirement
</div><div class='line'> </div><div class='line'>$ ./opencode --version
</div><div class='line'>0.0.0-eric_dev-202604120639
</div></pre></td></table></div></figure>
]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Some tricky command not in the official openclaw document]]></title>
<link href="https://blog.cloud-mes.com/2026/02/17/some-tricky-command-not-in-the-official-openclaw-document/"/>
<updated>2026-02-17T16:26:00+08:00</updated>
<id>https://blog.cloud-mes.com/2026/02/17/some-tricky-command-not-in-the-official-openclaw-document</id>
<category term="OpenClaw" />

      <content type="html"><![CDATA[<p data-sourcepos="1:1-1:80">Make pnpm install success on the MacOS machine already install libvips via brew.</p>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div></pre></td><td class='main  bash'><pre><div class='line'><span></span><span class="nv">SHARP_IGNORE_GLOBAL_LIBVIPS</span><span class="o">=</span><span class="m">1</span><span class="w"> </span>pnpm<span class="w"> </span>install
</div></pre></td></table></div></figure>
]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Quickly fix turbo version not match package.json + bun.lock]]></title>
<link href="https://blog.cloud-mes.com/2026/01/28/quickly-fix-turbo-version-not-match-package-dot-json-plus-bun-dot-lock/"/>
<updated>2026-01-28T06:54:22+08:00</updated>
<id>https://blog.cloud-mes.com/2026/01/28/quickly-fix-turbo-version-not-match-package-dot-json-plus-bun-dot-lock</id>
<category term="Bun" />

      <content type="html"><![CDATA[<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div></pre></td><td class='main  bash'><pre><div class='line'><span></span>rm<span class="w"> </span>-rf<span class="w"> </span>node_modules/turbo-darwin-arm64<span class="w"> </span>node_modules/turbo<span class="w"> </span>node_modules/.bin/turbo
</div><div class='line'>bun<span class="w"> </span>install<span class="w"> </span>--force
</div><div class='line'>./node_modules/.bin/turbo<span class="w"> </span>--version
</div></pre></td></table></div></figure>
]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Using git blame.ignoreRevsFile options to ignore your auto format coding commits]]></title>
<link href="https://blog.cloud-mes.com/2026/01/11/using-git-blame-dot-ignorerevsfile-options-to-ignore-your-auto-format-coding-commits/"/>
<updated>2026-01-11T13:44:00+08:00</updated>
<id>https://blog.cloud-mes.com/2026/01/11/using-git-blame-dot-ignorerevsfile-options-to-ignore-your-auto-format-coding-commits</id>
<category term="Git" />

      <content type="html"><![CDATA[<p data-sourcepos="1:1-1:148">After running any auto-format on a repository, <code data-sourcepos="1:48-1:58">git blame</code> becomes almost useless because every line is “last touched” by the formatting commit.</p>
<p data-sourcepos="3:1-3:73">Git has a built-in solution: tell <code data-sourcepos="3:35-3:45">git blame</code> to ignore specific commits.</p>
<h2 data-sourcepos="5:1-5:48">Create <code data-sourcepos="5:11-5:34">.git-blame-ignore-revs</code> in root repo.</h2>
<figure class='code'><figcaption>.git-blame-ignore-revs</figcaption><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div></pre></td><td class='main  text'><pre><div class='line'><span></span># Formatting / reindent / whitespace-only commits
</div><div class='line'>1a2b3c4d
</div><div class='line'>abcdef01
</div></pre></td></table></div></figure>
<h2 data-sourcepos="13:1-13:33">Enable it in your repo via git</h2>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div></pre></td><td class='main  bash'><pre><div class='line'><span></span>git<span class="w"> </span>config<span class="w"> </span>--local<span class="w"> </span>blame.ignoreRevsFile<span class="w"> </span>.git-blame-ignore-revs
</div></pre></td></table></div></figure>
<p data-sourcepos="19:1-19:99">Now when you run <code data-sourcepos="19:18-19:28">git blame</code>, those commits will be skipped and you can see the real history again.</p>
<h2 data-sourcepos="21:1-21:8">Notes</h2>
<ul data-sourcepos="23:1-24:127">
<li data-sourcepos="23:1-23:111">Commit <code data-sourcepos="23:10-23:33">.git-blame-ignore-revs</code> into your repo so GitHub (and other developers) can use the same ignore list.</li>
<li data-sourcepos="24:1-24:127">GitHub also reads <code data-sourcepos="24:21-24:44">.git-blame-ignore-revs</code> automatically in the web UI, so you’ll get the same “clean blame” there too.</li>
</ul>
]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Deploy Next.js 15.5 via capistrano into self-hosting Rocky Linux 9]]></title>
<link href="https://blog.cloud-mes.com/2025/12/03/deploy-next-dot-js-15-dot-5-via-capistrano-into-self-hosting-rocky-linux-9/"/>
<updated>2025-12-03T11:20:34+08:00</updated>
<id>https://blog.cloud-mes.com/2025/12/03/deploy-next-dot-js-15-dot-5-via-capistrano-into-self-hosting-rocky-linux-9</id>
<category term="capistrano" /><category term="NextJS" /><category term="Rocky" />

      <content type="html"><![CDATA[</div><div class='line'>sudo<span class="w"> </span>chown<span class="w"> </span>sql_chat:sql_chat<span class="w"> </span>sql_chat]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[召唤神龙！7 个 AI 编程智能体的许愿力测评]]></title>
<link href="https://blog.cloud-mes.com/2025/11/09/a-review-of-the-wish-granting-power-of-7-AI-coding-agents/"/>
<updated>2025-11-09T13:36:00+08:00</updated>
<id>https://blog.cloud-mes.com/2025/11/09/a-review-of-the-wish-granting-power-of-7-AI-coding-agents</id>


      <content type="html"><![CDATA[<blockquote data-sourcepos="1:1-1:130">
<p data-sourcepos="1:3-1:130">I planned a book, 7 Coding Agents in 7 Weeks. In the end, I only had two days—and this Chinese article was all I could manage.</p>
</blockquote>
<img class="" src="https://blog.cloud-mes.com//images/2025/7-coding-agent-in-7-weeks.jpg" title="苹果的组织图" >
<h1 data-sourcepos="5:1-5:81">Summon Shenron! A Review of the Wish-Granting Power of 7 AI Programming Agents.</h1>
<h2 data-sourcepos="7:1-7:24">测评原因及声明</h2>
<blockquote data-sourcepos="9:1-9:197">
<p data-sourcepos="9:3-9:197">声明：以下测评内容没有经过任何 AI 的润色或者重写，所以你发现了 AI 味道，那一定是我被影响了，欢迎指出拯救我的 AI 味，如同我的老登味一样</p>
</blockquote>
<p data-sourcepos="11:1-11:330">时光飞快，日月如梭，转眼到了中年，到了看到任何科技都是异端的年纪，但是谁会拒绝拥有一个言出法随，言听计从的智能体呢？如果一个不行，那就再来一个，于是，一个接着一个，我一不小心拥有了 7 个，那么就不妨来个个人风格横向测评吧！</p>
<p data-sourcepos="13:1-13:75">本次测评纯属我个人行为，无任何一拍即合的商业合作。</p>
<p data-sourcepos="15:1-15:144">本次测评使用的方法是不严谨的，仅供我个人记录回忆以及和朋友们的交流使用，您可以看作这是一次娱乐。</p>
<h2 data-sourcepos="17:1-17:15">测评方式</h2>
<p data-sourcepos="19:1-19:506">由于我们是测试比较 AI coding 智能体，而不是 LLM 大模型，所以为了尽量避免苹果和梨放在一起比较的尴尬，我还是控制了一下测试变量，如果硬要说我这个测试方式还是拿苹果和梨放在一起比较，那您一定是对的，只要定语加的足够多，我相信您的结论。但我这篇文章是没有定语的，测评的是全球范围的，不限制商业或者开源，但是受到一些合理工程成本限制的 AI Agent 们的能力。</p>
<p data-sourcepos="21:1-21:501">测试方式是日常开发使用场景，介绍一下背景，我是 15 年的 Rails 程序员，15 年的.Net 程序员，毕业在外企工作了 7 年，互联网公司 5 年，建筑设计公司 6 年。日常使用场景在被测试的 coding agent 上使用的方式都完全相同，coding agent 能接触到的工具就是他们自己的工具，使用的模型总是使用 coding agent 推荐的。如果默认的模型做出的结果不好，我会选择更加强力的模型再试一次。</p>
<p data-sourcepos="23:1-23:271">所有测试都是在本机上测试，环境是 MacOS 15.7.2，homebrew 安装的开发工具集，命令行工具也是系统自带，如果 coding agent 有内置的工具，比如 kimi-cli 就会自动安装 ripgrep，那么 kimi-cli 就用的是它自带的工具。</p>
<p data-sourcepos="25:1-25:195">所有 coding agent 的配置选项都是默认，如果 coding agent 有能力搜索 web，那它就可以搜索 web，如果 coding agent 有做 RAG，那就允许，不会做任何的限制。</p>
<p data-sourcepos="27:1-27:105">所有 coding agent 的测试都只考虑结果是否正确，不会特别考察 agent 的运行速度。</p>
<p data-sourcepos="29:1-29:514">另外关于测试题目，因为都是我的日常开发场景，所以必然有难有容易，也很难特别考虑区分度，我也不会在测评最后打分，因为我不想排序，作为成年人，我可能会排出掉 2～3 个 coding agent 后，余下的我都要。这个策略是现实中非常合理的，如果你日常大量使用 coding agent 的话，应该和我一样感到一个 coding agent 是肯定不够用的，但是如果直接买 200 美刀的 ultra 版本，显然也非常吃亏。</p>
<p data-sourcepos="31:1-31:292">目前我的常驻付费 coding agent 分别是 cursor 和 openai codex，opencode 也是我日常天天使用的，opencode 的付费是按照 token 用量，对于按照 token 用量的，我一般会一直保留使用，但是对于订阅的，我还是会评估，并进行成本优化。</p>
<h2 data-sourcepos="33:1-33:36">没有纳入测试对象及原因</h2>
<ul data-sourcepos="35:1-52:0">
<li data-sourcepos="35:1-35:81"><a data-sourcepos="35:3-35:35" href="https://windsurf.com/">windsurf</a>，只有 GUI，没有会员，不测试了。</li>
<li data-sourcepos="36:1-36:89"><a data-sourcepos="36:3-36:56" href="https://www.augmentcode.com/product/CLI">augmentcode</a>，没有会员，不测试了。</li>
<li data-sourcepos="37:1-37:85"><a data-sourcepos="37:3-37:44" href="https://github.com/Aider-AI/aider">aider</a>，2025 年 8 月后就没发新版本。</li>
<li data-sourcepos="38:1-38:175"><a data-sourcepos="38:3-38:41" href="https://github.com/cline/cline">cline</a>，被 roo cline fork 了，感觉社区治理有问题，另外只做 VS Code 插件，但是我不喜欢微软，也没装 VScode。</li>
<li data-sourcepos="39:1-39:127"><a data-sourcepos="39:3-39:53" href="https://github.com/RooCodeInc/Roo-Code">roo cline</a>，分叉 cline，感觉不尊重开源，另外也只有 VSCode 插件。</li>
<li data-sourcepos="40:1-40:126"><a data-sourcepos="40:3-40:46" href="https://github.com/Kilo-Org/kilocode">kilo</a>，只有 VSCode 插件的不测评。不过 MiniMax M2 目前免费，好评！</li>
<li data-sourcepos="41:1-41:80"><a data-sourcepos="41:3-41:50" href="https://github.com/QwenLM/qwen-code">qwen-code</a>，没时间，下次一定！</li>
<li data-sourcepos="42:1-42:208"><a data-sourcepos="42:3-42:41" href="https://github.com/block/goose">goose</a>，Rust 写的，又不是 OpenAI，应该赶不上 AI coding agent 的快速演进，忽略，另外名字起的也差，呆头鹅…，币圈的品味一言难尽。</li>
<li data-sourcepos="43:1-43:137"><a data-sourcepos="43:3-43:50" href="https://www.warp.dev/blog/how-warp-works">warp</a>，Rust 写的，UI 看起来品味真好，但是 20 美刀的订阅，下次一定！</li>
<li data-sourcepos="44:1-44:178"><a data-sourcepos="44:3-44:32" href="https://cli.iflow.cn/">IFLOW</a>，官网紫色，直接就想 pass 了，本着认真负责的精神，又看了文档站，全站没提到收费，怀疑有坑，坚定 pass。</li>
<li data-sourcepos="45:1-45:271"><a data-sourcepos="45:3-45:50" href="https://github.com/antinomyhq/forge">forgecode</a>，Rust 写的，发版本 5 天前，在一个快速发展的领域，真的不建议用 Rust 写，不过一个月 20 美刀 500 次的用量给的倒是非常慷慨，考虑撸一下羊毛？（算了，我是好人）</li>
<li data-sourcepos="46:1-46:141"><a data-sourcepos="46:3-46:50" href="https://github.com/plandex-ai/plandex">plandex</a>，官网不接受新用户？看一眼最后递交，上个月，可能不行了吧。🙏</li>
<li data-sourcepos="47:1-47:91"><a data-sourcepos="47:3-47:49" href="https://github.com/charmbracelet/crush">crush</a>，Go 写的，又开源，没啥黑点，</li>
<li data-sourcepos="48:1-48:181"><a data-sourcepos="48:3-48:46" href="https://openhands.dev/features">open hands</a>，Basecamp 风格的官网挺喜欢的，但是不知道他们要买啥，可能是团队应用？40 美刀起始直接劝退了我。</li>
<li data-sourcepos="49:1-49:359"><a data-sourcepos="49:3-49:49" href="https://aws.amazon.com/q/developer/">amazon Q</a>，官网介绍为啥要介绍 Java 的升级？显然不是面向我们非 Java 程序员的，定价很特殊，19 美刀一个月，4,000 LOC 的配额，我看了一眼我才用了 10 天的 cursor dashboard，代码改动 28678 accept，按照 AWS 的价格，24000x0.003=72 USD，简直是贵到飞起！</li>
<li data-sourcepos="50:1-50:351"><a data-sourcepos="50:3-50:59" href="https://www.npmjs.com/package/@sourcegraph/amp">Amp CLI</a>，这不是<a data-sourcepos="50:72-50:138" href="https://juejin.cn/post/6844903432084537357">王垠喷过的公司</a>么？要不留给他喷？可惜他 blog 都不维护了。。。除开这个，收费<a data-sourcepos="50:226-50:297" href="https://ampcode.com/manual#pricing">按照 token 收费其实很合理</a>，网站做的也很好，下次一定测评一下。</li>
<li data-sourcepos="51:1-52:0"><a data-sourcepos="51:3-51:37" href="https://factory.ai/pricing">droid</a>，很不错，20 美刀的订阅+token 后付费也很合理，还可以 share 给 50 个用户，考虑<a data-sourcepos="51:143-51:209" href="https://factory.ai/news/terminal-bench">OpenAI Codex 到期后转</a>。</li>
</ul>
<h2 data-sourcepos="53:1-53:15">测评对象</h2>
<ol data-sourcepos="55:1-62:0">
<li data-sourcepos="55:1-55:53"><a data-sourcepos="55:4-55:53" href="https://cursor.com/docs/cli/overview">Cursor CLI</a></li>
<li data-sourcepos="56:1-56:39"><a data-sourcepos="56:4-56:39" href="https://opencode.ai/docs">OpenCode</a></li>
<li data-sourcepos="57:1-57:44"><a data-sourcepos="57:4-57:44" href="https://openai.com/codex/">OpenAI codex</a></li>
<li data-sourcepos="58:1-58:63"><a data-sourcepos="58:4-58:63" href="https://github.com/google-gemini/gemini-cli">Google gemini</a></li>
<li data-sourcepos="59:1-59:61"><a data-sourcepos="59:4-59:61" href="https://code.claude.com/docs/zh-CN/overview">Claude Code</a></li>
<li data-sourcepos="60:1-60:53"><a data-sourcepos="60:4-60:53" href="https://github.com/MoonshotAI/kimi-cli">kimi-cli</a></li>
<li data-sourcepos="61:1-62:0"><a data-sourcepos="61:4-61:52" href="https://www.codebuddy.ai/cli">Tencent CodeBuddy</a></li>
</ol>
<h2 data-sourcepos="63:1-63:65">题目一：Tell me where is opencode store the credentials?</h2>
<ol data-sourcepos="65:1-66:0">
<li data-sourcepos="65:1-66:0">Cursor</li>
</ol>
<p data-sourcepos="67:1-67:232">模型 auto，3 次 greps, 2 次 files，准确指出代码行：<code data-sourcepos="67:66-67:108">packages/opencode/src/auth/index.ts:35-38</code>，实测<code data-sourcepos="67:118-67:152">~/.local/share/opencode/auth.json</code>找到配置 key，但是提到的 MacOS 路径不存在，基本回答正确。</p>
<ol data-sourcepos="69:1-70:0" start="2">
<li data-sourcepos="69:1-70:0">OpenCode</li>
</ol>
<p data-sourcepos="71:1-71:265">模型 big-pickle（免费），1 次 grep，2 次 files，回答“Opencode stores credentials in ~/.local/share/opencode/auth.json (or the equivalent XDG data directory on your system). The file is created with 0o600 permissions for security.”，完全准确。</p>
<ol data-sourcepos="73:1-74:0" start="3">
<li data-sourcepos="73:1-74:0">OpenAI codex</li>
</ol>
<p data-sourcepos="75:1-75:296">模型 gpt-5-codex high，直接读 AGENTS.md 后，回答“OpenCode never stores credentials in the repo—secrets are pulled from environment variables that sst.config.ts consumes, and .env* (or any other credential-bearing files) are kept out of version control entirely.”，回答错误。</p>
<p data-sourcepos="77:1-77:198">由于是 OpenAI 的最强模型，我不太相信这个结果，又做了一次实验，相同。猜测是 AGENTS.md 中的 Security &amp; Configuration Tips，提到了 sst.config.ts，干扰了祂。</p>
<p data-sourcepos="79:1-79:6">···</p>
<h2 data-sourcepos="80:1-80:32">Security &amp; Configuration Tips</h2>
<p data-sourcepos="81:1-82:6">Secrets load via environment variables consumed inside <code data-sourcepos="81:56-81:70">sst.config.ts</code>, so never commit <code data-sourcepos="81:89-81:95">.env*</code>, credentials, or generated <code data-sourcepos="81:124-81:130">logs/</code>. Execute binaries through <code data-sourcepos="81:158-81:171">bin/opencode</code> or the install script so patched dependencies in <code data-sourcepos="81:222-81:231">/patches</code> remain applied. When adding fixtures or docs, redact user-specific paths (prefer <code data-sourcepos="81:314-81:325">.opencode/</code> references) and strip identifiers from captured sessions before committing.
···</p>
<p data-sourcepos="84:1-84:162">删除上述 AGENTS.md 文件内容后，经过 3 次 serach，2 次 List，1 次 Read 后，得到正确答案。最终回答准确，但是应该无法得分。</p>
<ol data-sourcepos="86:1-87:0" start="4">
<li data-sourcepos="86:1-87:0">Google gemini</li>
</ol>
<p data-sourcepos="88:1-88:338">模型 gemini-2.5-pro，触发了 Codebase Investigator Agent 后，由子 agent 找到具体位置，但是主 Agent 仍然提到了 ~/Library/Application Support/opencode/auth.json，这个Cursor一样犯的错误，估计是XDG Base Directory Specification 这个关键词导致的干扰，但是回答应该还是认为基本准确。</p>
<ol data-sourcepos="90:1-91:0" start="5">
<li data-sourcepos="90:1-91:0">Claude Code</li>
</ol>
<p data-sourcepos="92:1-92:222">模型 minimax-m2，触发了 5 次 Search，5 次 Read 后，回答非常准确且详尽，仍然提到了不存在的 MacOS 路径，甚至有点用力过猛的给出了 project level 的位置。很卖力，能得分。</p>
<ol data-sourcepos="94:1-95:0" start="6">
<li data-sourcepos="94:1-95:0">kimi-cli</li>
</ol>
<p data-sourcepos="96:1-96:235">模型 kimi-for-coding，1 次 Grep，4 次 ReadFile，4 次 Bash 调用后，甚至直接在屏幕上打出了我的 OpenCoce Zen token，不仅准确，而且无所顾及，得分，以后做啥黑客的工作还得是国产模型！</p>
<ol data-sourcepos="98:1-99:0" start="7">
<li data-sourcepos="98:1-99:0">Tencent CodeBuddy</li>
</ol>
<p data-sourcepos="100:1-100:87">模型 auto，2 次 Search，4 次 Read，给出正确答案，中规中矩，得分。</p>
<h3 data-sourcepos="102:1-102:71">题目一结论：除了 codex 无法得分，其他全部晋级。</h3>
<h2 data-sourcepos="104:1-104:122">题目二：<a data-sourcepos="104:16-104:60" href="https://example.thape.com.cn/nc/supplier/edit">https://example.thape.com.cn/nc/supplier/edit</a> 调用这个接口的时候，增加传一个字段 nature_id</h2>
<ol data-sourcepos="106:1-107:0">
<li data-sourcepos="106:1-107:0">Cursor</li>
</ol>
<p data-sourcepos="108:1-108:120">模型 auto，一路中文推理后，修改正确，甚至还告诉我 nature_id（10 表示单位，20 表示个人）</p>
<ol data-sourcepos="110:1-111:0" start="2">
<li data-sourcepos="110:1-111:0">OpenCode</li>
</ol>
<p data-sourcepos="112:1-112:137">模型 big-pickle（免费），修改正确，但是会去掉几行无伤大雅的代码，可能这个模型还是有自己的品味。</p>
<ol data-sourcepos="114:1-115:0" start="3">
<li data-sourcepos="114:1-115:0">OpenAI codex</li>
</ol>
<p data-sourcepos="116:1-116:73">模型 gpt-5-codex high，7 次 Search，3 次 Read 后，修改正确。</p>
<ol data-sourcepos="118:1-119:0" start="4">
<li data-sourcepos="118:1-119:0">Google gemini</li>
</ol>
<p data-sourcepos="120:1-120:155">模型 gemini-2.5-pro，修改正确，但是修改甚至会跑 test，但是由于这个项目 test 是挂的，所以……，无论如何还是正确。</p>
<ol data-sourcepos="122:1-123:0" start="5">
<li data-sourcepos="122:1-123:0">Claude Code</li>
</ol>
<p data-sourcepos="124:1-124:67">模型 minimax-m2，7 次 Search，4 次 Read 后，修改正确。</p>
<ol data-sourcepos="126:1-127:0" start="6">
<li data-sourcepos="126:1-127:0">kimi-cli</li>
</ol>
<p data-sourcepos="128:1-128:141">模型 kimi-for-coding，修改正确，还告诉我 nature_id（10 表示单位，20 表示个人），甚至我都没开 thinking 模式。</p>
<ol data-sourcepos="130:1-131:0" start="7">
<li data-sourcepos="130:1-131:0">Tencent CodeBuddy</li>
</ol>
<p data-sourcepos="132:1-132:40">模型 auto (GLM 4.6) ，修改正确。</p>
<h3 data-sourcepos="134:1-134:126">题目二结论：：看来这个问题太简单了，白试了，还有就是以后用 Gemini 还是得修一下测试。</h3>
]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Migrate from yarn to pnpm package manager in the Rails way]]></title>
<link href="https://blog.cloud-mes.com/2025/10/31/migrate-from-yarn-to-pnpm-package-manager-in-the-rails-way/"/>
<updated>2025-10-31T14:40:00+08:00</updated>
<id>https://blog.cloud-mes.com/2025/10/31/migrate-from-yarn-to-pnpm-package-manager-in-the-rails-way</id>
<category term="Rails" /><category term="Node.js" /><category term="pnpm" /><category term="Yarn" />

      <content type="html"><![CDATA[<p data-sourcepos="1:1-1:151">After evaluating package managers for our Rails project, I decide migrated from Yarn to pnpm for stricter, faster, and more disk‑efficient installs.</p>
<p data-sourcepos="3:1-3:81">This guide is organized into four parts so you can adopt pnpm in the right order.</p>
<h2 data-sourcepos="5:1-5:11">Why pnpm</h2>
<ul data-sourcepos="7:1-11:0">
<li data-sourcepos="7:1-7:103"><strong data-sourcepos="7:3-7:21">Disk efficiency</strong>: A content‑addressable store and hardlinks dramatically reduce duplicate files.</li>
<li data-sourcepos="8:1-8:62"><strong data-sourcepos="8:3-8:11">Speed</strong>: Faster cold and warm installs with solid caching.</li>
<li data-sourcepos="9:1-9:82"><strong data-sourcepos="9:3-9:16">Strictness</strong>: Fails on missing/phantom deps and ensures reproducible installs.</li>
<li data-sourcepos="10:1-11:0"><strong data-sourcepos="10:3-10:16">Workspaces</strong>: First‑class monorepo support without heavy hoisting.</li>
</ul>
<p data-sourcepos="12:1-12:113">And the key reason: <code data-sourcepos="12:21-12:26">yarn</code> is not doing any release in past two years and META just lay-off huge people recently.</p>
<h2 data-sourcepos="14:1-14:35">How to do import in Node.js side</h2>
<ol data-sourcepos="16:1-17:0">
<li data-sourcepos="16:1-17:0">Install pnpm (prefer Corepack):</li>
</ol>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div><div data-line='4' class='line-number'></div><div data-line='5' class='line-number'></div><div data-line='6' class='line-number'></div><div data-line='7' class='line-number'></div></pre></td><td class='main  bash'><pre><div class='line'><span></span><span class="c1"># If Node comes with Corepack (Node 16.13+)</span>
</div><div class='line'>corepack<span class="w"> </span><span class="nb">enable</span>
</div><div class='line'>corepack<span class="w"> </span>prepare<span class="w"> </span>pnpm@latest<span class="w"> </span>--activate
</div><div class='line'>pnpm<span class="w"> </span>--version<span class="w"> </span><span class="c1"># should avtivate now</span>
</div><div class='line'> </div><div class='line'><span class="c1"># Otherwise fall back to npm with global</span>
</div><div class='line'>npm<span class="w"> </span>i<span class="w"> </span>-g<span class="w"> </span>pnpm@latest
</div></pre></td></table></div></figure>
<ol data-sourcepos="27:1-28:0" start="2">
<li data-sourcepos="27:1-28:0">Import your existing Yarn lockfile first:</li>
</ol>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div></pre></td><td class='main  bash'><pre><div class='line'><span></span><span class="c1"># Generates pnpm-lock.yaml from yarn.lock</span>
</div><div class='line'>pnpm<span class="w"> </span>import
</div><div class='line'>git<span class="w"> </span>add<span class="w"> </span>pnpm-lock.yaml
</div></pre></td></table></div></figure>
<ol data-sourcepos="35:1-36:0" start="3">
<li data-sourcepos="35:1-36:0">Remove Yarn artifacts and switch to pnpm in package.json:</li>
</ol>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div></pre></td><td class='main  bash'><pre><div class='line'><span></span>git<span class="w"> </span>rm<span class="w"> </span>yarn.lock
</div></pre></td></table></div></figure>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div></pre></td><td class='main  json'><pre><div class='line'><span></span><span class="p">{</span>
</div><div class='line'><span class="w">  </span><span class="nt">&quot;packageManager&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;pnpm@10&quot;</span>
</div><div class='line'><span class="p">}</span>
</div></pre></td></table></div></figure>
<ol data-sourcepos="47:1-48:0" start="4">
<li data-sourcepos="47:1-48:0">Clean and install deterministically:</li>
</ol>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div></pre></td><td class='main  bash'><pre><div class='line'><span></span>rm<span class="w"> </span>-rf<span class="w"> </span>node_modules<span class="w"> </span>.yarn<span class="w"> </span>.yarn-cache
</div><div class='line'>pnpm<span class="w"> </span>install<span class="w"> </span>--frozen-lockfile
</div><div class='line'>pnpm<span class="w"> </span>approve-builds
</div></pre></td></table></div></figure>
<ol data-sourcepos="55:1-56:0" start="5">
<li data-sourcepos="55:1-56:0">(Optional) Workspaces: add <code data-sourcepos="55:31-55:51">pnpm-workspace.yaml</code> in a monorepo:</li>
</ol>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div><div data-line='4' class='line-number'></div><div data-line='5' class='line-number'></div><div data-line='6' class='line-number'></div></pre></td><td class='main  yaml'><pre><div class='line'><span></span><span class="c1"># Only enable if you meeting build problem as pnpm by default using isolated</span>
</div><div class='line'><span class="c1"># https://pnpm.io/settings#nodelinker</span>
</div><div class='line'><span class="c1"># nodeLinker: hoisted</span>
</div><div class='line'><span class="nt">packages</span><span class="p">:</span>
</div><div class='line'><span class="w">  </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="s">&#39;.&#39;</span>
</div><div class='line'><span class="w">  </span><span class="c1"># - &#39;packages/**&#39;</span>
</div></pre></td></table></div></figure>
<h2 data-sourcepos="66:1-66:36">How to change Rails to using pnpm</h2>
<ol data-sourcepos="68:1-69:0">
<li data-sourcepos="68:1-69:0">Remove Yarn‑specific deploy helpers (if present):</li>
</ol>
<figure class='code'><figcaption>Gemfile</figcaption><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div></pre></td><td class='main  diff'><pre><div class='line'><span></span><span class="gd">- gem &#39;capistrano-yarn&#39;</span>
</div><div class='line'><span class="gi">+ gem &#39;capistrano-pnpm&#39;</span>
</div></pre></td></table></div></figure>
<figure class='code'><figcaption>Capfile</figcaption><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div></pre></td><td class='main  diff'><pre><div class='line'><span></span><span class="gd">- require &#39;capistrano/yarn&#39;</span>
</div><div class='line'><span class="gi">+ require &#39;capistrano/pnpm&#39;</span>
</div></pre></td></table></div></figure>
<ol data-sourcepos="80:1-81:0" start="2">
<li data-sourcepos="80:1-81:0">Add a <code data-sourcepos="80:10-80:19">bin/pnpm</code> wrapper so Rails tasks can call pnpm consistently:</li>
</ol>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div><div data-line='4' class='line-number'></div><div data-line='5' class='line-number'></div><div data-line='6' class='line-number'></div><div data-line='7' class='line-number'></div><div data-line='8' class='line-number'></div><div data-line='9' class='line-number'></div><div data-line='10' class='line-number'></div><div data-line='11' class='line-number'></div><div data-line='12' class='line-number'></div><div data-line='13' class='line-number'></div><div data-line='14' class='line-number'></div><div data-line='15' class='line-number'></div><div data-line='16' class='line-number'></div><div data-line='17' class='line-number'></div></pre></td><td class='main  ruby'><pre><div class='line'><span></span><span class="ch">#!/usr/bin/env ruby</span>
</div><div class='line'><span class="no">APP_ROOT</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="no">File</span><span class="o">.</span><span class="n">expand_path</span><span class="p">(</span><span class="s1">&#39;..&#39;</span><span class="p">,</span><span class="w"> </span><span class="n">__dir__</span><span class="p">)</span>
</div><div class='line'><span class="no">Dir</span><span class="o">.</span><span class="n">chdir</span><span class="p">(</span><span class="no">APP_ROOT</span><span class="p">)</span><span class="w"> </span><span class="k">do</span>
</div><div class='line'><span class="w">  </span><span class="n">pnpm</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="no">ENV</span><span class="o">.</span><span class="n">fetch</span><span class="p">(</span><span class="s1">&#39;PATH&#39;</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="no">File</span><span class="o">::</span><span class="no">PATH_SEPARATOR</span><span class="p">)</span>
</div><div class='line'><span class="w">               </span><span class="o">.</span><span class="n">reject</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="o">|</span><span class="n">dir</span><span class="o">|</span><span class="w"> </span><span class="no">File</span><span class="o">.</span><span class="n">expand_path</span><span class="p">(</span><span class="n">dir</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">__dir__</span><span class="w"> </span><span class="p">}</span>
</div><div class='line'><span class="w">               </span><span class="o">.</span><span class="n">product</span><span class="p">(</span><span class="sx">%w[pnpm pnpm.cmd pnpm.ps1]</span><span class="p">)</span>
</div><div class='line'><span class="w">               </span><span class="o">.</span><span class="n">map</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="o">|</span><span class="n">dir</span><span class="p">,</span><span class="w"> </span><span class="n">file</span><span class="o">|</span><span class="w"> </span><span class="no">File</span><span class="o">.</span><span class="n">expand_path</span><span class="p">(</span><span class="n">file</span><span class="p">,</span><span class="w"> </span><span class="n">dir</span><span class="p">)</span><span class="w"> </span><span class="p">}</span>
</div><div class='line'><span class="w">               </span><span class="o">.</span><span class="n">find</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="o">|</span><span class="n">file</span><span class="o">|</span><span class="w"> </span><span class="no">File</span><span class="o">.</span><span class="n">executable?</span><span class="p">(</span><span class="n">file</span><span class="p">)</span><span class="w"> </span><span class="p">}</span>
</div><div class='line'> </div><div class='line'><span class="w">  </span><span class="k">if</span><span class="w"> </span><span class="n">pnpm</span>
</div><div class='line'><span class="w">    </span><span class="nb">exec</span><span class="w"> </span><span class="n">pnpm</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="no">ARGV</span>
</div><div class='line'><span class="w">  </span><span class="k">else</span>
</div><div class='line'><span class="w">    </span><span class="vg">$stderr</span><span class="o">.</span><span class="n">puts</span><span class="w"> </span><span class="s1">&#39;pnpm executable was not detected in the system.&#39;</span>
</div><div class='line'><span class="w">    </span><span class="vg">$stderr</span><span class="o">.</span><span class="n">puts</span><span class="w"> </span><span class="s1">&#39;Install pnpm via https://pnpm.io/installation&#39;</span>
</div><div class='line'><span class="w">    </span><span class="nb">exit</span><span class="w"> </span><span class="mi">1</span>
</div><div class='line'><span class="w">  </span><span class="k">end</span>
</div><div class='line'><span class="k">end</span>
</div></pre></td></table></div></figure>
<p data-sourcepos="101:1-101:40">Make it executable: <code data-sourcepos="101:21-101:39">chmod +x bin/pnpm</code>.</p>
<ol data-sourcepos="103:1-104:0" start="3">
<li data-sourcepos="103:1-104:0">Keep backward compatibility by proxying <code data-sourcepos="103:44-103:53">bin/yarn</code> to pnpm (update existing file):</li>
</ol>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div><div data-line='4' class='line-number'></div><div data-line='5' class='line-number'></div><div data-line='6' class='line-number'></div><div data-line='7' class='line-number'></div><div data-line='8' class='line-number'></div><div data-line='9' class='line-number'></div><div data-line='10' class='line-number'></div><div data-line='11' class='line-number'></div><div data-line='12' class='line-number'></div><div data-line='13' class='line-number'></div><div data-line='14' class='line-number'></div><div data-line='15' class='line-number'></div><div data-line='16' class='line-number'></div><div data-line='17' class='line-number'></div><div data-line='18' class='line-number'></div></pre></td><td class='main  ruby'><pre><div class='line'><span></span><span class="ch">#!/usr/bin/env ruby</span>
</div><div class='line'><span class="no">APP_ROOT</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="no">File</span><span class="o">.</span><span class="n">expand_path</span><span class="p">(</span><span class="s1">&#39;..&#39;</span><span class="p">,</span><span class="w"> </span><span class="n">__dir__</span><span class="p">)</span>
</div><div class='line'><span class="no">Dir</span><span class="o">.</span><span class="n">chdir</span><span class="p">(</span><span class="no">APP_ROOT</span><span class="p">)</span><span class="w"> </span><span class="k">do</span>
</div><div class='line'><span class="w">  </span><span class="n">pnpm</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="no">ENV</span><span class="o">.</span><span class="n">fetch</span><span class="p">(</span><span class="s1">&#39;PATH&#39;</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="no">File</span><span class="o">::</span><span class="no">PATH_SEPARATOR</span><span class="p">)</span>
</div><div class='line'><span class="w">               </span><span class="o">.</span><span class="n">reject</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="o">|</span><span class="n">dir</span><span class="o">|</span><span class="w"> </span><span class="no">File</span><span class="o">.</span><span class="n">expand_path</span><span class="p">(</span><span class="n">dir</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">__dir__</span><span class="w"> </span><span class="p">}</span>
</div><div class='line'><span class="w">               </span><span class="o">.</span><span class="n">product</span><span class="p">(</span><span class="sx">%w[pnpm pnpm.cmd pnpm.ps1]</span><span class="p">)</span>
</div><div class='line'><span class="w">               </span><span class="o">.</span><span class="n">map</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="o">|</span><span class="n">dir</span><span class="p">,</span><span class="w"> </span><span class="n">file</span><span class="o">|</span><span class="w"> </span><span class="no">File</span><span class="o">.</span><span class="n">expand_path</span><span class="p">(</span><span class="n">file</span><span class="p">,</span><span class="w"> </span><span class="n">dir</span><span class="p">)</span><span class="w"> </span><span class="p">}</span>
</div><div class='line'><span class="w">               </span><span class="o">.</span><span class="n">find</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="o">|</span><span class="n">file</span><span class="o">|</span><span class="w"> </span><span class="no">File</span><span class="o">.</span><span class="n">executable?</span><span class="p">(</span><span class="n">file</span><span class="p">)</span><span class="w"> </span><span class="p">}</span>
</div><div class='line'> </div><div class='line'><span class="w">  </span><span class="k">if</span><span class="w"> </span><span class="n">pnpm</span>
</div><div class='line'><span class="w">    </span><span class="nb">warn</span><span class="w"> </span><span class="s1">&#39;Deprecated: bin/yarn now proxies to pnpm. Use bin/pnpm.&#39;</span><span class="w"> </span><span class="k">unless</span><span class="w"> </span><span class="no">ENV</span><span class="o">[</span><span class="s1">&#39;PNPM_PROXY_SILENT&#39;</span><span class="o">]</span>
</div><div class='line'><span class="w">    </span><span class="nb">exec</span><span class="w"> </span><span class="n">pnpm</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="no">ARGV</span>
</div><div class='line'><span class="w">  </span><span class="k">else</span>
</div><div class='line'><span class="w">    </span><span class="vg">$stderr</span><span class="o">.</span><span class="n">puts</span><span class="w"> </span><span class="s1">&#39;pnpm executable was not detected in the system.&#39;</span>
</div><div class='line'><span class="w">    </span><span class="vg">$stderr</span><span class="o">.</span><span class="n">puts</span><span class="w"> </span><span class="s1">&#39;Install pnpm via https://pnpm.io/installation&#39;</span>
</div><div class='line'><span class="w">    </span><span class="nb">exit</span><span class="w"> </span><span class="mi">1</span>
</div><div class='line'><span class="w">  </span><span class="k">end</span>
</div><div class='line'><span class="k">end</span>
</div></pre></td></table></div></figure>
<ol data-sourcepos="125:1-126:0" start="4">
<li data-sourcepos="125:1-126:0">Call pnpm from Rails scripts:</li>
</ol>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div><div data-line='4' class='line-number'></div><div data-line='5' class='line-number'></div></pre></td><td class='main  ruby'><pre><div class='line'><span></span><span class="c1"># bin/setup (snippet)</span>
</div><div class='line'><span class="nb">system</span><span class="o">!</span><span class="w"> </span><span class="s1">&#39;bin/pnpm&#39;</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;install&#39;</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;--frozen-lockfile&#39;</span>
</div><div class='line'> </div><div class='line'><span class="c1"># bin/update (snippet)</span>
</div><div class='line'><span class="c1"># system(&#39;bin/pnpm&#39;, &#39;install&#39;, &#39;--frozen-lockfile&#39;)</span>
</div></pre></td></table></div></figure>
<ol data-sourcepos="134:1-135:0" start="5">
<li data-sourcepos="134:1-135:0">Webpacker binaries (if you still use webpacker):</li>
</ol>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div></pre></td><td class='main  ruby'><pre><div class='line'><span></span><span class="c1"># Add to both bin/webpack and bin/webpack-dev-server</span>
</div><div class='line'><span class="no">ENV</span><span class="o">[</span><span class="s1">&#39;WEBPACKER_NODE_MODULES_BIN_PATH&#39;</span><span class="o">]</span><span class="w"> </span><span class="o">||=</span><span class="w"> </span><span class="no">File</span><span class="o">.</span><span class="n">expand_path</span><span class="p">(</span><span class="s1">&#39;../node_modules/.bin&#39;</span><span class="p">,</span><span class="w"> </span><span class="n">__dir__</span><span class="p">)</span>
</div></pre></td></table></div></figure>
<ol data-sourcepos="141:1-142:0" start="6">
<li data-sourcepos="141:1-142:0">Capistrano: use pnpm during deploys.</li>
</ol>
<p data-sourcepos="143:1-143:40">Create <code data-sourcepos="143:8-143:39">lib/capistrano/tasks/pnpm.rake</code>:</p>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div><div data-line='4' class='line-number'></div><div data-line='5' class='line-number'></div><div data-line='6' class='line-number'></div><div data-line='7' class='line-number'></div><div data-line='8' class='line-number'></div><div data-line='9' class='line-number'></div><div data-line='10' class='line-number'></div><div data-line='11' class='line-number'></div><div data-line='12' class='line-number'></div><div data-line='13' class='line-number'></div><div data-line='14' class='line-number'></div><div data-line='15' class='line-number'></div><div data-line='16' class='line-number'></div><div data-line='17' class='line-number'></div></pre></td><td class='main  ruby'><pre><div class='line'><span></span><span class="c1"># frozen_string_literal: true</span>
</div><div class='line'> </div><div class='line'><span class="n">namespace</span><span class="w"> </span><span class="ss">:pnpm</span><span class="w"> </span><span class="k">do</span>
</div><div class='line'><span class="w">  </span><span class="n">desc</span><span class="w"> </span><span class="s1">&#39;Install JavaScript dependencies using pnpm&#39;</span>
</div><div class='line'><span class="w">  </span><span class="n">task</span><span class="w"> </span><span class="ss">:install</span><span class="w"> </span><span class="k">do</span>
</div><div class='line'><span class="w">    </span><span class="n">on</span><span class="w"> </span><span class="n">roles</span><span class="p">(</span><span class="n">fetch</span><span class="p">(</span><span class="ss">:pnpm_roles</span><span class="p">,</span><span class="w"> </span><span class="ss">:web</span><span class="p">))</span><span class="w"> </span><span class="k">do</span>
</div><div class='line'><span class="w">      </span><span class="n">within</span><span class="w"> </span><span class="n">release_path</span><span class="w"> </span><span class="k">do</span>
</div><div class='line'><span class="w">        </span><span class="n">with</span><span class="w"> </span><span class="n">fetch</span><span class="p">(</span><span class="ss">:pnpm_env</span><span class="p">,</span><span class="w"> </span><span class="p">{})</span><span class="w"> </span><span class="k">do</span>
</div><div class='line'><span class="w">          </span><span class="n">flags</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="n">fetch</span><span class="p">(</span><span class="ss">:pnpm_flags</span><span class="p">,</span><span class="w"> </span><span class="sx">%w[--frozen-lockfile]</span><span class="p">))</span>
</div><div class='line'><span class="w">          </span><span class="n">execute</span><span class="w"> </span><span class="ss">:pnpm</span><span class="p">,</span><span class="w"> </span><span class="ss">:install</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="n">flags</span>
</div><div class='line'><span class="w">        </span><span class="k">end</span>
</div><div class='line'><span class="w">      </span><span class="k">end</span>
</div><div class='line'><span class="w">    </span><span class="k">end</span>
</div><div class='line'><span class="w">  </span><span class="k">end</span>
</div><div class='line'><span class="k">end</span>
</div><div class='line'> </div><div class='line'><span class="n">before</span><span class="w"> </span><span class="s1">&#39;deploy:updated&#39;</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;pnpm:install&#39;</span>
</div></pre></td></table></div></figure>
<p data-sourcepos="163:1-163:26">And in <code data-sourcepos="163:8-163:25">config/deploy.rb</code>:</p>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div><div data-line='4' class='line-number'></div><div data-line='5' class='line-number'></div></pre></td><td class='main  ruby'><pre><div class='line'><span></span><span class="c1"># Ensure node_modules is NOT a linked dir with pnpm</span>
</div><div class='line'><span class="n">append</span><span class="w"> </span><span class="ss">:linked_dirs</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;log&#39;</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;tmp/pids&#39;</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;tmp/cache&#39;</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;tmp/sockets&#39;</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;public/system&#39;</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;storage&#39;</span>
</div><div class='line'> </div><div class='line'><span class="c1"># Important: pass strict install flags to pnpm</span>
</div><div class='line'><span class="n">set</span><span class="w"> </span><span class="ss">:pnpm_flags</span><span class="p">,</span><span class="w"> </span><span class="sx">%w(--frozen-lockfile)</span>
</div></pre></td></table></div></figure>
<ol data-sourcepos="172:1-173:0" start="7">
<li data-sourcepos="172:1-173:0">(Optional, webpacker only) Replace the yarn check with a pnpm check:</li>
</ol>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div><div data-line='4' class='line-number'></div><div data-line='5' class='line-number'></div><div data-line='6' class='line-number'></div><div data-line='7' class='line-number'></div><div data-line='8' class='line-number'></div><div data-line='9' class='line-number'></div><div data-line='10' class='line-number'></div><div data-line='11' class='line-number'></div><div data-line='12' class='line-number'></div><div data-line='13' class='line-number'></div><div data-line='14' class='line-number'></div><div data-line='15' class='line-number'></div><div data-line='16' class='line-number'></div></pre></td><td class='main  ruby'><pre><div class='line'><span></span><span class="c1"># lib/tasks/pnpm.rake</span>
</div><div class='line'><span class="n">namespace</span><span class="w"> </span><span class="ss">:webpacker</span><span class="w"> </span><span class="k">do</span>
</div><div class='line'><span class="w">  </span><span class="k">begin</span>
</div><div class='line'><span class="w">    </span><span class="no">Rake</span><span class="o">::</span><span class="no">Task</span><span class="o">[</span><span class="s1">&#39;webpacker:check_yarn&#39;</span><span class="o">].</span><span class="n">clear</span>
</div><div class='line'><span class="w">  </span><span class="k">rescue</span><span class="w"> </span><span class="no">RuntimeError</span><span class="p">,</span><span class="w"> </span><span class="no">NameError</span>
</div><div class='line'><span class="w">  </span><span class="k">end</span>
</div><div class='line'> </div><div class='line'><span class="w">  </span><span class="n">desc</span><span class="w"> </span><span class="s1">&#39;Verifies if pnpm is installed (replaces webpacker yarn check)&#39;</span>
</div><div class='line'><span class="w">  </span><span class="n">task</span><span class="w"> </span><span class="ss">:check_yarn</span><span class="w"> </span><span class="k">do</span>
</div><div class='line'><span class="w">    </span><span class="n">pnpm_version</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="sb">`pnpm --version`</span><span class="o">.</span><span class="n">strip</span>
</div><div class='line'><span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">pnpm_version</span><span class="o">.</span><span class="n">empty?</span>
</div><div class='line'><span class="w">      </span><span class="vg">$stderr</span><span class="o">.</span><span class="n">puts</span><span class="w"> </span><span class="s1">&#39;pnpm not installed. Please install pnpm to compile webpacker assets.&#39;</span>
</div><div class='line'><span class="w">      </span><span class="nb">exit!</span>
</div><div class='line'><span class="w">    </span><span class="k">end</span>
</div><div class='line'><span class="w">  </span><span class="k">end</span>
</div><div class='line'><span class="k">end</span>
</div></pre></td></table></div></figure>
<h2 data-sourcepos="192:1-192:33">How to change CI/CD (optional)</h2>
<p data-sourcepos="194:1-194:69">Keep this for last. After local migration is green, update pipelines.</p>
<h3 data-sourcepos="196:1-196:18">GitHub Actions</h3>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div><div data-line='4' class='line-number'></div><div data-line='5' class='line-number'></div><div data-line='6' class='line-number'></div><div data-line='7' class='line-number'></div><div data-line='8' class='line-number'></div><div data-line='9' class='line-number'></div><div data-line='10' class='line-number'></div><div data-line='11' class='line-number'></div><div data-line='12' class='line-number'></div></pre></td><td class='main  yaml'><pre><div class='line'><span></span><span class="nt">jobs</span><span class="p">:</span>
</div><div class='line'><span class="w">  </span><span class="nt">build</span><span class="p">:</span>
</div><div class='line'><span class="w">    </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ubuntu-latest</span>
</div><div class='line'><span class="w">    </span><span class="nt">steps</span><span class="p">:</span>
</div><div class='line'><span class="w">      </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">actions/checkout@v4</span>
</div><div class='line'><span class="w">      </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">actions/setup-node@v4</span>
</div><div class='line'><span class="w">        </span><span class="nt">with</span><span class="p">:</span>
</div><div class='line'><span class="w">          </span><span class="nt">node-version</span><span class="p">:</span><span class="w"> </span><span class="s">&#39;lts/*&#39;</span>
</div><div class='line'><span class="w">          </span><span class="nt">cache</span><span class="p">:</span><span class="w"> </span><span class="s">&#39;pnpm&#39;</span>
</div><div class='line'><span class="w">      </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">corepack enable &amp;&amp; corepack prepare pnpm@latest --activate</span>
</div><div class='line'><span class="w">      </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">pnpm install --frozen-lockfile</span>
</div><div class='line'><span class="w">      </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">bin/rails assets:precompile</span>
</div></pre></td></table></div></figure>
<h3 data-sourcepos="213:1-213:13">GitLab CI</h3>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div><div data-line='4' class='line-number'></div><div data-line='5' class='line-number'></div><div data-line='6' class='line-number'></div><div data-line='7' class='line-number'></div><div data-line='8' class='line-number'></div><div data-line='9' class='line-number'></div><div data-line='10' class='line-number'></div><div data-line='11' class='line-number'></div><div data-line='12' class='line-number'></div><div data-line='13' class='line-number'></div><div data-line='14' class='line-number'></div><div data-line='15' class='line-number'></div><div data-line='16' class='line-number'></div><div data-line='17' class='line-number'></div><div data-line='18' class='line-number'></div><div data-line='19' class='line-number'></div></pre></td><td class='main  yaml'><pre><div class='line'><span></span><span class="nt">cache</span><span class="p">:</span>
</div><div class='line'><span class="w">  </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">key</span><span class="p">:</span>
</div><div class='line'><span class="w">      </span><span class="nt">files</span><span class="p">:</span>
</div><div class='line'><span class="w">        </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">pnpm-lock.yaml</span>
</div><div class='line'><span class="w">    </span><span class="nt">paths</span><span class="p">:</span>
</div><div class='line'><span class="w">      </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">.pnpm-store/</span>
</div><div class='line'> </div><div class='line'><span class="nt">before_script</span><span class="p">:</span>
</div><div class='line'><span class="w">  </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="p p-Indicator">|</span>
</div><div class='line'><span class="w">    </span><span class="no">if command -v corepack &gt;/dev/null; then</span>
</div><div class='line'><span class="w">      </span><span class="no">corepack enable</span>
</div><div class='line'><span class="w">      </span><span class="no">corepack prepare pnpm@latest --activate</span>
</div><div class='line'><span class="w">    </span><span class="no">else</span>
</div><div class='line'><span class="w">      </span><span class="no">npm i -g pnpm@latest</span>
</div><div class='line'><span class="w">    </span><span class="no">fi</span>
</div><div class='line'> </div><div class='line'><span class="nt">install</span><span class="p">:</span>
</div><div class='line'><span class="w">  </span><span class="nt">script</span><span class="p">:</span>
</div><div class='line'><span class="w">    </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">pnpm install --frozen-lockfile --store-dir .pnpm-store</span>
</div></pre></td></table></div></figure>
<h3 data-sourcepos="235:1-235:12">CircleCI</h3>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div></pre></td><td class='main  yaml'><pre><div class='line'><span></span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">node/install-packages</span><span class="p">:</span>
</div><div class='line'><span class="w">    </span><span class="nt">pkg-manager</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">pnpm</span>
</div><div class='line'><span class="w">    </span><span class="nt">cache-key</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">pnpm-lock.yaml</span>
</div></pre></td></table></div></figure>
<h2 data-sourcepos="243:1-243:13">Conclusion</h2>
<p data-sourcepos="245:1-245:45">Enjoy faster, stricter, and much leaner pnpm!</p>
]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[My 2025 Monthly Subscription Review List]]></title>
<link href="https://blog.cloud-mes.com/2025/10/15/my-2025-monthly-subscription-review-list/"/>
<updated>2025-10-15T16:20:00+08:00</updated>
<id>https://blog.cloud-mes.com/2025/10/15/my-2025-monthly-subscription-review-list</id>
<category term="Subscription" />

      <content type="html"><![CDATA[<p data-sourcepos="1:1-1:282">Like the previous years <a data-sourcepos="1:25-1:80" href="https://blog.cloud-mes.com//2022/02/21/my-monthly-subscription-review-list/">2022</a> / <a data-sourcepos="1:84-1:144" href="https://blog.cloud-mes.com//2023/07/06/my-2023-monthly-subscription-review-list/">2023</a> / <a data-sourcepos="1:148-1:208" href="https://blog.cloud-mes.com//2024/07/15/my-2024-monthly-subscription-review-list/">2024</a>, here is my current subscription list. The first number is RMB per month.</p>
<ol data-sourcepos="3:1-23:0">
<li data-sourcepos="3:1-3:17">(68) iCloud 2T</li>
<li data-sourcepos="4:1-4:31">(17) Apple Music family plan</li>
<li data-sourcepos="5:1-5:38">(26) Dragonruby Pro (annual 42 USD)</li>
<li data-sourcepos="6:1-6:47">(30) Bandwagon host (monthly 33 USD, shared)</li>
<li data-sourcepos="7:1-7:34">(6) Adblock Pro (annual 70 RMB)</li>
<li data-sourcepos="8:1-8:36">(6.5) Blog domain (annual 11 USD)</li>
<li data-sourcepos="9:1-9:37">(1.5) 香哈菜谱 (annual 18 RMB)</li>
<li data-sourcepos="10:1-10:55">(49) AWS hosting (3 years 206 USD, monthly 1.35 USD)</li>
<li data-sourcepos="11:1-11:34">(16.8) Meituan biking (monthly)</li>
<li data-sourcepos="12:1-12:57">(47) Google Workspace Business Starter (yearly 80 USD)</li>
<li data-sourcepos="13:1-13:46">(115) Cursor.sh AI editor. (yearly 192 USD)</li>
<li data-sourcepos="14:1-14:43">(8.2) Ivory for Mastodon (yearly 98 RMB)</li>
<li data-sourcepos="15:1-15:48">(8) IndieWeb.Social Backer. (monthly 1.5 SGD)</li>
<li data-sourcepos="16:1-16:49">(31) Sublime Text and Merge (3 years, 152 AUD)</li>
<li data-sourcepos="17:1-17:30">(21) Surge (yearly, 46 USD)</li>
<li data-sourcepos="18:1-18:35">(87) RORvsWild (monthly, 10 EUR)</li>
<li data-sourcepos="19:1-19:34">(156) ChatGPT (monthly, 22 USD)</li>
<li data-sourcepos="20:1-20:46">(17.9) Kapeli Dash.app (yearly, 215.33 RMB)</li>
<li data-sourcepos="21:1-21:47">(49) Kimi Andante for code (monthly, 49 RMB)</li>
<li data-sourcepos="22:1-23:0">(12.6) OpenCode zen (yearly, 151.82 RMB)</li>
</ol>
<p data-sourcepos="24:1-24:105">So totally 773 RMB per month to pay. In the previous year it was 480 RMB, so 61% higher compared to 2024.</p>
]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Install Oracle instant client 23.3 - the first macOS ARM64 driver and ruby-oci8 gem]]></title>
<link href="https://blog.cloud-mes.com/2025/09/02/install-oracle-instant-client-23-dot-3-the-first-macos-arm64-driver-and-ruby-oci8-gem/"/>
<updated>2025-09-02T14:36:00+08:00</updated>
<id>https://blog.cloud-mes.com/2025/09/02/install-oracle-instant-client-23-dot-3-the-first-macos-arm64-driver-and-ruby-oci8-gem</id>
<category term="Oracle" /><category term="Rails" /><category term="Ruby" />

      <content type="html"><![CDATA[<figure class='code'><figcaption>setting TNS_ADMIN</figcaption><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div></pre></td><td class='main  bash'><pre><div class='line'><span></span><span class="nb">export</span><span class="w"> </span><span class="nv">TNS_ADMIN</span><span class="o">=</span>/opt/instantclient_23_3/network/admin]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Expose local server to the internet without ngrok]]></title>
<link href="https://blog.cloud-mes.com/2025/08/18/expose-local-server-to-the-internet-without-ngrok/"/>
<updated>2025-08-18T21:08:00+08:00</updated>
<id>https://blog.cloud-mes.com/2025/08/18/expose-local-server-to-the-internet-without-ngrok</id>
<category term="Rails" /><category term="Linux" />

      <content type="html"><![CDATA[<h3 data-sourcepos="1:1-1:12">Option 1</h3>
<figure class='code'><figcaption>config/environments/development.rb</figcaption><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div></pre></td><td class='main  ruby'><pre><div class='line'><span></span><span class="no">Rails</span><span class="o">.</span><span class="n">application</span><span class="o">.</span><span class="n">configure</span><span class="w"> </span><span class="k">do</span>
</div><div class='line'><span class="w">  </span><span class="n">config</span><span class="o">.</span><span class="n">hosts</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s2">&quot;.example.com&quot;</span>
</div><div class='line'><span class="k">end</span>
</div></pre></td></table></div></figure>
<figure class='code'><figcaption>config/puma.rb</figcaption><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div><div data-line='4' class='line-number'></div><div data-line='5' class='line-number'></div></pre></td><td class='main  ruby'><pre><div class='line'><span></span><span class="n">ssl_bind</span><span class="w"> </span><span class="s2">&quot;0.0.0.0&quot;</span><span class="err">，</span><span class="s2">&quot;8443&quot;</span><span class="err">，</span><span class="p">{</span>
</div><div class='line'><span class="w">  </span><span class="c1"># Run &quot;certbot certificates&quot; to get these</span>
</div><div class='line'><span class="w">  </span><span class="n">key</span><span class="err">：</span><span class="w"> </span><span class="s2">&quot;server.key&quot;</span><span class="o">.</span>
</div><div class='line'><span class="w">  </span><span class="n">cert</span><span class="err">：</span><span class="s2">&quot;server.crt&quot;</span>
</div><div class='line'><span class="p">}</span>
</div></pre></td></table></div></figure>
<figure class='code'><figcaption>expose SSH port：</figcaption><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div></pre></td><td class='main  bash'><pre><div class='line'><span></span>ssh<span class="w"> </span>-R<span class="w"> </span><span class="m">8443</span>:localhost:8443<span class="w"> </span>-N<span class="w"> </span>user@example.com
</div></pre></td></table></div></figure>
<h3 data-sourcepos="21:1-21:12">Option 2</h3>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div></pre></td><td class='main  bash'><pre><div class='line'><span></span>ssh<span class="w"> </span>-C2qTnN<span class="w"> </span>-R<span class="w"> </span><span class="m">3003</span>:localhost:3003<span class="w"> </span>user@ssss.com
</div><div class='line'><span class="c1"># Then, configure an Nginx proxy with a 3003 domain name for external access</span>
</div></pre></td></table></div></figure>
<h3 data-sourcepos="28:1-28:12">Option 3</h3>
<p data-sourcepos="30:1-30:43">Open cursor, goto <em data-sourcepos="30:19-30:24">port</em> tab to create one.</p>
<p data-sourcepos="32:1-32:117">If meet error goto '/Applications/Cursor.app/Contents/Resources/app/bin' and rename <code data-sourcepos="32:85-32:99">cursor-tunnel</code> to <code data-sourcepos="32:104-32:116">code-tunnel</code>.</p>
]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Sponge command cheetsheet]]></title>
<link href="https://blog.cloud-mes.com/2025/07/27/sponge-command-cheetsheet/"/>
<updated>2025-07-27T00:34:00+08:00</updated>
<id>https://blog.cloud-mes.com/2025/07/27/sponge-command-cheetsheet</id>


      <content type="html"><![CDATA[<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div><div data-line='4' class='line-number'></div></pre></td><td class='main  bash'><pre><div class='line'><span></span>go<span class="w"> </span>build<span class="w"> </span>-o<span class="w"> </span><span class="k">$(</span>which<span class="w"> </span>sponge<span class="k">)</span><span class="w"> </span>cmd/sponge/main.go
</div><div class='line'>go<span class="w"> </span>build<span class="w"> </span>-o<span class="w"> </span><span class="k">$(</span>which<span class="w"> </span>protoc-gen-go-gin<span class="k">)</span><span class="w"> </span>cmd/protoc-gen-go-gin/main.go
</div><div class='line'>go<span class="w"> </span>build<span class="w"> </span>-o<span class="w"> </span><span class="k">$(</span>which<span class="w"> </span>protoc-gen-go-rpc-tmpl<span class="k">)</span><span class="w"> </span>cmd/protoc-gen-go-rpc-tmpl/main.go
</div><div class='line'>go<span class="w"> </span>build<span class="w"> </span>-o<span class="w"> </span><span class="k">$(</span>which<span class="w"> </span>protoc-gen-json-field<span class="k">)</span><span class="w"> </span>cmd/protoc-gen-json-field/main.go
</div></pre></td></table></div></figure>
]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Install a new Rails app in Rocky Linux 9.6 at Aliyun]]></title>
<link href="https://blog.cloud-mes.com/2025/07/12/install-a-new-rails-app-in-rocky-linux-9-dot-6-at-aliyun/"/>
<updated>2025-07-12T14:58:00+08:00</updated>
<id>https://blog.cloud-mes.com/2025/07/12/install-a-new-rails-app-in-rocky-linux-9-dot-6-at-aliyun</id>
<category term="Rails" /><category term="Rocky" />

      <content type="html"><![CDATA[</div><div class='line'>sudo<span class="w"> </span>chown<span class="w"> </span>ecs-user:ecs-user<span class="w"> </span>harman]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Running IRuby Notebook in Cursor]]></title>
<link href="https://blog.cloud-mes.com/2025/05/25/running-iruby-and-notebook-in-cursor/"/>
<updated>2025-05-25T10:02:00+08:00</updated>
<id>https://blog.cloud-mes.com/2025/05/25/running-iruby-and-notebook-in-cursor</id>
<category term="Jupyter" /><category term="Ruby" />

      <content type="html"><![CDATA[<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div><div data-line='4' class='line-number'></div><div data-line='5' class='line-number'></div><div data-line='6' class='line-number'></div><div data-line='7' class='line-number'></div></pre></td><td class='main  bash'><pre><div class='line'><span></span>brew<span class="w"> </span>install<span class="w"> </span>ruby
</div><div class='line'>brew<span class="w"> </span>install<span class="w"> </span>python3
</div><div class='line'>brew<span class="w"> </span>install<span class="w"> </span>zeromq<span class="w"> </span><span class="c1"># require by ipykernel</span>
</div><div class='line'>/opt/homebrew/bin/python3<span class="w"> </span>-m<span class="w"> </span>pip<span class="w"> </span>install<span class="w"> </span>ipykernel<span class="w"> </span>-U<span class="w"> </span>--user<span class="w"> </span>--force-reinstall<span class="w"> </span>--break-system-packages
</div><div class='line'>gem<span class="w"> </span>install<span class="w"> </span>iruby
</div><div class='line'>gem<span class="w"> </span>install<span class="w"> </span>rubygems-requirements-system
</div><div class='line'>iruby<span class="w"> </span>register<span class="w"> </span>--force
</div></pre></td></table></div></figure>
<p data-sourcepos="11:1-11:102">Also install <a data-sourcepos="11:14-11:91" href="https://marketplace.cursorapi.com/items?itemName=ms-toolsai.jupyter">Jupyter</a> in cursor.</p>
<p data-sourcepos="13:1-13:72">To make <a data-sourcepos="13:9-13:63" href="https://github.com/lmstudio-ai/mlx-engine">mlx-engine</a> running:</p>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div><div data-line='4' class='line-number'></div><div data-line='5' class='line-number'></div><div data-line='6' class='line-number'></div></pre></td><td class='main  plain'><pre><div class='line'>python3 -m pip install sentencepiece -U --user --force-reinstall --break-system-packages
</div><div class='line'>python3 -m pip install outlines -U --user --force-reinstall --break-system-packages
</div><div class='line'>python3 -m pip install outlines==1.1.1 --user --force-reinstall --ignore-requires-python --break-system-packages
</div><div class='line'>python3 -m pip install datasets==3.6.0 --user --force-reinstall --ignore-requires-python --break-system-packages
</div><div class='line'>python3 -m pip install mlx_vlm -U --user --force-reinstall --break-system-packages
</div><div class='line'>python3 -m pip install mlx-lm -U --user --force-reinstall --break-system-packages</div></pre></td></table></div></figure>
]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Install Open Project v16 in a Rocky Linux 9]]></title>
<link href="https://blog.cloud-mes.com/2025/04/21/install-open-project-v16-in-a-rocky-linux-9/"/>
<updated>2025-04-21T10:04:00+08:00</updated>
<id>https://blog.cloud-mes.com/2025/04/21/install-open-project-v16-in-a-rocky-linux-9</id>
<category term="OpenProject" /><category term="Rails" /><category term="Rocky" />

      <content type="html"><![CDATA[</div><div class='line'><span class="nb">cd</span><span class="w"> </span>/etc/sudoers.d]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Migrate DB from redis 7.4 to 7.2 and skip the RDB version 12 error]]></title>
<link href="https://blog.cloud-mes.com/2025/04/17/migrate-db-from-redis-7-dot-4-to-7-dot-2-and-skip-the-rdb-version-12-error/"/>
<updated>2025-04-17T11:30:00+08:00</updated>
<id>https://blog.cloud-mes.com/2025/04/17/migrate-db-from-redis-7-dot-4-to-7-dot-2-and-skip-the-rdb-version-12-error</id>
<category term="Redis" />

      <content type="html"><![CDATA[<p data-sourcepos="1:1-1:125">After I copy redis <code data-sourcepos="1:20-1:29">dump.rdb</code> from redis 7.4 to my Macbook homebrew redis 7.2 I got Can't handle RDB format version 12 error:</p>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div><div data-line='4' class='line-number'></div><div data-line='5' class='line-number'></div><div data-line='6' class='line-number'></div><div data-line='7' class='line-number'></div><div data-line='8' class='line-number'></div><div data-line='9' class='line-number'></div><div data-line='10' class='line-number'></div><div data-line='11' class='line-number'></div><div data-line='12' class='line-number'></div><div data-line='13' class='line-number'></div><div data-line='14' class='line-number'></div><div data-line='15' class='line-number'></div><div data-line='16' class='line-number'></div><div data-line='17' class='line-number'></div><div data-line='18' class='line-number'></div><div data-line='19' class='line-number'></div><div data-line='20' class='line-number'></div><div data-line='21' class='line-number'></div><div data-line='22' class='line-number'></div></pre></td><td class='main  text'><pre><div class='line'><span></span># /opt/homebrew/opt/redis/bin/redis-server /opt/homebrew/etc/redis.conf
</div><div class='line'>20066:C 17 Apr 2025 10:39:34.935 * oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
</div><div class='line'>20066:C 17 Apr 2025 10:39:34.935 * Redis version=7.2.7, bits=64, commit=00000000, modified=0, pid=20066, just started
</div><div class='line'>20066:C 17 Apr 2025 10:39:34.935 * Configuration loaded
</div><div class='line'>20066:M 17 Apr 2025 10:39:34.935 * Increased maximum number of open files to 10032 (it was originally set to 256).
</div><div class='line'>20066:M 17 Apr 2025 10:39:34.935 * monotonic clock: POSIX clock_gettime
</div><div class='line'> </div><div class='line'> </div><div class='line'>Redis 7.2.7 (00000000/0) 64 bit
</div><div class='line'> </div><div class='line'>Running in standalone mode
</div><div class='line'>Port: 6379
</div><div class='line'>PID: 20066
</div><div class='line'> </div><div class='line'> </div><div class='line'>      https://redis.io
</div><div class='line'> </div><div class='line'> </div><div class='line'>20066:M 17 Apr 2025 10:39:34.936 # WARNING: The TCP backlog setting of 511 cannot be enforced because kern.ipc.somaxconn is set to the lower value of 128.
</div><div class='line'>20066:M 17 Apr 2025 10:39:34.936 * Server initialized
</div><div class='line'>20066:M 17 Apr 2025 10:39:34.936 # Can&#39;t handle RDB format version 12
</div><div class='line'>20066:M 17 Apr 2025 10:39:34.936 # Fatal error loading the DB, check server logs. Exiting.
</div></pre></td></table></div></figure>
<p data-sourcepos="21:1-21:142">Two option available, upgrade redis version via <a data-sourcepos="21:49-21:142" href="https://redis.io/docs/latest/operate/oss_and_stack/install/install-stack/homebrew/">redis.io</a></p>
<h3 data-sourcepos="23:1-23:22">Using high version</h3>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div></pre></td><td class='main  bash'><pre><div class='line'><span></span>brew<span class="w"> </span>tap<span class="w"> </span>redis/redis
</div><div class='line'>brew<span class="w"> </span>install<span class="w"> </span>--cask<span class="w"> </span>redis
</div></pre></td></table></div></figure>
<p data-sourcepos="30:1-30:116">The solution is <em data-sourcepos="30:17-30:22">ugly</em> as redis will give you rc version of redis and it depend on the LLVM@18, which takes 1.7GB...</p>
<h3 data-sourcepos="33:1-33:18">Stay redis 7.2</h3>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div><div data-line='4' class='line-number'></div><div data-line='5' class='line-number'></div><div data-line='6' class='line-number'></div><div data-line='7' class='line-number'></div><div data-line='8' class='line-number'></div><div data-line='9' class='line-number'></div><div data-line='10' class='line-number'></div></pre></td><td class='main  bash'><pre><div class='line'><span></span>redis-cli<span class="w"> </span>shutdown
</div><div class='line'>brew<span class="w"> </span>uninstall<span class="w"> </span>redis
</div><div class='line'>brew<span class="w"> </span>untap<span class="w"> </span>redis/redis
</div><div class='line'><span class="c1"># make sure your DB no need!</span>
</div><div class='line'>rm<span class="w"> </span>/opt/homebrew/var/db/redis/dump.rdb
</div><div class='line'>rm<span class="w"> </span>/opt/homebrew/etc/redis-sentinel.conf
</div><div class='line'>rm<span class="w"> </span>/opt/homebrew/etc/redis.conf
</div><div class='line'>rm<span class="w"> </span>/opt/homebrew/etc/redis.conf.default
</div><div class='line'>brew<span class="w"> </span>install<span class="w"> </span>redis
</div><div class='line'>brew<span class="w"> </span>services<span class="w"> </span>start<span class="w"> </span>redis
</div></pre></td></table></div></figure>
<p data-sourcepos="48:1-48:80">Using <a data-sourcepos="48:7-48:56" href="https://github.com/delano/redis-dump">redis-dump</a> to dump and restore DB.</p>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div></pre></td><td class='main  bash'><pre><div class='line'><span></span>redis-dump<span class="w"> </span>-u<span class="w"> </span><span class="m">127</span>.0.0.1:6379<span class="w"> </span>-d<span class="w"> </span><span class="m">0</span><span class="w"> </span>&gt;<span class="w"> </span>db_db0.json
</div><div class='line'>cat<span class="w"> </span>db_db0.json<span class="w"> </span><span class="p">|</span><span class="w"> </span>redis-load<span class="w"> </span>-d<span class="w"> </span><span class="m">0</span>
</div></pre></td></table></div></figure>
]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Install smaug which is a DragonRuby version manager After openssl@1.1 disabled on 2024-10-24]]></title>
<link href="https://blog.cloud-mes.com/2025/04/11/install-smaug-which-is-a-dragonruby-version-manager-after-openssl-at-1-dot-1-disabled-on-2024-10-24/"/>
<updated>2025-04-11T16:48:00+08:00</updated>
<id>https://blog.cloud-mes.com/2025/04/11/install-smaug-which-is-a-dragonruby-version-manager-after-openssl-at-1-dot-1-disabled-on-2024-10-24</id>
<category term="DragonRuby" />

      <content type="html"><![CDATA[<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div><div data-line='4' class='line-number'></div><div data-line='5' class='line-number'></div></pre></td><td class='main  bash'><pre><div class='line'><span></span>brew<span class="w"> </span>tap<span class="w"> </span>rbenv/tap
</div><div class='line'>brew<span class="w"> </span>install<span class="w"> </span>rbenv/tap/openssl@1.1
</div><div class='line'>brew<span class="w"> </span>install<span class="w"> </span>rust
</div><div class='line'>brew<span class="w"> </span>tap<span class="w"> </span>ereborstudios/tap
</div><div class='line'>brew<span class="w"> </span>install<span class="w"> </span>-s<span class="w"> </span>smaug
</div></pre></td></table></div></figure>
<p data-sourcepos="9:1-9:183">Tips coming from <a data-sourcepos="9:18-9:183" href="https://www.reddit.com/r/macgaming/comments/1gbs6vw/comment/lzqcpzr/?utm_source=share&amp;utm_medium=web3x&amp;utm_name=web3xcss&amp;utm_term=1&amp;utm_content=share_button">reddit</a></p>
]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Make Tabnine continue work after official stop support the Sublime Text]]></title>
<link href="https://blog.cloud-mes.com/2025/04/09/make-tabnine-continue-work-after-official-stop-support-the-sublime-text/"/>
<updated>2025-04-09T22:14:00+08:00</updated>
<id>https://blog.cloud-mes.com/2025/04/09/make-tabnine-continue-work-after-official-stop-support-the-sublime-text</id>
<category term="TabNine" />

      <content type="html"><![CDATA[<p data-sourcepos="1:1-1:184">Today I found my TabNine stop working and after 2 hours, I found it <a data-sourcepos="1:69-1:184" href="https://github.com/codota/tabnine-sublime/issues/118#issuecomment-2220641203">officially stop support Sublime Text</a></p>
<p data-sourcepos="4:1-4:194">But if you having the API key here is how to make it continue work in local mode. Goto '/Users/[username]/Library/Application Support/Sublime Text/Packages' and change 'dl_binaries.sh' as below.</p>
<p data-sourcepos="6:1-6:44">Change targets to your platform if required.</p>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div><div data-line='4' class='line-number'></div><div data-line='5' class='line-number'></div><div data-line='6' class='line-number'></div><div data-line='7' class='line-number'></div><div data-line='8' class='line-number'></div><div data-line='9' class='line-number'></div><div data-line='10' class='line-number'></div><div data-line='11' class='line-number'></div><div data-line='12' class='line-number'></div><div data-line='13' class='line-number'></div><div data-line='14' class='line-number'></div><div data-line='15' class='line-number'></div><div data-line='16' class='line-number'></div><div data-line='17' class='line-number'></div><div data-line='18' class='line-number'></div><div data-line='19' class='line-number'></div><div data-line='20' class='line-number'></div><div data-line='21' class='line-number'></div><div data-line='22' class='line-number'></div><div data-line='23' class='line-number'></div></pre></td><td class='main  bash'><pre><div class='line'><span></span><span class="ch">#!/bin/sh</span>
</div><div class='line'><span class="nb">set</span><span class="w"> </span>-e
</div><div class='line'> </div><div class='line'><span class="c1"># This script downloads the binaries for the most recent version of TabNine.</span>
</div><div class='line'> </div><div class='line'><span class="nv">version</span><span class="o">=</span><span class="s2">&quot;4.4.25&quot;</span>
</div><div class='line'><span class="nv">targets</span><span class="o">=</span><span class="s1">&#39;aarch64-apple-darwin&#39;</span>
</div><div class='line'> </div><div class='line'>rm<span class="w"> </span>-rf<span class="w"> </span>./binaries
</div><div class='line'> </div><div class='line'><span class="nb">echo</span><span class="w"> </span><span class="s2">&quot;</span><span class="nv">$targets</span><span class="s2">&quot;</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="k">while</span><span class="w"> </span><span class="nb">read</span><span class="w"> </span>target
</div><div class='line'><span class="k">do</span>
</div><div class='line'><span class="w">    </span>mkdir<span class="w"> </span>-p<span class="w"> </span>binaries/<span class="nv">$version</span>/<span class="nv">$target</span>
</div><div class='line'><span class="w">    </span><span class="nv">path</span><span class="o">=</span><span class="nv">$version</span>/<span class="nv">$target</span>
</div><div class='line'><span class="w">    </span><span class="nb">echo</span><span class="w"> </span><span class="s2">&quot;downloading </span><span class="nv">$path</span><span class="s2">&quot;</span>
</div><div class='line'><span class="w">    </span>curl<span class="w"> </span>-sS<span class="w"> </span>https://update.tabnine.com/bundles/<span class="nv">$path</span>/TabNine.zip<span class="w"> </span>&gt;<span class="w"> </span>binaries/<span class="nv">$path</span>/TabNine.zip
</div><div class='line'><span class="w">    </span>unzip<span class="w"> </span>-o<span class="w"> </span>binaries/<span class="nv">$path</span>/TabNine.zip<span class="w"> </span>-d<span class="w"> </span>binaries/<span class="nv">$path</span>
</div><div class='line'><span class="w">    </span>rm<span class="w"> </span>binaries/<span class="nv">$path</span>/TabNine.zip
</div><div class='line'><span class="w">    </span>chmod<span class="w"> </span>+x<span class="w"> </span>binaries/<span class="nv">$path</span>/*
</div><div class='line'><span class="k">done</span>
</div><div class='line'> </div><div class='line'><span class="nv">binariesver</span><span class="o">=</span><span class="k">$(</span>grep<span class="w"> </span>-Eo<span class="w"> </span><span class="s1">&#39;!binaries/.*&#39;</span><span class="w"> </span>.gitignore<span class="w"> </span><span class="p">|</span><span class="w"> </span>cut<span class="w"> </span>-c10-<span class="k">)</span>
</div><div class='line'>sed<span class="w"> </span><span class="s2">&quot;s+</span><span class="nv">$binariesver</span><span class="s2">+/</span><span class="nv">$version</span><span class="s2">+g&quot;</span><span class="w"> </span>.gitignore<span class="w"> </span>&gt;.gitignore.tmp<span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span>mv<span class="w"> </span>.gitignore.tmp<span class="w"> </span>.gitignore
</div></pre></td></table></div></figure>
<p data-sourcepos="29:1-29:137">Run it to download, The <code data-sourcepos="29:25-29:32">4.4.25</code> is the most stable version and <code data-sourcepos="29:65-29:73">4.256.0</code> is the last known version works with sublime text 4 build 4196.</p>
<p data-sourcepos="31:1-31:309">You need also block <code data-sourcepos="31:21-31:40">update.tabnine.com</code> in hosts file to block TabNine auto upgrade, although <a data-sourcepos="31:96-31:259" href="https://github.com/codota/TabNine/commit/bca744fa0ccbba6e60ae092cf4a705e636e32655#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5R38">codota</a> says you can type <code data-sourcepos="31:279-31:308">TabNine::disable_auto_update</code>.</p>
<h2 data-sourcepos="33:1-33:40">Known model list and support language</h2>
<ul data-sourcepos="35:1-43:0">
<li data-sourcepos="35:1-35:28">Universal Small - ce94127b</li>
<li data-sourcepos="36:1-36:29">Universal Medium - b8373e4b</li>
<li data-sourcepos="37:1-37:34">cpp_specialized_model - b6e9f0da</li>
<li data-sourcepos="38:1-38:19">python - 4caf976f</li>
<li data-sourcepos="39:1-39:35">ruby_specialized_model - 29b87067</li>
<li data-sourcepos="40:1-40:15">go - 598b1f5b</li>
<li data-sourcepos="41:1-41:17">java - af421852</li>
<li data-sourcepos="42:1-43:0">rust_specialized_model - 46f17fa1</li>
</ul>
<p data-sourcepos="44:1-44:52">C#, JS, CSS, HTML and PHP belongs to Universal model</p>
]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[A Rails developer installation log on MacBook M4 Pro]]></title>
<link href="https://blog.cloud-mes.com/2025/04/06/a-rails-developer-installation-log-on-macbook-m4-pro/"/>
<updated>2025-04-06T11:06:00+08:00</updated>
<id>https://blog.cloud-mes.com/2025/04/06/a-rails-developer-installation-log-on-macbook-m4-pro</id>
<category term="macOS" /><category term="brew" />

      <content type="html"><![CDATA[</div><div class='line'><span class="nb">export</span><span class="w"> </span><span class="nv">BASH_IT_HTTP_PROXY</span><span class="o">=</span>http://127.0.0.1:6152]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[an AI roadmap in 2025 for a midsize non-IT company chinese]]></title>
<link href="https://blog.cloud-mes.com/2025/03/03/ai-roadmap-in-2025-for-a-midsize-non-it-company-chinese/"/>
<updated>2025-03-03T15:55:00+08:00</updated>
<id>https://blog.cloud-mes.com/2025/03/03/ai-roadmap-in-2025-for-a-midsize-non-it-company-chinese</id>
<category term="AI" /><category term="Chinese" />

      <content type="html"><![CDATA[<h1 data-sourcepos="1:1-1:64">中等规模的非 IT 企业在 2025 年的 AI 应用路线图</h1>
<p data-sourcepos="3:1-3:278">人工智能（AI）在过去两年呈爆发式发展，特别是 2024 年 12 月 26 日 DeepSeek V3 模型的发布，标志着中国正式进入 AI 智能时代。对于非 IT 主业的传统企业而言，制定清晰的 AI 战略路线图已成为数字化转型的关键。</p>
<h2 data-sourcepos="5:1-5:37">目前的 AI 现状与方向选择</h2>
<h3 data-sourcepos="7:1-7:40">DeepSeek V3 为何能成为里程碑</h3>
<p data-sourcepos="9:1-9:376">在 DS V3 实现大规模商用前，国内企业面临两大困境：其一，国际主流模型受地缘政策限制难以合规使用；其二，可用模型的调用成本居高不下（单次请求约 0.8 元），严重制约规模化应用。DS V3 通过技术突破将成本降低 40 倍（单次成本约 0.02 元），使企业级应用真正具备经济可行性。</p>
<h3 data-sourcepos="11:1-11:27">自部署 vs 调用 API</h3>
<p data-sourcepos="13:1-13:318">目前看来自部署的唯一优势就是隐私安全，其他完全不能和直接调用厂商 API 比较，调用 DS 的 API，2 月份花费不到 1 元，即使考虑需求在未来增长百倍，一年也不过 1200 元的费用，而一块 4090 的显卡目前价格在 2 万左右，等于可以用几十年。</p>
<p data-sourcepos="15:1-15:301">更重要的是调用 DS API 的模型是 670b 的 V3 或者 R1，从模型参数看，也比单块 4090 跑的 14b 要大 47 倍，而且这个差距不可弥补，使用 AI 最重要的是 AI 的智能，14b 的模型基本等于小学生的智能，而 V3 绝对可以达到大学本科的水平。</p>
<p data-sourcepos="17:1-17:507">自部署的 14b 在实际测试中，对于合同分析的问题，比如“收款条件第一笔是否为预付款，回答是或者否”，令人难以置信的是，硅基流动的线上版本的<a data-sourcepos="17:201-17:315" href="https://cloud.siliconflow.cn/models?target=deepseek-ai/DeepSeek-R1-Distill-Qwen-14B">DeepSeek-R1-Distill-Qwen-14B</a>的思考链效果也远远好于本地部署的<a data-sourcepos="17:364-17:435" href="https://ollama.com/library/deepseek-r1:14b">Ollama 的 DeepSeek-R1:14b</a>，理论上这两个模型应该是完全一样，实在令人不解。</p>
<p data-sourcepos="19:1-19:209">同时我还在微信群中看到有某单位领导部署 70b 模型后与公网差距巨大的截图，可见即使是完全相同的模型，在部署的时候的一些 knowhow 可能仍然是不公开的。</p>
<p data-sourcepos="21:1-21:440">DeekSeek 在 2025 年 3 月开源第 6 天的<a data-sourcepos="21:46-21:109" href="https://x.com/deepseek_ai/status/1895688300574462431">X 推文</a>中指出，DS 在部署中可以达到 545% 的理论每天利润率，与此同时，<a data-sourcepos="21:197-21:257" href="https://www.zhihu.com/question/13087686159">伯克利尤洋</a>却可以算出每月亏损 4 亿的奇怪数字，所以自部署模型无论从经济或者技术角度，可能都不是目前的最佳选择，这至少是目前看到的形式。</p>
<h3 data-sourcepos="23:1-23:23">RAG vs 模型微调</h3>
<p data-sourcepos="25:1-25:336">另外一个存在选择的方向是使用 RAG 搜索嵌入，或者对模型进行微调，这个在网上讨论也是非常多的，目前来看，RAG 的灵活性和实时性要好得多，可以优先尝试，其实这两个方向不存在矛盾，在以后积累了一定的问答数据集后，同样可以对模型进行微调。</p>
<p data-sourcepos="27:1-27:385">但第一优先的仍然应该是 RAG，RAG 的方式方法其实也非常多，在穷尽这些方法前我认为没有必要去看模型微调，尤其是 RAG 很直观，永远能从 Prompt Log 中看到引用了那些知识内容，理论上只要提供的准确的文本信息，模型能力到位，是完全可以得到准确答案的。这种确定性和实时性非常重要。</p>
<p data-sourcepos="29:1-29:345">相比之下模型微调只有在经过很长时间的一段时间的模型调整后才能查看结果，而且若对这次模型调整的新的例子的推理结果不满意的话，又要将准确的例子作为训练素材进行重新微调，一次微调耗时 1～2 天（硅基流动调用频率），显然无法和 RAG 对比实时性。</p>
<p data-sourcepos="31:1-31:189">当然在积累足够量的标注数据（≥1 万条）后，我们仍然可对基础模型进行领域适配。但需注意单次微调周期约 48 小时，且需要持续迭代优化。</p>
<p data-sourcepos="33:1-33:205">另外我们仍然需要考虑模型的优化速度，可能这些微调都没必要做，因为可能当我们的项目做了 3，4 个月后，更优秀的模型早就出了，可能都不用做微调。</p>
<h3 data-sourcepos="35:1-35:58">直接使用厂商 API vs 通过 AI 中间平台调用</h3>
<p data-sourcepos="37:1-37:242">由于 AI 调用的返回极其缓慢，导致直接调用厂商 API 性能收益约等于 0，可能通过 AI 中间平台调用会损失 1 秒，但是相比呼叫 AI 模型厂商动则需要等待 20 多秒的情况，可以忽略不计。</p>
<p data-sourcepos="39:1-39:419">使用 dify 应用开发平台，可以免费获得 prompt 调试环境，API 调用历史分析等功能，同时还可以将 AI 模型调整的工作从较为瓶颈的程序员下放到运营和产品经理身上，甚至最终用户身上，更加便于 AI 的使用者理解 AI 目前的局限性，所以肯定是使用类似 dify 这样的应用开发平台合适。直接调用厂商 API 都没有这些功能。</p>
<h2 data-sourcepos="41:1-41:27">未来的方向与展望</h2>
<p data-sourcepos="43:1-43:401">现在 AI 的瓶颈已经从模型端转移到应用端，对中等规模的非 IT 主业企业来说，最重要的是找到自己公司流程上各个可以运用 AI 智能，降低人力的应用点，逐个补强，至少是用 AI 平替这些点，这样才能在未来 AI 含量越来越高的市场环境中获得成本和反应速度优势，当然是在保持人类智能质量的前提下。</p>
<p data-sourcepos="45:1-45:251">目前我们已经在用的是 7777 IT 服务问答助手，PLM 问答助手，在研发的有 BIM 空间名称识别，合同分析测试，相信还有很多微小的可以用 AI 替代人工的点存在，所以 AI 应用在 2025 年大有可为。</p>
]]></content>
    </entry>
  
    <entry>
      




<title type="html"><![CDATA[Install sassc in Sequoia and brew ruby 3.4.1]]></title>
<link href="https://blog.cloud-mes.com/2025/01/28/install-sassc-in-sequoia-and-brew-ruby-3-dot-4-1/"/>
<updated>2025-01-28T17:28:00+08:00</updated>
<id>https://blog.cloud-mes.com/2025/01/28/install-sassc-in-sequoia-and-brew-ruby-3-dot-4-1</id>
<category term="macOS" /><category term="Ruby" />

      <content type="html"><![CDATA[<p data-sourcepos="1:1-1:113">My new Sequoia 15.3 seems not loading C++ standard library headers and lead several native gem failed to compile:</p>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div><div data-line='4' class='line-number'></div><div data-line='5' class='line-number'></div><div data-line='6' class='line-number'></div><div data-line='7' class='line-number'></div><div data-line='8' class='line-number'></div><div data-line='9' class='line-number'></div><div data-line='10' class='line-number'></div><div data-line='11' class='line-number'></div><div data-line='12' class='line-number'></div><div data-line='13' class='line-number'></div><div data-line='14' class='line-number'></div><div data-line='15' class='line-number'></div><div data-line='16' class='line-number'></div><div data-line='17' class='line-number'></div><div data-line='18' class='line-number'></div><div data-line='19' class='line-number'></div><div data-line='20' class='line-number'></div><div data-line='21' class='line-number'></div><div data-line='22' class='line-number'></div><div data-line='23' class='line-number'></div><div data-line='24' class='line-number'></div><div data-line='25' class='line-number'></div><div data-line='26' class='line-number'></div><div data-line='27' class='line-number'></div><div data-line='28' class='line-number'></div><div data-line='29' class='line-number'></div><div data-line='30' class='line-number'></div><div data-line='31' class='line-number'></div><div data-line='32' class='line-number'></div><div data-line='33' class='line-number'></div><div data-line='34' class='line-number'></div><div data-line='35' class='line-number'></div><div data-line='36' class='line-number'></div><div data-line='37' class='line-number'></div><div data-line='38' class='line-number'></div><div data-line='39' class='line-number'></div><div data-line='40' class='line-number'></div><div data-line='41' class='line-number'></div><div data-line='42' class='line-number'></div><div data-line='43' class='line-number'></div><div data-line='44' class='line-number'></div><div data-line='45' class='line-number'></div><div data-line='46' class='line-number'></div><div data-line='47' class='line-number'></div><div data-line='48' class='line-number'></div><div data-line='49' class='line-number'></div><div data-line='50' class='line-number'></div><div data-line='51' class='line-number'></div><div data-line='52' class='line-number'></div><div data-line='53' class='line-number'></div><div data-line='54' class='line-number'></div><div data-line='55' class='line-number'></div><div data-line='56' class='line-number'></div><div data-line='57' class='line-number'></div><div data-line='58' class='line-number'></div><div data-line='59' class='line-number'></div><div data-line='60' class='line-number'></div></pre></td><td class='main  text'><pre><div class='line'><span></span>┌─[±][master U:1 ✗][ 5:13PM][product_hunt]
</div><div class='line'>└─▪ bundle update
</div><div class='line'>Fetching gem metadata from https://rubygems.org/...........
</div><div class='line'>Resolving dependencies...
</div><div class='line'>Fetching sassc 2.4.0
</div><div class='line'>Installing sassc 2.4.0 with native extensions
</div><div class='line'>Gem::Ext::BuildError: ERROR: Failed to build gem native extension.
</div><div class='line'> </div><div class='line'>    current directory: /opt/homebrew/lib/ruby/gems/3.4.0/gems/sassc-2.4.0/ext
</div><div class='line'>/opt/homebrew/opt/ruby/bin/ruby extconf.rb
</div><div class='line'>creating Makefile
</div><div class='line'> </div><div class='line'>current directory: /opt/homebrew/lib/ruby/gems/3.4.0/gems/sassc-2.4.0/ext
</div><div class='line'>make DESTDIR\= sitearchdir\=./.gem.20250128-60884-opsqne sitelibdir\=./.gem.20250128-60884-opsqne clean
</div><div class='line'> </div><div class='line'>current directory: /opt/homebrew/lib/ruby/gems/3.4.0/gems/sassc-2.4.0/ext
</div><div class='line'>make DESTDIR\= sitearchdir\=./.gem.20250128-60884-opsqne sitelibdir\=./.gem.20250128-60884-opsqne
</div><div class='line'>compiling ./libsass/src/ast.cpp
</div><div class='line'>In file included from ./libsass/src/ast.cpp:3:
</div><div class='line'>In file included from ./libsass/src/sass.hpp:55:
</div><div class='line'>In file included from ./libsass/src/memory.hpp:8:
</div><div class='line'>./libsass/src/memory/allocator.hpp:8:10: fatal error: &#39;vector&#39; file not found
</div><div class='line'>    8 | #include &lt;vector&gt;
</div><div class='line'>      |          ^~~~~~~~
</div><div class='line'>1 error generated.
</div><div class='line'>make: *** [ast.o] Error 1
</div><div class='line'> </div><div class='line'>make failed, exit code 2
</div><div class='line'> </div><div class='line'>Gem files will remain installed in /opt/homebrew/lib/ruby/gems/3.4.0/gems/sassc-2.4.0 for inspection.
</div><div class='line'>Results logged to /opt/homebrew/lib/ruby/gems/3.4.0/extensions/arm64-darwin-24/3.4.0/sassc-2.4.0/gem_make.out
</div><div class='line'> </div><div class='line'>  /opt/homebrew/lib/ruby/site_ruby/3.4.0/rubygems/ext/builder.rb:126:in &#39;Gem::Ext::Builder.run&#39;
</div><div class='line'>  /opt/homebrew/lib/ruby/site_ruby/3.4.0/rubygems/ext/builder.rb:52:in &#39;block in Gem::Ext::Builder.make&#39;
</div><div class='line'>  /opt/homebrew/lib/ruby/site_ruby/3.4.0/rubygems/ext/builder.rb:44:in &#39;Array#each&#39;
</div><div class='line'>  /opt/homebrew/lib/ruby/site_ruby/3.4.0/rubygems/ext/builder.rb:44:in &#39;Gem::Ext::Builder.make&#39;
</div><div class='line'>  /opt/homebrew/lib/ruby/site_ruby/3.4.0/rubygems/ext/ext_conf_builder.rb:44:in &#39;Gem::Ext::ExtConfBuilder.build&#39;
</div><div class='line'>  /opt/homebrew/lib/ruby/site_ruby/3.4.0/rubygems/ext/builder.rb:195:in &#39;Gem::Ext::Builder#build_extension&#39;
</div><div class='line'>  /opt/homebrew/lib/ruby/site_ruby/3.4.0/rubygems/ext/builder.rb:229:in &#39;block in Gem::Ext::Builder#build_extensions&#39;
</div><div class='line'>  /opt/homebrew/lib/ruby/site_ruby/3.4.0/rubygems/ext/builder.rb:226:in &#39;Array#each&#39;
</div><div class='line'>  /opt/homebrew/lib/ruby/site_ruby/3.4.0/rubygems/ext/builder.rb:226:in &#39;Gem::Ext::Builder#build_extensions&#39;
</div><div class='line'>  /opt/homebrew/lib/ruby/site_ruby/3.4.0/rubygems/installer.rb:844:in &#39;Gem::Installer#build_extensions&#39;
</div><div class='line'>  /opt/homebrew/lib/ruby/site_ruby/3.4.0/bundler/rubygems_gem_installer.rb:111:in &#39;Bundler::RubyGemsGemInstaller#build_extensions&#39;
</div><div class='line'>  /opt/homebrew/lib/ruby/site_ruby/3.4.0/bundler/rubygems_gem_installer.rb:30:in &#39;Bundler::RubyGemsGemInstaller#install&#39;
</div><div class='line'>  /opt/homebrew/lib/ruby/site_ruby/3.4.0/bundler/source/rubygems.rb:205:in &#39;Bundler::Source::Rubygems#install&#39;
</div><div class='line'>  /opt/homebrew/lib/ruby/site_ruby/3.4.0/bundler/installer/gem_installer.rb:55:in &#39;Bundler::GemInstaller#install&#39;
</div><div class='line'>  /opt/homebrew/lib/ruby/site_ruby/3.4.0/bundler/installer/gem_installer.rb:17:in &#39;Bundler::GemInstaller#install_from_spec&#39;
</div><div class='line'>  /opt/homebrew/lib/ruby/site_ruby/3.4.0/bundler/installer/parallel_installer.rb:133:in &#39;Bundler::ParallelInstaller#do_install&#39;
</div><div class='line'>  /opt/homebrew/lib/ruby/site_ruby/3.4.0/bundler/installer/parallel_installer.rb:124:in &#39;block in Bundler::ParallelInstaller#worker_pool&#39;
</div><div class='line'>  /opt/homebrew/lib/ruby/site_ruby/3.4.0/bundler/worker.rb:62:in &#39;Bundler::Worker#apply_func&#39;
</div><div class='line'>  /opt/homebrew/lib/ruby/site_ruby/3.4.0/bundler/worker.rb:57:in &#39;block in Bundler::Worker#process_queue&#39;
</div><div class='line'>  &lt;internal:kernel&gt;:168:in &#39;Kernel#loop&#39;
</div><div class='line'>  /opt/homebrew/lib/ruby/site_ruby/3.4.0/bundler/worker.rb:54:in &#39;Bundler::Worker#process_queue&#39;
</div><div class='line'>  /opt/homebrew/lib/ruby/site_ruby/3.4.0/bundler/worker.rb:90:in &#39;block (2 levels) in Bundler::Worker#create_threads&#39;
</div><div class='line'> </div><div class='line'>An error occurred while installing sassc (2.4.0), and Bundler cannot continue.
</div><div class='line'> </div><div class='line'>In Gemfile:
</div><div class='line'>  sassc-rails was resolved to 2.1.2, which depends on
</div><div class='line'>    sassc
</div></pre></td></table></div></figure>
<p data-sourcepos="58:1-58:30">Below is the correct solution:</p>
<figure class='code'><div class='highlight'><table><td class='line-numbers' aria-hidden='true'><pre><div data-line='1' class='line-number'></div><div data-line='2' class='line-number'></div><div data-line='3' class='line-number'></div></pre></td><td class='main  bash'><pre><div class='line'><span></span>xcrun<span class="w"> </span>--show-sdk-path
</div><div class='line'><span class="nv">CPLUS_INCLUDE_PATH</span><span class="o">=</span>/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1<span class="w"> </span>bundle<span class="w"> </span>install
</div><div class='line'><span class="nv">CPLUS_INCLUDE_PATH</span><span class="o">=</span>/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1<span class="w"> </span>gem<span class="w"> </span>install<span class="w"> </span>rmmseg-cpp-new
</div></pre></td></table></div></figure>
]]></content>
    </entry>
  
</feed>
