内容
<div align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/lukaisailovic/openislands/main/apps/docs/public/logo-light.svg">
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/lukaisailovic/openislands/main/apps/docs/public/logo-dark.svg">
<img alt="OpenIslands" src="https://raw.githubusercontent.com/lukaisailovic/openislands/main/apps/docs/public/logo-light.svg" width="84" height="84">
</picture>
# OpenIslands
**由 AI 代理构建和维护的仪表盘,数据存储在本地机器上。**
指向一个文件夹中的文件,AI 代理会构建一个类型化的、持久的仪表盘,并持续维护数月,数据发生变化时也能保持健康。无需云服务,无需账户,无需渲染代码。
<p>
<a href="./LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/License-MIT-2dd4bf.svg"></a>
<img alt="Node >= 20" src="https://img.shields.io/badge/Node-%3E%3D_20-2dd4bf.svg">
<img alt="ESM only" src="https://img.shields.io/badge/Module-ESM-2dd4bf.svg">
<img alt="Status: alpha" src="https://img.shields.io/badge/Status-alpha-f59e0b.svg">
<a href="./CONTRIBUTING.md"><img alt="PRs welcome" src="https://img.shields.io/badge/PRs-welcome-2dd4bf.svg"></a>
</p>
<p>
<a href="#quickstart">快速开始</a> ·
<a href="#why-openislands">为什么选择 OpenIslands</a> ·
<a href="#how-it-works">工作原理</a> ·
<a href="#islands">Islands</a> ·
<a href="#documentation">文档</a> ·
<a href="./CONTRIBUTING.md">贡献</a>
</p>
</div>
---
AI 代理擅长于一次性构建仪表盘。但当列名更改、新的导出数据到来、或者提出新的问题时,生成的应用程序就会悄悄地崩溃或更糟糕地继续呈现错误的数据。OpenIslands 解决了代理不擅长的部分:保持仪表盘的活跃。
它是一个本地优先的编译器和运行时。应用程序是一个类型化的 **manifest**,由可重用的视觉 **islands**(KPI 卡、图表、表格、仪表、时间线)绑定到 **typed data contracts**,这些 contracts 是从您的文件中构建的。您的代理编辑 manifest,而不编辑渲染代码,通过一个管道来验证、差异化和回滚每个更改。当数据和 island 发生冲突时,构建会大声失败并命名 island 而不是绘制错误的内容。
## 快速开始
为项目搭建脚手架,然后在文件上提供服务:
```bash
npx openislands init my-dashboard # 空白启动器(空模板)
cd my-dashboard
npx openislands serve # http://127.0.0.1:4321
```
如果不带标志,`init` 会为 `empty` 模板搭建脚手架:一个空白启动器,您可以从自己的文件开始构建。想要一个填充的示例吗?传递 `--template finance`(旗舰:净资产、分配、持有和来自您拥有的 CSV 的交易)。`health` 和 `operations` 也已发货。
现在将 MCP 服务器添加到您选择的工具(Claude Code、Cursor 和朋友)中,指向项目目录:
```jsonc
// .mcp.json
{
"mcpServers": {
"openislands": {
"command": "npx",
"args": ["-y", "@openislands/mcp", "."]
}
}
}
```
然后直接问:
> 将 `data/spending.csv` 放入项目中,并添加一个图表,显示按类别划分的每月支出。
代理读取您的数据,提出更改建议,以便您在写入任何内容之前看到差异,应用更改并保留上一个版本的快照,如果结果不正确则回滚。保持 `serve` 运行,页面会在每个编辑落地时通过 SSE 进行实时更新。
### 代理和技能
`init` 为您设置了此功能。每个 scaffolded 项目都附带一个本地 `.mcp.json`、一个 `AGENTS.md` 和 OpenIslands 技能下的 `.agents/skills/openislands/`,因此打开文件夹的代理会拾取 MCP 工具和约定,而无需额外的布线。
您想在另一个项目或您自己的代理设置中使用该技能吗?在任何地方安装它:
```bash
npx skills add lukaisailovic/openislands --skill openislands
```
或者完全跳过脚手架,让代理通过一次粘贴来驱动:
> 阅读 https://openislands.sh/start.md,然后帮助我构建我的第一个由代理维护的仪表盘。
## 为什么选择 OpenIslands
| | |
|---|---|
| **您的数据,您的磁盘** | 您拥有的普通文件。无需帐户,无需云,无需登录。 |
| **构建以持久** | 来自封闭注册表的类型化岛屿。没有 300 行 React 组件会腐烂。 |
| **代理维护** | CLI 和 MCP 服务器,因此 Claude Code 或 Cursor 构建仪表盘并保持其健康。 |
| **失败时发出大声警告** | 将岛屿绑定到不存在的字段,验证停止并出现命名错误。您永远不会得到一个悄悄地错误地绘制的图表。 |
| **始终在线** | 编辑 manifest 或添加新的导出,仪表盘会根据您的实时文件更新。无需重建,无需快照来漂移。 |
它不是一个托管的应用程序构建器或 BI 平台。它是类型化的、基于文件的层,您的代理可以安全地编辑。
## 工作原理
```text
文件(CSV / JSON / Parquet / md)
│
▼
DuckDB 查询核心 ── 运行转换 + 查询实时 ──┐
│ │
manifest(类型岛屿) ──► 服务运行时 ──► 您的仪表盘
(TanStack Start SSR) ▲
│ SSE 文件更改 → 岛屿重新获取
AI 代理 ──(MCP:提出 → 验证 → 差异 → 应用 → 回滚)──┘
```
最小的合约首先是各个部分:
| 包 | 角色 |
|---|---|
| `@openislands/schema` | 基石。Zod 模式用于 manifest 和岛屿,作为 TypeScript 类型和 JSON 模式发出,用于编辑器自动完成和代理接地。所有其他功能都依赖于它。 |
| `@openislands/compiler` | DuckDB 查询核心。将文件转换为类型化的数据合约,运行转换和查询实时,并检查每个岛屿绑定是否与数据匹配。 |
| `@openislands/runtime` | 岛屿注册表和 `serve` 背后的渲染器(TanStack Start SSR + React 岛屿 + 实时更新)。 |
| `openislands` | CLI:`init`、`validate`、`serve`、`add`、`infer`。 |
| `@openislands/mcp` | MCP 服务器。读取多个,写入一个,以便代理编辑 manifest 而不会破坏它。 |
## 岛屿
岛屿是一个可重用的、类型化的视觉块。您在 manifest 中声明它,将它绑定到您数据中存在的字段,运行时就会渲染它。内置功能涵盖了大多数仪表盘:
- **指标和仪表**: KPI 卡、记分卡、目标环、仪表、状态网格。
- **图表**: 线形、柱形、组合和饼图,按时间或类别划分。
- **表格和信息流**: 可排序的网格和活动信息流。
- **内容和布局**: Markdown 注释、富文本编辑器和分组岛屿的行。
需要注册表中没有的东西吗?在 `components/custom/` 下添加一个渲染器,并像其他岛屿一样绑定它。完整的目录,包括必填字段和实时预览,在 [docs](#documentation) 中。
## 模板
仓库中附带三个模板,同一个引擎渲染所有这些模板,没有特定于领域的黑客:
- **`finance`**:净资产、投资组合分配、持有、交易。
- **`health`**:宏量、生物标志物和可穿戴设备(与 [health-mcp](https://github.com/lukaisailovic/health-mcp) 配套)。
- **`operations`**:一个非个人模板,证明了岛屿集的广度。
## 使用 Docker 自主托管
想让它始终在线 — 在家用服务器或 NAS 上,通过远程代理访问?运行发布的镜像。一个进程提供仪表盘 **和** MCP 服务器(通过 Streamable HTTP)在一个端口上。将单个应用程序或工作区目录挂载到 `/project`:
```bash
# MCP 是写入表面,因此它需要一个令牌:
docker run -d -p 127.0.0.1:4321:4321 \
-e OPENISLANDS_MCP_TOKEN="$(openssl rand -hex 32)" \
-v "$PWD/my-dashboard:/project" \
ghcr.io/lukaisailovic/openislands:latest
```
然后打开 [127.0.0.1:4321](http://127.0.0.1:4321)。要跨 LAN 访问它,请绑定 `0.0.0.0` 并保持令牌设置;对于没有代理写入路径的仅仪表盘容器,请设置 `OPENISLANDS_MCP=0` 以无令牌启动。有关完整指南,请参阅 [自托管](https://openislands.sh/self-hosting)。
## 状态
Alpha 版本,实时优先。模式、编译器、运行时、CLI、MCP 服务器和所有三个模板今天都有效,并且 `pnpm test` 为绿色。v1 中没有静态导出:`serve` 启动生产运行时,并根据每个请求查询您的文件。托管的发布/同步层可能会在以后推出。
## 文档
- [数据应用模型](./docs/data-app-model.md):manifest、岛屿目录、数据合约和工作区。
- [代理编辑循环](./docs/agent-edit-loop.md):读取多个、写入一个的 MCP 循环、操作、查询和连接器。
- [贡献](./CONTRIBUTING.md):添加岛屿、PR 门控、发布。
完整的文档站点位于 [`apps/docs`](./apps/docs)(使用 TanStack Start 上的 Fumadocs 构建,静态部署到 Cloudflare Workers)。
## 开发
```bash
pnpm install
pnpm build # 跨包的 tsdown(rolldown / Oxc)
pnpm test # vitest
pnpm typecheck # tsc --noEmit 每个包
pnpm lint # oxlint
pnpm validate:templates # 每个模板的 manifest + 绑定
pnpm demo # 在本地提供 finance 模板服务
```
工具链:pnpm + Turborepo + Changesets,tsdown 用于构建,oxlint 和 oxfmt 用于 lint/format,Vitest,Node ≥ 20,仅 ESM。请参阅 [CONTRIBUTING.md](./CONTRIBUTING.md)在打开 PR 之前。
## 许可证
[MIT](./LICENSE) © Luka Isailovic