<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>血衫非弧の一存</title>
    <description>网站记录了我运维开发的历程，着重于过程分享，希望能够帮助大家少踩坑，少有总结性。</description>
    <link>https://blog.kelu.org</link>
    <atom:link href="https://blog.kelu.org/atom.xml" rel="self" type="application/rss+xml" />
    
      <item>
        <title>QwenPaw 在 Mac Studio 上 KV Cache 命中率归零的排查与根因</title>
        <description>&lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/tags/qwenpaw.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;最近给 QwenPaw 配置 LM Studio 时，发现一个现象：LLM 请求的 KV Cache 命中率始终为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;排查了一圈配置和代理链路，最终发现这不是 bug，而是 &lt;strong&gt;Apple Silicon (MLX) 与 NVIDIA CUDA 在 KV Cache 实现上的根本性差异&lt;/strong&gt;。记录一下排查过程和实验数据。&lt;/p&gt;

&lt;h2 id=&quot;架构与现象&quot;&gt;架构与现象&lt;/h2&gt;

&lt;p&gt;我们的请求链路如下：&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;QwenPaw (Linux) → Docker(cli-proxyapi:8317) → LM Studio (Mac M2 Max, 100.100.100.11:1234)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在 LM Studio 的 Web UI 中，我已经开启了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KV缓存量化 (Experimental)&lt;/code&gt;，上下文长度设为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;262144&lt;/code&gt;。但 QwenPaw 的 token 用量日志显示，每次请求都是全新的 prompt，缓存从未命中。&lt;/p&gt;

&lt;h2 id=&quot;排查过程&quot;&gt;排查过程&lt;/h2&gt;

&lt;h3 id=&quot;step-1-排除代理层干扰&quot;&gt;Step 1: 排除代理层干扰&lt;/h3&gt;
&lt;p&gt;首先怀疑是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cli-proxyapi&lt;/code&gt; 在转发时注入了动态 header（如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X-Request-Id&lt;/code&gt;、时间戳等），导致每次请求的 HTTP 头不一致。&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl &lt;span class=&quot;nt&quot;&gt;-sv&lt;/span&gt; ... http://cli-proxyapi.sh4.local:8317/v1/chat/completions 2&amp;gt;&amp;amp;1 | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;^[&amp;lt;&amp;gt;]&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;结果&lt;/strong&gt;：两次请求的 header 完全一致，代理层干净。&lt;/p&gt;

&lt;h3 id=&quot;step-2-排除多实例负载均衡&quot;&gt;Step 2: 排除多实例负载均衡&lt;/h3&gt;
&lt;p&gt;如果 LM Studio 背后有多台机器轮询，缓存自然无法复用。我是单实例运行，无负载均衡。&lt;/p&gt;
&lt;h3 id=&quot;step-3-kv-cache-压力测试&quot;&gt;Step 3: KV Cache 压力测试&lt;/h3&gt;
&lt;p&gt;我构造了两组对比实验：&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;实验 A：完全相同的 prompt 重复发送&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;qwen3.6-35b-a3b@8bit&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;messages&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:[{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;system&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;You are a test bot.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;What is 1+1?&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;assistant&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;And 2+2?&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}],&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;max_tokens&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;temperature&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;Req1: &lt;strong&gt;1011ms&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Req2: &lt;strong&gt;444ms&lt;/strong&gt; (↓ 56% 加速)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;实验 B：相同前缀(100K chars) + 不同后缀（模拟 Agent 多轮对话）&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;PREFIX&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;python3 &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;print(&apos;A&apos;*100000)&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# 约 25K tokens&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Req1: system=&quot;$PREFIX&quot;, user=&quot;Say ONE word: test&quot;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Req2: system=&quot;$PREFIX&quot;, user=&quot;Say ONE word: test&quot; (完全相同)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;Req1: &lt;strong&gt;632ms&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Req2: &lt;strong&gt;753ms&lt;/strong&gt; (反而更慢，缓存未生效)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;核心结论mlx-vs-cuda-的-kv-cache-差异&quot;&gt;核心结论：MLX vs CUDA 的 KV Cache 差异&lt;/h2&gt;

&lt;p&gt;实验数据说明了原因：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;场景&lt;/th&gt;
      &lt;th&gt;CUDA (vLLM/TGI)&lt;/th&gt;
      &lt;th&gt;Apple Silicon (MLX/LM Studio)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;完全相同的 prompt&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;✅ 命中，复用 KV Cache&lt;/td&gt;
      &lt;td&gt;✅ 命中，复用 KV Cache&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;相同前缀 + 不同后缀&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;✅ 自动前缀缓存 (Prefix Caching)&lt;/td&gt;
      &lt;td&gt;❌ &lt;strong&gt;不支持&lt;/strong&gt;，必须逐字节完全匹配&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;QwenPaw 的 Agent 场景每轮发送的 prompt 结构如下：&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[固定 System Prompt (~15K tokens)] + [变化的对话历史] + [新的 User Message]
         ↑ 前缀固定                          ↑ 每轮变化
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在 CUDA 推理框架中，vLLM/TGI 会自动提取相同的前缀进行 KV Cache 复用，Agent 场景的缓存命中率通常能达到 &lt;strong&gt;30%~50%&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;但在 Apple Silicon 上，LM Studio 底层使用 &lt;strong&gt;MLX&lt;/strong&gt; 框架。MLX 的 KV Cache 实现较为朴素，仅支持精确匹配（Exact Match），&lt;strong&gt;不支持前缀缓存 (Prefix Caching)&lt;/strong&gt;。Apple Silicon 的 KV Cache 优化目前仍处于实验阶段，前缀复用功能尚未稳定。&lt;/p&gt;

&lt;h2 id=&quot;踩坑记录&quot;&gt;踩坑记录&lt;/h2&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Apple Silicon 的 MLX 框架限制&lt;/strong&gt;：MLX 在推理速度上已经非常优秀，但在企业级特性（如 Prefix Caching、Continuous Batching）上仍落后于 CUDA 生态。选型时需明确场景需求。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;实验设计&lt;/strong&gt;：用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;date +%s%N&lt;/code&gt; 记录毫秒级耗时，配合完全相同的 prompt vs 前缀相同后缀不同的对比，能最快定位缓存生效边界。&lt;/li&gt;
&lt;/ol&gt;
</description>
        <pubDate>Fri, 08 May 2026 00:00:00 +0800</pubDate>
        <link>https://blog.kelu.org/tech/2026/05/08/qwenpaw-kv-cache-mac-studio-diagnosis.html</link>
        <guid isPermaLink="true">https://blog.kelu.org/tech/2026/05/08/qwenpaw-kv-cache-mac-studio-diagnosis.html</guid>
      </item>
    
      <item>
        <title>Mac Studio 接入 Prometheus + Grafana 监控实践</title>
        <description>&lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/tags/prometheus.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;最近给 Mac Studio 配了一套监控方案，通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;macmon-prometheus-exporter&lt;/code&gt; 采集硬件指标，接入 Prometheus + Grafana。整个过程比想象中简单，记录一下细节。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/2026/05/image-20260508上午62046355.jpg&quot; alt=&quot;image-20260508上午62046355&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/2026/05/image-20260508上午62159332.jpg&quot; alt=&quot;image-20260508上午62159332&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;安装-macmon&quot;&gt;安装 macmon&lt;/h2&gt;

&lt;p&gt;参考&lt;a href=&quot;/tech/2026/04/30/macos-performance-monitoring-asitop-macmon.html&quot;&gt;macmon - Apple Silicon Mac 的性能监控利器&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;安装-exporter&quot;&gt;安装 Exporter&lt;/h2&gt;

&lt;p&gt;macmon-exporter 通过 Homebrew 一键安装：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;macmon-prometheus-exporter
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;安装后会自动注册为 launchd 服务，监听 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;9101&lt;/code&gt; 端口。验证一下：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl http://localhost:9101/metrics | &lt;span class=&quot;nb&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;关键指标一览&quot;&gt;关键指标一览&lt;/h2&gt;

