Skip to content

v1.0.40

Latest

Choose a tag to compare

@wxtsky wxtsky released this 23 Oct 05:07
Immutable release. Only release title and notes can be modified.

English

Important

  • Only you approve a request. When an agent's activity suggested that a pending approval had been answered in the terminal, CodeIsland answered it "allow", on any tool step in the same session from any agent. Claude Code's and Codex's approvals carry no id and subagents share their parent's session, so a subagent reading a file could approve the parent's pending command. A request CodeIsland drops on its own is now answered with no decision, so the agent asks in its own prompt, and it counts as stale only on a step from the same agent with the same tool and input. A session ending, a hook going away or a replaced request no longer answers "deny" for you either, and requests are matched to their own card, so another host can't answer a local one by its id. A request too large for the island to read (over 10 MB) is left to its agent as well, instead of being denied
  • iPhone Buddy can't answer requests for now. The Mac accepted every iPhone Buddy that found it without checking which device it was, so any nearby device running the app could approve, deny or answer a pending request. Until Buddy can pair with the Mac it still shows your sessions but can't answer for you; Settings → iPhone Buddy says so
  • A second CodeIsland quits instead of taking over. Launching another copy while one was running took the hook socket away from the first. The second copy now quits; to run a development build alongside, give it its own CODEISLAND_SOCKET_PATH (scripts/dev-hot-restart.sh --socket-path …). That script now stops only the build it started, never the installed app

