在 Mac mini 上把 OpenClaw 跑起来:从证书坑到 Qwen 接入(实战记录)

这篇记录的是我在一台 Mac mini(中国大陆网络环境)上安装并跑通 OpenClaw 的全过程:从一键安装开始,接入阿里 DashScope 的 OpenAI 兼容接口(Qwen),一路踩到 Node TLS 证书链问题,最后用 nvm 彻底解决,并成功进入 openclaw tui

背景与目标

我想在本机快速体验 OpenClaw(一个可执行工具调用的 AI Agent 框架)。目标很明确:

  • 在 macOS 上装起来
  • 不依赖海外大模型(尽量不需要外网)
  • 用 Qwen(DashScope 的 OpenAI-compatible 接口)作为模型后端
  • 最终能启动到交互界面(TUI)

环境

  • 设备:Mac mini
  • Shell:zsh
  • 网络:大陆网络(优先走国内接口)
  • 模型:DashScope OpenAI-compatible(Qwen)

先说结论:能跑通的最短路径

  1. 用 nvm 安装 LTS Node(避免 Homebrew Node 的证书链坑)
  2. 用 npm 全局安装 OpenClaw
  3. 用 Custom Provider 接入 DashScope 的 OpenAI-compatible endpoint
  4. 跳过所有非核心集成(channels/skills 依赖/hook/Google Places/Notion 等)
  5. openclaw tui 启动

下面按实际踩坑顺序复盘。

Step 1:安装 OpenClaw

我最开始走的是「能最快开始」的思路:先把 OpenClaw 装起来再说。

安装方式有两条:

  • 一键脚本(方便但依赖你当前 Node 环境)
  • npm 安装(更可控,适合排障后固化)

后面事实证明:想稳定,最终还是应该落回「nvm + npm」这条路。

Step 2:确定国内可用的模型接入方式(Qwen / DashScope)

在 onboarding 时选择:

  • Provider:Custom Provider
  • Endpoint compatibility:OpenAI-compatible
  • Base URL:https://dashscope.aliyuncs.com/compatible-mode/v1
  • API Key:DashScope Key