&lt;p&gt;macmon-exporter 暴露的指标都在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mac_&lt;/code&gt; 命名空间下，都是 Gauge 类型（瞬时值）：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;指标&lt;/th&gt;
      &lt;th&gt;含义&lt;/th&gt;
      &lt;th&gt;示例值&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mac_cpu_usage_percent&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;CPU 总使用率（%）&lt;/td&gt;
      &lt;td&gt;27.69&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mac_gpu_usage_percent&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;GPU 使用率（%）&lt;/td&gt;
      &lt;td&gt;100.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mac_cpu_power_watts&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;CPU 功耗（瓦特）&lt;/td&gt;
      &lt;td&gt;4.88&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mac_gpu_power_watts&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;GPU 功耗（瓦特）&lt;/td&gt;
      &lt;td&gt;50.86&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mac_cpu_temperature_celsius&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;CPU 温度（摄氏度）&lt;/td&gt;
      &lt;td&gt;52.69&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mac_gpu_temperature_celsius&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;GPU 温度（摄氏度）&lt;/td&gt;
      &lt;td&gt;48.97&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mac_memory_usage_percent&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;内存使用率（%）&lt;/td&gt;
      &lt;td&gt;62.00&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mac_memory_total_bytes&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;内存总量（字节）&lt;/td&gt;
      &lt;td&gt;103079215104&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：macmon-exporter 提供的是瞬时百分比值，不是累积计数器。这意味着在 Grafana 中&lt;strong&gt;不需要使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;irate()&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rate()&lt;/code&gt;&lt;/strong&gt;。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;prometheus-配置&quot;&gt;Prometheus 配置&lt;/h2&gt;

&lt;p&gt;prometheus.yml&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;job_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;node-studio&apos;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;static_configs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;targets&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;studio.local:9101&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;exported_instance&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;studio&quot;&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;studio&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;grafana-面板配置&quot;&gt;Grafana 面板配置&lt;/h2&gt;

&lt;h3 id=&quot;cpu--gpu-使用率&quot;&gt;CPU / GPU 使用率&lt;/h3&gt;

&lt;p&gt;Linux 节点通常用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;irate(node_cpu_seconds_total{mode=&quot;idle&quot;})&lt;/code&gt; 计算 CPU 使用率，但 Mac Studio 的 macmon-exporter 直接提供百分比值：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-promql&quot;&gt;# CPU 使用率（除以100因为Grafana自带百分号）
avg(mac_cpu_usage_percent{node=&quot;studio&quot;}) by (node) / 100

# GPU 使用率
avg(mac_gpu_usage_percent{node=&quot;studio&quot;}) by (node) / 100
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;cpu-核心数对比&quot;&gt;CPU 核心数对比&lt;/h3&gt;

&lt;p&gt;Linux 节点用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;count(node_cpu_seconds_total{mode=&quot;system&quot;})&lt;/code&gt; 统计核心数，Mac Studio 需要分别查询 P-Core 和 E-Core：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-promql&quot;&gt;# Mac Studio: 8P + 4E = 12 核心
sum(mac_pcpu_cores{node=&quot;studio&quot;}) + sum(mac_ecpu_cores{node=&quot;studio&quot;})
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;内存使用率&quot;&gt;内存使用率&lt;/h3&gt;

&lt;p&gt;同样，macmon-exporter 直接提供百分比：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-promql&quot;&gt;# 内存使用率（除以100）
avg(mac_memory_usage_percent{node=&quot;studio&quot;}) by (node) / 100

# 内存总量（注意单位）
mac_memory_total_bytes{node=&quot;studio&quot;} / 1024^3
&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;踩坑&lt;/strong&gt;：Grafana 默认使用十进制单位（1 GB = 10^9 bytes），所以 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mac_memory_total_bytes&lt;/code&gt; 直接除以 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1024^3&lt;/code&gt; 后显示为 &lt;strong&gt;96 GiB&lt;/strong&gt;（二进制），而不是 103 GB（十进制）。在 Grafana 面板中将 Unit 设为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gibibytes (GiB)&lt;/code&gt; 即可正确显示。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;cpu--gpu-温度&quot;&gt;CPU / GPU 温度&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&quot;language-promql&quot;&gt;# CPU 温度
mac_cpu_temperature_celsius{node=&quot;studio&quot;}

# GPU 温度
mac_gpu_temperature_celsius{node=&quot;studio&quot;}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;功耗监控&quot;&gt;功耗监控&lt;/h3&gt;

&lt;p&gt;Apple Silicon 的功耗数据很有参考价值：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-promql&quot;&gt;# CPU 功耗（瓦特）
mac_cpu_power_watts{node=&quot;studio&quot;}

# GPU 功耗（瓦特）
mac_gpu_power_watts{node=&quot;studio&quot;}

# 系统总功耗
mac_system_power_watts{node=&quot;studio&quot;}

# 过去1小时的平均系统功耗
avg_over_time(mac_system_power_watts{node=&quot;studio&quot;}[1h])

# 过去24小时的平均系统功耗
avg_over_time(mac_system_power_watts{node=&quot;studio&quot;}[24h])

# 过去7天的平均系统功耗
avg_over_time(mac_system_power_watts{node=&quot;studio&quot;}[7d])
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;注意事项&quot;&gt;注意事项&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;瞬时值 vs 计数器&lt;/strong&gt;：macmon-exporter 的百分比指标是 Gauge，不需要 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;irate()&lt;/code&gt;。只有累积计数器才需要 rate/irate。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;单位转换&lt;/strong&gt;：Grafana 的 Unit 设置会影响显示值，注意区分 GB（十进制）和 GiB（二进制）。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;温度监控&lt;/strong&gt;：macmon-exporter 只暴露 CPU/GPU 温度，没有硬盘 SMART 信息。如果需要磁盘温度，需要额外安装 smartmontools。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

</description>
        <pubDate>Fri, 08 May 2026 00:00:00 +0800</pubDate>
        <link>https://blog.kelu.org/tech/2026/05/08/mac-studio-prometheus-grafana-monitoring.html</link>
        <guid isPermaLink="true">https://blog.kelu.org/tech/2026/05/08/mac-studio-prometheus-grafana-monitoring.html</guid>
      </item>
    
      <item>
        <title>部署 CLIProxyAPI 和 CPA Usage Keeper</title>
        <description>&lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/tags/qwenpaw.jpg&quot; alt=&quot;docker&quot; /&gt;&lt;/p&gt;

&lt;p&gt;最近在折腾本地 AI 代理服务，把 CLIProxyAPI 和 CPA Usage Keeper 部署到了 Docker 里，记录一下过程。&lt;/p&gt;

&lt;h2 id=&quot;背景&quot;&gt;背景&lt;/h2&gt;

&lt;h3 id=&quot;cliproxyapi&quot;&gt;CLIProxyAPI&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/router-for-me/Cli-Proxy-API&quot;&gt;CLIProxyAPI&lt;/a&gt; 是一个开源的 AI API 代理服务，主要用来：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;转发 OpenAI/Gemini/Claude/Codex 等模型的 API 请求&lt;/li&gt;
  &lt;li&gt;支持 OAuth 登录，获取官方模型的配额&lt;/li&gt;
  &lt;li&gt;可以对接 OpenRouter 等第三方 API 聚合平台&lt;/li&gt;
  &lt;li&gt;提供 Web 管理界面和 API&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;对于我这种无法直接访问 OpenAI/Gemini 官方 API 的人来说，它是个不错的解决方案。可以把请求转发到 OpenRouter，由 OpenRouter 帮我调用意愿的模型。&lt;/p&gt;

&lt;h3 id=&quot;cpa-usage-keeper&quot;&gt;CPA Usage Keeper&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/willxup/cpa-usage-keeper&quot;&gt;CPA Usage Keeper&lt;/a&gt;（简称 CPA）是 CLIProxyAPI 的配套管理工具，主要功能：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;同步 CLIProxyAPI 的使用数据（请求数、Token 消耗等）&lt;/li&gt;
  &lt;li&gt;管理 API Keys 和凭证&lt;/li&gt;
  &lt;li&gt;提供使用量统计和可视化界面&lt;/li&gt;
  &lt;li&gt;支持多用户/多项目统计&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;简单说就是给 CLIProxyAPI 做一个”后台”，方便查看花了多少钱、用了多少 Token。&lt;/p&gt;

&lt;h2 id=&quot;部署步骤&quot;&gt;部署步骤&lt;/h2&gt;

&lt;h3 id=&quot;1-准备目录和配置文件&quot;&gt;1. 准备目录和配置文件&lt;/h3&gt;

&lt;p&gt;创建工作目录：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /root/docker/cliproxyapi
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /root/docker/cliproxyapi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;配置文件 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;config.yaml&lt;/code&gt;：&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;0.0.0.0&quot;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;8317&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;remote-management&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;allow-remote&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;secret-key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;my-simple-key&quot;&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;api-keys&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;cliproxy-default-key&quot;&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;openai-compatibility&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;openrouter&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;prefix&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;openrouter&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;base-url&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;https://openrouter.ai/api/v1&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;Content-Type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;application/json&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;api-key-entries&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;api-key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;你的&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;OpenRouter&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Key&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;minimax/minimax-m2.5:free&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;alias&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;minimax-m2.5-free&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;2-configyaml-完整配置&quot;&gt;2. config.yaml 完整配置&lt;/h3&gt;