Security

  • Hide never answers a request for you. In some cases Hide approved a hidden child's request automatically. Now a Codex or Cursor child's request shows on a card of its own (or goes back to Codex's auto-review), and a plugin-proxied request goes back undecided so the agent asks you itself. A request that's waiting is also never denied because its card was folded or hidden by a background pass
  • Remote sessions can't act on this Mac. A remote session's process id is never watched or signalled here, its transcript path is never read from this Mac's disk, Smart Suppress never inspects this Mac's terminals for it, and links in its replies open only on the web. "Always allow" on a remote Codex request now holds for that session instead of writing a rule into this Mac's ~/.codex, and a remote Codex request is never handed to auto-review because of this Mac's Codex settings. A hook could also name any program as its Herdr binary, and CodeIsland ran it while checking whether the Herdr pane was in front: it now only runs a program called herdr, and never for a remote session. Rules an earlier version saved for a remote request stay in ~/.codex/rules/codeisland.rules until you remove them
  • Hooks only talk to a socket you own. /tmp/codeisland-<uid>.sock is a predictable path, and on a Mac shared by several accounts another user could create it first: CodeIsland then failed to listen without saying so, and every hook (the bridge, the pi, Oh My Pi, OpenCode and OpenClaw plugins, the remote hook) sent its events, prompts and commands there, where an answer could approve a tool and rewrite its input. Every client now checks that the socket belongs to its own user before sending anything, and the bridge also checks who is listening; if the path is held by someone else, Settings → Hooks says by whom, with a Try Again button. The bridge's debug log, which holds every hook's raw input, is now readable only by you and is never written through a link
  • Your session file and hook scripts are yours alone. ~/.codeisland was readable by the other accounts on the Mac, and its sessions.json holds every session's last prompt and reply. The folder is now private to you (files 0600, scripts 0700), and existing installs are tightened at launch
  • The bridge log records what each hook was, not what it said. Since June it wrote every hook's full input (prompts, commands, file contents) to /tmp/codeisland-bridge.log, without a size limit. It now writes one line per hook (event, source, session, tool and field names, no values), keeps about 5 MB, and logs whole payloads only with CODEISLAND_DEBUG=1
  • Diagnostics exports leave out secrets and conversations. The export copied each CLI's settings verbatim, API tokens in env included, and the whole sessions file. Settings are now redacted (env values, keys, tokens, passwords, auth headers, well-known key formats), and sessions keep their structure with prompts cut to 80 characters and no replies, as the export's description says
  • Links in replies open only on the web. In every session, a link in an agent's reply opens only if it is http, https or mailto; a file: or app link, which an agent could write to run something when clicked, does nothing
  • OpenCode's terminal title can't carry escape codes. The plugin wrote the session title to the terminal with only newlines removed, so a title holding control characters could send other terminal sequences (such as a clipboard write). They are now removed (plugin v11)
  • Host settings can't turn into commands. Every ssh call now ends its options before the host, so a host or user field starting with - (such as -oProxyCommand=…) can't become an ssh option, and the values CodeIsland puts into commands on the host are shell-quoted. A host with an empty id no longer connects

Remote hosts

  • Remote hosts no longer lose events. The remote hook sent its event and closed the connection at once, and macOS's network listener silently drops a connection whose client has already closed before it is set up, so remote sessions lost events (5 to 23 of 80 in a test run even with an idle island, nearly all of them while the island was busy), and a lost Stop or SessionEnd left a card behind. The island now accepts hook connections with a plain socket on a background queue, where the kernel keeps every request until it is read, however early its hook closed. Remote tool steps still leave right after sending, so a tool call on a remote host doesn't wait for a round trip; lifecycle events wait briefly for the island's answer so an older CodeIsland doesn't lose them either
  • One reading of every hook, local or remote. The bridge's understanding of hooks (which agent sent it, Cursor's imported Claude hooks, Cline, Hermes, Gemini answers and more) moved into a single component the island also runs on events from remote hosts, so a fix lands for both at once. The remote hook now sends facts about its environment instead of interpreting events itself; it is updated on the next connect. docs/hook-edge-protocol.md describes the protocol for other clients such as the community Windows bridge
  • Each remote host talks to the island over a socket of its own. Remote hooks reached the same socket as local ones and said themselves which host they came from, so anything on a remote host that could reach the forwarded socket could leave the host out and be taken for a local session, or claim to be another host. Each connected host now gets its own socket in a private folder, the island stamps every request arriving there with that host whatever it claims, and the Mac's own socket refuses requests that claim to come from a remote host. The SSH tunnel starts only after the host's socket is listening, so it never leads to a socket someone else holds. On the remote host, the forwarded socket is now set to the SSH user alone; a new per-host option, Agents Run as Other Users, opens it to the other accounts there for agents that run in containers or under sudo
  • A remote host can't wear the island down. Each host now has limits (1 MB per request, 300 s to finish sending one, 64 open connections, 32 requests waiting for an answer), so one host can't use up the island's memory or connections and starve local agents' approvals
  • The island's socket on a remote host sits in a private folder. The forwarded socket is now /tmp/codeisland-<uid>/island.sock, in a folder only the SSH user can enter, checked before the tunnel starts and again once it is up; if a check fails, the host says why instead of connecting. On the Mac, each host's socket moved into your private temporary folder, which no other account can create first. The remote hook also asks the kernel who is listening before it sends anything. An agent started before the update still runs the old hook command, which now tries that folder first, so a tunnel an older version left running can't swallow its events. On an SSH host, Hermes asks once more to approve CodeIsland's hooks, because their command changed (see Hermes in the README)
  • Remote tool steps that arrive out of order keep the running tool. A long tool result from a remote host can arrive after the next tool has started; the card no longer marks the newer tool finished because of it

