会话与登录 / Sessions & Auth
会话与持久化
一次登录,后续运行直接是登录态;多个 agent 各开一个隔离浏览器,
互不打架。这一页讲三件事:把会话状态存下来跨运行复用、用
--session 并行跑多个浏览器、以及会话守护进程卡住时怎么干净地复位它。
state save / --state / --session-name 是给 chrome-use 自己启动的浏览器和 --session 隔离浏览器用的——它们开局没有登录态,得靠状态文件跨运行续上。走扩展连接驱动你真实 Chrome 时用不到这些:登录态本来就在你真实 profile 里、原生持久化,重启也还在。见 真实 Chrome。
跨运行保存登录态
登录一次,把 cookies 和 localStorage 存进一个文件,之后的运行加载它就直接是登录态——
不用每次都重新走一遍登录表单。用 state save 保存;启动时用 --state 带上,
或用 state load 把状态注入当前会话再继续:
# 登录一次,保存 cookies + localStorage + 登录状态
$ chrome-use state save ./auth.json
# 启动时带上状态,开局就是登录态
$ chrome-use --state ./auth.json open https://app.example.com
# 或把已保存的状态注入当前会话,再继续操作
$ chrome-use state load ./auth.json
$ chrome-use open https://app.example.com/dashboard
怎么先干净地登录、再把会话存下来,见 登录与凭证——那一页从登录流程的角度讲了同一个 state save。
状态文件是一份普通 JSON,包含 cookies、两种 storage 和来源列表:
{
"cookies": [...],
"localStorage": {...},
"sessionStorage": {...},
"origins": [...]
}
auth.json 里装着可登录的 cookies 和 token——别提交进 Git
(echo "*.auth-state.json" >> .gitignore),用完及时删除,别放进任何会被打包分发的目录。
自动存取:--session-name
不想手动 save/load,就用 --session-name(或环境变量
AGENT_BROWSER_SESSION_NAME)——同名会话的状态会自动保存、并在后续运行时自动恢复:
$ AGENT_BROWSER_SESSION_NAME=my-app chrome-use open https://app.example.com
# 之后用同一个 name 再跑,状态自动恢复
cf_clearance cookie 绑定在你的 IP + User-Agent 上。
对隔离会话,--session-name 的存取会连同它一起保存/恢复,只要出口 IP 和 UA 不变,就能跳过重复挑战。
更多登录与凭证细节见 登录与凭证。
用 --session 并行跑多个浏览器
每个 --session <name> 是一个相互隔离的浏览器——各自独立的 cookies、
LocalStorage / SessionStorage、IndexedDB、缓存、历史记录和标签页。适合测多用户流程或并行抓取:
$ chrome-use --session a open https://app.example.com
$ chrome-use --session b open https://app.example.com
$ chrome-use --session a fill @e1 "alice@test.com"
$ chrome-use --session b fill @e1 "bob@test.com"
省略 --session 时,chrome-use 会优先从受支持的运行器 ID 派生稳定的独立会话。
Codex 任务会自动使用 CODEX_THREAD_ID,Claude Code 用 CLAUDE_PID,
其他运行器可以提供 AGENT_BROWSER_SESSION_ID;没在名单里的运行器,只要导出
<产品名>_SESSION_ID / _THREAD_ID / _CONVERSATION_ID
这类变量也会被自动识别。都没有时退回到终端 ID(WT_SESSION、
TERM_SESSION_ID 等),仍然什么都没有的普通 shell 才用 default。
想知道当前 shell 到底会落到哪个会话、是靠哪个变量派生的,跑 chrome-use doctor
看 Default session 那一行。想显式设置当前 shell 的默认会话,用
AGENT_BROWSER_SESSION=myapp。会话不需要时用 close 关掉,用
session list 看还有哪些活跃会话:
cu-<repo>-<tag>:<tag> 来自 agent / 终端 id,
<repo> 只是当前目录的 basename。以前换个目录执行就会造出另一个名字、打到一个没有任何 ref 的新守护进程
(报 「Unknown ref」)。现在只要有一个活着的守护进程带着同一个 agent tag(前缀不同),就会复用它,
agent 的标签和 ref 跨 cd 保留。显式 --session <name> / AGENT_BROWSER_SESSION 仍然优先。
「Unknown ref」报错现在会说明是哪个会话在应答、它有没有 ref:一个都没有时提示「此会话尚未运行过 snapshot;如果你在别的目录或终端做的快照,
用 session list 找到它并用 --session 钉住」,否则列出它实际持有的 ref 范围。
$ AGENT_BROWSER_SESSION=myapp chrome-use open https://example.com
# 关掉指定会话
$ chrome-use --session auth close
# 列出活跃会话
$ chrome-use session list
eval/screenshot 带偏)。两个 agent 共用同一个会话
(比如都用裸默认会话)会共享一个守护进程和一个活跃标签,互相覆盖。Codex 任务现在自动隔离;
其他环境请给每个 agent 一个独立的 --session <name> 或
AGENT_BROWSER_SESSION_ID。
--session 拿到自己彩色的 Chrome 标签组,
会话之间从不碰彼此的标签。裸 --cdp <port> 不隔离——每个会话都挂到同一个浏览器的现有目标上,
第二个会话的首次 open 可能导航到兄弟会话的标签。同一台真实 Chrome 上跑并发 agent,用扩展(各带一个不同的
--session),别用裸 --cdp。见 真实 Chrome。
跨会话拿指定标签:targetId 收养
每个会话有自己的标签组、各自分配 t<N> 序号(同一个物理标签在 A 会话是 t8、
在 B 会话是 t1),所以 t<N> 不是跨会话稳定的句柄。要从另一个会话拿到某个具体标签
(比如某会话把表单填了一半、句柄却死了),用稳定的 CDP targetId:
# 重新同步实时标签,每行打印 target: <id>
$ chrome-use tab list --full --session B
# 收养那个确切的标签,不刷新,状态保留
$ chrome-use tab adopt <targetId> --session B
tab list 每次调用都重新发现实时标签集,所以新会话能看到别的会话开的标签(以及被重新挂上的标签),
而不只是自己的。按 targetId 收养会让 B 会话落到那个搁浅的标签上而不重新加载它,
半填的表单因此得以保留。
open 同一个入口 URL,加 --reuse-tab:若已有标签正显示那个 URL
(按 origin+path 匹配),就切过去,而不是再开一个新标签堆起来。
给标签组起个人看得懂的名字
在你的真 Chrome 里,一个会话开的标签会被收进一个标签组。默认组名是
会话 id(cu-myproject-fb0742)——那是路由键,
对着自己浏览器的人完全看不出 agent 在干什么。
$ chrome-use session name "🔎 查快递单号"
✓ tab group for session 'cu-myproject-fb0742' is now 🔎 查快递单号
$ chrome-use session name # 显示当前的
$ chrome-use session name --clear # 恢复显示会话 id
在开标签之前设。组名是建组时定的,所以设晚了只影响之后新开的标签; 已经打开的那些要靠扩展去改名,装的扩展版本够新才行。两种情况命令都会明说是哪一种, 不会让你以为全都改好了。
名字短一点、和任务相关、用一个中性友好的 emoji 开头,在标签栏里最好认;拿不准就用 🔎。 改名不影响任何路由——会话 id 才是身份,组名纯粹是给人看的。
复位卡住的守护进程状态
每个会话跑一个后台守护进程 worker 来持有页面句柄。这个守护进程也是 boa JS 引擎的落脚点——
引擎跑在页面外面,script 才能扛住整页硬跳转不丢状态。
如果某个会话开始出问题——命令打到错的标签、
refs/句柄看起来陈旧,或者你在会话中途升级了 chrome-use 导致旧 worker 残留——
直接重启守护进程,别去 pgrep/kill 手动找 PID:
# 列出运行中的会话守护进程(含 relay 状态)
$ chrome-use daemon status
# 优雅停止一个守护进程(默认当前会话)
$ chrome-use session stop [name]
# 优雅停止所有活动会话守护进程
$ chrome-use session prune
# 杀掉所有会话守护进程 worker
$ chrome-use daemon restart
daemon restart 不碰扩展的原生消息桥(__nm-host),所以到你实时 Chrome 的 relay
保持在线——下一条命令只是对同一个浏览器起一个干净的新守护进程。它不会关掉任何标签。
极少数情况:把会话交接给用户(session handoff / resume)
bwu get … | chrome-use fill … --stdin)、读 TOTP/2FA 验证码、走 OAuth、用 state save / --session-name 存会话让下次直接登录态。别因为有密码或 2FA 就把登录交给用户——自己解决。见 登录与凭证。
session handoff 是逃生口,不是登录方式。只在某一步 agent 真的做不到时才用——解不了的图形/行为验证码、拿不到的短信/验证器码、硬件密钥轻触、银行"在手机上确认"。先尝试自主完成,实在不行才交接:
$ chrome-use session handoff # 最后手段:标记会话归用户;告诉用户具体要做什么
# …… 用户做那件 agent 真做不了的事 ……
$ chrome-use session resume # 取回控制——务必等用户确认做完再执行
session resume 的原命令),所以 agent 不会和用户抢标签页。默认零影响——不调 handoff 时 agent 一直拥有并自主驱动每个会话(含自主登录)。
session status 看归属,session list 列出每个会话及其归属。别自己 resume 抢回来——等用户说做完了。