&lt;p&gt;记得开启 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;usage-statistics-enabled&lt;/code&gt;，否则不会记录使用量：&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;0.0.0.0&quot;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;8317&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;remote-management&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;allow-remote&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;secret-key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;my-key&quot;&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;api-keys&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;cliproxy-key&quot;&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;openai-compatibility&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;openrouter&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;prefix&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;openrouter&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;base-url&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;https://openrouter.ai/api/v1&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;Content-Type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;application/json&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;api-key-entries&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;api-key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;你的&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;OpenRouter&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Key&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;minimax/minimax-m2.5:free&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;alias&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;minimax-m2.5-free&quot;&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;DeepSeek&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;base-url&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://api.deepseek.com&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;deepseek-v4-pro&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;deepseek-v4-flash&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;Authorization&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Bearer 你的DeepSeek-API-Key&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;Content-Type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;application/json&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;prefix&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ds&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;lmstudio&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;prefix&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;studio&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;base-url&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;http://本地IP:1234/v1&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;qwen3.6-35b-a3b@8bit&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;usage-statistics-enabled&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;3-docker-composeyml&quot;&gt;3. docker-compose.yml&lt;/h3&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;3&apos;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;cli-proxy-api&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;eceasy/cli-proxy-api:latest&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;cli-proxyapi&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;network_mode&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;bridge&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./config.yaml:/CLIProxyAPI/config.yaml&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./auths:/root/.cli-proxy-api&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./logs:/CLIProxyAPI/logs&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;unless-stopped&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;cpa-usage-keeper&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ghcr.io/willxup/cpa-usage-keeper:latest&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;cli-cpa&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;unless-stopped&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;network_mode&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;bridge&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TZ=Asia/Shanghai&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;CPA_BASE_URL=http://cliproxyapi.local:8317&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;REDIS_QUEUE_ADDR=cliproxyapi.local:8317&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;CPA_MANAGEMENT_KEY=my-key&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;AUTH_ENABLED=true&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;LOGIN_PASSWORD=password&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./keeper:/data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;4-启动服务&quot;&gt;4. 启动服务&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker-compose up &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;5-验证&quot;&gt;5. 验证&lt;/h3&gt;

&lt;p&gt;检查容器状态：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker ps | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;cli-
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;CLIProxyAPI 默认监听在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8317&lt;/code&gt;，CPA 默认监听在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8080&lt;/code&gt;。&lt;/p&gt;

&lt;h2 id=&quot;调用示例&quot;&gt;调用示例&lt;/h2&gt;

&lt;p&gt;配置好模型后，就可以像调用普通 OpenAI API 一样调用 CLIProxyAPI：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl http://cliproxyapi:8317/v1/chat/completions &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Authorization: Bearer cliproxy-key&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Content-Type: application/json&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{
    &quot;model&quot;: &quot;minimax-m2.5-free&quot;,
    &quot;messages&quot;: [
      {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;Hello!&quot;}
    ]
  }&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;参数说明：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;参数&lt;/th&gt;
      &lt;th&gt;值&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;地址&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://cliproxyapi:8317&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;API Key&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cliproxy-key&lt;/code&gt; (config.yaml 中配置的 api-keys)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Model&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minimax-m2.5-free&lt;/code&gt; (config.yaml 中定义的 alias)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;如果需要添加更多模型，只需要在 config.yaml 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openai-compatibility.models&lt;/code&gt; 中添加即可。&lt;/p&gt;

&lt;p&gt;其他模型示例：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl http://cliproxyapi:8317/v1/chat/completions &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Authorization: Bearer cliproxy-key&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Content-Type: application/json&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{
    &quot;model&quot;: &quot;qwen3.6-35b-a3b@8bit&quot;,
    &quot;messages&quot;: [
      {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;你好&quot;}
    ]
  }&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;一些坑&quot;&gt;一些坑&lt;/h2&gt;

&lt;h3 id=&quot;1-密钥配置&quot;&gt;1. 密钥配置&lt;/h3&gt;

&lt;p&gt;CLIProxyAPI 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;secret-key&lt;/code&gt; 支持明文配置，启动时会自动 bcrypt 哈希。所以直接写明文就行，别像我一开始那样直接贴个 bcrypt 哈希上去，结果两边密钥对不上。&lt;/p&gt;

&lt;h3 id=&quot;2-免密登录&quot;&gt;2. 免密登录&lt;/h3&gt;

&lt;p&gt;试了下把 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;secret-key&lt;/code&gt; 设为空想免密，结果管理 API 直接返回 404 不可用了。CPA 还需要管理 API 来同步数据，所以没法完全免密。好在明文密钥两边会自动哈希匹配，保持一致很简单。&lt;/p&gt;

&lt;h3 id=&quot;-使用量统计默认关闭&quot;&gt;. 使用量统计默认关闭&lt;/h3&gt;

&lt;p&gt;一开始 CPA 怎么都拉不到数据，后来发现 CLIProxyAPI 默认关闭了使用量统计。需要在 config.yaml 里加上：&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;usage-statistics-enabled&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;4-cpa-登录保护&quot;&gt;4. CPA 登录保护&lt;/h3&gt;

&lt;p&gt;CPA 默认不带密码，如果暴露在公网很危险。启用登录保护：&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;AUTH_ENABLED=true&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;LOGIN_PASSWORD=password&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;访问&quot;&gt;访问&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;CLIProxyAPI API: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://CLIProxyAPI:8317&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;CLIProxyAPI Dashboard: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://CLIProxyAPI:8317/v0/management&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/2026/05/image-20260503下午45248789.jpg&quot; alt=&quot;image-20260503下午45248789&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;CPA 管理界面: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://CPA:8080&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/2026/05/image-20260503下午45318458.jpg&quot; alt=&quot;image-20260503下午45318458&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;小结&quot;&gt;小结&lt;/h2&gt;

&lt;p&gt;这两个工具配合起来挺香的，CLIProxyAPI 做代理转发，CPA 做使用量统计和密钥管理。内部网络环境下，通过 OpenRouter 访问各种模型还是很方便的。&lt;/p&gt;
</description>
        <pubDate>Sun, 03 May 2026 00:00:00 +0800</pubDate>
        <link>https://blog.kelu.org/tech/2026/05/03/cli-proxy-api-and-cpa-usage-keeper-installation.html</link>
        <guid isPermaLink="true">https://blog.kelu.org/tech/2026/05/03/cli-proxy-api-and-cpa-usage-keeper-installation.html</guid>
      </item>
    
      <item>
        <title>macmon - Apple Silicon Mac 的性能监控利器</title>
        <description>&lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/tags/homebrew.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;跑本地 LLM 模型的时候，一直想看 GPU 和 ANE 的实时功耗和温度。macOS 自带的 Activity Monitor 只有 CPU 使用率，看不到功耗数据。之前有 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;powermetrics&lt;/code&gt; 可以看，但要 sudo 权限，输出也是纯文本。后来发现了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;macmon&lt;/code&gt;，Rust 写的 TUI 工具，不需要 sudo 就能看到芯片级的实时数据，果断装上。&lt;/p&gt;

&lt;h2 id=&quot;安装&quot;&gt;安装&lt;/h2&gt;

&lt;p&gt;通过 Homebrew 安装：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/opt/homebrew/bin/brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;macmon
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;⚠️ 仅支持 Apple Silicon（M1-M5），x86 的 Homebrew 会报架构不兼容。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;功能&quot;&gt;功能&lt;/h2&gt;

&lt;p&gt;macmon 通过 macOS 私有 API 采集数据，和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;powermetrics&lt;/code&gt; 用同一个底层接口，但不需要 root 权限。主要功能包括：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;⚡ &lt;strong&gt;实时功耗&lt;/strong&gt;：CPU / GPU / ANE 的实时功耗（瓦特）&lt;/li&gt;
  &lt;li&gt;📊 &lt;strong&gt;CPU 集群利用率&lt;/strong&gt;：E-Core 和 P-Core 分开显示&lt;/li&gt;
  &lt;li&gt;💾 &lt;strong&gt;内存 / Swap 使用量&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;🌡️ &lt;strong&gt;CPU / GPU 温度&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;📈 &lt;strong&gt;历史曲线&lt;/strong&gt;：带平均值和最大值&lt;/li&gt;
  &lt;li&gt;🎨 &lt;strong&gt;6 种配色主题&lt;/strong&gt;，按 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c&lt;/code&gt; 切换&lt;/li&gt;
  &lt;li&gt;🪟 紧凑模式可以塞进小窗口&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;使用&quot;&gt;使用&lt;/h2&gt;

&lt;h3 id=&quot;基本-tui&quot;&gt;基本 TUI&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;macmon
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/2026/04/image-20260430下午114907974.jpg&quot; alt=&quot;image-20260430下午114907974&quot; /&gt;&lt;/p&gt;

