技术实现见 docs/handover/dashboard.md(看板系统)和 docs/handover/generative-ui.md(widget 渲染基础设施)
受 Moxt 启发。Moxt 定位为 AI-native workspace,核心洞察:
- AI 应该在原生格式里工作:md/csv/html/代码,而非 PDF/PPT/传统文档
- 文件系统是 AI 最熟悉的图书馆:层级目录 > 传统知识库的非结构化检索
- 0 摩擦:AI 处理信息带宽极大,1% 摩擦在 n 次幂后趋近于 0——必须保障每次通信零损耗
- Less Content is More Context(对组织而言):AI 产出远超人类,需要用 AI 习惯的方式维护内容
Moxt 实践中最具启发性的案例:直接在 Moxt 中用生成式 UI 替代了 Jira 看板——不是用 AI 操控旧看板,而是直接实现看板本身。"同样的信息和数据,你想怎么看就怎么看"。
当前 widget 绑死在聊天消息里。模型花大量 token 生成一个精心设计的图表或流程图,但用户下次需要类似内容时必须重新描述、重新生成。widget 的复用率为零。
打开一个项目,看到的是聊天列表——纯文本、线性、需要翻阅。用户无法一眼看到"这个项目现在什么状态"。对助理工作区尤其明显:memory.md 是纯文本,daily notes 分散在文件里,缺少一个整合的视觉入口。
生成式 UI 产出的图表和示意图质量很高,但只能在 CodePilot 内部看到。用户想把 AI 的分析结果发到社交媒体或分享给团队时,没有导出途径。
看板不是"保存的 widget 集合",而是 AI 对项目的理解在视觉维度上的投影。每个卡片背后是一个数据契约——"这个 widget 展示什么数据、数据从哪来"。每次打开或刷新时,AI 读取最新数据重新填入,布局和样式保持不变。
传统看板的思路:用户手动创建卡片 → 定义字段 → 拖拽排列 → 手动更新数据。
AI-first 的思路:
- AI 主动提议初始看板:首次打开时,AI 已经读过项目全部文件,直接提议一版看板。助理工作区 → 日程/待办/记忆摘要;代码项目 → 提交活动/TODO 分布/依赖状态。
- AI 自动推断数据契约:用户在聊天里 pin 一个 widget 时,AI 根据上下文自动推断数据来源和刷新方式,用户一键确认。
- AI 驱动更新:daily check-in 后 AI 顺便更新看板数据;对话中状态变化时 AI 建议同步到看板。
- AI 建议新卡片:用户连续多天提到某个话题,AI 主动提议新增对应卡片。
对话和看板不是割裂的两个界面,而是同一个 AI 理解的两种呈现:
- 对话 → 看板:好的 widget 一键固定;对话中提到的状态变化反映到看板
- 看板 → 对话:点击卡片发起相关话题对话;看板状态注入对话 context,AI 知道项目全貌
- 看板内对话:看板页面底部有输入框,用户可以对着看板说话——"把商单B标记为已签约"、"给我加一个本月支出统计"
保存的是 widget 代码 + 数据契约 + 数据源定义:
- widget 代码:原始 HTML/JS/CSS(作为"设计参考",保留布局和样式)
- 数据契约:自然语言描述,说明这个 widget 展示什么数据、如何从原始数据中提取
- 数据源:结构化定义,可以是文件路径、MCP tool 调用、CLI 命令、或它们的组合
每次刷新时,系统按数据源获取最新数据,把「原始代码 + 最新数据」喂给模型,模型只更新数据部分,保留布局和样式。
不做模板语法——模型天然理解"保持设计,换新数据"。
type DataSource =
| { type: 'file'; paths: string[]; query?: string }
| { type: 'mcp_tool'; server: string; tool: string; args: Record<string, unknown> }
| { type: 'cli'; command: string }
| { type: 'composite'; sources: DataSource[] }存在项目目录 .codepilot/dashboard/ 下:
- 跟着项目走,git 可追踪
- AI 在对话中可直接读写
- 每个项目天然隔离
- 符合 Moxt "文件系统是 AI 的图书馆"理念
用户可配,提供开关:
- 自动刷新:每次打开看板时调模型更新所有卡片(不在乎 token 的用户)
- 手动刷新:提供刷新按钮,用户按需触发(在乎 token 的用户)
附加优化:数据源文件 mtime 没变则跳过刷新,用上次缓存结果。
看板作为右侧面板,和 Git 面板、文件树面板、预览面板同级。理由:
- 项目级归属:看板是项目维度的,放在右侧面板天然和当前项目绑定,不需要改动左侧 Chat List 的层级结构
- 与聊天共存:用户可以边聊天边看看板,符合"对话 ↔ 看板飞轮"的交互模型
- 复用现有架构:ResizeHandle、PanelContext、TopBar toggle 按钮全部现成
面板宽度参数:
| 参数 | 值 |
|---|---|
| MIN_WIDTH | 320px |
| MAX_WIDTH | 800px |
| DEFAULT_WIDTH | 640px |
参考:预览面板 320-800px 默认 480px,看板默认值更大因为 widget 内容更丰富。640px 渲染图表和表格完全够用,类似 Claude Artifacts / Gemini 的侧边网页渲染宽度。
Widget 直接在面板内用 iframe 渲染,复用聊天中的 WidgetRenderer 组件。不做摘要模式、不做展开模式——桌面端空间充裕,用户拖窄面板导致样式问题是用户自己的选择,我们只保证默认宽度下体验良好。
看板不只是聊天 widget 的持久化。生成式 UI 应该成为 CodePilot 所有子系统的通用可视化出口。
┌─────────────┐
│ 看板 │ ← 持久化展示层
│ Dashboard │
└──────┬──────┘
│ pin / render / refresh
┌──────┴──────┐
│ 生成式 UI │ ← 通用渲染层
│ Widget 系统 │
└──────┬──────┘
┌──────┬───────┼───────┬──────┐
│ │ │ │ │
┌──┴──┐┌──┴──┐┌──┴──┐┌──┴──┐┌──┴──┐
│ Chat ││ MCP ││ CLI ││Skill││Bridge│
└─────┘└─────┘└─────┘└─────┘└─────┘
MCP 工具返回的结构化数据可以直接渲染为 widget。用户配的任何 MCP server(Notion/Linear/数据库等)都自动成为看板的潜在数据源。
场景:用户问"看看 Linear 里这周的 bug 统计" → 模型调 MCP tool → 返回 JSON → 渲染为柱状图 widget → 用户 pin 到看板 → 看板每次刷新时重新调 MCP tool。
生态杠杆巨大——社区几百个 MCP server,每一个都可以成为看板数据提供者。
CLI 工具的输出天然是结构化数据,适合可视化:
git log --stat→ 提交活动时间线docker ps→ 容器状态卡片npm audit→ 依赖安全仪表盘
CLI 数据源的刷新可以不调模型——命令输出格式稳定,首次生成后可以做纯前端解析。
最有想象力的组合。两个方向:
看板 → IM 推送:每日早上自动刷新看板 → 生成截图 → 通过桥接推送到 Telegram/飞书。从"打开才能看"变成"推到你面前"。这是"导出图片"的自动化版本。
IM → 看板更新:用户在 Telegram 里说"商单B签了" → 桥接收到 → AI 处理 → 更新数据源文件 → 看板状态随之更新。
Skill 变成 widget 工厂:
/weekly-report→ 产出周报 widget(含本周完成事项、关键指标、下周计划),可 pin 可导出/codebase-health→ 运行多个 CLI 工具后产出健康度仪表盘 widget
每个 skill 不只输出文字结论,还输出可持久化的视觉组件。
interface DashboardContext {
selectedDate?: string;
selectedItem?: { type: string; id: string };
filters?: Record<string, unknown>;
}每个 widget 声明 publish(我发布什么事件)和 subscribe(我订阅什么状态),通过 DashboardContext 中转,widget 之间不直接通信。
- 助理"我的一周":点日程表某天 → 右侧刷新当天详情 → 点详情某事项 → 下方进度卡片聚焦相关条目
- 代码"项目健康度":选提交 → 热力图高亮相关文件 → 点文件 → 展开 diff 摘要
- 内容"排期 + 数据":选已发布内容 → 显示表现数据;选未发布 → 显示草稿 + 优化建议
看板底部输入框,用户对着整个看板说话:
- "把商单B的状态更新为已签约" → 商单进度 widget 数据更新
- "这周三的会取消了" → 日程 widget 更新 + 数据源文件同步修改
- "给我加一个本月支出统计的卡片" → 新 widget 生成并添加
模型知道所有 widget 的数据契约和来源,可以精准修改。
| 维度 | Moxt | CodePilot 看板 |
|---|---|---|
| 定位 | 组织级 AI 原生办公室 | 个人级项目 AI 原生控制台 |
| 部署 | 云端 | 本地优先 |
| 协作 | 多 AI 同事 + 多人 | 单人 + 单 AI |
| 上下文深度 | 广但浅(文档为主) | 窄但深(在代码仓库内部,git/文件/运行时全可达) |
| 数据归属 | 云端 | 完全本地,不上传 |
| 优势场景 | 组织知识管理、多人协作 | 深度项目理解、开发者工作流、个人助理 |
我们不是在做"轻量版 Moxt",而是在做 "每个项目的 AI 原生控制台"。
| 阶段 | 内容 | 价值 |
|---|---|---|
| P0 | 聊天 → 看板核心链路(pin widget、看板展示、数据刷新) | 最小可用 |
| P0 | AI 自动推断数据契约 | AI-first 体验基础 |
| P1 | AI 主动提议初始看板 | 零配置上手 |
| P1 | MCP 数据源支持 | 生态杠杆,接入外部数据 |
| P1 | 看板 ↔ 对话双向联动 | 飞轮效应 |
| P1 | 导出图片 | 分享传播 |
| P2 | CLI 数据源支持 | 代码项目杀手功能 |
| P2 | 看板 → Bridge 推送 | 被动变主动 |
| P2 | widget 间点击联动 | 体验飞跃 |
| P2 | 对话式看板操控 | 终极交互形态 |
| P3 | Skill → Widget 工厂 | 锦上添花 |
| P3 | check-in 后自动更新看板 | 助理深度集成 |
- Token 成本:每次刷新都调模型,看板卡片多时 token 消耗显著。mtime 缓存可缓解但不能消除。
- 刷新延迟:模型生成 widget 需要几秒,多个卡片串行刷新体验差。需要并行刷新 + 骨架屏。
- 数据契约漂移:数据源文件结构变化后,原有数据契约可能失效。需要错误检测和自动修复机制。
- MCP 依赖:外部 MCP server 的稳定性不可控,看板卡片可能因 MCP 故障显示空白。
- 第三方 API Provider 限制:同现有 widget 系统——部分三方 provider 不处理 appendSystemPrompt,widget 功能可能不可用。
项目地址:chenglou/pretext 作者:chenglou(React 核心贡献者、Reason 语言作者)
纯 JS/TS 的多行文本测量与排版库。核心能力:不触发 DOM reflow 就能精确计算多行文本布局。
两阶段架构:
prepare(text, font):一次性分析——文本分段 + CanvasmeasureText()测量宽度 + 缓存。500 段文本约 19ms。layout(prepared, maxWidth, lineHeight):纯算术换行——基于缓存宽度做行折断。500 段文本约 0.09ms。
第二步是纯数学运算,零 DOM 操作,可在 resize/动画/虚拟化场景下高频调用。
语言支持极广:CJK、日文、阿拉伯文、泰文、缅甸文、emoji、混合双向文本,各语言有专门 corpus 测试。渲染目标不绑定 DOM——可渲染到 DOM、Canvas、SVG,计划支持服务端渲染。
1. 高质量图片导出
导出看板为图片(社交媒体分享)时,如果用 Canvas 渲染而非简单截图,文本排版是最大难题。Pretext 让我们在 Canvas 上精确排列多行文本,不需要 DOM。意味着:比截图更高质量的导出、文本位置/换行/对齐完全可控、未来服务端图片生成(定时推送到 IM)不依赖浏览器。
2. Widget 高度预计算(解决高度跳动)
当前最大 UX 痛点之一是 widget 高度跳动——iframe 加载前不知道高度,加载后突然撑开。如果 widget 文本内容已知,Pretext 可以在 iframe 加载前算出预期高度,提前分配空间,彻底消除跳动。
3. 看板布局引擎
看板排列多个 widget 卡片,每个卡片标题/描述文本长度不同。Pretext 可以不渲染就预计算所有卡片高度:无闪烁瀑布流布局、拖拽排序精确占位、响应式重排即时高度计算(0.09ms 级别)。
4. 异形布局 Widget
layoutNextLine() 支持每行不同宽度——文本可环绕图片、沿曲线排列、在不规则形状内流动。对生成式 UI 有价值:文本环绕图表的信息卡片、圆形/多边形内文字排版、瀑布流中的精确文本截断。
5. Widget 内部文本虚拟化
看板 widget 可能包含大量文本(一周日程、几十条商单)。如果 widget 内需要文本虚拟化(只渲染可见区域),Pretext 可提前算好所有文本行高,不需要把文本真的渲染到 DOM 里去测量。
作者在 thoughts.md 中的核心观点:"80% of CSS spec could be avoided if userland had better control over text." 主张把能力下放到 userland 而非无限扩展规范。这与我们的生成式 UI 理念一致——不用预设模板,让 AI 自由生成 HTML/SVG/JS,Pretext 为 AI 生成的代码提供强大的文本排版基础设施。
| 维度 | 情况 |
|---|---|
| 包大小 | 轻量,纯 TS,零运行时依赖 |
| 兼容性 | Chrome/Safari/Firefox 全通过精度测试 |
| 成熟度 | v0.0.2,早期但测试极严格(多语言 corpus + 跨浏览器精度验证) |
| 集成方式 | npm install @chenglou/pretext,ESM |
| 风险 | 版本早期,API 可能变动;核心架构已稳定 |
- P0-P1 不需要引入:看板核心链路用现有 iframe 渲染够用
- P2 值得引入:导出图片(Canvas + Pretext 高质量生成)、看板布局预计算(消除高度跳动)
- 远期关键依赖:服务端看板截图(Bridge 定时推送)的非 DOM 渲染方案
以下是 P0-P2 全部实现完成后的回顾,包含实际踩坑、设计取舍、以及对未来方向的重新审视。
| 阶段 | 内容 | 状态 | 备注 |
|---|---|---|---|
| P0 | 核心 pin → 展示 → 刷新 | ✅ | MCP 统一路径 |
| P0 | AI 自动推断数据契约 | ✅ | 在对话上下文中推断 |
| P1 | MCP 数据源支持 | ✅ | file / mcp_tool / cli 三种 |
| P1 | 看板 ↔ 对话双向联动 | ✅ | 标题点击 + context 注入 |
| P1 | 导出图片 | ✅ | Electron 隔离窗口截图 |
| P1 | AI 主动提议初始看板 | ⏸ 暂缓 | 时机不成熟 |
| P2 | CLI 数据源 | ✅ | 通过 bash tool 审批执行 |
| P2 | widget 间联动 | ✅ | pub/sub via postMessage |
| P2 | 对话式看板操控 | ✅ → 移除 | 输入框多余,聊天统一入口 |
| P2 | 看板 → Bridge 推送 | ⏸ 暂缓 |
整个开发过程中最严重的回归不是来自代码逻辑,而是来自修改 WIDGET_SYSTEM_PROMPT 中的格式示例。
原始格式块:
{"title":"snake_case_id","widget_code":"<raw HTML/SVG string>"}
我把 title 从 "snake_case_id" 改成 "Short human-readable title in the user's language" ——一个看似无害的改动——直接导致 GLM-5-Turbo 模型开始输出各种非标准 fence 格式(单反引号、分离的 json 代码块等),widget 全部渲染为 JSON 代码。
根因:模型把格式示例当作"应该长这样"的模板来模仿。当模板中的值从短字符串变成长描述性文本,部分模型会把整个格式块理解为"指导说明"而非"严格模板",从而在格式执行上放松。
修复:还原格式示例,把标题指导放到 rules 列表末尾。同时重写了 widget 解析器为 fence-agnostic(用 JSON brace matching 替代固定 regex),作为防御性改进。
教训:对模型行为有影响的 prompt 改动,必须像改数据库 schema 一样谨慎——在目标模型上做 A/B 测试,而不是"看起来合理就改"。
-
"只加 CSP"不等于安全。
connect-src 'none'阻断 fetch/XHR/WebSocket,但img-src *允许通过图片请求信道泄漏数据,will-navigate允许通过 top-level 导航泄漏。安全封堵必须覆盖所有出口通道。 -
auto-approved MCP 工具不能执行 shell 命令。即使是在对话上下文中,如果工具内部直接
execSync(),用户看到的审批界面只有 widgetId,完全不知道自己批准了什么命令。正确做法:MCP 工具返回命令文本,让模型通过 bash tool(有标准审批流程)执行。 -
导出 iframe 的
allow-same-origin是个陷阱。看起来"临时的所以安全",但 widget 脚本在 finalize 阶段执行时就已经拥有了 parent.document 访问权。最终采用 Electron 隔离 BrowserWindow 方案——独立进程、独立 partition、无 preload、导航阻断。
这次实现中最花时间的部分不是功能逻辑,而是 iframe 的各种行为边界:
- 排序:React 重排 keyed 元素会 detach+reattach DOM,对普通 div 无感,但 iframe 会重载。最终用 CSS
order解决。 - CDN 脚本:inline script 和 CDN script 的执行时序不可预测。模型生成的代码经常不按 guidelines 写 onload。receiver script 的 CDN 处理逻辑迭代了 5 个版本才稳定。
- 导出:sandbox iframe 不能
contentDocument,加allow-same-origin又有安全问题。foreignObject 方案抓不到 canvas 像素。最终转向 Electron native 截图。 - 高度同步:
body.scrollHeight是唯一可靠的高度来源,但固定高度容器 + content-box 会导致内容溢出底部 padding。
每个问题的最终解都不复杂,但找到它们的过程说明:iframe 作为隔离边界是一种妥协——它提供的不是完美的隔离,而是"在可接受的成本下足够好的隔离"。
看板的核心价值不在于"展示图表",而在于让 AI 持续了解项目状态。几个高价值场景:
1. 项目健康监控
让 AI 生成一组监控 widget——git 提交热力图、dependency 更新状态、test coverage 趋势——pin 到看板。每次打开项目,AI 通过 <active-dashboard> 知道这些指标,能在对话中主动提醒"你的 test coverage 这周下降了 3%"。
2. 外部数据源集成
配了 Linear/Notion MCP server 的用户可以 pin MCP 数据源 widget。"帮我可视化 Linear 里本周的 bug 统计" → 模型调 Linear MCP tool 获取数据 → 生成图表 → pin 到看板。刷新时模型自动调 MCP tool 获取最新数据。
3. CLI 输出可视化
git log --stat / docker ps / npm audit 这类命令输出变成持久化的可视化卡片。开发者不需要记命令、不需要手动看终端输出——AI 把它变成一目了然的图表。
4. 跨 widget 联动分析
筛选器 widget + 数据列表 widget 组合使用。点击筛选条件,相关数据自动过滤。这不是写死的联动逻辑,而是 AI 在生成 widget 时用 __widgetPublish / widget-filter API 实现的动态联动。
实现过程中总结的几个原则:
-
先修根因,再加防御。widget 渲染问题的根因是 prompt 格式示例被改动,但同时也暴露了解析器过于脆弱。两个都修:还原 prompt(修根因)+ fence-agnostic 解析器(加防御)。
-
安全是最后验证,不是最后添加。每个涉及代码执行的路径(iframe sandbox、export window、CLI 刷新)都在实现后被审查出安全问题。应该在设计阶段就列出所有出口通道并逐一封堵。
-
不要维护两条路径。最初设计了"API 路由 pin + MCP 对话 pin"两条路径。用户正确指出这增加维护成本和出错可能。统一到 MCP 一条路径后,代码量更少、行为更一致。
-
DOM 操作要考虑 iframe 的特殊性。对普通 div 有效的操作(React key 重排、setState 触发 re-render、DOM clone for screenshot)在 iframe 上都可能失效或产生副作用。
看板是 AI agent 的"工作台",不是用户的"仪表盘"。
传统仪表盘的设计思路是:用户定义指标 → 系统展示数据 → 用户看数据做决策。这是 human-first 的思路。
AI-first 的看板应该是:AI 在工作中产出的视觉工件的展示空间。AI 分析了代码就产出 coverage widget,AI 处理了 issue 就更新 issue 状态 widget,AI 做了 code review 就产出 diff 统计 widget。看板不是用户配置出来的——是 AI 工作过程中自然涌现出来的。
这个方向上还有几个关键的未解问题:
-
AI 什么时候应该主动更新看板? 对话中提到了相关数据就更新?每次 check-in 后自动更新?还是只在用户明确要求时更新?目前没有自动更新触发机制。
-
widget 的生命周期管理。看板卡片会越来越多,但没有"这个 widget 已经过时了"的检测。需要一种机制让 AI 或用户能识别和清理不再有价值的卡片。
-
多看板 / 看板视图。一个项目可能有多个关注维度——代码健康、产品指标、团队协作。当前是单一看板,未来可能需要分组或分页。
-
widget 的可编辑性。用户看到 widget 上的数据不对,目前只能在对话中说"帮我改一下"。能否直接在 widget 上双击编辑数值?这涉及到 widget 从"只读展示"变成"可交互表单"的架构转变。
-
widget 作为 AI 的"视觉记忆"。当 AI 看到看板上有一个"本周计划"widget,它应该能理解这些计划的完成状态,并在后续对话中主动跟进。这需要
<active-dashboard>注入的内容更丰富——不只是标题和数据契约,可能需要包含 widget 的核心数据摘要。
最终愿景:打开一个项目,看板上已经有 AI 根据项目特征自动生成的卡片。开始工作后,AI 在对话中产出的分析自然沉淀到看板。一天结束时,看板是 AI 今天帮你做了什么的视觉记录。第二天打开,AI 看着看板说:"昨天你要做的三件事还有一件没完成,要现在继续吗?"
这就是"AI 原生项目控制台"的含义——不是人配置给 AI 看的,是 AI 工作给人看的。
回顾 CodePilot 目前的能力拼图——聊天、MCP 工具生态、CLI 工具库、素材库、远程桥接、Skills、助理工作区、生成式 UI、看板——每一个功能独立看都有价值,但真正的力量在于它们开始互相连接。
看板的实现让我看到了这种连接的具体形态:
MCP 是血管。用户装一个 Linear MCP server,它不只是"对话中能查 issue"——它同时成为看板的数据源、widget 的数据提供者、bridge 推送的内容来源。一个 MCP 接入点辐射到整个系统。社区有几百个 MCP server,每个都是 CodePilot 生态的潜在新器官。
生成式 UI 是眼睛。在这之前,AI 的所有产出都是文字——用户需要用自己的脑子去"可视化"一段 JSON 或一份日志。widget 让 AI 有了"画出来给你看"的能力。这不是锦上添花——这是一种新的表达维度。一个 AI agent 如果只能说话不能画图,就像一个人只能打字不能画白板。
Bridge 是嘴巴。看板生成的可视化结果,通过 bridge 推到 Telegram/飞书,AI 的工作成果就从"打开才能看"变成了"推到你面前"。这关联到一个更大的问题:AI 的产出不应该被困在一个应用窗口里。
Skills 是手。每个 skill 不只是一段提示词模板——当 skill 可以产出 widget、widget 可以 pin 到看板、看板可以推到 IM,一个 skill 就变成了一条完整的自动化管线。/weekly-report 不只是生成一段文字,而是生成可视化周报 → pin 到看板 → 每周一自动推到团队群。
这些连接目前大部分还是潜在的——bridge 推送还没做,skill 产出 widget 还需要约定协议。但架构上的可能性已经打开了。CodePilot 不是一堆功能的集合,而是一个有循环的有机系统。
做完整个看板系统后,我对"AI 应该怎么和人交互"有了一些新的认识。
文字对话是必要的,但不充分。
当前 AI 产品的主流交互是对话——用户问,AI 答。这对"解答问题"足够了,但对"持续协作"远远不够。持续协作需要共享工作空间——双方都能看到、都能修改、状态持续保持的东西。传统软件用文档、看板、代码仓库来做这件事。AI 时代,这个共享工作空间应该是什么?
我认为生成式 UI 给出了一个方向:AI 产出的、人类可理解的、可持久化的视觉工件。不是文档(太重)、不是代码(人类不可直接理解)、不是纯文字(没有结构)——而是一个图表、一张卡片、一个交互式组件。
"同样的数据,你想怎么看就怎么看"
这是 Moxt 的核心理念,也是生成式 UI 最深刻的启示。传统 BI 工具的做法是:系统预定义 10 种图表类型,用户从中选一种,把数据拖进去。生成式 UI 的做法是:你用自然语言描述你想怎么看,AI 当场画出来。
这意味着展示层完全由用户定义。用户说"用环形图"就是环形图,说"用时间线"就是时间线,说"加一个筛选器"就加一个筛选器。开发者不需要预先实现各种图表组件——AI 生成 HTML/JS/CSS 就是最灵活的"组件库"。
做完看板后,我开始想一个更大的问题:如果我们把上下文搞对,是不是根本不需要预设的 UI?
想象一下:CodePilot 没有预先写死的"看板面板"、"Git 面板"、"文件树面板"。它只有一个空白的右侧区域和一个对话框。用户说"我想看 Git 状态",AI 生成一个 Git diff 可视化 widget。用户说"我想管理我的 TODO",AI 生成一个交互式 TODO list widget。用户说"帮我监控 Docker 容器",AI 生成一个实时状态面板。
每个"面板"都不是开发者预先实现的——而是 AI 根据用户需求实时生成的。开发者只需要保证三件事:
- 上下文完整:AI 能访问文件系统、Git、终端、MCP 工具、网络——所有它需要的数据源。
- 渲染能力完整:生成式 UI 能渲染任何 HTML/JS/CSS,包括图表、表格、表单、动画。
- 持久化能力完整:用户觉得好的 widget 能保存,下次打开还在。
其他一切——布局、样式、交互逻辑、数据展示方式——全部由 AI 根据用户的自然语言描述生成。
这当然是一个极端的设想。现实中预设 UI 仍然有价值——启动速度快、行为可预期、不消耗 token。但这个思考方向揭示了一个趋势:AI 应用的 UI 层会越来越薄,上下文层会越来越厚。
传统应用:厚 UI + 薄上下文(CRUD 界面 + 数据库查询) AI 应用:薄 UI + 厚上下文(渲染容器 + AI 生成内容 + 丰富的数据访问)
CodePilot 正在走这条路。聊天区是一个通用的文字渲染容器,WidgetRenderer 是一个通用的 HTML 渲染容器,看板是一个通用的持久化展示容器。它们不关心"展示什么"——这由 AI 决定。它们只关心"怎么安全地渲染和持久化"。
做这个项目让我重新理解了一件事:基础设施的价值不在于它能做什么,而在于它让什么成为可能。
一个 iframe sandbox + postMessage 通信协议,让任意 AI 生成的代码能在用户面前安全执行。 一个 MCP 工具注册 + 关键词门控机制,让 AI 在对话中按需获得新能力。 一个 JSON 文件 + 数据契约,让一次性的对话产物变成持久化的项目工件。
每一层都很简单。但堆叠起来,它们创造了一种新的人机协作模式——AI 不只是回答问题的工具,而是一个有视觉表达能力、有持久记忆、能接入外部世界的协作伙伴。
这只是开始。
以下是跳出看板功能本身,站在 CodePilot 整体产品的视角来看这一切意味着什么。
回头看 CodePilot 已经实现的所有子系统,表面上是独立的功能模块,但它们其实在回答同一个问题:怎样让 AI 成为一个完整的工作伙伴,而不是一个问答机器?
| 子系统 | 解决的问题 | AI 获得的能力 |
|---|---|---|
| CLI 工具库 | AI 知道要用工具但装不了 | 发现、安装、执行系统级工具 |
| MCP 生态 | AI 只能操作本地文件 | 接入任意外部服务(Linear、Notion、数据库…) |
| 助理工作区 | 对话结束 AI 就失忆 | 持久人格、长期记忆、每日复盘 |
| 素材库 | AI 生成的图片/音频散落各处 | 统一媒体管理、跨会话复用 |
| 生成式 UI | AI 只能用文字解释 | 用图表、流程图、交互组件"画"出来 |
| 看板 | 对话中的好东西是一次性的 | 持久化视觉工件、持续追踪项目状态 |
| 远程桥接 | 用户必须坐在电脑前 | 通过 Telegram/飞书/Discord 远程指挥 AI |
| Skills | 重复的工作流每次都要重新描述 | 封装成可复用的"技能包",一键触发 |
把这张表竖着看:AI 获得了工具使用能力、外部世界连接能力、记忆能力、视觉表达能力、持久化能力、远程通信能力、程序化工作流能力。
这不是一个"聊天应用加了很多功能"。这是一个 AI agent 的运行时环境——和操作系统为程序提供的能力类似,CodePilot 为 AI 提供了感知、记忆、行动、表达的完整能力栈。
在所有子系统中,MCP 扮演着特殊角色。它不是一个"功能"——它是一个能力扩展协议。
CLI 工具库通过 MCP 暴露工具管理能力。看板通过 MCP 暴露 pin/refresh/update 能力。素材库通过 MCP 暴露图片生成和导入能力。Widget 系统通过 MCP 暴露设计指南加载能力。
这意味着每新增一个 MCP server,AI 同时获得了在对话中使用它、在看板中展示它的数据、通过 bridge 远程触发它的能力。能力不是线性增长的——是组合增长的。
社区有几百个 MCP server。一个 Linear MCP server 接入 CodePilot 后,AI 可以:
- 在对话中查询 issue(MCP 基本能力)
- 生成 issue 统计图表(生成式 UI)
- 把图表 pin 到看板持续追踪(看板 MCP)
- 定期刷新数据(看板刷新机制)
- 在飞书群里推送周报图表(Bridge + 导出)
- 一键触发完整流程(Skills 封装)
一个 MCP 接入点,六个价值输出通道。这才是"生态杠杆"的含义。
传统 AI 聊天产品的心智模型是:用户发问 → AI 回答 → 对话结束。CodePilot 正在变成另一种东西:用户描述意图 → AI 在一个持久环境中持续工作。
这个"持久环境"包含:
- 工作空间:文件系统、Git 仓库、CLI 工具——AI 的操作对象
- 记忆:助理工作区的 soul/user/memory 文件——AI 知道"我是谁、用户是谁、我们在做什么"
- 视觉空间:看板上的 widget——AI 的工作成果可视化
- 外部连接:MCP server + Bridge——AI 能触达的外部世界
在这个环境中,"对话"只是 AI 和人类之间的通信通道之一,不是唯一通道。AI 还可以通过看板展示、Bridge 消息推送、文件系统修改来和用户"沟通"。
insights/cli-tools.md 提到了一个关键趋势:CLI 正在成为 AI Agent 时代的标准接口。ElevenLabs、Stripe、网易云音乐都在做 Agent-first 的 CLI。
这意味着未来的软件服务会越来越多地提供 CLI/MCP 接口,而非(或不仅仅是)GUI。对 CodePilot 来说,这是巨大的利好——每个新的 CLI 工具和 MCP server 都自动扩展了 AI 的能力范围,而 CodePilot 已经有了完整的基础设施来消费这些能力。
CLI 工具的 Agent 兼容度评分系统(5D:Agent 原生设计 / JSON 输出 / Schema 自省 / Dry Run / 上下文友好)本质上是在回答:这个工具对 AI 来说有多"好用"? 随着更多工具为 AI 优化,CodePilot 作为 AI 的"工作台"价值会不断放大。
传统软件生态:开发者写应用 → 用户安装使用 → 应用有固定的 UI 和功能
AI 时代的新模式:用户描述需求 → AI 生成 widget → widget 就是"应用"
一个 widget 可以是一个待办清单、一个项目监控面板、一个数据分析报表、一个交互式筛选器。它由 AI 根据上下文实时生成,天然适配用户的具体需求。不需要去应用商店搜索,不需要学习新软件——用自然语言描述你要什么,AI 当场造出来。
看板让这些"AI 造的应用"有了持久化的生命:它们不再是对话中一闪而过的气泡,而是项目工作空间的一部分,每天都在那里,随数据更新。
这其实是一种新的软件分发方式:不是下载安装,而是描述生成。
把所有这些连在一起看,CodePilot 给用户开启了一种全新的工作方式:
独立开发者 / 创作者:
- 打开项目 → 看板上是 AI 自动维护的项目健康度、依赖状态、TODO 追踪
- 在飞书/Telegram 上说"看看今天的 issue 情况" → AI 生成图表推送过来
- 写代码时遇到问题 → 对话中 AI 直接画出架构图帮你理解
- 做完一天的工作 → AI 自动更新看板上的进度,写入每日记忆
小团队:
- 看板作为团队共享的项目状态面板(.codepilot/dashboard 可以 git 追踪)
- 每个人的 CodePilot 看到的是同一份看板数据
- AI 根据不同人的角色(soul.md)以不同方式解读同一份数据
个人助理场景:
- 助理工作区 + 看板 = AI 原生的个人管理系统
- "帮我做一个本月商单进度看板" → AI 读取你的文件,生成追踪面板
- "商单 B 签了" → AI 更新数据源文件 → 看板自动刷新
核心价值主张不是"我们有 N 个功能",而是"你用自然语言描述你想要什么样的工作环境,AI 帮你构建出来"。
回到那个激进的问题:是不是只要搞定上下文,所有的设置和展示方式都可以由用户自己定义?
答案比"是"或"否"更微妙。
用户不想"配置"——他们想"描述"。"帮我做一个看板,追踪我的 GitHub stars 和 issue 数量"和"在设置页面创建一个新面板,添加两个数据源,选择图表类型,配置刷新频率"——同一个目标,前者是自然语言描述,后者是传统配置界面。
CodePilot 的架构已经在朝这个方向走了:
- 生成式 UI 让"展示方式"由用户用自然语言定义
- MCP 让"数据来源"由用户用自然语言指定
- 看板让"持久化什么"由用户用自然语言决定
- Skills 让"工作流程"由用户用自然语言封装
还缺什么?缺的是上下文的深度和广度:
- AI 还不够了解项目的全部状态(只有 working_directory 下的文件)
- AI 还不够了解用户的完整意图(只有当前对话 + 助理记忆)
- AI 还不能持续观察变化(只有手动触发的刷新,没有事件驱动的自动感知)
当这些上下文补齐,真正的"用户定义一切"才会实现。到那时,CodePilot 不再是一个"有很多功能的 AI 聊天工具"——它是一个AI 原生操作系统,用户用自然语言"编程"它要做什么、监控什么、展示什么、推送什么。
开发者的工作不再是写"功能",而是写"能力基础设施"——更好的上下文获取、更安全的代码执行、更可靠的持久化、更丰富的渲染。功能本身,由 AI 和用户在对话中共同创造。