Fixes

  • A grep that Claude Code runs is no longer mistaken for its session. Claude Code's own binary is also the grep, find and rg that its shell and Grep tool run, and its background helpers. Session discovery could bind a card to one of those processes, so the card disappeared when the grep finished, and an orphaned grep could be sent SIGTERM and its card removed. Cards now follow only Claude Code's CLI, and CodeIsland never signals one of its helpers
  • Claude Code sessions sharing a folder keep their own process. With several sessions open in one folder (several terminals in your home folder, say), discovery gave the newest transcript to whichever process it found first: a card could follow another session's process and disappear when that terminal closed, and the other session got no card until its next hook. CodeIsland now pairs each process with the session Claude Code itself records for it; with older Claude Code it works as before
  • An interrupted turn no longer rings "done". Stopping a turn yourself (Esc in Claude Code, a stopped Hermes turn, a cancelled Cline task) played the task-complete chime as if it had finished. It now ends quietly; each agent's card behaves as before
  • A subagent's failure no longer hides its parent's completion push. A subagent that ended on an error pushed that error under its parent's card, and the push dedupe then dropped the parent's own "done" moments later, so the phone heard "error" for a turn that finished fine. Only a session's own failure pushes now
  • Smart Suppress covers queued completion cards too. A completion card that waited behind another one appeared even when its session's terminal tab was the one in front. The tab check now runs whenever a card actually appears, right away or out of the queue
  • Follow-up reminders from several sessions all ring. Reminders shared the failed-turn sound's debounce, so a second session's reminder right after another's stayed silent
  • A Cursor Task folded into its chat stays quiet. With Agent Sub-Sessions on Merge into main or Hide, a Task whose own Stop folds its card away no longer rings, pushes or opens a completion card for a card that no longer exists
  • An aborted AiWork stream isn't chased as finished. It no longer gets a "still waiting · finished" reminder and push
  • A turn that ends without a card hands the island on. A Hermes gateway chat, or a Stop with On completion set to Glance dot or Do nothing, kept the island's active spot instead of passing it to another working session
  • Agent Sub-Sessions treats every kind of child the same way. Codex subagent threads, Cursor Tasks, plugin-proxied sessions (such as omo in OpenCode) and children that name their parent (pi, Oh My Pi) now go through one set of rules. With Show separately, a Codex thread or Cursor Task whose parent is known keeps its own card but stays quiet (no chime, completion card or push), as pi children already did; its approvals and questions still alert you. A child stays where it started: switching the setting mid-run, or Cursor's process becoming ambiguous, no longer moves it between cards
  • Codex subagent fixes. With Merge into main, a folded thread's follow-up turns show up again (they were dropped), and a thread's Stop no longer ends its parent's turn early. A rollout that says a thread is a root beats a same-process guess, Desktop threads only fold into Desktop cards, and Desktop grandchildren fold into the right card
  • Codex "Always" says exactly what it saves. The rule came from a prefix_rule anywhere in the request, including text the model wrote, and the card never showed it, so a request to run ls -la could save a rule allowing every bash command. The rule now comes from the command itself (its first three words), and the link names it: "Always allow commands starting with git push --force — saved to ~/.codex/rules". A request no rule can describe is allowed for the session instead
  • Codex's state database is read while Codex has it closed. Codex deletes the database's WAL files whenever its last connection closes (an idle Codex Desktop, for one), and every read CodeIsland made then failed, so Desktop threads, subagent links, finding a thread's transcript and the end-of-turn check came up empty. CodeIsland now reads the closed database as a snapshot, and never creates or changes anything in ~/.codex
  • pi is recognized by its own program only. pi and Oh My Pi were matched by the start of a program's name, so pinentry (which gpg starts to sign a commit), pigz or pico in a pi session's folder could be taken for pi: the card followed it and went when it exited, and once orphaned it could be sent SIGTERM. Now only pi, omp or pi's npm package counts
  • An approval waits as long as its agent does. A held approval or question was cancelled after 5 minutes although the agent waits up to a day, so an approval left while you stepped away could no longer be answered. It now stays answerable until its agent gives up. When one waiting hook is killed, only its own request goes away: the other requests of the same session used to be denied with it
  • A launch leaves hook configs that are already current alone. Every launch rewrote about 15 of your CLI configs (Codex, Cursor, Gemini, Qwen, Factory, Trae and others) with nothing changed but their key order, so dotfiles under git showed a diff after each launch. A config is now written only when its hooks need to change
  • Smaller fixes. A malformed _ppid in a hook can no longer crash CodeIsland; remote card keys no longer get the host prefix twice; a SessionStart no longer unlinks a child from its parent; guesses by process id never match a card on another host; subagent rows created by a request take the hook's agent type