&lt;p&gt;运行后界面分几个区域：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;顶部&lt;/strong&gt;：芯片型号、E/P 核心数、GPU 核心数、内存大小&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;CPU 使用率曲线&lt;/strong&gt;：E-Core 和 P-Core 分开显示，macOS 日常用 E-Core，重负载才切 P-Core&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;GPU 使用率&lt;/strong&gt;：图形处理负载&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;功耗和温度&lt;/strong&gt;：系统总功耗、CPU/GPU/ANE 分项功耗，以及 CPU/GPU 平均温度&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;键盘操作：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;快捷键&lt;/th&gt;
      &lt;th&gt;功能&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;q&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;退出&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;切换 Sparkline / Gauge 视图&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;切换配色主题&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;控制采样间隔&quot;&gt;控制采样间隔&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;macmon &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; 500
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;默认 1000ms 刷新，可以改成 500ms 更频繁。&lt;/p&gt;

&lt;h3 id=&quot;输出-json-给其他工具&quot;&gt;输出 JSON 给其他工具&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;macmon pipe &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; 10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;会输出 10 条 JSON 格式的指标数据，适合管道到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jq&lt;/code&gt; 或者其他脚本处理。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;macmon &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; 500 pipe &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; 10 | jq
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;http-server-模式&quot;&gt;HTTP Server 模式&lt;/h3&gt;

&lt;p&gt;macmon 还支持把指标暴露为 HTTP 服务，方便接入 Prometheus / Grafana：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;macmon serve          &lt;span class=&quot;c&quot;&gt;# 默认 9090 端口&lt;/span&gt;
macmon serve &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 8080  &lt;span class=&quot;c&quot;&gt;# 自定义端口&lt;/span&gt;
macmon serve &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; 500   &lt;span class=&quot;c&quot;&gt;# 采样间隔 500ms&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;两个端点：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;端点&lt;/th&gt;
      &lt;th&gt;格式&lt;/th&gt;
      &lt;th&gt;说明&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GET /json&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;JSON&lt;/td&gt;
      &lt;td&gt;当前指标快照&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GET /metrics&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Prometheus&lt;/td&gt;
      &lt;td&gt;Prometheus 格式指标&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;接入 Prometheus 的配置示例：&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;scrape_configs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;job_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;macmon&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;static_configs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;targets&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;localhost:9090&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;小结&quot;&gt;小结&lt;/h2&gt;

&lt;p&gt;macmon 是目前 Apple Silicon Mac 上最方便的终端监控工具，Rust 实现，单二进制文件，无需 sudo 就能看到芯片级功耗和温度。对于跑本地模型、监控系统负载来说非常实用。&lt;/p&gt;

&lt;h2 id=&quot;参考&quot;&gt;参考&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;macmon GitHub：https://github.com/vladkens/macmon&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Thu, 30 Apr 2026 00:00:00 +0800</pubDate>
        <link>https://blog.kelu.org/tech/2026/04/30/macos-performance-monitoring-asitop-macmon.html</link>
        <guid isPermaLink="true">https://blog.kelu.org/tech/2026/04/30/macos-performance-monitoring-asitop-macmon.html</guid>
      </item>
    
      <item>
        <title>修复 opencode 命令运行时报错 TypeError fn3 is not a function</title>
        <description>&lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/tags/opencode.jpg&quot; alt=&quot;opencode&quot; /&gt;&lt;/p&gt;

&lt;p&gt;最近在使用 opencode 时遇到了一个奇怪的报错：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;opencode
TypeError: fn3 is not a &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;In &lt;span class=&quot;s1&quot;&gt;&apos;fn3(input)&apos;&lt;/span&gt;, &lt;span class=&quot;s1&quot;&gt;&apos;fn3&apos;&lt;/span&gt; is an instance of Object&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; at &amp;lt;anonymous&amp;gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;src/plugin/index.ts:87:28&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;但 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opencode --help&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opencode debug&lt;/code&gt; 却能正常运行。排查下来发现是&lt;strong&gt;版本过旧 + Homebrew upgrade 失效&lt;/strong&gt;导致的问题，后续又牵连出一系列插件配置问题。记录一下完整的排查过程。&lt;/p&gt;

&lt;h2 id=&quot;问题排查&quot;&gt;问题排查&lt;/h2&gt;

&lt;h3 id=&quot;确认环境&quot;&gt;确认环境&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;node &lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt;
v18.20.8

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;npm &lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt;
10.8.2

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;which opencode
/opt/homebrew/bin/opencode

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;opencode &lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt;
1.1.50
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;发现版本不匹配&quot;&gt;发现版本不匹配&lt;/h3&gt;

&lt;p&gt;怀疑是版本问题，尝试 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brew upgrade opencode&lt;/code&gt;，但升级后版本仍然是 1.1.50。进一步查看：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew info opencode
&lt;span class=&quot;o&quot;&gt;==&amp;gt;&lt;/span&gt; opencode: stable 1.4.10 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;bottled&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
AI coding agent, built &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;the terminal
https://opencode.ai

Installed:
/opt/homebrew/Cellar/opencode/1.1.50 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;4 files, 101.5MB&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Tap 源已经有 &lt;strong&gt;1.4.10&lt;/strong&gt;，但本地还停留在 &lt;strong&gt;1.1.50&lt;/strong&gt;——&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brew upgrade&lt;/code&gt; 没有生效。&lt;/p&gt;

&lt;h3 id=&quot;原因分析&quot;&gt;原因分析&lt;/h3&gt;

&lt;p&gt;我最初安装 opencode 时，它还未被收录进 Homebrew 官方核心库（homebrew-core），而是通过第三方 tap &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anomalyco/tap&lt;/code&gt; 安装的。后来 opencode 被官方收录，但本地环境依然优先读取旧的第三方 tap，导致版本停滞在旧版本。&lt;/p&gt;

&lt;p&gt;可以通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brew info&lt;/code&gt; 的 “From” 行来确认来源：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 旧的第三方 tap 来源&lt;/span&gt;
From: https://github.com/anomalyco/homebrew-tap/blob/HEAD/opencode.rb

&lt;span class=&quot;c&quot;&gt;# 新的官方来源&lt;/span&gt;
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/o/opencode.rb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;解决方案&quot;&gt;解决方案&lt;/h2&gt;

&lt;h3 id=&quot;1-卸载旧版本&quot;&gt;1. 卸载旧版本&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew uninstall opencode
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;2-移除旧的-tap-源&quot;&gt;2. 移除旧的 Tap 源&lt;/h3&gt;

&lt;p&gt;这一步是关键，将 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anomalyco/tap&lt;/code&gt; 从本地库中移除：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew untap anomalyco/tap
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;3-更新并重新安装&quot;&gt;3. 更新并重新安装&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew update
brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;opencode
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这一次系统会从 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;homebrew-core&lt;/code&gt; 拉取最新版本：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;🍺  /opt/homebrew/Cellar/opencode/1.4.10: 12 files, 101.3MB
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;4-验证修复&quot;&gt;4. 验证修复&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;opencode &lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt;
1.4.10

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;opencode &lt;span class=&quot;nt&quot;&gt;--help&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# 正常显示所有命令&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew postinstall opencode
&lt;span class=&quot;c&quot;&gt;# 确保 post-install 步骤执行完成&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;重新安装后，CLI 模式正常工作，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TypeError&lt;/code&gt; 报错消失。&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;后续插件配置问题&quot;&gt;后续：插件配置问题&lt;/h2&gt;

&lt;p&gt;升级版本后，CLI 模式已经正常，但使用 Web 界面时又遇到新错误：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;unknown certificate verification error
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;实际排查后发现，真正的原因是 API 验证错误：&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;error&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;code&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;34&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;request validation errors&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;errors&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Extra inputs are not permitted&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;loc&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;body&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;tools[0]&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;eager_input_streaming&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;msg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Extra inputs are not permitted&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;input&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;定位配置&quot;&gt;定位配置&lt;/h3&gt;

&lt;p&gt;opencode 的配置文件不在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.opencode/&lt;/code&gt;，而是在：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; ~/.config/opencode/
opencode.json  oh-my-opencode.json.bak
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;发现问题插件&quot;&gt;发现问题插件&lt;/h3&gt;

&lt;p&gt;查看 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opencode.json&lt;/code&gt; 后发现：&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;$schema&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://opencode.ai/config.json&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;plugin&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;oh-my-openagent@latest&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这里配置的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oh-my-openagent&lt;/code&gt; 插件向 Minimax API 发送了不支持的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eager_input_streaming&lt;/code&gt; 参数，导致验证失败。&lt;/p&gt;

&lt;h3 id=&quot;临时解决&quot;&gt;临时解决&lt;/h3&gt;

