这几天opencsg发生了巨变,不仅之前注册的账号秒没,新注册的号也开始强制实名,否则不给余额(悲🤔估计是被某fisch上面那些没轻没重的给薅怕力(确信🤔我买了一个存量号,它貌似还有50余额,但没过实名,估计是以前注册的但存活至今,不清楚这种号能不能用🤔
我听说某种申必加密货币,能在50⑨0上面挖出一天60的法币,不清楚真的假的,要知道以太坊挖矿最猖撅的时候也不过如此(不过那时是30⑨0一天60🤔考虑到我前段时间调侃过以opencsg的八卡h20实例逆天的网速,它唯一可能的应用是挖矿,这下好力,不会有人真做了⑧(🤔难怪我这几天打开它的新建notebook页面,h20早就租不到力🤔
那么a800的挖矿效率又如何捏?a800大概约等于1.0x个3090,而我们都指定3090大概是0.4个5090,所以换算下来a800大概两三十一天?🤔注意这里的一天是24小时,,,算下来一个50的账号大概只能挖几块钱?🤔而这个50的号本身需要两块钱来买,,,总之,评价为不如主板机刷广告(吴慈悲🤔唯一比前者强的是脚本配置好后可以全自动,主板机啥的还得养号还得写刷广告代码啥的,还要和平台风控吉列豆蒸🤔不是很确定挖矿vs卖token,哪种是消耗新能源发电发出来的多余电最有效率的方法,,,
box.simular.ai
灵感来源(大嘘):https://mp.weixin.qq.com/s/fYEIFg46yoll_-EJXwur6g
这是一个一个一个一个grok bot平替啊啊啊啊啊,也支持图形界面(使用某种申必linux桌面环境),也支持需要人工接管的情况下人工接管,但原理和grok bot等略微不同,grok bot本质上还是个webagent,但它是种mcp服务,只要本地agent支持mcp(或者写一个mcp客户端,如果它不支持的话)就能用(确信🤔拿它跑claude code我没试过,但拿它跑codex随便跑,首先它貌似自带codex,然后closedai不那么检查ip,所以也许可以跳过上家宽ip代理环节,直接用(确信🤔如果已经登录的话拷auth.json过去,如果没有登录的话开启device code登录,然后让本地agent配置好box上的codex,使用device code登录,让它打印出device code,填进去即可(确信🤔登录后让它在配置文件里写入全自动配置,然后使用codex exec来调用它,应该就vans力(🤔
用相同或者相近的套路也可以使用claude code,我没用过a畜的订阅,但估计大差不差,先解决网络问题(家宽socks代理在这些地方用起来刚刚好,至少不用过一遍墙,,,),然后将claude code cli套在一个强制加代理的wrapper里(我看教程里运行claude之前强行检查一遍ip,如果ip不对则强行熔断),然后每次使用它时调用这个wrapper,vans🤔我就懒得买它那6美元一个月的家宽测这套玩意力,但要用的话,https://www.swiftproxy.net/pricing/static-residential-proxies,请(吴慈悲🤔
现在这套玩法存在一个一个一个一个问题,它只支持单次调用codex/cc,如果需要反复互动的话,,,可能得需要另外一套玩法🤔它这个mcp支持操纵某个interactive shell吗?🤔
那当然支持,,,在一顿雷霆探索后,dsh已经可以驱动它进行多次会话力,使用它自带的tmux来整🤔行,是时候让它将所有东西(包括如何将box集成进dsh)写个文档力🤔
thonk
但这套玩意真的有用吗?🤔无论是grok bot还是这个box,它作为一种临时容器性能是极其有限的,很多ai开发的任务很快本地的硬件需求就会超过这些个容器,比如那些乱七八糟的3d开发,或者逆向并移植xx游戏之类的🤔但以我和各种奇怪容器乃至服务器吉列豆蒸的经验,说不定它们可以通过使用这些容器反向操纵本机的方式解决,尽管这听起来有点奇怪,用本机dsh操纵box上的codex/claude code,然后让它们反过来再连接本机,在本机上部署xx并反编译xxx,,,好像也不是⑧行,但考虑到我现在既不用gpt系也不用claude系模型,我也爱莫能助,,,
wiebitte
顺便我拿那个可以选择各种渠道的中转站,使用各种渠道(包括传说中的azure渠道)测了那个传说中的逆天鹈鹕提示词,反正,,,没一个成功画出正确svg图像的,,,这就非常尴尬力,莫非它里面每一个模型都偷偷换成了别的玩意?🤔
以下全是aigc,,,
借助 box 用 DSH 操纵 Codex
一句话版本:把 box 当成一台一次性的远端 Ubuntu 机器,用 DSH 的两个 MCP server 连上去装好
codex并登录,然后既可以用codex exec非交互地跑单条任务,也可以用tmux造出伪终端去操作交互式 TUI,包括模型切换、工具调用审批和按 session id 续聊。
目录
1. box(box.simular.ai)简介
box 是 Simular(由前 DeepMind 科学家创立)推出的给 AI agent 用的云端电脑。官网的定位一句话就能概括:"A cloud computer with a desktop, Chrome and a shell, for any agent that speaks MCP."
它是什么
- 一台云端 Ubuntu 桌面:带完整桌面环境、Chrome、以及一个持久化 bash 会话
- 一个账号一台 box:名字如
box_7f2q,空闲时自动休眠,被连接时约 1 秒唤醒,文件与状态持久保留 - 可实时观看和接管:在 https://box.simular.ai/box 用 VNC 看它正在做什么,随时抢过鼠标键盘
- 接入方式是 MCP:对客户端来说它就是一个 remote MCP server,Streamable HTTP、OAuth 登录,地址
https://mcp.box.simular.ai/mcp
它暴露的工具面
官方文档把工具分成四组,这也是为什么它能承载本文的用法:
| 分组 | 工具 | 用途 |
|---|---|---|
| Shell & files | shell read_file write_file edit_file list_dir |
持久 bash 会话 + 文件读写改 |
| Browser | browser_navigate browser_snapshot browser_click browser_type browser_fill browser_read browser_fetch browser_tabs |
驱动 Chrome(快照 + 元素 ref) |
| Desktop | screenshot computer_state computer_act |
看屏幕/窗口/无障碍树,点击、打字、按键 |
| Automation | gui_plan script_run desk |
一次调用跑多步 GUI 计划、用 TypeScript 脚本化桌面、直接查无障碍树 |
为什么本文要用 box
用本机跑 Codex 实验有三个麻烦:装一堆 node 包、污染本机 ~/.codex、交互式实验容易把本机终端搞乱。box 把这三件事都变成了「在远端一台可丢弃的机器上折腾」:
- 本机保持干净:codex 装在 box 上,凭据落在 box 的
~/.codex - 可以放心做破坏性实验:改 config、切模型、测审批拒绝、删凭据重登,全都不影响本机
- 有桌面兜底:真需要 GUI(比如浏览器登录)时,
computer_act/ VNC 都能上
本次实测的 box 环境
uname -a → Linux main 6.8.0-142-generic #142-Ubuntu ... x86_64 GNU/Linux
node → v24.21.0
npm → 11.19.0
box name → main box id → cb-114514191981 image → sbxdesk:v10
Node.js 已预装,这对第 3 节用 npm 装 codex 很关键。
2. 把 box 集成进 DSH:不用官方插件,只用 MCP
2.1 官方方式,以及为什么我们放弃它
box 官方对 DSH 给的建议是装插件:
dsh plugin add https://github.com/simular-ai/box-plugin/releases/download/dsh-v0.2.1/dsh-box.tgz
export BOX_TOKEN=cb_your_key
# 重启 dsh,工具以 mcp__box__* 出现
官方文档也点明了 DSH 的特殊之处:dsh can't sign in, so it uses a personal key(dsh 不能走 OAuth 浏览器登录,只能贴 personal key)。
但这套插件依赖 DSH 的 remote.credentials 服务,老版本 DSH 没有这个服务,插件在启动时挂住:
1 entry did not activate @simular/dsh-box: pending (waiting for service: remote.credentials)
插件的 patch 行里写了 inject: [boxAuth],它的 host 半边会等 remote.credentials 就绪。整个 boot 因此失败。
2.2 正确姿势:绕过插件,直接配 MCP client
关键洞察:MCP client 本体是 DSH 自带的(@deepseek-ai/dsh-mcp-client),插件只是「注册 + 注入服务」的糖。既然我们不需要注入任何服务,一行普通 config 就够了。
在 $DSH_HOME/profiles/<profile>/cordis.patch.yml(本文为 ~/.dsh/profiles/web/cordis.patch.yml)里追加两个 insert 条目:
# box MCP over Streamable HTTP,不使用 @simular/dsh-box 插件。
- insert:
# ---- 第 1 个 server:box 实例管理 ----------------------------------
- id: mcp-box
name: '@deepseek-ai/dsh-mcp-client'
config:
serverName: box
transport: streamable-http
url: !!js process.env.BOX_MCP_URL || 'https://mcp.box.simular.ai/mcp'
headers:
Authorization: !!js process.env.BOX_MCP_AUTH
# 唤醒 box、截图可能超过 60s 默认值
toolCallTimeoutMs: 180000
# ---- 第 2 个 server:per-box / 文件与命令 --------------------------
- id: mcp-box-perbox
name: '@deepseek-ai/dsh-mcp-client'
config:
serverName: boxmcp
transport: streamable-http
url: !!js process.env.BOX_PERBOX_MCP_URL || 'https://mcp.box.simular.ai/mcp/<box-id>'
headers:
Authorization: !!js process.env.BOX_MCP_AUTH
toolCallTimeoutMs: 180000
重启 dsh 后,工具分成两个命名空间出现在会话里。
2.3 两个 MCP 的分工(重点)
「两个 MCP」对应 box 的两条路由,同一个 box、同一把 key,但工具集和参数约定不同:
server box(基础路由) |
server boxmcp(per-box 路由) |
|
|---|---|---|
| URL | https://mcp.box.simular.ai/mcp(或 https://relay.simular.cloud/mcp) |
https://mcp.box.simular.ai/mcp/<box-id>(或 https://relay.simular.cloud/mcp/<box-id>) |
| 工具前缀 | mcp__box__* |
mcp__boxmcp__* |
| 工具数 | 30~31 个(本会话暴露 30,探测报告 31) | 19 个 |
box 参数 |
几乎每个工具都要传 box(只有 box_delete 必须) |
完全不传,已绑定到那一台 box |
| 独占工具 | 实例生命周期:box_list box_ensure box_save box_hibernate box_upgrade box_snapshots box_status box_restore_paths box_create box_delete box_usage |
— |
| 核心用途 | 操纵 box 实例本身 | 文件与命令:shell read_file write_file edit_file list_dir |
所以「一个用来操纵 box 实例,一个用来实现文件操作」的直觉是对的:管理类动作(列出/唤醒/保存/删 box)只在基础路由上;文件与 shell 两条路由都有,但 per-box 路由不用写
box参数,写文件更顺手。想彻底不要
box参数也可以——把BOX_MCP_URL直接指向 per-box 路由,基础路由那行就不需要了。保留两行的价值在于管理工具。
2.4 鉴权:personal key 放在 .env
DSH 不能走 OAuth,必须用 personal key:
- 打开 https://box.simular.ai/keys,在 Keys and devices 下点 Create key
- key 形如
cb_8918...,只显示一次,立刻保存 - 写进
$DSH_HOME/.env(本文~/.dsh/.env):
BOX_MCP_AUTH="Bearer cb_your_key_here"
为什么放 .env:dsh-app-boot 的 loadLayeredEnv() 会在合成配置之前把 $DSH_HOME/.env 读进 process.env,所以 key 不会出现在 cordis.patch.yml 里,也不进 credentials store。key 是启动时读一次,不是每次请求读——轮换 key 后必须重启 dsh。
2.5 三个必须知道的坑
坑 1:.env 最后一行没有换行,会吞掉上一行的值。
实测现场:SERPER_API_KEY 和 BOX_MCP_AUTH 挤在同一行——
SERPER_API_KEY=114514BOX_MCP_AUTH="Bearer cb_8918..."
结果 BOX_MCP_AUTH 侥幸还能解析出来(box 工具正常工作),但 SERPER_API_KEY 被污染,web_search 直接报 serper search failed: Unauthorized.。往 .env 追加任何一行前,先确认上一行以换行结尾。
坑 2:per-box 路由的 MCP session 会过期,且 dsh 不会自动重建。
Error: Streamable HTTP error: Error POSTing to endpoint:
{"jsonrpc":"2.0","id":null,"error":{"code":-32001,"message":"unknown or expired session"}}
重试无效——DSH 的 MCP client 会一直带着已失效的 Mcp-Session-Id,只有重启 dsh 才会重新 initialize。而基础路由(serverName: box)不受影响,全程正常。所以:长期自动化优先用基础路由 + box 参数,把 per-box 路由当成便利项。
坑 3:box 重建后 box-id 会变。
per-box URL 里写死了 id。box 一旦 delete/create,id 就换,必须用 BOX_PERBOX_MCP_URL 覆盖再重启,否则 404 / session 错误。
2.6 验证集成成功
box_list → 列出 main (running, sbxdesk:v10)
box__shell → uname -a / node -v / npm -v
box__write_file → 写一个小文件
box__read_file → 读回来比对
本次两条路由的实测结果:mcp__box__write_file / read_file 往返一致;mcp__boxmcp__write_file 在 session 过期后不可用(坑 2)。
3. 在 box 上安装并登录 Codex
3.1 安装最新版 codex CLI
box 已预装 Node.js v24.21.0 / npm 11.19.0,直接全局装:
npm install -g @openai/codex
codex --version
本次核对结果:
npm view @openai/codex version→0.166.0- GitHub 最新 release tag →
rust-v0.166.0 - box 上已装的就是
codex-cli 0.166.0(/usr/local/bin/codex→/opt/coding-clis/bin/codex→@openai/codex/bin/codex.js)
也就是说 box 镜像里通常已经是最新,先 codex --version 确认再决定要不要重装。
3.2 路线 A:本地已登录 → 迁移 auth.json
本地文件位置(Windows):
C:\Users\<你>\.codex\auth.json
结构(本次样本,4277 字节):
{
"OPENAI_API_KEY": null,
"auth_mode": "chatgpt",
"last_refresh": "1919-08-10T11:45:14.191981000Z",
"tokens": { "access_token": "...", "account_id": "...", "id_token": "...", "refresh_token": "..." }
}
auth_mode: "chatgpt" 说明是 ChatGPT OAuth 登录(不是 API key)。
传输通道:box 与本机之间没有共享文件系统,只能靠 MCP 搬。两条路:
(a)用文件 MCP 直接写(推荐,简单)
读本地 auth.json 内容,然后:
mcp__box__write_file
box = "main"
path = "/home/user/.codex/auth.json"
content = <auth.json 全文>
(b)走 shell + base64/gzip 管道(内容不宜明写时)
# 本机:gzip + base64 后作为一行文本发过去
umask 077
mkdir -p ~/.codex
cat > /tmp/auth.b64 <<'EOF'
<base64 内容>
EOF
base64 -d /tmp/auth.b64 | gunzip > ~/.codex/auth.json
chmod 600 ~/.codex/auth.json
rm -f /tmp/auth.b64
压缩的好处:4277 字节的 JSON 压到约 1.4 KB 的 base64,且原始 token 不会以明文出现在日志/对话里。
验证:
codex login status # → Logged in using ChatGPT
坑:凭据可能「看起来没过期,其实已被吊销」。
本次迁移就踩到了。本地 access token 的 JWT exp 还有一周(11-12 到期),但直接从 box 请求:
# 带 access_token 请求
GET https://chatgpt.com/backend-api/codex/models → 401 token_revoked
GET https://chatgpt.com/backend-api/me → 401 token_revoked
# 直接打刷新端点
POST https://auth.openai.com/oauth/token (grant_type=refresh_token)
→ {"error":{"code":"refresh_token_invalidated","message":"Your session has ended. Please log in again."}}
也就是说整个 token family 在服务端已被吊销,拷来拷去都没用。判断方法:不只看本地 exp,要看真实请求返回。遇到 token_revoked / refresh_token_invalidated 就直接改走 device code,别浪费时间重拷。
(顺带:本机 curl 到 chatgpt.com 返回 http=000——本机出网被限制,所以无法在本地交叉验证,必须在 box 里验。)
3.3 路线 B:本地没登录 / 凭据失效 → device code
- 清掉旧凭据并确认已登出:
rm -f ~/.codex/auth.json
codex login status # → Not logged in
- 后台启动 device auth(必须后台:该命令会轮询等待授权,前台会占死 MCP 调用):
setsid nohup codex login --device-auth > /tmp/codex_device.log 2>&1 < /dev/null &
- 读日志拿码:
sleep 12 && cat /tmp/codex_device.log
1. Open this link in your browser and sign in to your account
https://auth.openai.com/codex/device
2. Enter this one-time code (expires in 15 minutes)
0OGO-78QO2
- 把链接和设备码发给用户,由用户在浏览器里填。码15 分钟有效,且只能用于你刚发起的那次登录(提示语也明确写了:如果不是你自己在 Codex 里发起的登录,请取消)。
-
确认成功:
tail -3 /tmp/codex_device.log # → Successfully logged in
ls -l ~/.codex/auth.json # → 新文件,权限 600
codex login status # → Logged in using ChatGPT
本次实测:从填码到 Successfully logged in 约 1 分钟内完成,auth.json 4130 字节,新 token 有效期 10 天。
3.4 登录之后:先看这个账号能用哪些模型
模型列表是按账号套餐下发的,不是客户端写死的:
codex debug models > /tmp/models.json # 服务端返回的原始模型目录(JSON)
对比本次两个账号:
| 套餐 | 模型数 | 内容 |
|---|---|---|
| Plus(已失效) | 12 | 含 gpt-6-astra gpt-6.1-sol gpt-6.1-terra gpt-6-sol gpt-6-luna gpt-5.6-sol gpt-5.6-terra gpt-5.6-luna gpt-5.5 + 3 个隐藏 |
| free(当前) | 5 | gpt-6-luna gpt-5.6-terra gpt-5.6-luna + 隐藏的 gpt-reserve codex-auto-review |
两个要点:
visibility: "list"的才会出现在/model选择器里。free 账号目录有 5 个,但 TUI 只列 3 个。- 不支持的模型会被服务端明确拒绝,不是静默降级:
$ codex exec -m gpt-6.1-sol "output exactly: ojbk"
warning: Model metadata for `gpt-6.1-sol` not found.
ERROR: The 'gpt-6.1-sol' model is not supported when using Codex with a ChatGPT account.
所以「换个模型跑跑」之前,先 codex debug models 确认这个账号到底有什么。
4. 非交互与交互式使用 Codex
4.1 非交互:codex exec
最基本的一条:
codex exec -m gpt-6-luna "output exactly: ojbk"
常用 flag:
| flag | 说明 |
|---|---|
-m, --model |
指定模型;不指定则取 ~/.codex/config.toml 的 model |
-s, --sandbox |
read-only / workspace-write / danger-full-access |
-a, --ask-for-approval |
on-request(模型自己决定何时问)/ never(从不问) |
--skip-git-repo-check |
非 git 目录必加,否则直接报错退出 |
--ephemeral |
不落盘,不产生可 resume 的 session |
-o, --output-last-message |
把最后一条 agent 消息写文件 |
--json |
输出 NDJSON 事件流(脚本化首选) |
-C, --cd |
指定工作目录 |
用 --json 做脚本化,事件流长这样:
{"type":"thread.started","thread_id":"01a1aaac-6b0b-7473-9e49-f3e939c4ba30"}
{"type":"turn.started"}
{"type":"item.completed","item":{"id":"item_0","type":"agent_message","text":"ojbk"}}
{"type":"turn.completed","usage":{"input_tokens":13193,"cached_input_tokens":10880,"output_tokens":6}}
非交互续聊(等价于交互式的 codex resume):thread.started 里的 thread_id 就是 session id,用 codex exec resume 接着问:
# 第一轮:记住一个暗号
OUT=(codex exec -m gpt-6-luna -s read-only --skip-git-repo-check --json \
"记住暗号 MANGO-7,只回复 OK")
TID=(echo "OUT" | python3 -c "
import sys,json
for l in sys.stdin:
l=l.strip()
if not l: continue
try: o=json.loads(l)
except: continue
if o.get('type')=='thread.started': print(o['thread_id']); break
")
# 第二轮:续同一会话
codex exec resume "TID" -m gpt-6-luna --skip-git-repo-check \
"我刚才让你记住的暗号是什么?只回答暗号本身"
# → MANGO-7
两个 resume 专属注意点:
exec resume不接受-s(会报unexpected argument '-s' found),能用的是-m-c--skip-git-repo-check--json等;沙箱改用-c sandbox_mode=...。- 不指定
-m时用的是当前 config 的模型,若与建档时不同会告警:
This session was recorded with model `gpt-6-luna` but is resuming with `gpt-5.6-terra`.
Consider switching back to `gpt-6-luna` as it may affect Codex performance.
想让历史会话干净复现,续聊时显式带 -m。
4.2 交互式:MCP 没有 PTY,用 tmux 造一个
先明确能力边界:box 的 MCP 没有原生交互式 PTY 通道。mcp__box__shell 每次调用都是一条一次性命令——
$ tty → not a tty
$ echo $TERM → dumb
所以无法跨调用往同一个前台进程里「持续敲键盘」。两种可行路径:
- tmux(本文采用):tmux server 常驻,跨 MCP 调用用
send-keys打字、capture-pane读屏,等价于操纵交互式 shell。快、稳。 - 桌面 GUI 自动化(
computer_act/desk/gui_plan):在 box 桌面开个终端窗口,走无障碍树点击打字。真交互但慢且脆,仅作兜底。
前置:预置信任目录,避开 trust 弹窗
mkdir -p ~/interactive
cat > ~/.codex/config.toml <<'EOF'
model = "gpt-6-luna"
model_provider = "openai"
[projects."/home/user/interactive"]
trust_level = "trusted"
EOF
不写这段,TUI 会卡在 "Do you trust the files in this folder?" 上。
起会话 / 打字 / 读屏
# 1) 起一个分离的 tmux 会话(-L 用独立 socket,避免干扰 desktop 上已有的 tmux)
tmux -L codexlab kill-server 2>/dev/null
tmux -L codexlab new-session -d -s codexlab -x 130 -y 45
# 2) 拉起 TUI
tmux -L codexlab send-keys -t codexlab 'cd ~/interactive && codex' Enter
sleep 9
# 3) 读屏
tmux -L codexlab capture-pane -p -t codexlab | grep -v '^$' | tail -8
>_ OpenAI Codex (v0.166.0)
~/interactive
› Ask Codex to do anything
GPT-6-Luna default · ~/interactive
← for agents · ? for shortcuts
发消息:-l 发字面量(否则中文/符号会被 tmux 当键名解析),Enter 单独再发一次:
tmux -L codexlab send-keys -t codexlab -l '我们在讨论一个代号为 ZEBRA-42 的排序算法项目。'
sleep 1
tmux -L codexlab send-keys -t codexlab Enter
退出并取 session id:发 /quit,然后必须带滚动历史读(退出提示会滚出可视区):
tmux -L codexlab send-keys -t codexlab -l '/quit'; sleep 1
tmux -L codexlab send-keys -t codexlab Enter; sleep 6
tmux -L codexlab capture-pane -p -S -60 -t codexlab | grep -v '^$' | tail -20
Disconnected from this task. Any running work continues.
To reconnect, run:
codex resume 01a1aa9e-174c-75f3-a7e9-dcec9441432f
Token usage so far: total=3,235 input=3,157 (+ 24,192 cached) output=78 (reasoning 24)
注意 0.166 的措辞是 To reconnect, run: codex resume <uuid>,不是老版本的 session id: xxx。
按 id 重进:
tmux -L codexlab send-keys -t codexlab 'codex resume 01a1aa9e-174c-75f3-a7e9-dcec9441432f' Enter
历史会被完整回填,可以接着问。
4.3 实验一:会话连续性(三问跨进程)
| 轮次 | 发送内容 | 结果 |
|---|---|---|
| Q1 | 讨论代号 ZEBRA-42 的排序项目,怎么处理降序需求 |
「将比较器改为逆序比较,同时保留相等元素的相对顺序」(1s) |
| Q2 | 追问:用 Python 给一行代码实现刚才的逆序比较 | result = sorted(items, key=lambda item: item.key, reverse=True)——直接引用了「刚才说的」 |
| 退出 | /quit |
打印 codex resume 01a1aa9e-... |
| 重进 | codex resume 01a1aa9e-... |
前两问历史完整回填 |
| Q3 | 项目代号是什么?讨论过哪种排序需求? | 「项目代号是 ZEBRA-42,我们讨论的是降序排序需求」 ✅ |
会话落盘在 ~/.codex/sessions/2026/11/05/rollout-2026-11-05T07-30-49-<uuid>.jsonl(129K)。
4.4 实验二:TUI 内模型切换
输入 /model,是两步选择器——先选模型,再选 reasoning level:
Select Model and Effort
› 1. GPT-6-Luna (current) Fast and affordable model for easier tasks.
2. GPT-5.6-Terra Older balanced model for straightforward work.
3. GPT-5.6-Luna Older fast and efficient model.
enter select · esc back
(只有 visibility: "list" 的模型出现,隐藏的 gpt-reserve / codex-auto-review 不列。)
选中第 2 项 → 自动进入第二步:
Select Reasoning Level for GPT-5.6-Terra
1. Low Fast responses with lighter reasoning
› 2. Medium (default) Balances speed and reasoning depth for everyday tasks
3. High Greater reasoning depth for complex problems
4. Extra high Extra high reasoning depth for complex problems
5. More reasoning… Max and Ultra consume usage limits faster
enter default · s session · esc back
按 Enter 确认后:
• Model changed to gpt-5.6-terra medium
GPT-5.6-Terra medium · ~/interactive
关键行为:选择会持久化到 ~/.codex/config.toml,重启 TUI 后仍是新模型:
model = "gpt-5.6-terra"
model_provider = "openai"
model_reasoning_effort = "medium"
所以「只想这次有效」要用启动参数 codex -m gpt-6-luna,别在 TUI 里切。
4.5 实验三:工具调用与审批流
默认(未显式指定沙箱/审批):模型直接执行 shell,无提示。
› 请在工作目录创建一个 hello.txt,内容就是 ojbk,然后用 shell 读回来确认。
• 我会创建文件并立即用 shell 回读核对内容。
• Ran pwd && touch hello.txt && printf 'ojbk' > hello.txt && cat hello.txt
└ /home/user/interactive
ojbk
• 已创建 hello.txt,并回读确认内容为 ojbk。
Worked for 4s
用 codex -s read-only -a on-request 启动:写操作会弹审批,三条命令加一个 reason:
• Running printf 'ojbk' > blocked.txt
Would you like to run the following command?
Environment: local
Reason: 是否允许我在当前目录创建 blocked.txt 并写入 `ojbk`?
$ printf 'ojbk' > blocked.txt
› 1. Yes, proceed (y)
2. Yes, and don't ask again for commands that start with `printf 'ojbk' > blocked.txt` (p)
3. No, and tell Codex what to do differently (esc)
Press enter to confirm or esc to cancel
- 批准(
y+ Enter):
✔ You approved codex to run printf 'ojbk' > blocked.txt this time
• Ran printf 'ojbk' > blocked.txt
• 已创建 blocked.txt,内容为 ojbk。
- 拒绝(
Esc):
✗ You canceled the request to run printf 'ojbk' > rejected.txt
• Exited (status 1) printf 'ojbk' > rejected.txt
■ Conversation interrupted - use /feedback if something went wrong
rejected.txt 确实没有被创建(read-only 换不到写权限,被拒绝就是拒绝)。
选项 2(p)很实用:把「等价于这条命令前缀」的命令加入白名单,后续同类操作不再问。
4.6 状态栏:自动标题
每轮对话后底部会多出一段自动生成的标题,方便在 codex resume 选择器里辨认:
GPT-5.6-Terra medium · ~/interactive · 创建 blocked.txt 文件
4.7 收尾
tmux -L codexlab send-keys -t codexlab -l '/quit'; sleep 1
tmux -L codexlab send-keys -t codexlab Enter; sleep 4
tmux -L codexlab kill-server
5. 附录:实测事实清单与踩坑速查
5.1 本次实测环境
| 项 | 值 |
|---|---|
| box | name main,id cb-114514191981,image sbxdesk:v10 |
| box OS | Ubuntu,kernel 6.8.0-142-generic,x86_64 |
| box Node / npm | v24.21.0 / 11.19.0 |
| codex | codex-cli 0.166.0(= npm latest = GitHub rust-v0.166.0) |
| dsh | web profile,$DSH_HOME = C:\Users\fegeleinirl\.dsh |
| box MCP | 基础路由 mcp__box__* 30 工具;per-box 路由 mcp__boxmcp__* 19 工具 |
| 登录账号 | free 套餐,5 个模型(无 gpt-6.1-sol) |
5.2 踩坑速查表
| 现象 | 原因 | 解决 |
|---|---|---|
boot 失败 pending (waiting for service: remote.credentials) |
装了 @simular/dsh-box 插件但老版 dsh 没这个服务 |
不装插件,直接配 @deepseek-ai/dsh-mcp-client 两行 config |
web_search 报 Unauthorized |
.env 上一行缺换行,SERPER_API_KEY 值被 BOX_MCP_AUTH 粘连 |
保证 .env 每行以换行结尾 |
unknown or expired session (-32001) |
per-box 路由 MCP session 过期,dsh 不自动重建 | 重启 dsh;长期任务改用基础路由 + box 参数 |
| per-box URL 突然 404 | box 被重建,box-id 变了 | 用 BOX_PERBOX_MCP_URL 覆盖并重启 |
401 token_revoked / refresh_token_invalidated |
OAuth token family 已在服务端吊销(本地 exp 看着还有效也没用) |
删 auth.json,改走 --device-auth |
codex login --device-auth 把 MCP 调用卡死 |
该命令轮询等待授权,前台阻塞 | setsid nohup ... > /tmp/log 2>&1 < /dev/null & 后台跑,再读日志取码 |
ERROR: The 'gpt-6.1-sol' model is not supported when using Codex with a ChatGPT account. |
模型随套餐下发,该账号没有 | 先 codex debug models 看可用集 |
| TUI 卡在 trust 弹窗 | 目录未预授权 | ~/.codex/config.toml 写 [projects."<dir>"] trust_level = "trusted" |
send-keys 发的文字被当按键 |
tmux 会解析键名 | 用 send-keys -l 发字面量,Enter 单独发 |
| 读不到 session id | 退出提示滚出可视区 | capture-pane -p -S -60 带滚动历史 |
codex exec resume 报 unexpected argument '-s' |
resume 的 flag 集不同 |
去掉 -s,用 -c sandbox_mode=... |
续聊告警 session was recorded with model X but is resuming with Y |
未指定 -m,用了当前 config 的模型 |
续聊时显式带 -m <原模型> |
本机 curl chatgpt.com 返回 http=000 |
本机出网受限 | 所有验证都在 box 里做 |
5.3 一页速记
# 集成
DSH_HOME/profiles/web/cordis.patch.yml ← 两个 insert: serverName box / boxmcpDSH_HOME/.env ← BOX_MCP_AUTH="Bearer cb_..."
# 装 codex
npm install -g @openai/codex && codex --version
# 迁移凭据(本地已登录)
mcp__box__write_file box=main path=/home/user/.codex/auth.json content=<auth.json>
# 或 device code(本地未登录)
rm -f ~/.codex/auth.json
setsid nohup codex login --device-auth > /tmp/codex_device.log 2>&1 < /dev/null &
sleep 12 && cat /tmp/codex_device.log # 取 https://auth.openai.com/codex/device 与 15 分钟码
# 非交互
codex exec -m gpt-6-luna --skip-git-repo-check --json "output exactly: ojbk"
codex exec resume <thread_id> -m gpt-6-luna --skip-git-repo-check "..."
# 交互
tmux -L codexlab new-session -d -s codexlab -x 130 -y 45
tmux -L codexlab send-keys -t codexlab 'cd ~/interactive && codex' Enter
tmux -L codexlab send-keys -t codexlab -l '你的问题'; tmux -L codexlab send-keys -t codexlab Enter
tmux -L codexlab capture-pane -p -S -60 -t codexlab