关键点:

  • Base URL 只能填“服务根”,不要带具体路径(不要填 /models、不要填 /chat/completions

我中途就犯过一次错:把 Base URL 填成了 .../v1/models,导致验证直接 404。

Step 3:第一个大坑——NODE_EXTRA_CA_CERTS 指向不存在的证书文件

症状:

  • OpenClaw / Node 请求报 fetch failed
  • 并出现类似:
    • Ignoring extra certs ... /opt/homebrew/etc/ca-certificates/cert.pem
    • UNABLE_TO_GET_ISSUER_CERT_LOCALLY

排查方式:

  • 看环境变量:printenv NODE_EXTRA_CA_CERTS
  • 查 shell 配置:grep -n "NODE_EXTRA_CA_CERTS" ~/.zshrc ...

最终在 ~/.zshrc 找到类似:

  • export NODE_EXTRA_CA_CERTS=$(brew --prefix)/etc/ca-certificates/cert.pem

处理:

  • 注释/删除这行
  • source ~/.zshrc

但这还没完。

Step 4:第二个大坑——curl 能通,但 Node 仍然 TLS 失败

我用 curl 打 DashScope:

  • curl <https://dashscope.aliyuncs.com/compatible-mode/v1/models> -H "Authorization: Bearer ..."

返回一大段 JSON —— 说明网络和 key 都没问题。

但 Node 继续失败:

  • node -e "fetch('.../models', { headers: { Authorization: 'Bearer ...' }})..."

仍然报 UNABLE_TO_GET_ISSUER_CERT_LOCALLY

这意味着:

  • 系统证书链 OK(curl 走系统链)
  • 你当前 Node 的 TLS/证书链环境不 OK

我一开始用的是 Homebrew 的 Node(甚至还遇到 v23 这种非 LTS 线),换到 node@22 也仍然失败。

Step 5:最终解法——改用 nvm 的干净 Node(关键转折点)

这一步是全程的“破局点”。

安装 nvm:

  • curl -o- <https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh> | bash

加载 nvm(或重开终端):

  • export NVM_DIR="$HOME/.nvm"
  • [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"

安装并切到 Node 22:

  • nvm install 22
  • nvm use 22

验证 Node 是否已切换:

  • which node 应该指向 ~/.nvm/...

再跑同样的 Node fetch 测试:

  • 能返回大段 JSON

到这里就确认:TLS 问题被彻底解决。

Step 6:在 nvm 的 Node 下安装 OpenClaw

  • npm install -g openclaw@latest

安装完成后就可以继续 onboarding。

Step 7:onboarding 的关键选择(少折腾原则)

为了今晚“先跑起来”,我采用了一个非常有效的策略:

  • 非核心集成全部跳过

具体包括:

  • Channel:Skip for now
  • Search:先选 DuckDuckGo(免 key)
  • Skills:Yes(先启用基本能力)
  • Missing dependencies:Skip for now
  • Google Places / Notion / hooks 等:一律 No / Skip

这样可以最大概率避免再进入一轮“配置地狱”。

Step 8:启动与复盘

我在 onboarding 中选择了:Hatch in TUI。

所以之后启动不是直接 openclaw,而是:

  • openclaw tui

如果你只运行 openclaw 看到 Usage 帮助,说明 CLI 正常,但你还没进入交互模式。

最终结果

  • OpenClaw 成功安装
  • DashScope(Qwen)自定义 OpenAI-compatible endpoint 验证成功
  • 成功进入 openclaw tui
  • 今晚目标达成

常用命令速记

  • 进入交互:openclaw tui
  • 重新配置:openclaw onboard
  • 新开终端如果找不到命令:先 nvm use 22

Read more

传统 SaaS 转向 AI 时代,我目前的一点理解:先把数据能力变成 Agent 可调用的基础设施

最近我一直在思考一个问题:传统 SaaS 到底应该怎么转向 AI? 一开始很容易想到的方向是:给原来的系统加一个 AI 助手。 比如在页面右下角放一个聊天框,让用户可以问数据、生成报告、总结内容、解释指标。这个当然有价值,但我现在越来越觉得,这只是比较表层的一种转型。 真正的变化,可能不是“在 SaaS 里面加 AI”,而是 SaaS 本身的能力形态发生变化。 过去的 SaaS,核心是给人使用。 人登录系统,看页面、点按钮、筛选数据、导出报表、判断问题,然后再去做决策。数据库是给 Web 页面供数的,后端 API 是给前端页面服务的,整个产品的中心是“人如何操作软件”。 但 AI 时代,尤其是 Agent 逐渐发展之后,

By ladydd

对 Python 应用场景的一次重新思考:FastAPI、协程、线程、数据库与任务系统边界

最近在重新设计一个任务系统时,我顺便把自己对 Python,尤其是 CPython 应用场景的理解重新梳理了一遍。 这次讨论的背景是一个典型的异步任务服务: 上游提交任务 API 立即返回 task_id 后台 worker 慢慢执行 用户通过 task_id 查询任务状态 任务主要是 LLM 调用、图片下载、外部 HTTP 请求这类 I/O 型工作。 一开始关注的是队列、Redis、PostgreSQL、worker 并发控制这些问题。但聊到后面,其实更核心的问题变成了: Python 到底应该放在什么位置? 哪些并发适合 Python? 哪些并发不要硬塞给 Python? FastAPI、协程、线程、数据库之间应该怎么分工? 这篇文章就是这次思考的整理。 一、我不想抛弃 Python,

By ladydd

Go 和 Python 的并发模型对比:进程、线程、协程、并发和并行到底怎么理解?

最近我在写 worker 任务系统的时候,重新理解了一遍 Python 和 Go 的并发差异。 以前写 Python,多 worker 经常要考虑: 多进程怎么管理? 日志会不会串? 一个 worker 崩了怎么办? 怎么吃满多核心? 后来换成 Go,发现一个进程里开多个 goroutine worker 就很自然: go worker(1) go worker(2) go worker(3) go worker(4) 日志也好管,状态也好管,而且单进程还能利用多个 CPU 核心。 一开始很容易误会成: Python 不行,Go 行 但更准确的理解应该是: Python 和

By ladydd

Python 进程和 Go 进程的区别:为什么 Go 单进程多 worker 用起来更爽?

最近我在做 worker 任务系统的时候,突然意识到一个很关键的问题: 以前写 Python,多 worker 的时候经常要小心日志串、文件切割乱、时间不好管理。 但是换成 Go 以后,一个进程里开多个 goroutine worker,反而可以比较自然地写到同一个日志文件里。 一开始我以为这是“Python 和 Go 写日志能力不一样”,后来想明白了,核心不是日志本身,而是: Python 常见 worker 模型:多进程 Go 常见 worker 模型:单进程 + 多 goroutine 这背后其实是两个语言在并发模型上的巨大差异。 一、进程、线程、goroutine 先分清楚 先把几个概念捋一下。 进程:操作系统分配资源的单位 线程:CPU 调度执行的基本单位

By ladydd
陕公网安备61011302002223号 | 陕ICP备2025083092号