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
41 changes: 27 additions & 14 deletions AppIcon.icon/Assets/logo 2.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion AppIcon.icon/icon.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"fill" : "system-light",
"fill" : "system-dark",
"groups" : [
{
"layers" : [
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Changelog

## [v1.0.28] - 2026-06-01

### English
- Fix WeChat notification dismissal logic — new messages now correctly trigger Dynamic Island popup even when previous unread count is unchanged (#200)
- Previously, dismissing a WeChat notification would suppress all future notifications with the same badge count
- Now detects database signature changes to distinguish truly new messages from dismissed ones
- Ensures smooth user experience: dismiss once, but still get alerted for genuinely new messages

### 中文
- 修复微信通知 dismissal 逻辑——即使未读数量相同,新消息也能正确触发灵动岛弹出 (#200)
- 之前 dismiss 微信通知后,所有相同 badge 数量的通知都会被抑制不再显示
- 现在通过检测数据库签名变化来区分真正的新消息和已被 dismiss 的消息
- 确保流畅的用户体验:dismiss 一次,但真正的新消息仍然会收到提醒

## [v1.0.27] - 2026-05-30

### English
Expand Down
12 changes: 6 additions & 6 deletions Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>CodeIsland</string>
<string>UniIsland</string>
<key>CFBundleIconFile</key>
<string>AppIcon</string>
<key>CFBundleIconName</key>
<string>AppIcon</string>
<key>CFBundleIdentifier</key>
<string>com.codeisland.app</string>
<string>com.uniisland.desktop</string>
<key>CFBundleName</key>
<string>CodeIsland</string>
<string>UniIsland</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
Expand All @@ -26,15 +26,15 @@
<true/>
</dict>
<key>NSAppleEventsUsageDescription</key>
<string>CodeIsland needs to control terminal apps to jump to the correct window and tab when you click a session.</string>
<string>UniIsland needs to control terminal apps to jump to the correct window and tab when you click a session.</string>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>CodeIsland uses Bluetooth to mirror the island onto Buddy.</string>
<string>UniIsland uses Bluetooth to mirror the island onto Buddy.</string>
<key>SUAutomaticallyUpdate</key>
<false/>
<key>SUEnableAutomaticChecks</key>
<true/>
<key>SUFeedURL</key>
<string>https://raw.githubusercontent.com/wxtsky/CodeIsland/main/appcast.xml</string>
<string>https://raw.githubusercontent.com/wxtsky/UniIsland/main/appcast.xml</string>
<key>SUPublicEDKey</key>
<string>oqLtx5s2hc8Xgsp4rEuTwnQ8UGRT4ma4tjlf+1i3YHA=</string>
<key>SUScheduledCheckInterval</key>
Expand Down
30 changes: 15 additions & 15 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import PackageDescription

let package = Package(
name: "CodeIsland",
name: "UniIsland",
platforms: [.macOS(.v14)],
dependencies: [
// Sparkle — auto-update framework. Pinned to 2.6+ for stable
Expand All @@ -12,38 +12,38 @@ let package = Package(
],
targets: [
.target(
name: "CodeIslandCore",
path: "Sources/CodeIslandCore"
name: "UniIslandCore",
path: "Sources/UniIslandCore"
),
.executableTarget(
name: "CodeIsland",
name: "UniIsland",
dependencies: [
"CodeIslandCore",
"UniIslandCore",
.product(name: "Sparkle", package: "Sparkle"),
.product(name: "Yams", package: "Yams"),
],
path: "Sources/CodeIsland",
path: "Sources/UniIsland",
resources: [
.copy("Resources")
]
),
.executableTarget(
name: "codeisland-bridge",
dependencies: ["CodeIslandCore"],
path: "Sources/CodeIslandBridge"
name: "uniisland-bridge",
dependencies: ["UniIslandCore"],
path: "Sources/UniIslandBridge"
),
.testTarget(
name: "CodeIslandCoreTests",
dependencies: ["CodeIslandCore"],
path: "Tests/CodeIslandCoreTests"
name: "UniIslandCoreTests",
dependencies: ["UniIslandCore"],
path: "Tests/UniIslandCoreTests"
),
.testTarget(
name: "CodeIslandTests",
name: "UniIslandTests",
dependencies: [
"CodeIsland",
"UniIsland",
.product(name: "Yams", package: "Yams"),
],
path: "Tests/CodeIslandTests"
path: "Tests/UniIslandTests"
),
]
)
78 changes: 43 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<h1 align="center">
<img src="logo.png" width="48" height="48" alt="CodeIsland Logo" valign="middle">&nbsp;
CodeIsland
<img src="logo.png" width="48" height="48" alt="UniIsland Logo" valign="middle">&nbsp;
UniIsland
</h1>
<p align="center">
<b>Real-time AI coding agent status panel for macOS Dynamic Island (Notch)</b><br>
Expand All @@ -14,12 +14,12 @@
---

<p align="center">
<img src="docs/images/notch-panel.png" width="700" alt="CodeIsland Panel Preview">
<img src="docs/images/notch-panel.png" width="700" alt="UniIsland Panel Preview">
</p>

## What is CodeIsland?
## What is UniIsland?

CodeIsland lives in your MacBook's notch area and shows you what your AI coding agents are doing — in real time. No more switching windows to check if Claude is waiting for approval or if Codex finished its task.
UniIsland lives in your MacBook's notch area and shows you what your AI coding agents are doing — in real time. No more switching windows to check if Claude is waiting for approval or if Codex finished its task.

It connects to **12 AI coding tools** via Unix socket IPC, displaying session status, tool calls, permission requests, and more — all in a compact, pixel-art styled panel.

Expand All @@ -42,34 +42,34 @@ It connects to **12 AI coding tools** via Unix socket IPC, displaying session st

| | Tool | Events | Jump | Status |
|:---:|------|--------|------|--------|
| <img src="docs/images/mascots/claude.gif" width="28"> | <img src="Sources/CodeIsland/Resources/cli-icons/claude.png" width="16"> Claude Code | 13 | Terminal tab | Full |
| <img src="docs/images/mascots/codex.gif" width="28"> | <img src="Sources/CodeIsland/Resources/cli-icons/codex.png" width="16"> Codex | 3 | Terminal | Basic |
| <img src="docs/images/mascots/gemini.gif" width="28"> | <img src="Sources/CodeIsland/Resources/cli-icons/gemini.png" width="16"> Gemini CLI | 6 | Terminal | Full |
| <img src="docs/images/mascots/cursor.gif" width="28"> | <img src="Sources/CodeIsland/Resources/cli-icons/cursor.png" width="16"> Cursor | 10 | IDE | Full |
| <img src="docs/images/mascots/trae.gif" width="28"> | <img src="Sources/CodeIsland/Resources/cli-icons/traecli.png" width="16"> TraeCli | 10 | Terminal | Full |
| <img src="docs/images/mascots/qoder.gif" width="28"> | <img src="Sources/CodeIsland/Resources/cli-icons/qoder.png" width="16"> Qoder | 10 | IDE | Full |
| | <img src="Sources/CodeIsland/Resources/cli-icons/copilot.png" width="16"> Copilot | 6 | Terminal | Full |
| <img src="docs/images/mascots/factory.gif" width="28"> | <img src="Sources/CodeIsland/Resources/cli-icons/factory.png" width="16"> Factory | 10 | IDE | Full |
| <img src="docs/images/mascots/codebuddy.gif" width="28"> | <img src="Sources/CodeIsland/Resources/cli-icons/codebuddy.png" width="16"> CodeBuddy | 10 | APP/Terminal | Full |
| | <img src="Sources/CodeIsland/Resources/cli-icons/kimi.png" width="16"> Kimi Code CLI | 10 | Terminal | Full |
| <img src="docs/images/mascots/opencode.gif" width="28"> | <img src="Sources/CodeIsland/Resources/cli-icons/opencode.png" width="16"> OpenCode | All | APP/Terminal | Full |
| <img src="docs/images/mascots/cline.gif" width="28"> | <img src="Sources/CodeIsland/Resources/cli-icons/cline.png" width="16"> Cline | 5 | VSCode | Full |
| <img src="docs/images/mascots/claude.gif" width="28"> | <img src="Sources/UniIsland/Resources/cli-icons/claude.png" width="16"> Claude Code | 13 | Terminal tab | Full |
| <img src="docs/images/mascots/codex.gif" width="28"> | <img src="Sources/UniIsland/Resources/cli-icons/codex.png" width="16"> Codex | 3 | Terminal | Basic |
| <img src="docs/images/mascots/gemini.gif" width="28"> | <img src="Sources/UniIsland/Resources/cli-icons/gemini.png" width="16"> Gemini CLI | 6 | Terminal | Full |
| <img src="docs/images/mascots/cursor.gif" width="28"> | <img src="Sources/UniIsland/Resources/cli-icons/cursor.png" width="16"> Cursor | 10 | IDE | Full |
| <img src="docs/images/mascots/trae.gif" width="28"> | <img src="Sources/UniIsland/Resources/cli-icons/traecli.png" width="16"> TraeCli | 10 | Terminal | Full |
| <img src="docs/images/mascots/qoder.gif" width="28"> | <img src="Sources/UniIsland/Resources/cli-icons/qoder.png" width="16"> Qoder | 10 | IDE | Full |
| | <img src="Sources/UniIsland/Resources/cli-icons/copilot.png" width="16"> Copilot | 6 | Terminal | Full |
| <img src="docs/images/mascots/factory.gif" width="28"> | <img src="Sources/UniIsland/Resources/cli-icons/factory.png" width="16"> Factory | 10 | IDE | Full |
| <img src="docs/images/mascots/codebuddy.gif" width="28"> | <img src="Sources/UniIsland/Resources/cli-icons/codebuddy.png" width="16"> CodeBuddy | 10 | APP/Terminal | Full |
| | <img src="Sources/UniIsland/Resources/cli-icons/kimi.png" width="16"> Kimi Code CLI | 10 | Terminal | Full |
| <img src="docs/images/mascots/opencode.gif" width="28"> | <img src="Sources/UniIsland/Resources/cli-icons/opencode.png" width="16"> OpenCode | All | APP/Terminal | Full |
| <img src="docs/images/mascots/cline.gif" width="28"> | <img src="Sources/UniIsland/Resources/cli-icons/cline.png" width="16"> Cline | 5 | VSCode | Full |

## Installation

### Homebrew (Recommended)

```bash
brew tap wxtsky/tap
brew install --cask codeisland
brew install --cask uniisland
```

### Manual Download

1. Go to [Releases](https://github.com/wxtsky/CodeIsland/releases)
2. Download `CodeIsland.dmg`
3. Open the DMG and drag `CodeIsland.app` to your Applications folder
4. Launch CodeIsland — it will automatically install hooks for all detected AI tools
1. Go to [Releases](https://github.com/wxtsky/UniIsland/releases)
2. Download `UniIsland.dmg`
3. Open the DMG and drag `UniIsland.app` to your Applications folder
4. Launch UniIsland — it will automatically install hooks for all detected AI tools

> **Note:** On first launch, macOS may show a security warning. Go to **System Settings → Privacy & Security** and click **Open Anyway**.

Expand All @@ -78,35 +78,35 @@ brew install --cask codeisland
Requires **macOS 14+** and **Swift 5.9+**.

```bash
git clone https://github.com/wxtsky/CodeIsland.git
cd CodeIsland
git clone https://github.com/wxtsky/UniIsland.git
cd UniIsland

# Development (debug build + launch; Buddy Bluetooth needs the .app below)
swift build && ./.build/debug/CodeIsland
swift build && ./.build/debug/UniIsland

# Release (universal binary: Apple Silicon + Intel)
./build.sh
open .build/release/CodeIsland.app
open .build/release/UniIsland.app
```

## How It Works

```
AI Tool (Claude/Codex/Gemini/Cursor/...)
→ Hook event triggered
codeisland-bridge (native Swift binary, ~86KB)
→ Unix socket → /tmp/codeisland-<uid>.sock
CodeIsland app receives event
uniisland-bridge (native Swift binary, ~86KB)
→ Unix socket → /tmp/uniisland-<uid>.sock
UniIsland app receives event
→ Updates UI in real time
```

CodeIsland installs lightweight hooks into each AI tool's config. When the tool triggers an event (session start, tool call, permission request, etc.), the hook sends a JSON message through a Unix socket. CodeIsland listens on this socket and updates the notch panel instantly.
UniIsland installs lightweight hooks into each AI tool's config. When the tool triggers an event (session start, tool call, permission request, etc.), the hook sends a JSON message through a Unix socket. UniIsland listens on this socket and updates the notch panel instantly.

For **OpenCode**, a JS plugin connects directly to the socket — no bridge binary needed.

## Settings

CodeIsland provides a 7-tab settings panel:
UniIsland provides a 7-tab settings panel:

- **General** — Language, launch at login, display selection
- **Behavior** — Auto-hide, smart suppress, session cleanup
Expand All @@ -125,13 +125,21 @@ CodeIsland provides a 7-tab settings panel:

This project was inspired by [claude-island](https://github.com/farouqaldori/claude-island) by [@farouqaldori](https://github.com/farouqaldori). Thanks for the original idea of bringing AI agent status into the macOS notch.

### Open-Source Citations & References

UniIsland incorporates and builds upon capabilities inspired by the following excellent open-source utilities:
- **NotchDrop** ([GitHub](https://github.com/NotchDrop/NotchDrop)) — Inspiration for the dynamic file drop zone and temporary files panel logic.
- **Boring Notch** ([GitHub](https://github.com/lsw/Boring-Notch)) — References for media playback controllers, diagnostic monitors, and Pomodoro focus workflows.
- **Atoll** ([GitHub](https://github.com/atoll-app/Atoll)) & **DynamicNotch** ([GitHub](https://github.com/shobhit99/SuperIsland)) — Inspiration for modular settings and diagnostic activity HUD design layouts.
- **SuperIsland** ([GitHub](https://github.com/shobhit99/SuperIsland)) — Core references for system battery level animations, EventKit calendar lookup count-downs, and automated virtual meeting joining.

## Star History

<a href="https://www.star-history.com/?repos=wxtsky%2FCodeIsland&type=date&legend=bottom-right">
<a href="https://www.star-history.com/?repos=wxtsky%2FUniIsland&type=date&legend=bottom-right">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=wxtsky/CodeIsland&type=date&theme=dark&legend=top-left" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=wxtsky/CodeIsland&type=date&legend=top-left" />
<img alt="Star History Chart" src="https://api.star-history.com/chart?repos=wxtsky/CodeIsland&type=date&legend=top-left" />
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=wxtsky/UniIsland&type=date&theme=dark&legend=top-left" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=wxtsky/UniIsland&type=date&legend=top-left" />
<img alt="Star History Chart" src="https://api.star-history.com/chart?repos=wxtsky/UniIsland&type=date&legend=top-left" />
</picture>
</a>

Expand Down
Loading