Performance

  • Less work on the main thread. Session titles, model names, Cursor's YOLO badge and the end-of-turn check for desktop apps are read in the background now, and session discovery runs entirely off the main thread. A title that came from a hook or from Codex's app-server is no longer cleared by a session store that has none, so a Codex subagent card split out of its parent keeps its agent's name. A pending approval or question no longer makes every hook re-split the card's text for an ESP32 Buddy that isn't connected (137 ms a hook behind a 1 MB prompt), and sessions.json keeps the first 64 K characters of each prompt and reply instead of re-encoding a whole pasted log on every save
  • Silent tool steps no longer ask the window server whether the screen is locked. With sounds on, every tool hook read the lock state on the main thread before checking whether that event plays a sound at all

中文

重要

  • 只有你能批准请求。 以前 agent 的活动一旦显示某个挂起的审批「已经在终端里回答过」,CodeIsland 就会替它回答「允许」,而且同一会话里任何 agent 的任何工具步骤都算数。Claude Code 和 Codex 的审批请求不带 id,子代理又和父会话共用会话,于是一个子代理读一下文件,就可能批准父会话正在等待的命令。现在 CodeIsland 自行撤掉的请求一律回复「不做决定」,由 agent 在自己的提示里询问你;而且只有同一个 agent 的、工具和输入都一致的步骤,才会让请求被视为过期。会话结束、hook 退出、请求被取代时,也不会再替你回答「拒绝」;请求只和它自己的卡片匹配,其他主机无法凭 id 回答本机的请求。灵动岛读不完的超大请求(超过 10 MB)现在也交给 agent 自己处理,不再直接拒绝
  • iPhone Buddy 暂时不能替你回答请求。 Mac 以前会接受任何找到它的 iPhone Buddy,并不核对是哪台设备,于是附近任何运行这个 App 的设备都能批准、拒绝或回答挂起的请求。在 Buddy 能与 Mac 配对之前,它仍会显示你的会话,但不能替你作答;「设置 → iPhone Buddy」里有说明
  • 第二个 CodeIsland 会直接退出,不再抢占。 以前在一个实例运行时再启动一份,会把 hook socket 从第一个手里抢走。现在第二份会直接退出;如果要同时运行开发版,请给它单独的 CODEISLAND_SOCKET_PATH(scripts/dev-hot-restart.sh --socket-path …)。这个脚本现在只会停掉它自己启动的构建,不会再停掉已安装的 App

