状态伴侣类工具有一条硬性要求:既要知道 agent 在干什么,又绝不能改变它们的运行方式。Agent Island 完全不往 Claude Code 或 Codex 里注入任何东西——这两个工具本来就把每个会话记录成本地文件,app 只是去读。
会话文件在哪
Claude Code 把每个会话写成一份 JSONL transcript:~/.claude/projects/<项目>/<会话id>.jsonl——用户消息、assistant 回合、工具结果,一行一条 JSON。通过 Claude 桌面端打开的会话,还会在 ~/Library/Application Support/Claude/claude-code-sessions/ 下多一份记录文件,带着人类可读的标题、归档标记,以及指回 CLI transcript 的 cliSessionId。Agent Island 把两边接起来,桌面线程就能带着真实标题显示。
Codex 的 rollout 在 ~/.codex/sessions/YYYY/MM/DD/。第一行是 session_meta,带会话 id、工作目录和 originator。一个实战细节:这一行内嵌了完整的 base instructions,可能有几十 KB——固定大小的读取会把 JSON 拦腰截断,所以扫描器会持续读块,直到真正遇到第一个换行符。
从行到状态
岛上那几个状态——working、your turn、stalled、rate-limited、auth required——来自架在 transcript 尾部的一个小状态机。真正有意思的是哪些东西不算回合完成:
- assistant 行带
stop_reason: "end_turn"通常意味着轮到你了。但 Claude 的限流横幅("You've hit your session limit…")用的是同一个信封,唯一的区别是isApiErrorMessage: true。从 1.5.1 起这类行永远不算完成——"被告知要等"不是"轮到你"。 - 标了
isSidechain的行(老版本 Claude Code 会把子线程流量混进主 transcript)直接跳过。 - Codex 的子线程和自动化 rollout 在扫描层就被过滤——那是另一篇的故事。
文件监听让这一切足够便宜:FSEvents 在 transcript 写入时触发重扫,一个跑完的回合通常一到两秒就到你屏幕上,没有轮询循环。
这个 app 发出的每一个网络请求
额度环需要的数据不在磁盘上,所以有一份很短、但完整的清单:
api.anthropic.com/api/oauth/usage——Claude 额度窗口,用你本地已登录 Claude Code 的 OAuth token;chatgpt.com/backend-api/wham/usage——Codex 额度窗口,同样用你本地的 Codex 凭证;- GitHub——Sparkle appcast 和 release 源(检查更新),以及官网头部 star 数用的公开仓库 API。
清单到此为止。没有 Agent Island 服务器、没有账号体系、没有分析 SDK、没有崩溃上报。transcript 内容只在本地解析出状态,从不离开你的机器。代码开源,这个说法可以验证:全局搜 URLSession / HttpClient,你找到的就是上面这几个端点。
再压缩一点就是:你的 agent 早就把一切告诉了文件系统。Agent Island 只是去听——并且只在真正需要人的时候打断你。