&lt;p&gt;将插件列表清空：&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;$schema&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://opencode.ai/config.json&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;plugin&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;禁用插件后，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opencode run &quot;你好&quot;&lt;/code&gt; 可以正常收到 AI 回复。&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;关于-oh-my-opencode-插件&quot;&gt;关于 oh-my-opencode 插件&lt;/h2&gt;

&lt;p&gt;opencode 本身只是一个框架，真正的能力来自插件。&lt;a href=&quot;https://github.com/anomalyco/oh-my-opencode&quot;&gt;oh-my-opencode&lt;/a&gt;（后改名为 oh-my-openagent）是 opencode 的插件集合，提供多种专业 agent。&lt;/p&gt;

&lt;h3 id=&quot;安装&quot;&gt;安装&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bunx oh-my-opencode &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--no-tui&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--skip-auth&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--no-tui&lt;/code&gt; 参数可以跳过图形界面交互，适合非交互式环境。&lt;/p&gt;

&lt;h3 id=&quot;模型配置&quot;&gt;模型配置&lt;/h3&gt;

&lt;p&gt;安装后可能会遇到模型验证问题：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Agent atlas&apos;s configured model opencode/glm-4.7-free is not valid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;解决方法是更换为有效的模型，例如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opencode/big-pickle&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opencode/gpt-5-nano&lt;/code&gt;。&lt;/p&gt;

&lt;h3 id=&quot;包名变更&quot;&gt;包名变更&lt;/h3&gt;

&lt;p&gt;2026 年 3 月发生了一个重要变化：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;项目&lt;/th&gt;
      &lt;th&gt;旧名称&lt;/th&gt;
      &lt;th&gt;新名称&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;npm 包&lt;/td&gt;
      &lt;td&gt;oh-my-opencode&lt;/td&gt;
      &lt;td&gt;oh-my-openagent（v3.11.0, 2026-03-07）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;配置文件&lt;/td&gt;
      &lt;td&gt;oh-my-opencode.json&lt;/td&gt;
      &lt;td&gt;保留不变&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Schema 文件&lt;/td&gt;
      &lt;td&gt;oh-my-opencode.schema.json&lt;/td&gt;
      &lt;td&gt;保留不变&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;配置文件名称有意保留旧名以保持向后兼容：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 两种配置名都能工作&lt;/span&gt;
~/.config/opencode/oh-my-opencode.json    &lt;span class=&quot;c&quot;&gt;# 传统（推荐）&lt;/span&gt;
~/.config/opencode/oh-my-openagent.json    &lt;span class=&quot;c&quot;&gt;# 新式&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;agent-体系&quot;&gt;Agent 体系&lt;/h3&gt;

&lt;p&gt;oh-my-opencode 中包含一套完整的 agent 协作体系：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Agent&lt;/th&gt;
      &lt;th&gt;角色&lt;/th&gt;
      &lt;th&gt;说明&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Sisyphus&lt;/td&gt;
      &lt;td&gt;执行者&lt;/td&gt;
      &lt;td&gt;负责任务分解、代码实现&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Prometheus&lt;/td&gt;
      &lt;td&gt;规划代理&lt;/td&gt;
      &lt;td&gt;通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/start-work&lt;/code&gt; 激活，负责生成执行计划&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Metis&lt;/td&gt;
      &lt;td&gt;预规划咨询&lt;/td&gt;
      &lt;td&gt;在规划阶段识别歧义和隐藏意图&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Momus&lt;/td&gt;
      &lt;td&gt;计划评审&lt;/td&gt;
      &lt;td&gt;对执行计划进行清晰度和完整性审查&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;opencode-vs-openclaw&quot;&gt;opencode vs openclaw&lt;/h2&gt;

&lt;p&gt;之前也有人问 opencode 和 openclaw 的区别：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;特性&lt;/th&gt;
      &lt;th&gt;opencode&lt;/th&gt;
      &lt;th&gt;openclaw&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;类型&lt;/td&gt;
      &lt;td&gt;AI 编程助手&lt;/td&gt;
      &lt;td&gt;AI 控制器&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;核心&lt;/td&gt;
      &lt;td&gt;终端 IDE&lt;/td&gt;
      &lt;td&gt;远程控制&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;通道&lt;/td&gt;
      &lt;td&gt;本地为主&lt;/td&gt;
      &lt;td&gt;WhatsApp/Telegram&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;定位&lt;/td&gt;
      &lt;td&gt;编码工作流&lt;/td&gt;
      &lt;td&gt;远程任务管理&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;两者定位不同，没有必要互相替换。&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;总结&quot;&gt;总结&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;问题&lt;/th&gt;
      &lt;th&gt;解决方法&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TypeError: fn3 is not a function&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;卸载旧 tap 源，从 homebrew-core 重新安装最新版&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eager_input_streaming&lt;/code&gt; 验证错误&lt;/td&gt;
      &lt;td&gt;清空 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plugin&lt;/code&gt; 配置或更换兼容插件&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;配置目录找不到&lt;/td&gt;
      &lt;td&gt;记住在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config/opencode/&lt;/code&gt; 而非 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.opencode/&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;几点经验教训：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;遇到奇怪错误，先检查版本&lt;/strong&gt;：很多问题就是版本太旧导致的&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brew upgrade&lt;/code&gt; 不一定可靠&lt;/strong&gt;：如果升级后版本没变，可能需要先 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;untap&lt;/code&gt; 再重装&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;第三方 tap 要注意迁移&lt;/strong&gt;：当项目被 Homebrew 官方收录后，旧的第三方 tap 可能不会自动更新&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;错误信息要看完整&lt;/strong&gt;：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unknown certificate verification error&lt;/code&gt; 是误报，真正的错误在 API 响应体里&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;插件配置要核对&lt;/strong&gt;：确保插件名称与实际安装的包一致&lt;/li&gt;
&lt;/ol&gt;
</description>
        <pubDate>Mon, 27 Apr 2026 00:00:00 +0800</pubDate>
        <link>https://blog.kelu.org/tech/2026/04/27/fix-opencode-error.html</link>
        <guid isPermaLink="true">https://blog.kelu.org/tech/2026/04/27/fix-opencode-error.html</guid>
      </item>
    
      <item>
        <title>Mac 下 QwenPaw 安装记录 - 从零配置 OpenRouter MiniMax 模型</title>
        <description>&lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/tags/claw.jpg&quot; alt=&quot;qwenpaw&quot; /&gt;&lt;/p&gt;

&lt;p&gt;把 QwenPaw（原 CoPaw）装好了，记录一下安装和配置过程。&lt;/p&gt;

&lt;h2 id=&quot;背景&quot;&gt;背景&lt;/h2&gt;

&lt;p&gt;QwenPaw 是 AgentScope 团队开源的个人 AI 助手，支持钉钉、飞书、微信、Discord 等多渠道，还能本地运行、扩展 Skills。GitHub 星标 15K+。&lt;/p&gt;

&lt;h2 id=&quot;问题卡点&quot;&gt;问题卡点&lt;/h2&gt;

&lt;p&gt;官方推荐三种安装方式：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip install qwenpaw&lt;/code&gt; — 需要 Python 3.10+&lt;/li&gt;
  &lt;li&gt;安装脚本 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl -fsSL https://qwenpaw.agentscope.io/install.sh | bash&lt;/code&gt; — 自动下载 uv&lt;/li&gt;
  &lt;li&gt;Docker&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;我的系统自带 Python 是 3.9.6，pip 版本也老（21.2.4），而 qwenpaw 要求 Python 3.10-3.14。我平时用 &lt;strong&gt;conda&lt;/strong&gt; 管理 Python 环境，所以直接走 conda 路线。&lt;/p&gt;

&lt;h2 id=&quot;用-conda-创建环境&quot;&gt;用 conda 创建环境&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 1. 创建 Python 3.11 虚拟环境&lt;/span&gt;
conda create &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; qwenpaw &lt;span class=&quot;nv&quot;&gt;python&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;3.11 &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 2. 激活环境&lt;/span&gt;
conda activate qwenpaw

&lt;span class=&quot;c&quot;&gt;# 3. 安装 qwenpaw&lt;/span&gt;
pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;qwenpaw
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这样就搞定了，不需要额外引入 uv。环境激活后 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip&lt;/code&gt; 都指向 conda 环境内的版本，不会产生污染。&lt;/p&gt;

&lt;h2 id=&quot;配置-openrouter-minimax-模型&quot;&gt;配置 OpenRouter MiniMax 模型&lt;/h2&gt;