安全

  • 「隐藏」不再替你回答请求。 以前「隐藏」在某些情况下会自动批准被隐藏的子会话的请求。现在 Codex 或 Cursor 子会话的请求会显示在它自己的卡片上(或交回 Codex 的自动审查),插件代理的请求原样交回、不作决定,由 agent 自己来问你。正在等待的请求也不会因为卡片被后台流程折叠或隐藏而被拒绝
  • 远程会话不能再在本机上执行操作。 远程会话的进程号不会在本机被监控或发送信号,它的 transcript 路径不会从本机磁盘读取,智能抑制不会为它检查本机终端,它回复里的链接只会在浏览器中打开。对远程 Codex 请求点「总是允许」,现在只在该会话内有效,不再往本机的 ~/.codex 写规则;远程 Codex 请求也不会因为本机的 Codex 设置而交给自动审查。另外,hook 可以把任意程序声明为 Herdr 可执行文件,CodeIsland 在检查 Herdr 面板是否在前台时会运行它;现在只运行名为 herdr 的程序,远程会话则一律不运行。旧版本为远程请求保存的规则仍留在 ~/.codex/rules/codeisland.rules 里,不需要的话请自行删除
  • hook 只会连到属于你自己的 socket。 /tmp/codeisland-<uid>.sock 是可预测的路径,在多个账户共用的 Mac 上,别的用户可以抢先创建它:CodeIsland 会无声地监听失败,而所有 hook(bridge,pi、Oh My Pi、OpenCode、OpenClaw 插件,远程 hook)都会把事件、提示词和命令发到那里,对方的答复还能批准工具调用、改写工具输入。现在每个客户端在发送任何内容之前,都会确认 socket 属于自己的用户,bridge 还会核对正在监听的是谁;路径被别人占用时,「设置 → Hooks」会说明被谁占用,并提供「重试」按钮。bridge 的调试日志记录着每个 hook 的原始输入,现在只有你自己能读,也不会再通过链接写入
  • 会话文件和 hook 脚本只属于你自己。 ~/.codeisland 以前其他账户也能读,而其中的 sessions.json 存着每个会话最近的提示词和回复。现在这个目录只有你能访问(文件 0600,脚本 0700),已有的安装会在启动时自动收紧权限
  • bridge 日志只记录 hook 是什么,不记录它说了什么。 从 6 月起,它会把每个 hook 的完整输入(提示词、命令、文件内容)写进 /tmp/codeisland-bridge.log,而且没有大小限制。现在每个 hook 只记一行(事件、来源、会话、工具和字段名,不含值),最多保留约 5 MB,只有设置 CODEISLAND_DEBUG=1 时才记录完整内容
  • 诊断导出不再包含密钥和对话内容。 导出以前会原样复制各个 CLI 的设置(包括 env 里的 API token)和整个会话文件。现在设置会先脱敏(env 的值、各类 key、token、密码、认证头、常见密钥格式),会话只保留结构,提示词截到 80 个字符、不含回复,和导出说明一致
  • 回复里的链接只会在浏览器中打开。 在所有会话里,agent 回复中的链接只有 http、https 或 mailto 才能打开;file: 或 app 链接(agent 可以借此让你点击后运行某些东西)点了不会有反应
  • OpenCode 写入的终端标题不能再夹带控制字符。 插件写终端标题时只去掉了换行,标题里的控制字符可以发出其他终端序列(比如写入剪贴板)。现在会全部去掉(插件 v11)
  • 主机设置不会变成命令。 现在每个 ssh 调用都会在主机名之前结束选项,以 - 开头的主机或用户字段(比如 -oProxyCommand=…)不会再被当成 ssh 选项;CodeIsland 放进远程命令里的值也都做了 shell 转义。id 为空的主机不再连接

远程主机

  • 远程主机不再丢事件。 远程 hook 发完事件就立刻关闭连接,而 macOS 的网络监听器会悄悄丢掉「建立前客户端就已关闭」的连接,于是远程会话会丢事件(即使灵动岛空闲,一轮测试里 80 个也会丢 5 到 23 个;灵动岛忙时几乎全丢),丢了 Stop 或 SessionEnd 就会留下僵尸卡片。现在灵动岛改用后台队列上的普通 socket 接收 hook 连接,内核会把每个请求保留到被读取为止,不管 hook 多早关闭。远程的工具事件仍然发完就走,远程主机上的每次工具调用不用等一次往返;生命周期事件会短暂等待灵动岛的回复,这样旧版 CodeIsland 也不会丢
  • 本机和远程的 hook 用同一套解读。 bridge 对 hook 的理解(是哪个 agent 发来的、Cursor 导入的 Claude hook、Cline、Hermes、Gemini 的答复格式等)收进了一个组件,灵动岛也用它处理来自远程主机的事件,修一处两边同时生效。远程 hook 改为只发送环境信息、不再自己解读事件,下次连接时会自动更新。docs/hook-edge-protocol.md 说明了这个协议,供社区的 Windows bridge 等其他客户端参考
  • 每台远程主机通过自己的 socket 与灵动岛通信。 以前远程 hook 和本机 hook 连的是同一个 socket,由 hook 自己说明来自哪台主机,于是远程主机上任何能连到转发 socket 的程序,都可以不写主机、被当成本机会话,或者冒充另一台主机。现在每台连接的主机在一个私有目录里有自己的 socket,灵动岛给从那里进来的每个请求盖上这台主机的章,不管它自称什么;本机的 socket 则拒绝自称来自远程主机的请求。SSH 隧道只在这台主机的 socket 开始监听之后才建立,因此不会通向别人占用的 socket。远程主机上转发出来的 socket 现在只有 SSH 用户本人能用;新增的主机选项「Agent 以其他用户身份运行」,可以为在容器或 sudo 下运行的 agent,向那台主机上的其他账户开放
  • 远程主机无法拖垮灵动岛。 每台主机现在都有上限(单个请求 1 MB、发完一个请求最多 300 秒、同时打开 64 个连接、同时等待答复的请求 32 个),一台主机无法耗尽灵动岛的内存或连接,进而让本机 agent 的审批失效
  • 远程主机上的 socket 放进了私有目录。 转发出来的 socket 现在是 /tmp/codeisland-<uid>/island.sock,所在目录只有 SSH 用户能进入;隧道建立前会检查一次,建立后再检查一次,检查不通过时主机会说明原因,而不是继续连接。在 Mac 上,各主机的 socket 移到了你的私有临时目录,其他账户无法抢先创建。远程 hook 在发送任何内容之前,也会先向内核确认正在监听的是谁。更新前就已启动的 agent 仍在用旧的 hook 命令,现在它会先找这个目录,旧版本遗留的隧道不会再吞掉它的事件。在 SSH 主机上,Hermes 会再请你批准一次 CodeIsland 的 hook,因为命令变了(见 README 中 Hermes 的说明)
  • 远程工具事件乱序到达时,不会误报正在运行的工具已结束。 远程主机上较长的工具结果,可能在下一个工具开始之后才到达;卡片不会再因此把新工具标记为已完成

