Expo Team Unveils Exact Cross-Platform UI Framework

Original title: Exact – a new cross platform UI framework by the Expo team
78AI Score

The Expo team has released Exact, a cross-platform UI framework that runs the same code natively on web, macOS, iOS, and Linux, and is explicitly designed for AI coding agents to build, run, observe, and test apps. In a demo, Claude Code built a todo app and passed tests on all three platforms in about 57 minutes, with 26 KB of code versus React's 81 KB and roughly 99 ms edit latency.

Full Report

Contents3 sections

Exact

应用只写一次。它就能以原生方式运行在 Web、macOS、iOS 和 Linux 上,而 AI agent 可以在每一个平台上构建它、运行它、查看它并测试它。

[!TIP] 用编码 agent 试一试。 在一台已安装 Xcode、Rust、Bun 和 Chrome 的 Mac 上,把下面这段提示词交给 Claude Code:

TEXT
Clone https://github.com/expo/exact and follow its README to make a new Exact
app with `exact new`. Run `bun scripts/exact.mjs setup` once first. Make a todo
list where I can add items, check them off, delete them,
and see how many are left. Put the view in Contract and keep the list in `app.ts`.
Write an `app.test.contract`, pass it on web, macOS, and the iOS Simulator with
`scripts/agent.mjs`, then open the app for me on all three.

在一个干净的克隆上,一个全新的 agent 拿到这段提示词的早期版本(Hermes 已在机器缓存中,Cargo 缓存已预热),大约 57 分钟就完成了,而且它的测试在三个平台上全部通过。其中约 25 分钟花在首次 macOS 和 iOS 构建上,各约 13 分钟;之后的构建只需一两分钟。在缺少 Hermes 的机器上,会先进行源码构建,从而增加耗时。当前的安装流程改为一次性下载并校验固定版本的 host/iOS bundle;日常构建则保持离线。

<table> <tr> <th>Web</th> <th>iOS</th> <th>macOS</th> </tr> <tr valign="top"> <td><img src="docs/screenshots/softwear-web.webp" width="360" alt="Softwear 的连帽衫页面在 Chrome 中的显示"></td> <td><img src="docs/screenshots/softwear-ios.webp" width="160" alt="Softwear 的连帽衫页面作为原生 iOS 应用的显示"></td> <td><img src="docs/screenshots/softwear-macos.webp" width="290" alt="Softwear 的连帽衫页面作为原生 macOS 应用的显示"></td> </tr> <tr valign="top"> <td>浏览器自身的 DOM 和 CSS</td> <td>UIKit 视图、原生控件和系统标签栏</td> <td>AppKit 视图和原生控件</td> </tr> </table>

<sub>一个 <code>app.contract</code>,同一个界面在三个宿主上的呈现,由 agent 驱动捕获。Softwear 是一个演示商店,你可以从 exact-templates 生成它:它展示 Alternative Apparel 的商品目录,与该品牌并无关联,也不接受真实订单或付款。</sub>

Exact 是一个跨平台应用运行时。你用 Contract——一种小型声明式语言——来描述界面,用 TypeScript 或 Rust 编写数据逻辑。Contract 编译器会把界面转换成一个紧凑的计划。在 Web 上,这个计划会变成一个 ES 模块,运行在约 20 KB 的运行时之上,驱动真实的 DOM。在 macOS、iOS 和 Linux 上,一个 Rust runner 执行同一个计划,一个 Rust 布局内核用 CSS 规则计算每一个盒子,各平台再用自己的工具绘制:AppKit、UIKit 或 GPU 绘制器。UI 中没有 webview,也没有 JavaScript 桥接,并且在第一个像素出现之前不会运行任何应用 JavaScript。

[!NOTE] Exact 尚未发布 1.0,每天都在变化。按照设计,它没有 API 稳定性保证,不提供向后兼容,也没有迁移指南。

升级说明:Snapback 变更回复现在会以 ok: false 抛出 refused(why) 并暴露 failure(slot);snapback4 包的 README 中有前后对比和继承应用的命令。

三条原则

1. Agent 原生

Exact 假定大部分代码将由 AI agent 编写。agent 可以创建应用、运行它、查看它、操作它,并在无需人工介入的情况下证明它能正常工作。

  • 十个操作,在每个宿主上完全一致。 tree · screenshot · tap · type · state · layout · logs · clock · prefer · perf 通过同一个脚本 scripts/agent.mjs 驱动 Web、macOS、iOS(模拟器或真机 iPhone)和 Linux。之所以刻意定为十个:agent API 会一次一个“合理”地增加,直到没人能把它记在脑子里。
  • 时钟归 agent 所有。 在两个操作之间,一切静止不动。agent 不必等到动画结束,而是说 clock +60000 或 clock settle,然后读取结果。没有时序抖动,没有等待。
  • 测试就是这些操作组成的脚本。 一个 app.test.contract 文件在任何宿主上都能原样运行,不需要第二个求值器。
  • 每个工具都能与机器对话。 contract build --json 给出带有稳定 id 和源码范围的诊断信息。contract symbols 提供导航。开发用 source map 可以从屏幕上的任意节点追溯到声明它的那一行。驱动会拒绝驱动比其源码更旧的构建,并指出需要重新构建。
  • Contract 刻意保持小巧。 整个应用都能放进一个上下文窗口。每次写入都是声明式的,每个列表都有 key,每个值都有类型。错误是说明该做什么的拒绝,而不是悄无声息的错误行为。
BASH
bun scripts/agent.mjs web tree "tap change-station" "type station-search Palo" \
  "clock +60000" state "screenshot out.png"

2. 速度至上

应用的速度和循环的速度。rules/RULES.md 中的每一项预算都会在每次提交时被跟踪,一旦出现回退就是 P0 级问题,并且会明确责任人。

预算目标
冷启动到可交互首帧100 ms p50
开发重启,从编辑到呈现100 ms p50
首像素前执行的应用 JavaScript无
改动一行,重新构建该 crate30 s
整个阻塞式检查套件65 s

设计如何保持这些数字:

  • 启动路径不执行也不编译任何东西。 TypeScript 在构建时被编译为 Hermes 字节码,并在首像素之后加载。首帧来自预先烘焙进计划中的数据。
  • 只为用到的部分付费。 GPU 渲染、Markdown 编辑器、文本流和浏览器 SQLite 都是独立的产物,按需加载。没有任何一项是核心 crate 上的功能开关。
  • Web 拥有自己的小型运行时。 在 RealWorld(“Conduit”)基准测试中,Exact 的运行时在 React SSR 构建完成 hydration 之前约 300 ms 就已启动。它使用了 26 KB 的代码,而 React 为 81 KB(apps/realworld 中的 RealWorld 基准测试)。
  • 编辑约在十分之一秒内生效。 在由 exact new 创建的新应用中,保存的 Contract 或 TypeScript 编辑在 99 ms 内完成重建并进入页面。

(注:更多技术实现细节与完整 API 文档请查阅原项目 README)