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
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ It connects to **14 AI coding tools** via Unix socket IPC, displaying session st
## Features

- **Notch-native UI** — Expands from the MacBook notch, collapses when idle
- **14 AI tools supported** — Claude Code, Codex, Grok CLI, Gemini CLI, Cursor, Copilot, Trae/Traecli, Qoder, Factory, CodeBuddy, OpenCode, Kimi Code CLI, Cline, Pi / Oh My Pi
- **15 AI tools supported** — Claude Code, Codex, Grok CLI, Gemini CLI, Cursor, Copilot, Trae/Traecli, Qoder, Factory, CodeBuddy, OpenCode, Kimi Code CLI, Cline, Pi / Oh My Pi, DeepSeek Harness
- **Live status tracking** — See active sessions, tool calls, and AI responses in real time
- **Permission management** — Approve/deny tool permissions directly from the panel
- **Question answering** — Respond to agent questions without leaving your current app
Expand Down Expand Up @@ -57,6 +57,7 @@ It connects to **14 AI coding tools** via Unix socket IPC, displaying session st
| <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="Sources/CodeIsland/Resources/cli-icons/pi.png" width="16"> Pi / Oh My Pi | 8 | Terminal | Full |
| | <img src="Sources/CodeIsland/Resources/cli-icons/dsh.png" width="16"> DeepSeek Harness | 9 | Terminal | Full |

## Installation

Expand Down Expand Up @@ -118,6 +119,14 @@ CodeIsland installs lightweight hooks into each AI tool's config. When the tool

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