修复

  • Claude Code 跑的 grep 不再被当成它的会话。 Claude Code 自己的可执行文件同时也是它的 shell 和 Grep 工具调用的 grep、find、rg,以及它的后台辅助进程。会话发现可能把卡片绑到这些进程上:grep 一结束卡片就消失;成了孤儿的 grep 还可能被发 SIGTERM,连同卡片一起移除。现在卡片只跟随 Claude Code 的 CLI 进程,CodeIsland 也不会再向它的辅助进程发信号
  • 同一文件夹里的 Claude Code 会话各自跟随自己的进程。 同一个文件夹里开着多个会话时(比如主目录里开了好几个终端),会话发现会把最新的转录交给它最先找到的那个进程:卡片可能跟着别的会话的进程走,那个终端一关卡片就消失,而另一个会话要等到下一次 hook 才有卡片。现在 CodeIsland 按 Claude Code 自己为每个进程记录的会话来配对;旧版 Claude Code 的行为保持不变
  • 自己打断的回合不再响「完成」。 自己停止一个回合(Claude Code 里按 Esc、停止 Hermes 回合、取消 Cline 任务)时,以前会响「任务完成」提示音,好像它真的做完了。现在会安静结束,各 agent 的卡片表现不变
  • 子代理出错不再吞掉父会话的完成推送。 子代理以错误结束时,错误推送记在父卡片名下,几秒后父会话自己的「完成」推送被去重规则丢掉,手机上只收到「出错」,实际这个回合是正常完成的。现在只有会话自己的失败才会推送
  • 智能抑制也覆盖排队中的完成卡片。 排在另一张卡片后面的完成卡片,即使它的终端标签页就在前台,也照样弹出。现在每次卡片真正出现时(立即或从队列中出来)都会检查标签页
  • 多个会话的跟进提醒都会响。 提醒和「回合失败」提示音共用同一个防抖,另一个会话刚提醒过时,紧接着的提醒就不响了
  • 折叠进对话的 Cursor Task 保持安静。 「Agent 子会话」设为合并到主会话或隐藏时,因自身 Stop 而被折叠掉的 Task 卡片,不再响铃、推送,也不会为已经不存在的卡片弹出完成卡片
  • 被中止的 AiWork 流不再被当成已完成去跟进。 不再收到「仍在等待 · 已完成」的提醒和推送
  • 不弹卡片就结束的回合会让出刘海位置。 Hermes 网关对话,或「任务完成时」设为「仅亮起指示点」或「无动作」时的 Stop,以前会一直占着刘海的活跃位置,不让给其他正在工作的会话
  • 「Agent 子会话」对各类子会话一视同仁。 Codex 子线程、Cursor Task、插件代理的会话(例如 OpenCode 里的 omo),以及会声明父会话的子代理(pi、Oh My Pi)现在走同一套规则。「独立显示」时,能确定父会话的 Codex 子线程和 Cursor Task 保留自己的卡片,但保持安静(不响铃、不弹完成卡片、不推送),和 pi 子代理一样;它们的审批和提问仍会提醒。子会话在哪里开始就留在哪里:运行中切换设置,或 Cursor 进程变得无法区分,都不会再把它挪到别的卡片上
  • Codex 子线程修复。 「合并到主会话」时,已折叠的子线程后续的回合重新显示(以前会丢);子线程的 Stop 也不会再提前结束父会话的回合。rollout 记录表明是根线程时,优先于同进程的推测;桌面版子线程只会并入桌面版卡片;桌面版的孙线程会并入正确的卡片
  • Codex 的「总是允许」会明确写出它保存的规则。 以前规则取自请求中任意位置的 prefix_rule(包括模型写的内容),卡片上也从不显示,于是一个运行 ls -la 的请求,可能保存一条允许所有 bash 命令的规则。现在规则取自命令本身(前三个词),链接会写明,例如「总是允许以 git push --force 开头的命令——保存到 ~/.codex/rules」。无法用规则描述的请求,改为只在本次会话内允许
  • Codex 关闭数据库时也能读取它的状态库。 Codex 每次关闭最后一个连接(比如 Codex Desktop 空闲时)都会删掉数据库的 WAL 文件,此时 CodeIsland 的读取全部失败,Desktop 线程、子代理关联、线程转录的定位和回合结束检测都会落空。现在 CodeIsland 会把已关闭的数据库当作快照读取,也绝不会在 ~/.codex 里创建或修改任何东西
  • pi 只按它自己的程序名识别。 以前按程序名的开头匹配 pi 和 Oh My Pi,所以 pi 会话目录里的 pinentry(gpg 签名提交时会启动它)、pigz、pico 可能被当成 pi:卡片会跟着它走,它一退出卡片就消失,成了孤儿时还可能被发 SIGTERM。现在只认 pi、omp 或 pi 的 npm 包
  • 审批会一直等到 agent 放弃为止。 等待中的审批或提问以前 5 分钟后就会被取消,而 agent 最长会等一天,于是离开座位期间收到的审批,回来后已经无法回答。现在会一直可以回答,直到 agent 自己放弃。某个等待中的 hook 被杀掉时,只会撤掉它自己的请求;以前同一会话的其他请求会被一并拒绝
  • 启动时不再改写已经是最新的 hook 配置。 以前每次启动都会把大约 15 个 CLI 配置(Codex、Cursor、Gemini、Qwen、Factory、Trae 等)重写一遍,内容不变,只是键的顺序变了,放在 git 里管理的 dotfiles 每次启动都会出现 diff。现在只有 hook 确实需要改动时才写入
  • 其他小修复。 hook 里格式错误的 _ppid 不会再让 CodeIsland 崩溃;远程卡片的 key 不会再重复加主机前缀;SessionStart 不会再解除子会话和父会话的关联;按进程 id 的推测不会匹配到其他主机上的卡片;由请求创建的子任务行会使用 hook 里的 agent 类型

性能

  • 主线程的负担更轻。 会话标题、模型名、Cursor 的 YOLO 标记,以及桌面 app 的回合结束检测,现在都在后台读取;会话发现的扫描也全部移出了主线程。来自 hook 或 Codex app-server 的标题,不会再被一个没有标题的会话存储清空,所以从父会话拆出来的 Codex 子线程卡片会保留它的 agent 名称。有待处理的审批或提问时,每个 hook 不再为没有连接的 ESP32 Buddy 重新切分卡片文字(1 MB 的 prompt 下每个 hook 要 137 ms);sessions.json 只保留每条 prompt 和回复的前 64K 个字符,不再每次保存都重新编码整段粘贴进来的日志
  • 静默的工具步骤不再向窗口服务器查询锁屏状态。 声音开启时,每个工具 hook 都会先在主线程读取锁屏状态,然后才检查这个事件是否需要响铃