&lt;p&gt;qwenpaw 内置支持 OpenRouter provider，配置很简单。编辑 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.copaw/config.json&lt;/code&gt;：&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;$schema&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://qwenpaw.agentscope.io/schema.json&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;models&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;minimax-free&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;provider&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;minimax/minimax-m2.5:free&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;base_url&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://openrouter.ai/api/v1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;api_key&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;你的OPENROUTER_KEY&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;enabled&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;default_model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;minimax-free&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：OpenRouter 的 MiniMax 模型 ID 格式是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minimax/minimax-m2.5:free&lt;/code&gt;，用&lt;strong&gt;冒号&lt;/strong&gt;而不是连字符。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;启动与验证&quot;&gt;启动与验证&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 激活 conda 环境后，qwenpaw 命令可直接使用&lt;/span&gt;
conda activate qwenpaw

&lt;span class=&quot;c&quot;&gt;# 初始化（需要交互式终端）&lt;/span&gt;
qwenpaw init

&lt;span class=&quot;c&quot;&gt;# 或者启动 Web UI&lt;/span&gt;
qwenpaw app
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;启动后打开浏览器访问 &lt;strong&gt;http://127.0.0.1:8088/&lt;/strong&gt; 进行配置和聊天。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/2026/04/89eeb908eec1d5c35b25e24bafb645cc.jpg&quot; alt=&quot;89eeb908eec1d5c35b25e24bafb645cc&quot; /&gt;&lt;/p&gt;

&lt;p&gt;验证安装：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;qwenpaw &lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# QwenPaw, version 1.1.3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;agent-配置让-agent-理解你是谁&quot;&gt;Agent 配置：让 Agent 理解你是谁&lt;/h2&gt;

&lt;p&gt;安装完成只是第一步，真正的关键在于&lt;strong&gt;记忆文件配置&lt;/strong&gt;。&lt;/p&gt;

&lt;h3 id=&quot;核心记忆文件&quot;&gt;核心记忆文件&lt;/h3&gt;

&lt;p&gt;QwenPaw 的工作区位于 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.copaw/workspaces/default/&lt;/code&gt;，包含以下文件：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;文件&lt;/th&gt;
      &lt;th&gt;作用&lt;/th&gt;
      &lt;th&gt;优先级&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PROFILE.md&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Agent 身份 + 用户资料&lt;/td&gt;
      &lt;td&gt;🔴 必须配置&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SOUL.md&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Agent 灵魂宣言（行为准则）&lt;/td&gt;
      &lt;td&gt;🔴 必须配置&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MEMORY.md&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;长期记忆（工具设置/经验教训）&lt;/td&gt;
      &lt;td&gt;🟡 建议配置&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AGENTS.md&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Agent 行为准则模板&lt;/td&gt;
      &lt;td&gt;🟢 可选定制&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HEARTBEAT.md&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;定时任务清单&lt;/td&gt;
      &lt;td&gt;🟢 可选配置&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/2026/04/cbce4ba5762672dac29e8274baad8fe4.jpg&quot; alt=&quot;cbce4ba5762672dac29e8274baad8fe4&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;配置流程&quot;&gt;配置流程&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;首次启动&lt;/strong&gt; — Agent 自动读取所有记忆文件，为空则使用默认模板。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;手动配置&lt;/strong&gt; — 编辑 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PROFILE.md&lt;/code&gt; 定义身份和偏好，编辑 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SOUL.md&lt;/code&gt; 定义行为边界。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;持续迭代&lt;/strong&gt; — Agent 会在每次会话中主动记录重要信息到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memory/YYYY-MM-DD.md&lt;/code&gt;，定期提炼到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MEMORY.md&lt;/code&gt;。&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;关键&lt;/strong&gt;：QwenPaw &lt;strong&gt;不会&lt;/strong&gt;每次重启都重新初始化。记忆通过文件持久化，会话中断后自动恢复上下文。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;依赖规模&quot;&gt;依赖规模&lt;/h2&gt;

&lt;p&gt;qwenpaw 的依赖比较多（约 244 个包），包括：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;agentscope 1.0.19&lt;/li&gt;
  &lt;li&gt;playwright 1.58.0（39MB）&lt;/li&gt;
  &lt;li&gt;transformers 5.5.4（9.8MB）&lt;/li&gt;
  &lt;li&gt;onnxruntime 1.23.2（16MB）&lt;/li&gt;
  &lt;li&gt;chromadb 1.5.8（20MB）&lt;/li&gt;
  &lt;li&gt;grpcio 1.80.0（11MB）&lt;/li&gt;
  &lt;li&gt;pandas 3.0.2（9.5MB）&lt;/li&gt;
  &lt;li&gt;阿里系 SDK（alibabacloud-dingtalk 等）&lt;/li&gt;
  &lt;li&gt;消息渠道 SDK（discord-py、twilio 等）&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;首次安装需要下载不少内容，耐心等待即可。conda 环境下这些依赖会被隔离在环境目录中，不会影响系统。&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;相关工具对比&quot;&gt;相关工具对比&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;工具&lt;/th&gt;
      &lt;th&gt;语言&lt;/th&gt;
      &lt;th&gt;特点&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;QwenPaw&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Python&lt;/td&gt;
      &lt;td&gt;多渠道、本地优先、Skills 扩展&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;OpenCode&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;TypeScript&lt;/td&gt;
      &lt;td&gt;IDE 集成、MCP 生态&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Claude Code&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;TypeScript&lt;/td&gt;
      &lt;td&gt;Anthropic 官方&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;QwenPaw 和 OpenCode 可以通过 ACP（Agent Communication Protocol）互联，默认配置中已开启：&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;&quot;acp&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;agents&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;opencode&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;enabled&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;qwen_code&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;enabled&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;claude_code&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;enabled&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;参考资料&quot;&gt;参考资料&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;QwenPaw 官网：https://qwenpaw.agentscope.io/&lt;/li&gt;
  &lt;li&gt;GitHub：https://github.com/agentscope-ai/QwenPaw&lt;/li&gt;
  &lt;li&gt;OpenRouter MiniMax M2.5 Free：https://openrouter.ai/minimax/minimax-m2.5:free&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Wed, 22 Apr 2026 00:00:00 +0800</pubDate>
        <link>https://blog.kelu.org/tech/2026/04/22/qwenpaw-installation.html</link>
        <guid isPermaLink="true">https://blog.kelu.org/tech/2026/04/22/qwenpaw-installation.html</guid>
      </item>
    
      <item>
        <title>OpenCode 配置 MiniMax 免费模型指南</title>
        <description>&lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/tags/ai.jpg&quot; alt=&quot;minimax&quot; /&gt;&lt;/p&gt;

&lt;p&gt;今天把 OpenCode 的默认模型配置成了 MiniMax M2.5 Free，教程记录一下。&lt;/p&gt;

&lt;h2 id=&quot;背景&quot;&gt;背景&lt;/h2&gt;

&lt;p&gt;我想把自己的 OpenCode 配置成使用 MiniMax 的免费模型，于是研究了一下。最新版本是 M2.7（2026年3月发布），但是在 OpenRouter 上免费只有 &lt;strong&gt;M2.5&lt;/strong&gt;，且 oh-my-openagent 插件内部也硬编码了 M2.7，需要一并修改。&lt;/p&gt;

&lt;h2 id=&quot;minimax-m25-free-配置教程&quot;&gt;MiniMax M2.5 Free 配置教程&lt;/h2&gt;

&lt;h3 id=&quot;1-申请-openrouter-api-key&quot;&gt;1. 申请 OpenRouter API Key&lt;/h3&gt;

&lt;p&gt;OpenRouter 是一个聚合多家 AI 模型 API 的平台，其中提供了免费的 MiniMax 模型。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;访问 https://openrouter.ai/keys&lt;/li&gt;
  &lt;li&gt;点击 &lt;strong&gt;“Create a new key”&lt;/strong&gt; 创建免费 API Key&lt;/li&gt;
  &lt;li&gt;复制生成的 Key&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;2-配置-opencode&quot;&gt;2. 配置 OpenCode&lt;/h3&gt;

&lt;p&gt;编辑配置文件 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config/opencode/opencode.json&lt;/code&gt;：&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;$schema&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://opencode.ai/config.json&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;plugin&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;oh-my-openagent@latest&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;mcp&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;playwright&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;local&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;command&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;bun&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;x&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;@playwright/mcp@latest&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;enabled&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;provider&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;openrouter&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;npm&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;@ai-sdk/openai-compatible&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;MiniMax M2.5 Free&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;options&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;baseURL&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://openrouter.ai/api/v1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;apiKey&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;你的 OpenRouter API Key&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;models&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;minimax-m2.5-free&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;minimax/minimax-m2.5:free&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/minimax/minimax-m2.5:free&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;3-配置-oh-my-openagent如有安装&quot;&gt;3. 配置 oh-my-openagent（如有安装）&lt;/h3&gt;