For **DeepSeek Harness (DSH)**, the [dsh-island](https://github.com/cdxiaodong/dsh-island) cordis plugin listens to DSH's built-in events (`session/created`, `tools/pre-execute`, `approval/request`, …) and writes the same JSON over the Unix socket. Install it inside DSH:

```bash
dsh plugin --profile <profile> add github:cdxiaodong/dsh-island
```

DSH is plugin-native, so no hook configuration is installed — CodeIsland only needs to know the `dsh` source name to render its session card.

## Settings

CodeIsland provides a 7-tab settings panel:
Expand Down
11 changes: 10 additions & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ CodeIsland 住在你 MacBook 的刘海区域,实时展示 AI 编码 Agent 的
## 功能特性

- **刘海原生 UI** — 从 MacBook 刘海处展开,空闲时自动收起
- **支持 14 种 AI 工具** — Claude Code、Codex、Grok CLI、Gemini CLI、Cursor、Copilot、Trae/Traecli、Qoder、Factory、CodeBuddy、OpenCode、Kimi Code CLI、Cline、Pi / Oh My Pi
- **支持 15 种 AI 工具** — Claude Code、Codex、Grok CLI、Gemini CLI、Cursor、Copilot、Trae/Traecli、Qoder、Factory、CodeBuddy、OpenCode、Kimi Code CLI、Cline、Pi / Oh My Pi、DeepSeek Harness
- **实时状态追踪** — 查看活跃会话、工具调用和 AI 回复
- **权限管理** — 直接在面板上审批/拒绝工具权限请求
- **问题回答** — 无需离开当前应用即可回答 Agent 的问题
Expand Down Expand Up @@ -57,6 +57,7 @@ CodeIsland 住在你 MacBook 的刘海区域,实时展示 AI 编码 Agent 的
| <img src="docs/images/mascots/opencode.gif" width="28"> | <img src="Sources/CodeIsland/Resources/cli-icons/opencode.png" width="16"> OpenCode | All | APP/终端 | 完整 |
| <img src="docs/images/mascots/cline.gif" width="28"> | <img src="Sources/CodeIsland/Resources/cli-icons/cline.png" width="16"> Cline | 5 | VSCode | 完整 |
| | <img src="Sources/CodeIsland/Resources/cli-icons/pi.png" width="16"> Pi / Oh My Pi | 8 | 终端 | 完整 |
| | <img src="Sources/CodeIsland/Resources/cli-icons/dsh.png" width="16"> DeepSeek Harness | 9 | 终端 | 完整 |

## 安装

Expand Down Expand Up @@ -118,6 +119,14 @@ CodeIsland 在每个 AI 工具的配置中安装轻量级 hooks。当工具触

**OpenCode** 使用 JS 插件直接连接 socket,无需 bridge 二进制。

**DeepSeek Harness(DSH)** 通过 [dsh-island](https://github.com/cdxiaodong/dsh-island) cordis 插件接入:插件监听 DSH 内置事件(`session/created`、`tools/pre-execute`、`approval/request` 等),把同样的 JSON 写入 Unix socket。在 DSH 内安装:

```bash
dsh plugin --profile <profile> add github:cdxiaodong/dsh-island
```

DSH 是插件原生运行时,因此无需安装任何 hook 配置 —— CodeIsland 只需识别 `dsh` source 即可渲染它的会话卡片。

## 设置

CodeIsland 提供 7 个标签页的设置面板:
Expand Down
36 changes: 35 additions & 1 deletion Sources/CodeIsland/ConfigInstaller.swift
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,19 @@ struct ConfigInstaller {
format: .none,
events: []
),
// DSH (DeepSeek Harness) — cordis plugin runtime ("everything is a
// plugin"). No shell hooks: the dsh-island plugin
// (github:cdxiaodong/dsh-island) listens to DSH's built-in events and
// forwards them over the CodeIsland socket directly. CodeIsland only
// needs the source name so DSH events render as their own session card.
CLIConfig(
name: "DeepSeek Harness",
source: "dsh",
configPath: ".dsh",
configKey: "",
format: .none,
events: []
),
// ZCode (Z.ai) — Electron desktop app, NOT a Claude Code fork. Reads
// hooks from ~/.zcode/cli/config.json (strict event whitelist, no
// hot-reload — see `.zcode` HookFormat doc for details) (#245).
Expand Down Expand Up @@ -935,7 +948,7 @@ struct ConfigInstaller {
if !installHermesHooks(fm: fm) { ok = false }
} else if cli.format == .zcode {
if !installZcodeHooks(fm: fm) { ok = false }
} else if cli.source == "pi" || cli.source == "omp" || cli.source == "openclaw" {
} else if cli.source == "pi" || cli.source == "omp" || cli.source == "openclaw" || cli.source == "dsh" {
continue
} else {
if !installExternalHooks(cli: cli, fm: fm) { ok = false }
Expand Down Expand Up @@ -992,6 +1005,8 @@ struct ConfigInstaller {
uninstallOmpExtension(fm: fm)
} else if cli.source == "openclaw" {
uninstallOpenclawPlugin(fm: fm)
} else if cli.source == "dsh" {
// DSH is bridged via the dsh-island plugin; no shell hooks to remove.
} else {
uninstallHooks(cli: cli, fm: fm)
}
Expand All @@ -1013,6 +1028,7 @@ struct ConfigInstaller {
if source == "pi" { return isPiExtensionInstalled(fm: FileManager.default) }
if source == "omp" { return isOmpExtensionInstalled(fm: FileManager.default) }
if source == "openclaw" { return isOpenclawPluginInstalled(fm: FileManager.default) }
if source == "dsh" { return isDshInstalled() }
if source == "traecli" { return isTraecliHooksInstalled(fm: FileManager.default) }
if source == "hermes" { return isHermesHooksInstalled(fm: FileManager.default) }
if source == "zcode" { return isZcodeHooksInstalled(fm: FileManager.default) }
Expand All @@ -1030,6 +1046,13 @@ struct ConfigInstaller {
if source == "pi" { return FileManager.default.fileExists(atPath: piAgentDir) }
if source == "omp" { return FileManager.default.fileExists(atPath: ompAgentDir) }
if source == "openclaw" { return FileManager.default.fileExists(atPath: openclawDir) }
if source == "dsh" {
// DSH harness home defaults to ~/.dsh (override with $DSH_HOME).
if let home = ProcessInfo.processInfo.environment["DSH_HOME"], !home.isEmpty {
return FileManager.default.fileExists(atPath: home)
}
return FileManager.default.fileExists(atPath: NSHomeDirectory() + "/.dsh")
}
if source == "grok" { return FileManager.default.fileExists(atPath: grokHome()) }
if source == "copilot" { return FileManager.default.fileExists(atPath: NSHomeDirectory() + "/.copilot") }
if source == "cline" {
Expand All @@ -1053,6 +1076,17 @@ struct ConfigInstaller {
return FileManager.default.fileExists(atPath: cli.dirPath)
}

/// DSH (DeepSeek Harness) is bridged via the dsh-island plugin
/// (`dsh plugin add github:cdxiaodong/dsh-island`). CodeIsland cannot
/// introspect the cordis plugin store, so "installed" means the harness is
/// present on this machine — its plugin wiring is the user's responsibility.
static func isDshInstalled() -> Bool {
if let home = ProcessInfo.processInfo.environment["DSH_HOME"], !home.isEmpty {
return FileManager.default.fileExists(atPath: home)
}
return FileManager.default.fileExists(atPath: NSHomeDirectory() + "/.dsh")
}

// Keep backward compat
static func isCodexInstalled() -> Bool { isInstalled(source: "codex") }

Expand Down
1 change: 1 addition & 0 deletions Sources/CodeIsland/NotchPanelView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2918,6 +2918,7 @@ private let cliIconFiles: [String: String] = [
"omp": "pi",
"opencode": "opencode",
"cline": "cline",
"dsh": "dsh",
// Rendered from the in-house pixel mascots via
// MascotRenderHarness/testRenderCliIcons (MASCOT_ICON_DIR=…).
"kiro": "kiro",
Expand Down
Binary file added Sources/CodeIsland/Resources/cli-icons/dsh.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions Sources/CodeIslandCore/Models.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ public enum CLIProcessResolver {
return lowercasedPath.hasSuffix("/codex") || lowercasedPath.contains("/codex ")
case "claude":
return lowercasedPath.hasSuffix("/claude") || lowercasedPath.contains("/claude ")
case "dsh":
// DeepSeek Harness CLI ships a `dsh` binary. It has no shell hooks —
// the dsh-island plugin forwards events over the socket directly.
return lowercasedPath.hasSuffix("/dsh") || lowercasedPath.contains("/dsh ")
case "qwen":
return lowercasedPath.hasSuffix("/qwen")
|| lowercasedPath.hasSuffix("/qwen-code")
Expand Down
1 change: 1 addition & 0 deletions Sources/CodeIslandCore/SessionSnapshot.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public struct SessionSnapshot: Sendable {
"pi",
"kiro",
"cline",
"dsh",
"zcode",
]

Expand Down