An always-on desktop "dynamic island" host that knows only how to connect, push, and draw — with zero business logic. All data comes from independent, out-of-process plugins ("bricks"). The protocol is the product.
常驻桌面灵动岛宿主:只懂"怎么连、怎么推、怎么画",不含任何业务逻辑。一切数据来自独立进程的插件("积木")。协议即产品。
📸 Screenshot / demo coming soon. / 截图与演示稍后补上。
Isle is a floating, always-on-top island that sits at the top of your screen and aggregates live information at a glance — without you switching between N apps and terminals. The host is domain-blind: it never understands what your data means. Each brick runs in its own process, normalizes its data into one of a small set of render kinds, and pushes it to the host over SSE. The host only switches on kind and colors by tone. Built on Electron — Windows-first today, cross-platform-capable by design.
Isle 是一个浮于桌面顶部、常驻置顶的小岛,把实时信息聚合成"抬眼一瞥",免去在 N 个 app 与终端之间来回切换。宿主对数据域完全无知——它永远不知道你的数据是什么意思。每块积木在独立进程里运行,把自己的数据归一化成少数几种**渲染词表(render kind)**之一,通过 SSE 推给宿主。宿主只按 kind 分发、按 tone 上色。基于 Electron——当前以 Windows 为先,架构上跨平台可期。
brick (independent process) → normalized Signal bus → render kinds (host built-in) → island shell UI
The arrow is the coupling direction. A brick knows its data source + which render kind it emits; the host knows render kinds + how to draw them. The two never discuss domain meaning.
| frame | direction | shape |
|---|---|---|
| manifest | discovery | plugin.json in ~/.island/plugins/<id>/; declares port, emits, collapsed glyph/badge, optional actions, heartbeat, launch |
| signal | brick → host (SSE) | { kind, ts, data } |
| action | host → brick (POST /action) |
{ name } |
Transport is SSE (the host opens a long stream) + POST, not WebSocket — so a brick can be written in ~20 lines in any language.
| kind | shape the host sees |
|---|---|
list |
{ items: [{ text, state?, badge? }] } |
metrics |
{ items: [{ label, value, delta?, tone? }] }, tone ∈ up/down/flat |
status |
{ items: [{ label, state, tone?, detail? }] }, tone ∈ neutral/active/attention/error |
text |
{ blocks } or { text } |
control |
{ controls: [{ label, action }] } |
view |
{ html, controls? } (sandboxed iframe) |
state is an opaque string to the host; only tone carries meaning. The meaning→tone mapping lives in the brick.
A brick is just a process that (1) drops a manifest where the host can find it and (2) streams signal frames over SSE. No SDK, any language.
积木就是一个进程:(1) 把 manifest 放到宿主能发现的位置,(2) 通过 SSE 推 signal 帧。无需 SDK,任意语言皆可。
// server.js — then: node server.js (host discovers & connects automatically)
import http from 'node:http';
http.createServer((req, res) => {
if (req.url !== '/events') return void res.writeHead(404).end();
res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache' });
setInterval(() => {
const signal = { kind: 'text', ts: Math.floor(Date.now() / 1000),
data: { text: new Date().toLocaleTimeString() } };
res.write(`event: signal\ndata: ${JSON.stringify(signal)}\n\n`);
}, 1000);
}).listen(7820);
// Optional: accept POST /action for host → brick controls. / 可选:接 POST /action 收宿主控件回推。@isle/protocol— the wire contract + runtime guards (parseSignal/parseManifest). Versioned independently.@isle/host— the Electron + React island host: shell, Signal bus, render kinds, lifecycle.@isle/mock-brick— a scripted mock brick that exercises every render kind and the failure paths. It is the host's acceptance surface.
Requires Node ≥ 20. pnpm 9 is managed by Corepack — enable it once so pnpm is on your PATH (the scripts below shell out to pnpm). / 需 Node ≥ 20;pnpm 9 由 Corepack 管理,先一次性启用,让 pnpm 进 PATH(下面脚本会调用 pnpm)。
# one-time: put the pnpm 9 shim on PATH (Windows: run in an elevated shell, / 一次性:把 pnpm 9 shim 装到 PATH(Windows 需管理员终端,
# or `corepack enable --install-directory <dir>` into a folder you add to PATH) / 或 enable 到自定义目录再加进 PATH)
corepack enable pnpm
pnpm install
# build / typecheck / lint across all packages
pnpm build
pnpm typecheck
pnpm lint
# run host + mock together, one command / 一键同时起 host + mock
pnpm dev
# …or run them separately / 或分开起
pnpm dev:host # the host (Electron dev) / 宿主
pnpm dev:mock # the mock brick / mock 积木Host v1 reached the v0.1.0 milestone tag — protocol + bus + render kinds + shell + lifecycle, validated end-to-end by the scripted mock brick (every render kind plus all failure paths: reconnect, slow-response timeout, control→action, brick-offline), no real data source required. It's an internal milestone, not yet a published release — no real bricks ship with it.
宿主 v1 达到 v0.1.0 里程碑 tag —— 协议 + bus + 渲染词表 + 壳 + 生命周期,由脚本化 mock 积木端到端验收(六种 render kind 加全部失败路径:重连、慢响应超时、control→action、积木下线),无需真数据源。这是内部里程碑,尚非对外发布版本(不附带任何真积木)。
- v1 — Host ✅ milestone tagged
v0.1.0— protocol + bus + render kinds + shell + lifecycle, mock-all-green (not yet a published release). / 里程碑已打 tagv0.1.0——协议 + bus + 渲染词表 + 壳 + 生命周期,mock 全绿(尚非对外发布)。 - Next — Downstream bricks real bricks built on the protocol (prices, agents, notes). / 建在协议之上的真积木(行情、agent、笔记)。
- Later — Extension bricks & reach weather / wallpaper (exercising
control+view), and broader cross-platform support. / 天气 / 壁纸(验证control+view),以及更广的跨平台支持。
Tech stack: Electron + React + Framer Motion + TypeScript. Commits follow Conventional Commits (feat|fix|chore(scope): …, scope ∈ protocol/host/mock), and every PR ships a changeset. Read CLAUDE.md for the architectural invariants and docs/DESIGN.md for the rationale before opening a PR.
技术栈:Electron + React + Framer Motion + TypeScript。提交遵循 Conventional Commits,每个 PR 附带一个 changeset。开 PR 前请读 CLAUDE.md(不变量)与 docs/DESIGN.md(设计论证)。
MIT © 2026 Gavin