&lt;p&gt;如果安装了 oh-my-openagent 插件，它内部默认配置了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minimax-m2.7-free&lt;/code&gt; 模型，但 OpenRouter 上免费只有 M2.5。需要修改插件配置。&lt;/p&gt;

&lt;p&gt;编辑 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config/opencode/oh-my-openagent.json&lt;/code&gt;，将所有 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openrouter/minimax/minimax-m2.5:free&lt;/code&gt; 替换为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openrouter/minimax/minimax-m2.5:free&lt;/code&gt;：&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;$schema&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://raw.githubusercontent.com/code-yeongyu/oh-my-opencode/master/assets/oh-my-opencode.schema.json&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;agents&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;hephaestus&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/minimax/minimax-m2.5:free&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;oracle&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/minimax/minimax-m2.5:free&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;librarian&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/minimax/minimax-m2.5:free&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;explore&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/minimax/minimax-m2.5:free&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;multimodal-looker&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/minimax/minimax-m2.5:free&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;prometheus&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/minimax/minimax-m2.5:free&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;metis&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/minimax/minimax-m2.5:free&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;momus&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/minimax/minimax-m2.5:free&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;sisyphus&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/minimax/minimax-m2.5:free&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;sisyphus-junior&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/minimax/minimax-m2.5:free&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;atlas&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/minimax/minimax-m2.5:free&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;categories&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;visual-engineering&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ollama/qwen3-coder-next:q4_K_M&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ultrabrain&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/minimax/minimax-m2.5:free&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;deep&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/minimax/minimax-m2.5:free&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;artistry&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/minimax/minimax-m2.5:free&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;quick&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/minimax/minimax-m2.5:free&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;unspecified-low&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/minimax/minimax-m2.5:free&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;unspecified-high&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/minimax/minimax-m2.5:free&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;writing&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;openrouter/minimax/minimax-m2.5:free&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;4-重启-opencode&quot;&gt;4. 重启 OpenCode&lt;/h3&gt;

&lt;p&gt;配置完成后重启 OpenCode 即可使用免费的 MiniMax 模型。&lt;/p&gt;

&lt;h2 id=&quot;模型信息&quot;&gt;模型信息&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;模型&lt;/th&gt;
      &lt;th&gt;价格&lt;/th&gt;
      &lt;th&gt;Context&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;MiniMax M2.5 Free&lt;/td&gt;
      &lt;td&gt;$0/M tokens&lt;/td&gt;
      &lt;td&gt;196K tokens&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;完全免费！香！&lt;/p&gt;

&lt;h2 id=&quot;参考资料&quot;&gt;参考资料&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;MiniMax 官方文档：https://platform.minimax.io/docs/&lt;/li&gt;
  &lt;li&gt;OpenRouter：https://openrouter.ai/&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Tue, 21 Apr 2026 00:00:00 +0800</pubDate>
        <link>https://blog.kelu.org/tech/2026/04/21/minimax-free-model-opencode.html</link>
        <guid isPermaLink="true">https://blog.kelu.org/tech/2026/04/21/minimax-free-model-opencode.html</guid>
      </item>
    
      <item>
        <title>为什么 cAdvisor 在部分节点采集不到容器的内存数据？</title>
        <description>&lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/tags/prometheus.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;最近在搞跨云节点的容器监控，遇到一个非常诡异的问题：在 Grafana 面板上，有很多容器拉不到内存信息。&lt;/p&gt;

&lt;p&gt;具体表现是，看 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;container_memory_max_usage_bytes{image!=&quot;&quot;}&lt;/code&gt; 这个指标时，老节点的数据一切正常，能读到具体的字节数；但新节点的数据全都是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;仔细对比了一下指标的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt; 标签：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;有数据的节点&lt;/strong&gt;：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/docker/5282f5...&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;没数据的节点&lt;/strong&gt;：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/system.slice/docker-153d1e...scope&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;路径明显不一致。为了解决这个”断流”问题，踩了几个坑，在这里记录一下排查和修复的全过程。&lt;/p&gt;

&lt;h2 id=&quot;坑一盲改-cadvisor-启动参数&quot;&gt;坑一：盲改 cAdvisor 启动参数&lt;/h2&gt;

&lt;p&gt;一开始我以为是 cAdvisor 的 cgroup 挂载路径偏移导致的。因为在新节点里，Docker 使用了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt; 作为 Cgroup Driver。&lt;/p&gt;

&lt;p&gt;于是我尝试修改 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cadvisor.service&lt;/code&gt; 文件，加入了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--runtime_full_cgroup_path=true&lt;/code&gt; 参数。结果改完重启，Systemd 直接报错 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Failed with result &apos;exit-code&apos;&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;查看 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;journalctl -u cadvisor -f&lt;/code&gt; 发现两个致命错误：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;参数语法错误&lt;/strong&gt;：我把 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KillMode=process&lt;/code&gt; 写在了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExecStart&lt;/code&gt; 后面，导致解析失败。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;版本弃用&lt;/strong&gt;：我用的是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v0.46.0&lt;/code&gt; 版本的 cAdvisor，这个版本已经完全&lt;strong&gt;弃用&lt;/strong&gt;了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-runtime_full_cgroup_path&lt;/code&gt; 参数！强行加进去只会触发 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flag provided but not defined&lt;/code&gt; 报错。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;坑二寻找消失的物理路径&quot;&gt;坑二：寻找消失的物理路径&lt;/h2&gt;

&lt;p&gt;既然参数没法调，我决定直接去宿主机上看看 cgroup 的实际目录层级。
按照以往的经验，我执行了：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; /sys/fs/cgroup/memory/system.slice/docker-&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.scope
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;结果提示：文件不存在。&lt;/p&gt;

&lt;p&gt;为了精准定位，采用反向溯源的方法，先拿到容器内主进程的 PID，然后直接看它挂载在哪里：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 拿到容器的 PID&lt;/span&gt;
docker inspect &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{{.State.Pid}}&apos;&lt;/span&gt; iperf-server

&lt;span class=&quot;c&quot;&gt;# 查看对应 PID 的 cgroup (假设 PID 是 12345)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /proc/12345/cgroup
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;输出结果：
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0::/system.slice/docker-153d1e883aa123826...scope&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&quot;真相大白cgroup-v1-与-v2-的代沟&quot;&gt;真相大白：Cgroup v1 与 v2 的代沟&lt;/h2&gt;

&lt;p&gt;看到开头的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0::&lt;/code&gt;，懂了。&lt;strong&gt;这是 Cgroup v2（统一层级）的特征签名。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;根本不是 cAdvisor 挂载错了，也不是参数配错了，而是底层操作系统架构变了：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;老节点跑的是 &lt;strong&gt;Cgroup v1&lt;/strong&gt;，有单独的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/memory/&lt;/code&gt; 目录，内核提供了最大内存使用量的统计接口，所以 cAdvisor 能读到数据。&lt;/li&gt;
  &lt;li&gt;新节点跑的是 &lt;strong&gt;Cgroup v2&lt;/strong&gt;，底层去掉了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memory&lt;/code&gt; 目录。在 Cgroup v2 环境下，cAdvisor 获取不到历史极值，于是强行给 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;container_memory_max_usage_bytes&lt;/code&gt; 这个指标塞了一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;最终方案在-promql-层面无缝缝合&quot;&gt;最终方案：在 PromQL 层面无缝缝合&lt;/h2&gt;

&lt;p&gt;既然底层都不提供这个数据了，死磕 cAdvisor 配置毫无意义。解决办法是直接在查询层更换跨版本兼容的”真实内存”指标：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;container_memory_working_set_bytes&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;但我希望能保留老节点上 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max_usage&lt;/code&gt; 的历史数据。&lt;/p&gt;

&lt;p&gt;利用 PromQL 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;or&lt;/code&gt; 逻辑，实现新老数据的缝合替换。修改 Grafana 的查询语句如下：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-promql&quot;&gt;(container_memory_max_usage_bytes{image!=&quot;&quot;} &amp;gt; 0)
or
(container_memory_working_set_bytes{image!=&quot;&quot;})
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;执行逻辑：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;首先尝试获取老指标。因为新节点这个值全是 0，所以 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt; 0&lt;/code&gt; 的条件会把新节点直接过滤掉。&lt;/li&gt;
  &lt;li&gt;对老节点来说，左侧条件成立，画出老指标的线。&lt;/li&gt;
  &lt;li&gt;对新节点来说，左侧为空，触发 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;or&lt;/code&gt; 逻辑，自动替补使用右侧的新指标 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;working_set&lt;/code&gt; 并在图表上画线。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;保存查询，刷新面板。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;：排查监控数据缺失问题，不要一上来就去猜参数。顺藤摸瓜，从 PID 反查 cgroup 挂载点，直接看操作系统的底层到底给了什么，从根本上解决问题。&lt;/p&gt;
