Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,13 +189,35 @@ runs as an accessory app with no Dock icon and no menu bar.
- **Display:** used/remaining percentages, Usage and Cost visualization styles,
target display, and island width on non-notched screens.
- **Providers:** Claude/Codex visibility and status, token-counting mode, and a
manual refresh for local cost data.
manual refresh for local cost data. When Claude is hidden, an optional local
Codex task signal can fill the freed half.

Preferences are stored in `UserDefaults` under `MacIsland.*` keys (Sparkle
manages its own `SU*` update keys, and Launch at Login uses
`SMAppService.mainApp`). Refresh, display, and provider changes apply live;
changing the app language offers to restart CodexIsland.

Codex task status is inferred locally from recent
`~/.codex/sessions/**/*.jsonl` rollout lifecycle events. It reports only the
states the current rollout format can support reliably: running, waiting for
approval, idle, cancelled, error, or unavailable. Approval is detected from an
unresolved `request_permissions` call. User-input waits are not claimed because
current rollout files do not expose a reliable event for that state. The
Comment on lines +202 to +205

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove unsupported approval behavior from the documentation.

The README claims approval detection and approval-specific sounds, but the current contract supports only running, idle, cancelled, error, and unavailable, with completion and attention sounds.

  • README.md#L202-L205: remove waiting for approval and the request_permissions approval-detection claim.
  • README.md#L209-L210: remove approval uses Ping and the separate cancellation/error mappings.
📍 Affects 1 file
  • README.md#L202-L205 (this comment)
  • README.md#L209-L210
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 202 - 205, Update README.md lines 202-205 to remove
“waiting for approval” and the claim that approval is detected from unresolved
request_permissions calls, while retaining only supported states. Update
README.md lines 209-210 to remove “approval uses Ping” and the separate
cancellation/error sound mappings, documenting only the supported completion and
attention sounds.

feature is off by default, polls only while enabled with Claude hidden and
Codex visible, and never displays prompts, commands, or output.

Optional status sounds are event-specific: completion uses Glass, approval
uses Ping, cancellation uses Funk, and errors use Basso. Notifications are
emitted only for top-level sessions; Codex guardian/subagent rollouts are
excluded so internal work cannot produce a false completion alert. Monitoring
generations also prevent an old scan or queued sound from leaking across a
provider or setting change.

The compact and peek views are visual-only so their normal click-to-expand
behavior is preserved. The expanded status card can open the related task in
the Codex app when available. Disable the feature at any time to restore the
original per-model token breakdown.

## Build from source

Requires macOS 13+ and a Swift toolchain from Xcode / Command Line Tools.
Expand Down
15 changes: 15 additions & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,25 @@ Claude:
| 低功耗模式 | `LowPowerModeStore` | `MacIsland.lowPowerMode` | Boolean,默认 `false` |
| Claude 可见 | `ProviderVisibilityStore` | `MacIsland.claudeVisible` | Boolean,默认 `true` |
| Codex 可见 | `ProviderVisibilityStore` | `MacIsland.codexVisible` | Boolean,默认 `true` |
| Codex 任务状态 | `CodexTaskStatusStore` | `MacIsland.codexTaskStatus` | Boolean,默认 `false` |
| 状态显示 | `CodexTaskStatusStore` | `MacIsland.codexTaskStatusDisplayMode` | `icon`, `iconAndText`,默认 `icon` |
| 登录启动 | `LaunchAtLoginStore` | 由 `SMAppService.mainApp` 管理 | 系统登录项状态 |

刷新间隔会立即生效。`UsageStore` 会重置当前计时器,并用新的间隔重新安排下一次拉取。

隐藏 Claude、保留 Codex 时,可以选择显示本地 Codex 任务状态。状态从
`~/.codex/sessions/**/*.jsonl` 当前实际记录的生命周期事件推断,只显示运行中、等待审批、
空闲、已取消、异常和不可用。等待审批通过尚未获得响应的 `request_permissions` 调用识别;
当前 rollout 文件仍没有可靠的等待用户输入事件,因此本功能不会声称能够识别该状态。

状态提示音可选开启:完成使用 Glass,等待审批使用 Ping,取消使用 Funk,
报错使用 Basso。只有顶层任务会触发提示,Codex 内部的 guardian/子任务日志会被排除,
避免主任务尚未完成时误播放完成音。监控代次也会防止旧扫描结果或排队中的声音跨设置切换继续生效。

该功能默认关闭,并且只有在功能已开启、Claude 已隐藏且 Codex 可见时才轮询。收起和预览
状态仅用于显示,不会抢占灵动岛原本的点击展开行为;只有展开后的状态卡会尝试打开 Codex
任务。关闭功能后会恢复原有的按模型 Token 用量视图。

## 从源码构建

