1. 为什么要在 WSL 里用浏览器跑 OpenCode
OpenCode 不只是终端里的一个 TUI 工具,它还能以完整的 Web 应用形态跑起来,直接在浏览器里管理会话、挂载终端、切换模型。对长期在 Windows 上做开发的人来说,这件事的价值在于:你不需要为了用 AI 编码助手而改变自己的工作流,浏览器标签页就是入口。
但 Windows 原生环境跑opencode web有几个绕不开的坑。文件系统访问路径和 Linux 不一致,终端集成经常出现字符编码或 PTY 分配问题,某些依赖在 PowerShell 下的行为和在 bash 下完全不同。我试过直接在 PowerShell 里启动,会话能开,但挂载终端时反复报错,最后还是在 WSL 里跑才稳定下来。
所以这篇的路线是:在 WSL(Ubuntu 为例)里启动 OpenCode Web 服务,通过 TaoToken 统一 Key 接入模型通道,再从 Windows 侧的浏览器访问 WSL 的服务端口。整条链路涉及三个配置点——OpenCode 的config.toml、TaoToken 的 Key 管理、WSL 的端口转发。下面按可复制的顺序拆开讲。
适合谁看:已经在用 WSL 做日常开发、想用浏览器界面管理 OpenCode 会话、并且希望用一个统一 Key 接入多家模型通道的人。如果你还没装 WSL,先装好 Ubuntu 发行版再回来,后面的命令都假设你在 WSL 终端里执行。
2. TaoToken 前置:统一 Key 与通道准备
TaoToken 在这里的角色是「统一 Key 通道」。OpenCode 本身支持配置多个 provider,但如果你手上有多个模型来源,逐个配 API Key、逐个改 base_url 会很碎。TaoToken 提供一个统一的 API 入口,OpenCode 只需要认一个 Key 和一个 base_url,模型切换在服务端完成。
你需要先拿到两样东西:API Key 和 API 地址。Key 在控制台的 API Keys 页面创建,地址是固定的https://taotoken.net/api(注意这个地址不带任何查询参数,直接作为 base_url 使用)。
创建 Key 的入口在这里:
控制台 API Keys:https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite
创建时建议给 Key 起一个能区分用途的名字,比如opencode-wsl,这样以后在控制台看用量时能对上。Key 只在创建时完整显示一次,复制后先存到 WSL 的环境变量里,不要直接写进会提交到 git 的配置文件。
接入文档在这里,配置字段有疑问时对照查:
接入文档:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite
如果你只是想先验证模型通道是否通,不想动 OpenCode 配置,可以先用模型对话页面发一条测试消息:
模型对话:https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=model_chat&utm_campaign=rewrite
这一步的目的是确认 Key 本身有效、账户有可用额度。很多人后面 OpenCode 报 401,回头查半天,其实 Key 在创建时就没复制全。先在这里发一条消息,能省掉后面大量排查时间。
3. 可复制配置:config.toml 与 settings.json 骨架
OpenCode 的配置分两层:一层是 OpenCode 自己的config.toml,管 provider 和模型;另一层是 Web 服务的settings.json(或opencode.json),管端口、hostname、密码这些。两者不要混在一起写。
先建配置目录。WSL 里的路径按 XDG 规范走:
mkdir -p ~/.config/opencode然后是~/.config/opencode/config.toml的骨架。关键点是把 provider 的 base_url 指向 TaoToken 的 API 地址,apiKey 从环境变量读取,不要硬编码:
# ~/.config/opencode/config.toml # OpenCode provider 配置:统一走 TaoToken 通道 [provider.taotoken] name = "TaoToken" baseURL = "https://taotoken.net/api" apiKey = "{env:TAOTOKEN_API_KEY}" # 模型列表按你账户可用的填,这里给两个常见示例 [[provider.taotoken.models]] id = "claude-sonnet-4-20250514" name = "Claude Sonnet 4" [[provider.taotoken.models]] id = "gpt-4.1" name = "GPT-4.1" # 默认使用的模型 [model] provider = "taotoken" name = "claude-sonnet-4-20250514"{env:TAOTOKEN_API_KEY}这个写法是让 OpenCode 从环境变量里取 Key,这样配置文件本身可以安全地放进 dotfiles 仓库。环境变量在 WSL 的~/.bashrc或~/.zshrc里设置:
# 追加到 ~/.bashrc export TAOTOKEN_API_KEY="你的Key粘贴在这里"改完执行source ~/.bashrc让它生效。验证一下:
echo $TAOTOKEN_API_KEY | head -c 8能打印出 Key 的前几位就说明环境变量挂上了。
接下来是 Web 服务的settings.json。这个文件放在 OpenCode 的工作目录或全局配置目录都行,内容如下:
{ "server": { "port": 4096, "hostname": "0.0.0.0", "mdns": false, "cors": [] } }这里hostname设成0.0.0.0是为了让 Windows 侧的浏览器能访问到 WSL 里的服务。如果你只在 WSL 内部用localhost访问,可以保持127.0.0.1,但那样 Windows 浏览器就连不上,必须做端口转发。两种方案后面都会讲。
port固定成 4096 是为了端口转发时不用每次查随机端口。OpenCode 默认会随机挑端口,固定下来省事。
关于密码:如果OPENCODE_SERVER_PASSWORD没设置,Web 服务是无保护状态。仅在 WSL 本机访问时问题不大,但一旦做了端口转发让 Windows 或局域网访问,就必须设密码。启动时这样写:
export OPENCODE_SERVER_PASSWORD="你设一个密码" opencode web --port 4096 --hostname 0.0.0.0访问时的用户名默认是opencode,可以用OPENCODE_SERVER_USERNAME改。
4. WSL 端口转发与浏览器验证
WSL2 的网络是 NAT 模式,WSL 里的0.0.0.0:4096并不会自动映射到 Windows 的localhost:4096。有两种方式打通。
第一种是 WSL2 自带的 localhost 转发。较新的 WSL2 版本会自动把 WSL 里监听的端口转发到 Windows 的 localhost,但前提是服务绑定在0.0.0.0或127.0.0.1且 WSL 版本支持。你可以先在 Windows 浏览器里直接试http://localhost:4096,能打开就说明自动转发生效了,不用额外操作。
如果打不开,用第二种:手动端口转发。在 Windows 的 PowerShell(管理员权限)里执行:
# 先查 WSL 的 IP wsl hostname -I拿到类似172.24.xxx.xxx的地址后,做端口转发:
# 把 Windows 的 4096 转发到 WSL 的 4096 netsh interface portproxy add v4tov4 listenport=4096 listenaddress=0.0.0.0 connectport=4096 connectaddress=172.24.xxx.xxxconnectaddress换成你上一步查到的 WSL IP。然后确认转发规则:
netsh interface portproxy show v4tov4如果 Windows 防火墙拦了,加一条入站规则:
New-NetFirewallRule -DisplayName "OpenCode Web 4096" -Direction Inbound -LocalPort 4096 -Protocol TCP -Action Allow现在在 Windows 浏览器打开http://localhost:4096,应该能看到 OpenCode 的 Web 界面。如果设了密码,会先弹认证框,用户名opencode,密码是你设的那个。
进入界面后,验证会话是否真的走了 TaoToken 通道,做这几个检查动作:
第一,看主页的会话列表能否正常创建新会话。点新建会话,如果 provider 配置有问题,这里会直接报错或模型下拉框为空。
第二,发一条测试消息,比如「用一句话说明这个项目是做什么的」。消息发出后,观察返回是否正常。如果返回 401,说明 Key 没读到或无效;如果返回 404 或 model not found,说明模型 id 填错了。
第三,点界面上的「See Servers」按钮,查看已连接服务器状态。这里能看到当前会话绑定的 provider 和模型。确认 provider 显示的是taotoken,模型是你配置的那个。
第四,如果想同时用终端 TUI 和 Web 界面,在 WSL 里另开一个终端执行挂载:
opencode attach http://localhost:4096挂载成功后,在终端里发的消息会同步出现在浏览器界面,两边共享同一套会话状态。这一步能验证 Web 服务和 TUI 是否连的是同一个后端。
5. 本篇常见错排查
浏览器打不开 localhost:4096。先确认 WSL 里服务真的在跑:curl -I http://localhost:4096在 WSL 终端里执行,有响应说明服务正常。然后确认hostname是0.0.0.0而不是127.0.0.1。如果 WSL 自动转发没生效,走手动 portproxy 那条路。注意 WSL 重启后 IP 会变,portproxy 的connectaddress要重新设,可以写个脚本每次开机跑。
401 Unauthorized。九成是 Key 没读到。在 WSL 里执行echo $TAOTOKEN_API_KEY确认环境变量有值。如果是在opencode web启动之后才设的环境变量,服务进程读不到,要重启服务。另外确认config.toml里写的是{env:TAOTOKEN_API_KEY}而不是直接写 Key 字符串。
模型下拉框为空或报 model not found。config.toml里[[provider.taotoken.models]]的id必须和 TaoToken 侧实际可用的模型 id 完全一致。去模型对话页面确认一下当前账户能用哪些模型,把 id 抄准。[model]段的provider和name要和上面定义的对应。
挂载终端时报连接被拒绝。opencode attach的地址要和opencode web启动时的 hostname/port 匹配。如果 web 绑的是0.0.0.0:4096,attach 用http://localhost:4096通常没问题;如果绑的是 WSL IP,attach 也要用那个 IP。另外确认没有多个 OpenCode 实例抢同一个端口。
改了 settings.json 但端口没变。命令行标志的优先级高于配置文件。如果你启动时带了--port,它会覆盖settings.json里的port。想用配置文件的值,启动命令里就不要带--port。
浏览器界面能开但发消息一直转圈。检查 WSL 到 TaoToken API 地址的网络连通性:curl -I https://taotoken.net/api。如果这里不通,OpenCode 的请求也出不去。另外看 OpenCode 的日志输出,启动时加--verbose能看到请求详情。
6. 长期编码场景的接入建议
如果你只是偶尔用浏览器开个会话,上面的配置够了。但如果是长期做编码、跑 Agent 任务,建议把 Key 管理做得更规范一些。
在 TaoToken 控制台里按用途分 Key,比如opencode-wsl一个、ci-agent一个,这样用量和排查都能对上号。Key 不要写进任何会进版本控制的文件,统一走环境变量。WSL 的~/.bashrc里只放 export,真正的 Key 值可以放在一个不被 git 跟踪的~/.env.local里再 source 进来。
对于需要长时间跑的编码任务,可以了解一下 Coding Plan 的额度模式,比按次调用更适合持续会话:
Coding Plan:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite
WSL 的 IP 会变这个问题,长期来看最好写一个开机脚本,自动查 IP 并更新 portproxy 规则。或者干脆用 WSL2 的镜像网络模式(在.wslconfig里设networkingMode=mirrored),这样 WSL 和 Windows 共享网络栈,localhost 直接通,省掉 portproxy 这一层。不过镜像模式对某些网络场景有兼容性问题,切换前先确认你的 WSL 版本支持。
最后,OpenCode 的 Web 界面和 TUI 共享会话状态这个特性,在长期编码里很实用:浏览器里看整体会话列表和状态,终端里做具体操作,两边同步。把opencode attach加到日常启动脚本里,开一个 web 服务,再 attach 一个终端,工作流就固定下来了。