</description>
        <pubDate>Wed, 08 Apr 2026 00:00:00 +0800</pubDate>
        <link>https://blog.kelu.org/tech/2026/04/08/cadvisor-cgroup-v2-memory-metrics-missing.html</link>
        <guid isPermaLink="true">https://blog.kelu.org/tech/2026/04/08/cadvisor-cgroup-v2-memory-metrics-missing.html</guid>
      </item>
    
      <item>
        <title>Mac 上安装 OrbStack 替代 Docker Desktop</title>
        <description>&lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/tags/docker.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;什么是-orbstack&quot;&gt;什么是 OrbStack&lt;/h2&gt;

&lt;p&gt;OrbStack 是一个轻量级的 Docker 替代工具，相比 Docker Desktop：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;启动更快&lt;/li&gt;
  &lt;li&gt;资源占用更低&lt;/li&gt;
  &lt;li&gt;有原生 macOS GUI&lt;/li&gt;
  &lt;li&gt;免费（基本功能）&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;安装过程&quot;&gt;安装过程&lt;/h2&gt;

&lt;h3 id=&quot;1-下载安装&quot;&gt;1. 下载安装&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;https://orbstack.dev/download
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;下载完成后，双击打开 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.dmg&lt;/code&gt; 文件，将 OrbStack 拖入 Applications 文件夹即可。&lt;/p&gt;

&lt;h3 id=&quot;2-启动-docker&quot;&gt;2. 启动 Docker&lt;/h3&gt;

&lt;p&gt;打开 OrbStack 应用，点击 “Start” 按钮启动 Docker 环境。&lt;/p&gt;

&lt;p&gt;验证安装：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;orbctl status
Running

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker version &lt;span class=&quot;nt&quot;&gt;--format&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{{.Server.Version}}&apos;&lt;/span&gt;
28.5.2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;配置国内镜像源&quot;&gt;配置国内镜像源&lt;/h2&gt;

&lt;p&gt;配置 Docker 的镜像源来加速拉取。&lt;/p&gt;

&lt;h3 id=&quot;1-创建配置文件&quot;&gt;1. 创建配置文件&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /etc/docker
&lt;span class=&quot;nb&quot;&gt;sudo tee&lt;/span&gt; /etc/docker/daemon.json &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOF&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;
{
  &quot;registry-mirrors&quot;: [
    &quot;https://registry.docker-cn.com&quot;,
    &quot;https://mirror.ccs.tencentyun.com&quot;,
    &quot;https://docker.mirrors.ustc.edu.cn&quot;
  ]
}
&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;2-重启-docker&quot;&gt;2. 重启 Docker&lt;/h3&gt;

&lt;p&gt;在 OrbStack 菜单中：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Stop Docker&lt;/li&gt;
  &lt;li&gt;Start Docker&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;测试运行&quot;&gt;测试运行&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;完美！🎉&lt;/p&gt;

&lt;h2 id=&quot;参考&quot;&gt;参考&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://orbstack.dev&quot;&gt;OrbStack 官网&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.orbstack.dev/compare/colima&quot;&gt;OrbStack vs Colima 对比&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Wed, 01 Apr 2026 00:00:00 +0800</pubDate>
        <link>https://blog.kelu.org/tech/2026/04/01/install-orbstack.html</link>
        <guid isPermaLink="true">https://blog.kelu.org/tech/2026/04/01/install-orbstack.html</guid>
      </item>
    
      <item>
        <title>Mac Studio 安装 OpenClaw 多实例共存实录</title>
        <description>&lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/tags/openclaw.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;最近在研究多 Agent 编排，本机已经跑着 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;copaw&lt;/code&gt;。今天心血来潮，决定把底层的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openclaw&lt;/code&gt; 单独拎出来跑个 UI 界面看看。&lt;/p&gt;

&lt;p&gt;做个记录，备忘。&lt;/p&gt;

&lt;h3 id=&quot;1-opencode-辅助安装一场优雅的权限绕过&quot;&gt;1. Opencode 辅助安装：一场优雅的权限绕过&lt;/h3&gt;

&lt;p&gt;为了省事，我直接唤醒了终端里的 AI 助手（Opencode，挂的 MiniMax 模型）帮我装。AI 的排错逻辑挺有意思：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;它首先尝试了官方的无脑脚本：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl -fsSL https://openclaw.ai/install.sh | bash&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;发现走不通，立刻切成了全局 NPM 安装：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm install -g openclaw@latest&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;随后触发了经典报错：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local/bin/openclaw&lt;/code&gt; 文件已存在，引发软链接冲突。&lt;/li&gt;
  &lt;li&gt;它的第一反应是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo rm&lt;/code&gt; 强删，但被系统的交互式密码输入卡住了（终端里的 AI 无法直接帮你输密码）。&lt;/li&gt;
  &lt;li&gt;接着它立刻放弃提权，直接用普通权限 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rm -f /usr/local/bin/openclaw &amp;amp;&amp;amp; npm install -g openclaw@latest&lt;/code&gt;。因为我当前账户对该目录有写权限，直接物理抹除并重新接管成功。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;最终拿到了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OpenClaw 2026.3.28&lt;/code&gt; 版本。AI 时代，连写环境配置都变成了一种结对编程。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/2026/03/image-20260330下午31734247.jpg&quot; alt=&quot;image-20260330下午31734247&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/2026/03/image-20260330下午31826704.jpg&quot; alt=&quot;image-20260330下午31826704&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/2026/03/image-20260330下午31858691.jpg&quot; alt=&quot;image-20260330下午31858691&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/2026/03/image-20260330下午32135388.jpg&quot; alt=&quot;image-20260330下午32135388&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/2026/03/image-20260330下午32433093.jpg&quot; alt=&quot;image-20260330下午32433093&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;2-端口冲突&quot;&gt;2. 端口冲突&lt;/h3&gt;

&lt;p&gt;装完后，按常规流程初始化：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;openclaw setup
openclaw gateway
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;结果直接吃了个闭门羹：日志提示 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pid 539 kelu: openclaw-gateway (*:18789)&lt;/code&gt;。18789 端口已经被占用了。&lt;/p&gt;

&lt;p&gt;因为我本机还在跑着 copaw，copaw 也是将 OpenClaw 作为底层通信引擎，早就已经在后台静默拉起了一个 Gateway 守护进程，用了 18789 端口和默认的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.openclaw&lt;/code&gt; 工作区。&lt;/p&gt;

&lt;h3 id=&quot;3-开启-dev-沙盒模式&quot;&gt;3. 开启 Dev 沙盒模式&lt;/h3&gt;

&lt;p&gt;我想同时保留 copaw 的运行状态，又想自己独立玩 OpenClaw 的 Dashboard。既然不能同归于尽，那就只能物理隔离。&lt;/p&gt;

&lt;p&gt;OpenClaw 官方提供了一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--dev&lt;/code&gt; 参数，可以解决了多实例共存的问题。&lt;/p&gt;

&lt;p&gt;启动独立网关：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;openclaw &lt;span class=&quot;nt&quot;&gt;--dev&lt;/span&gt; gateway
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这行命令直接开辟了一个平行宇宙：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;配置文件被隔离到了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.openclaw-dev/openclaw.json&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;数据工作区被重定向到了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.openclaw/workspace-dev&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;网关端口自动偏移到了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;19001&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;甚至连局域网的 Bonjour 广播名字，都聪明地加上了后缀 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kelu的Mac Studio (OpenClaw) (2)&lt;/code&gt; 以防冲突&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/2026/03/image-20260330下午30028713.jpg&quot; alt=&quot;image-20260330下午30028713&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;4-唤醒-ui-控制台&quot;&gt;4. 唤醒 UI 控制台&lt;/h3&gt;

&lt;p&gt;后台引擎在 19001 端口平稳怠速后，新开一个终端页，带上 dev 参数直连：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;openclaw &lt;span class=&quot;nt&quot;&gt;--dev&lt;/span&gt; dashboard
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;浏览器瞬间弹出。虽然目前版本的 Web UI 纯英文，没有任何 zh-CN 的汉化选项，但这并不妨碍。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn.kelu.org/blog/2026/03/image-20260401上午95833705.jpg&quot; alt=&quot;image-20260401上午95833705&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Mon, 30 Mar 2026 00:00:00 +0800</pubDate>
        <link>https://blog.kelu.org/tech/2026/03/30/mac-studio-openclaw-copaw-dual-instance.html</link>
        <guid isPermaLink="true">https://blog.kelu.org/tech/2026/03/30/mac-studio-openclaw-copaw-dual-instance.html</guid>
      </item>
    
  </channel>
</rss>