需要 macOS 13+ 和来自 Xcode / Command Line Tools 的 Swift 工具链。
Expand Down
28 changes: 27 additions & 1 deletion Resources/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@
"General" = "General";
"Follows macOS" = "Follows macOS";
"Glow only on refresh, hover, or limit alerts." = "Glow only on refresh, hover, or limit alerts.";
"Idle" = "Idle";
"idle" = "idle";
"Input + output" = "Input + output";
"Input + output only. Matches Anthropic's claude.ai stats." = "Input + output only. Matches Anthropic's claude.ai stats.";
Expand Down Expand Up @@ -101,6 +100,33 @@
"Ring" = "Ring";
"scanning local logs…" = "scanning local logs…";
"Settings" = "Settings";
"Codex task status" = "Codex task status";
"Show local Codex task state when the Claude side is hidden." = "Show local Codex task state when the Claude side is hidden.";
"Running" = "Running";
"Running short" = "Running";
"Waiting for approval" = "Waiting for approval";
"Approval short" = "Approval";
"Idle" = "Idle";
"Cancelled" = "Cancelled";
"Cancelled short" = "Cancelled";
"Error" = "Error";
"Unavailable" = "Unavailable";
"Unavailable short" = "Unknown";
"Open this task in Codex" = "Open this task in Codex";
"Unable to open Codex" = "Unable to open Codex";
"Codex is not installed on this Mac." = "Codex is not installed on this Mac.";
"Codex could not be opened." = "Codex could not be opened.";
"OK" = "OK";
"Codex status: %@" = "Codex status: %@";
"%@ — open in Codex" = "%@ — open in Codex";
"Status display" = "Status display";
"Choose an icon only or include a localized label." = "Choose an icon only or include a localized label.";
"Icon" = "Icon";
"Icon + Text" = "Icon + Text";
"Updated %@" = "Updated %@";
"Status sounds" = "Status sounds";
"Play a sound when a running task completes, is cancelled, or fails." = "Play a sound when a running task completes, is cancelled, or fails.";
"Use distinct sounds for completion, approval, cancellation, and errors." = "Use distinct sounds for completion, approval, cancellation, and errors.";
"Show on" = "Show on";
"Sparkline" = "Sparkline";
"Spacing" = "Spacing";
Expand Down
28 changes: 27 additions & 1 deletion Resources/zh-Hans.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@
"General" = "通用";
"Follows macOS" = "跟随 macOS";
"Glow only on refresh, hover, or limit alerts." = "仅在刷新、悬停或限额提醒时显示辉光。";
"Idle" = "空闲";
"idle" = "空闲";
"Input + output" = "输入 + 输出";
"Input + output only. Matches Anthropic's claude.ai stats." = "只统计输入 + 输出;与 Anthropic 的 claude.ai 统计一致。";
Expand Down Expand Up @@ -101,6 +100,33 @@
"Ring" = "环形";
"scanning local logs…" = "正在扫描本地日志…";
"Settings" = "设置";
"Codex task status" = "Codex 任务状态";
"Show local Codex task state when the Claude side is hidden." = "隐藏 Claude 一侧时显示本地 Codex 任务状态。";
"Running" = "运行中";
"Running short" = "运行";
"Waiting for approval" = "等待审批";
"Approval short" = "审批";
"Idle" = "空闲";
"Cancelled" = "已取消";
"Cancelled short" = "取消";
"Error" = "异常";
"Unavailable" = "不可用";
"Unavailable short" = "未知";
"Open this task in Codex" = "在 Codex 中打开此任务";
"Unable to open Codex" = "无法打开 Codex";
"Codex is not installed on this Mac." = "这台 Mac 尚未安装 Codex。";
"Codex could not be opened." = "Codex 无法启动。";
"OK" = "好";
"Codex status: %@" = "Codex 状态:%@";
"%@ — open in Codex" = "%@ — 在 Codex 中打开";
"Status display" = "状态显示";
"Choose an icon only or include a localized label." = "选择仅显示图标,或同时显示本地化文字。";
"Icon" = "仅图标";
"Icon + Text" = "图标与文字";
"Updated %@" = "更新于%@";
"Status sounds" = "状态提示音";
"Play a sound when a running task completes, is cancelled, or fails." = "运行中的任务完成、取消或失败时播放提示音。";
"Use distinct sounds for completion, approval, cancellation, and errors." = "任务完成、等待审批、取消和报错时使用不同的提示音。";
"Show on" = "显示在";
"Sparkline" = "折线";
"Spacing" = "间距";
Expand Down
1 change: 1 addition & 0 deletions Sources/App.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
// Wire the alert engine after the usage store so its initial
// recompute sees whatever values the first refresh has produced.
AlertEngine.shared.start()
CodexTaskStatusStore.shared.start()

// Touch the shared updater so Sparkle starts its background scheduler.
_ = UpdaterController.shared
Expand Down
Loading