Skip to content

v1.0.39

Choose a tag to compare

@wxtsky wxtsky released this 22 Oct 04:39
· 169 commits to main since this release
Immutable release. Only release title and notes can be modified.

English

Important: v1.0.36 to v1.0.38 contained v1.0.35's app

  • Releases ship the code they list again. v1.0.36, v1.0.37 and v1.0.38 carried v1.0.35's app and hook bridge under new version numbers. After the build Mac moved to Xcode 27, SwiftPM's new default build system wrote its products to .build/out/Products/Release, while the release script kept copying from .build/<arch>-apple-macosx/release, where the v1.0.35 build still sat. Everything those three releases list arrives with this one. The release script now pins SwiftPM's native build system (the new one also writes both architectures to the same folder, so the second overwrote the first, and records the 14.0 deployment target as the SDK, which runs AppKit in its old-SDK compatibility mode), asks SwiftPM where the products are (#379, thanks @Naitellos), deletes the previous ones before building and refuses a binary with the wrong architecture or SDK

That includes MiniMax Code and Xiaomi MiMo support, the redesigned session list, approval and question cards, Claude plan limits on the collapsed island, Hermes prompts and titles, and every fix in those three releases. See the changelog for the full list.

Fixes

  • Remote hosts reconnect after the Mac wakes. An SSH host only retried after its tunnel dropped, 10 times with growing gaps, then gave up for good, and nothing listened for wake or the network. With the lid closed every attempt failed at once and each dark wake fired the next overdue one, so a long sleep used them all up and the host stayed down until you clicked Connect. Waking up (including the displays coming on after Power Nap) or the network coming back now reconnects every host you still want connected, with a fresh backoff and a short wait for Wi-Fi; offline, a failure waits for the network instead of using up an attempt; after the fast retries it keeps trying every 15 minutes. A host you disconnected stays disconnected, one you connected by hand is restored too, and a failed host that is still retrying shows a Disconnect button. A host that failed slowly no longer retries every few seconds forever, and Disconnect while a connection is being prepared no longer leaves an ssh tunnel running (#375, thanks @KingsleyCl)
  • Cursor sessions show as Cursor, not Claude. Cursor also runs the Claude Code hooks in ~/.claude/settings.json ("Include third-party Plugins, Skills, and other configs", on by default), with its own payload. CodeIsland's Claude hook carries no --source, and Cursor's processes are never used to guess a source, so those events, most of a Cursor agent's tool activity, landed on cards labelled Claude. A payload carrying cursor_version now counts as Cursor's own (Cursor CLI under cursor-agent), locally and over Remote-SSH; Claude Code itself running inside Cursor stays Claude. A prompt or finished turn that reaches both of CodeIsland's hooks rings once instead of twice, cards already saved as Claude switch on their next event, Cursor Task cards still fold under their chat, and a hook Cursor runs never waits on the island or answers in a format Cursor can't use (#377, thanks @4pure)
  • Only the session you started rings when pi or Oh My Pi subagents finish. pi-subagents runs each background child as a pi session of its own that loads the same CodeIsland extension, and Oh My Pi loads it into every task subagent, so each child got a card and rang the completion sound: one parent with two children chimed three times. The extensions (pi v5, Oh My Pi v9) now tell CodeIsland which session a child works for (_parent_session_id, which any agent can send), and Agent Sub-Sessions applies to them: Show separately keeps each child on its own card that never chimes, pops a completion card or sends a push; Merge into main folds it into the parent's card as a subagent; Hide hides it. A child's approvals and questions still alert you and are never answered automatically. A subagent compacting its context no longer shows its parent card as Compacting. Restart pi or Oh My Pi (or /reload) after updating (#378, thanks @uniStark)
  • Clicking a Codex or Claude Code card in tmux lands on its own pane. Several Codex sessions started from one shared background process all inherited the pane that process started in, so clicking any of them switched to the same pane. CodeIsland now finds the pane each session really runs in from the process tree, matches a session that shares a process by its pane's title and folder, and when the hook's pane is known to be another session's and nothing else matches, brings the terminal forward without switching panes instead of guessing. When a pane can't be checked at all (several clients, a detached session, tmux not answering) the hook's pane is used as before. A Codex CLI session no longer opens Codex.app just because the desktop app is running, Claude Code sessions missing terminal info pick up their Ghostty/tmux details from their process, and Settings… (⌘,) or reopening the app shows the real settings window instead of a blank one (#373, thanks @cynicalight)
  • Codex app-servers started by ChatGPT's bundled tools keep their CLI identity. A codex app-server started by one of ChatGPT's bundled tool hosts (such as Contents/Resources/cua_node/bin/node_repl) shares ChatGPT's bundle id, so it was taken for Desktop's shared app-server and its threads were keyed as Desktop threads. Only an app-server whose parent is the app's own executable in Contents/MacOS counts as Desktop now (#372, thanks @burgerseater)

Performance

  • The island stays responsive with many Claude sessions open. With Agent Sub-Sessions set to Merge into main or Hide, every hook event and discovery scan walked all of ~/.cursor/projects on the main thread once per Claude card, looking for a Cursor Task transcript with that card's id. With a large Cursor history that took most of the main thread (80% of samples with 18 cards), and hovering or expanding the island stuttered. The lookup now reads an index built in the background, each card is looked up at most five times in its first two minutes, and remote cards and Show separately never walk at all. Session discovery also lists each Claude project folder once per scan instead of reading every transcript's date once per Claude process (#374, thanks @x4vierli)

中文

重要:v1.0.36 至 v1.0.38 实际装的是 v1.0.35

  • 发布包重新装着它列出的代码。 v1.0.36、v1.0.37、v1.0.38 实际装的是 v1.0.35 的主程序和 hook 桥接程序,只换了版本号。构建机升级到 Xcode 27 后,SwiftPM 新的默认构建系统把产物写到 .build/out/Products/Release,发版脚本却仍从 .build/<架构>-apple-macosx/release 复制,那里一直放着 v1.0.35 的构建结果。这三个版本列出的改动都随本版本一起送达。发版脚本现在固定使用 SwiftPM 的 native 构建系统(新构建系统还会把两个架构写进同一个目录,后编译的覆盖先编译的,并把 14.0 的部署目标记成 SDK 版本,让 AppKit 以旧 SDK 兼容模式运行),向 SwiftPM 询问产物位置(#379,感谢 @Naitellos),构建前删除旧产物,架构或 SDK 不对的二进制拒绝打包

其中包括 MiniMax Code 和小米 MiMo 支持、重新设计的会话列表与审批/提问卡片、收起状态下的 Claude 用量额度、Hermes 的提示和标题,以及这三个版本里的所有修复。完整列表见更新日志。

修复

  • Mac 唤醒后,远程主机会自动重连。 以前 SSH 主机只在隧道断开后按递增间隔重试 10 次,之后就永久放弃,也不监听唤醒和网络变化。合盖时每次重试都会立刻失败,每次 DarkWake 又会触发下一次到期的重试,睡得久了 10 次用完,主机就一直断着,直到手动点「连接」。现在系统唤醒(包括 Power Nap 之后屏幕点亮)或网络恢复时,会对仍需保持连接的主机重置退避并重连,并稍等 Wi‑Fi 就绪;离线时失败会等网络恢复,不消耗重试次数;快速重试用完后每 15 分钟再试一次。手动断开的主机保持断开,手动连上的主机唤醒后也会恢复,仍在重试的失败主机会多出「断开」按钮。连接很慢才失败的主机不再每隔几秒无限重试,在连接准备阶段点「断开」也不会再留下运行中的 ssh 隧道(#375,感谢 @KingsleyCl)
  • Cursor 的会话显示为 Cursor,不再是 Claude。 Cursor 也会运行 ~/.claude/settings.json 里的 Claude Code hooks(「Include third-party Plugins, Skills, and other configs」,默认开启),传的是 Cursor 自己的 payload。CodeIsland 的 Claude hook 不带 --source,Cursor 的进程又不参与来源推断,于是这些事件(Cursor agent 的大部分工具调用)都落到了标成 Claude 的卡片上。现在带 cursor_version 的 payload 算作 Cursor 自己的事件(在 cursor-agent 下算 Cursor CLI),本机和 Remote-SSH 都一样;在 Cursor 里运行的 Claude Code 本身仍是 Claude。同一个提示或回合结束同时触发 CodeIsland 的两个 hook 时只响一次,不再响两次;已存成 Claude 的卡片在下一个事件到达时自动改过来;Cursor 的子任务卡片仍会折叠到所属对话下;Cursor 运行的 hook 不会等待灵动岛审批,也不会输出 Cursor 无法识别的答复(#377,感谢 @4pure)
  • pi 和 Oh My Pi 的子代理完成时,只有你自己启动的会话会响。 pi-subagents 把每个后台子代理作为独立的 pi 会话运行,加载的是同一个 CodeIsland 扩展;Oh My Pi 也会把扩展加载进每个任务子代理。于是每个子代理都有自己的卡片,各响一次完成提示音:一个父会话带两个子代理会响三次。现在扩展(pi v5、Oh My Pi v9)会告诉 CodeIsland 子代理属于哪个会话(_parent_session_id,其他 agent 也可以发送),「Agent 子会话」设置也对它们生效:「独立显示」时子代理保留自己的卡片,但不响铃、不弹完成卡片、不推送;「合并到主会话」时并入父卡片,作为子任务显示;「隐藏」时不显示。子代理的审批和提问仍会提醒,也不会被自动批准。子代理压缩上下文时,父卡片也不再显示「Compacting」。更新后需重启 pi 或 Oh My Pi(或执行 /reload)(#378,感谢 @uniStark)
  • 在 tmux 里点 Codex 或 Claude Code 的卡片,会跳到它自己的 pane。 从同一个后台进程启动的多个 Codex 会话,都继承了这个进程最初所在的 pane,点哪张卡都切到同一个 pane。现在按进程树找到每个会话实际所在的 pane;共享进程的会话按 pane 的标题和目录匹配;如果确定 hook 给的 pane 属于别的会话、又找不到唯一匹配,就只把终端提到前台,不再猜。完全无法验证时(多个 client、session 已 detach、tmux 没有响应)照旧使用 hook 的 pane。Codex 桌面版开着时,点命令行会话不会再打开 Codex.app;缺少终端信息的 Claude Code 会话会从进程里补全 Ghostty/tmux 信息;按 ⌘, 或「设置...」、以及重新打开 app,都会显示真正的设置窗口,不再出现空白窗口(#373,感谢 @cynicalight)
  • ChatGPT 内置工具启动的 Codex app-server 保持命令行身份。 ChatGPT 内置工具(例如 Contents/Resources/cua_node/bin/node_repl)启动的 codex app-server 和 ChatGPT 共用同一个 bundle id,之前被当成桌面版共享的 app-server,它的对话被算作桌面版对话。现在只有父进程是 App 自己 Contents/MacOS 里的可执行文件时,才算桌面版(#372,感谢 @burgerseater)

性能

  • 开着很多 Claude 会话时,刘海不再卡顿。 「Agent 子会话」设为合并到主会话或隐藏时,每个 hook 事件和每次会话发现扫描,都会为每张 Claude 卡在主线程上遍历一遍 ~/.cursor/projects,查找对应 id 的 Cursor Task 记录。Cursor 历史多时,主线程大部分时间耗在这里(18 张卡时 80% 的采样),悬停和展开刘海明显卡顿。现在改为查后台建好的索引,每张卡只在头两分钟里最多查五次,远程卡片和「独立显示」模式完全不遍历。会话发现也改为每轮扫描每个 Claude 项目目录只列一次,不再为每个 Claude 进程逐个读取 transcript 的修改时间(#374,感谢 @x4vierli)