mcpField
Z
Zenith

Zenith

本地服务
github.com媒体与设计222 周前更新

关于 Zenith

Zenith 是面向 AI Agent 的设计文档格式与引擎,以纯文本 .zen 文件描述设计内容。同一文件始终渲染为相同像素,可输出 PNG、SVG 和 PDF。项目提供命令行工具,并支持 npm 安装的 MCP 包,适合需要可审查、可校验设计源文件的团队。

主要功能

  1. 01基于 KDL 的纯文本 .zen 设计格式
  2. 02校验诊断、格式化与设计令牌查看
  3. 03确定性渲染为 PNG、SVG 和 PDF
  4. 04通过类型化事务安全编辑设计源文件
  5. 05提供命令行与 Rust 库 crate

适用场景

  1. 01由 Agent 生成并校验海报、图表或社交图片
  2. 02在版本控制中审查设计变更的文本差异
  3. 03批量渲染多页文档或多个设计变体

MCP 相关

该项目提供 @zenitheditor/zenith-mcp 包,即 npm 发布的 MCP 服务,用于向 MCP 客户端暴露 zenith 引擎的功能。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"zenitheditor-zenith": {
"command": "npx",
"args": [
"-y",
"@zenitheditor/zenith-mcp"
]
}
}
}
启动命令npx -y @zenitheditor/zenith-mcp

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npm@zenitheditor/zenith-mcp0.0.8

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

Zenith

Zenith — 赋予 AI Agent 创建和编辑真实设计的能力
专为 AI Agent 时代打造的设计文档格式和引擎。

纯文本 .zen 设计文件,可供阅读、比较差异、审阅、验证,并让 Agent 安全编辑 — 确定性地编译为像素精确的 PNG、自包含 SVG 和可直接用于印刷的 PDF。

安装 快速开始 功能 验证 命令 Agent

CI 状态 最新 GitHub 版本 crates.io 上的 zenith-tool crates.io 下载量 MCP 注册表条目 Zenith 示例展示 许可证

本 README 中的每一幅横幅和示意图都是使用 Zenith 创建的 — 源文件位于 assets/showcase/。


Zenith 是一种用于设计文件的纯文本格式和引擎,适用于海报、演示文稿、书籍、社交媒体图片、示意图等。理念很简单:设计应该像代码一样运作。 你应该能够阅读、比较差异、审阅、测试,并让 Agent 安全地编辑设计。

.zen 文件是人类可读的 KDL 文本。引擎会解析文件,根据大量诊断规则集进行验证,将其编译为与后端无关的场景,并将同一文件每次都渲染为相同的像素 — 输出为 PNG、自包含 SVG 或可直接用于印刷的 PDF。

下方各节默认处于折叠状态,方便快速浏览本页 — 点击任意标题旁的 ▸ 即可展开。安装和快速开始默认展开。

安装

推荐使用安装脚本来安装 zenith CLI;脚本会检测你的平台,并从 GitHub Releases 下载匹配的预编译二进制文件。

Linux / macOS

curl -fsSL https://raw.githubusercontent.com/zenitheditor/zenith/main/scripts/install.sh | sh

Windows (PowerShell)

irm https://raw.githubusercontent.com/zenitheditor/zenith/main/scripts/install.ps1 | iex

设置 ZENITH_INSTALL_DIR 可更改安装位置(默认值为 ~/.local/bin):

ZENITH_INSTALL_DIR=/usr/local/bin \
  curl -fsSL https://raw.githubusercontent.com/zenitheditor/zenith/main/scripts/install.sh | sh
使用 cargo
cargo install zenith-tool    # from crates.io (installs the `zenith` binary)
cargo install --git https://github.com/zenitheditor/zenith zenith-tool   # from source

面向直接基于该引擎构建的 Rust 项目,共有 13 个库 crate 以各自的名称发布:zenith-geometry、zenith-session、zenith-core、zenith-layout、zenith-raster、zenith-scene、zenith-perception、zenith-zpx、zenith-render、zenith-tx、zenith-producers、zenith-pipeline 和 zenith-editor。zenith-editor-wasm 和 zenith-editor-bench 未发布。

使用 npm
npm install -g @zenitheditor/zenith-mcp
npx -y @zenitheditor/zenith-mcp --help

npm 包会从 GitHub Releases 安装匹配的预编译 zenith 二进制文件,主要面向 MCP Registry 发布路径。未加作用域的 zenith 二进制文件仍是 Rust CLI。

GitHub Releases

直接从 GitHub Releases 下载:

平台架构资源
Linuxx86_64zenith-<version>-linux-x64.tar.gz
Linuxaarch64zenith-<version>-linux-arm64.tar.gz
macOSx86_64zenith-<version>-macos-x64.tar.gz
macOSApple Siliconzenith-<version>-macos-arm64.tar.gz
Windowsx86_64zenith-<version>-windows-x64.zip
更新
zenith update                   # latest stable release
zenith update --pre             # latest prerelease
zenith update --version <tag>   # a specific release tag, e.g. the ones on the Releases page

使用 zenith --version 验证。

从源代码构建

用于本地开发或从源代码安装:

git clone --recurse-submodules https://github.com/zenitheditor/zenith
cd zenith
cargo build --release
cargo install --path zenith-cli   # installs `zenith` to ~/.cargo/bin
./scripts/install.sh --local      # installs the local build to ~/.local/bin

发布二进制文件位于 target/release/zenith。无需 C 工具链或系统库——依赖关系不包含 C,且整个工作区禁止使用 unsafe。

快速开始

zenith validate examples/hello.zen          # report diagnostics (add --json for machine output)
zenith fmt examples/hello.zen               # canonical, idempotent formatting
zenith fix draft.zen --apply                # apply machine fixes (tokens, typos) in one step
zenith tokens examples/hello.zen            # list design tokens and their resolved values
zenith inspect examples/hello.zen           # print the node tree (read-only)
zenith render examples/hello.zen --png hello.png          # render to PNG

zenith render examples/multipage.zen --all-pages out/     # one PNG per page
zenith render examples/hello.zen --pdf hello.pdf          # print-ready PDF
zenith render examples/hello.zen --svg hello.svg          # self-contained SVG
zenith render examples/multipage.zen --svg page.svg --page 2
zenith render examples/multipage.zen --all-pages-svg svg-pages/
zenith render examples/hello.zen --scene scene.json       # dump the scene IR
导出标志输出
--svg OUT默认导出第 1 页,并将文字转为轮廓。
--pdf OUT默认将所有页面导出到一个 PDF 中。
--page N为单输出标志选择一个页面,包括 PDF。
--all-pages-svg DIR按文档顺序写入 page-N.svg。
--raster-scale FSVG/PDF 回退分辨率。取值为有限数,满足 0 < F <= 4,默认为 1。
--scale FPNG 输出缩放比例。取值为有限数,满足 0 < F <= 4,默认为 1。
--deny render.svg_rasterized禁止需要栅格回退的 SVG 导出。
--deny render.pdf_rasterized禁止需要栅格回退的 PDF 导出。
  • **SVG 资源:**RGB 颜色和嵌入的图像资源使产物可以独立使用。
  • **SVG 文字:**转为轮廓后可保留外观,但无法编辑、选择和搜索。
  • **SVG 回退:**效果会捕获其完整作用范围。非正常混合模式会捕获整个页面。交叉作用范围和位图字形需要捕获。
  • **PDF 回退:**不支持的功能会捕获其所需作用范围或整个页面。捕获的文字无法选择和搜索。捕获的链接会失去点击目标。
  • 分辨率:--raster-scale 会更改回退像素,但不会更改矢量几何形状或页面尺寸。现有位图资源会保留其源分辨率。
  • 报告:render.svg_rasterized 和 render.pdf_rasterized 会报告页面、命令范围和原因。JSON 中包含结构化的栅格化区域。
  • **PDF 错误:**CLI 和 MCP 会拒绝捕获和资源错误。返回 Vec<u8> 的旧版库 API 会继续兼容性输出。严格错误请使用报告 API。
  • **策略:**阻止型诊断会阻止输出写入。验证源内容后,请读取导出报告。
  • **写入:**每个文件都会先写入同目录临时文件,再进行重命名。写入错误会保留现有目标文件。后续 I/O 错误发生时,先前已提交的输出可能仍会保留。
  • **批处理报告:**部分行和变体会保留已提交的路径,并标记失败状态。清单写入错误会保留批处理错误计数。
  • **文件系统限制:**写入会拒绝只读目标。符号链接输出会替换解析后的目标,并保留链接。替换会保留权限,其他硬链接不受影响。不保证崩溃后的持久性。
zenith render examples/multipage.zen --pdf book.pdf --raster-scale 2 --json
zenith render examples/hello.zen --svg hello.svg --raster-scale 2 --json

最小有效文档:

zenith version=1 {
  project id="proj.hello" name="Hello Zenith"
  tokens format="zenith-token-v1" {
    token id="color.bg" type="color" value="#f8fafc"
    token id="color.ink" type="color" value="#111827"
    token id="font.body" type="fontFamily" value="Noto Sans"
    token id="size.heading" type="dimension" value=(px)42
  }
  styles {}
  document id="doc.hello" title="Hello Zenith" {
    page id="page.hello" w=(px)480 h=(px)160 {
      rect id="rect.bg" x=(px)0 y=(px)0 w=(px)480 h=(px)160 fill=(token)"color.bg"
      text id="text.hello" x=(px)24 y=(px)24 w=(px)432 h=(px)112 fill=(token)"color.ink" font-family=(token)"font.body" font-size=(token)"size.heading" { span "Hello Zenith" }
    }
  }
}

参见 examples/,其中包含可运行的 .zen 文件,涵盖形状、富文本、内联 markdown(从外部文件加载)、代码块、图像、框架/组、多页文档和样式,以及更丰富的功能——gradient、shadow、blur、filter、mask、table、flowchart(形状 + 连接线)、图表(柱状图/折线图/面积图/饼图/圆环图/迷你图,支持图例、数值标签和数据绑定)以及 anchors。

为什么

代码有源代码管理、类型、测试和 PR,设计文件却什么都没有——这给人们带来了困扰,也阻碍了 AI。

代码有源代码管理、类型、测试和拉取请求。设计文件却什么都没有。它们是不透明的二进制文件——无法比较差异、无法评审更改,而且同一个文件在不同机器上的渲染结果可能不同。

这对人们来说是个问题,对 AI 来说问题更大。Agent 已经能编写代码并发起拉取请求,因为代码是它们可以阅读和推理的文本。让它们进入设计工具,它们就会两眼一抹黑。让 Agent“把标题改成品牌红色并收紧布局”,却没有任何安全可靠的操作对象——没有稳定的目标、没有验证、没有预览,也无法检查结果。

Zenith 解决了这个问题。我们的目标是让设计文件像代码一样可以安全地自动化处理:

  • 纯文本,由你掌控——可读、可比较差异,并且永远属于你。
  • 稳定 ID,让每项更改都是可评审的补丁,而不是鼠标拖拽。
  • 确定性渲染——同一个文件始终生成相同的像素。
  • 真正的验证——文本适配、颜色来自设计系统,而且没有内容溢出页面。
  • 安全编辑——每项更改都是经过类型定义的事务,在应用前会经过检查并可预览,同时提供源文件差异和审计记录。

它不是 AI 图像生成

与图像模型正好相反:Zenith 生成的是可编辑的设计,而不是一张扁平图片。

这是最常见的误解,值得开门见山地说明:Zenith 与 Nano Banana、ChatGPT image 或 Grok Imagine 这样的图像模型正好相反。

图像生成器给你一张扁平图片。它只是一堆像素——你无法打开它来移动徽标,无法强制标题使用你指定的品牌颜色,而要求“同样的内容,只是日期不同”会得到另一张图片。没有任何东西可以编辑、评审或保证。

Zenith 不生成图片,而是生成_设计本身_——一份结构化、可编辑的文档,其中每个元素都真实存在且可定位。Agent(或人)可以修改一行内容、替换一个颜色令牌,或重新生成一百个符合品牌规范的变体,而且每次渲染都精准且可重复。AI 编写和编辑源文件;Zenith 则保证其含义和呈现效果。

Agent 原生优先,而不是事后加上 API 的工具

基础是程序化、确定性的引擎;可视化编辑器是其上的客户端——自动化才是入口。

大多数设计工具都是为人们拖拽方框而构建的,自动化 API 则是后来才添加的事后功能——它只是覆盖在一个本就不是为软件驱动而设计的模型之上的薄弱、受限层。

Zenith 则反其道而行。它的基础是程序化、基于文本的确定性引擎。Agent、脚本和命令行都能直接驱动它。因此,自动化不是侧门,而是正门。

编辑器。 引擎和 CLI 是 AI Agent 驱动的界面。浏览器编辑器是构建于同一引擎之上的客户端:设计师可以微调一个方框,Agent 可以调整一百个变体的样式,两者都基于相同的确定性核心运行,并使用相同的验证、事务和版本历史记录。GUI 并不是一个事后附加自动化功能的独立产品。

## 工作原理
一条确定性流水线:解析 + 验证 → AST → 编译 → 场景 IR → 渲染(PNG/SVG/PDF)。

.zen 文档会经过一条统一的确定性流水线。每个阶段都是独立的 crate,拥有清晰的契约边界,因此 GPU 后端或编辑器都可以使用相同的场景 IR:

流水线:.zen 源文件 → 验证 → 编译 → 场景 IR → 渲染

由 Zenith 渲染 — 源文件:assets/showcase/pipeline.zen。

  design.zen  (KDL plain text)
       │  parse + validate           zenith-core   →  diagnostics (Error/Warning/Advisory)
       ▼
  Document AST  ──transaction ops──▶  Document AST'  zenith-tx  →  dry-run / apply + audit record
       │  compile                    zenith-scene + zenith-layout
       │    · resolve tokens, geometry, anchors
       │    · shape text (rustybuzz), wrap, hyphenate
       ▼
  Scene IR  (backend-neutral display list)
       │  render                     zenith-render
       ├─▶ PNG   (tiny-skia, byte-identical)
       ├─▶ SVG   (outlined text, embedded assets)
       └─▶ PDF   (vector, native CMYK, bleed / trim / crop)

  local history / undo / versions    zenith-session   (off the render path; never affects pixels)

渲染路径上的所有部分都具有确定性且不含 C 代码:没有时间、随机性、HashMap、unsafe 或 C 依赖。无论在哪台机器上,相同的输入字节始终产生相同的输出字节。

功能

标记、完整的节点集、真正的排版、视觉效果、锚点、配方、事务引擎、确定性 PNG/SVG/PDF、历史记录、库和数据合并。 - **脚手架与身份** — `zenith new` 可创建可立即编辑的文档(最简有效模板,或通过 `--starter flyer|letterhead|handout|deck|poster|menu|card|report` 创建已完成、可换主题的布局,默认使用 `.zen` 扩展名,并自动创建父目录),首次写入时生成稳定的 `doc-id`;任何 `.zen` 文件都会在首次编辑时自动获得身份和工作区存储,无需手动设置。 - **纯文本 `.zen` 格式** — 使用 KDL v2 源码,采用 `project` / `tokens` / `styles` / `document` / `page` 结构;每个节点都有稳定的 ID。 - **设计令牌** — 包括 `color`(sRGB **和**原生 CMYK)、`dimension`、`number`、`fontFamily`、`fontWeight`、`gradient`(线性/径向)、`shadow`、`filter` 和 `mask`,支持别名链和循环检测。 - **完整的节点集** — `rect`、`ellipse`、`line`、`polygon`、`polyline`、`text`、`code`、`image`、`frame`、`group`、`pattern`、`shape`、`connector`、`chart`、`instance`、`field`、`footnote`、`toc` 和 `table`,并可无损直通未知节点,以实现向前兼容。 - **真正的排版** — 使用 `rustybuzz` 进行字形整形,内置 Noto Sans / Noto Sans Mono,支持字体回退、Knuth–Liang 断词、富文本行内样式(粗体/斜体/下划线/删除线/高亮/行内代码/链接)、文本串接流排(链)、首字下沉、制表位前导符、文本环绕,以及字形不可用时触发的 `font.glyph_missing` 诊断。 - **精简的长篇文本** — 通过从外部 `.md` / `.txt` 文件(`text src="copy/article.md"`)或数据字段引入正文,保持 `.zen` 文件精简;还可启用 **markdown**(`format="markdown"`),支持行内标记(`**bold**`、`*italic*`、`==highlight==`、`++underline++`、`~~strike~~`、`` `code` ``、`[label](url)`)和完整的 **块结构** — `# headings`(h1–h6)、以空行分隔的段落、块引用、有序/无序列表、围栏代码块和 `---` 分隔线。每种角色的排版(字体、字号、字重、填充、间距)由文档、页面或文本作用域中的 `block role="h1" …` 声明控制(级联顺序:文本 > 页面 > 文档),因此 `.zen` 负责所有布局和样式,而 `.md` 文件只保留纯文本内容。对于超出单个文本框容量的长篇内容,可使用 `chain` 连接多个 `text` 节点以手动分页;内容无法完全容纳时会触发 `text.overflow` 警告。 - **视觉效果** — 线性与径向渐变、分层阴影、高斯模糊、羽化蒙版、12 种 Porter-Duff 混合模式、不透明度级联、逐角半径,以及图像适配/裁剪形状/对象位置。 - **锚点** — 相对于页面、安全区、父容器或同级节点的 9 点定位(优先级:区域 > 同级节点 > 父级 > 页面),全部转换为明确且确定的几何数据(未设置锚点时,生成的字节与手动放置坐标完全一致)。 - **程序化配方** — `recipes` 溯源区块会记录生成图案的方式(类型、种子、生成器、参数、调色板令牌、展开后的节点 ID),可通过类型化配方事务进行检查和编辑,让程序化视觉效果保持可复现且可重新调整。 - **事务引擎** — 提供类型化操作集(设置填充/描边/几何属性、添加/移除/重新设置父级/分组、对齐/分布、页面操作、令牌操作、查找替换、分离图案等),默认以 **试运行** 方式执行,并强制执行引用完整性和 ID 唯一性检查,同时提供源代码差异、移动/缩放后的节点框、受影响节点 ID 和审计记录。 - **确定性渲染** — 通过 tiny-skia 生成像素精确的 PNG,以及可供印刷的 PDF(原生 DeviceRGB/CMYK、MediaBox/TrimBox/BleedBox、不嵌入时间戳);支持单页、所有页面或对页跨页版式。可将场景 IR 导出为 JSON。 - **真正的 PDF 文本,而非图片** — PDF 输出默认嵌入真实、可选择/可搜索/可索引的文本(子集字体 + ToUnicode)和可点击超链接;在 `text` / `code` 节点上设置 `selectable=#false`,即可将其渲染为轮廓而非文本。`--embed-full-fonts` 会嵌入完整字体,而非子集字体。不透明线性和径向渐变保留为原生渐变。位图字形、半透明渐变,以及外侧或非严格色标偏移的渐变,会将其完整封闭作用域栅格化。需要组不透明度的效果和合成图层会将其完整封闭作用域栅格化。非正常混合模式会将整页栅格化,以保留背景。栅格化范围内的文本和链接将失去可选择性和可点击性;范围外的文本保留原生 PDF 行为。导入的 SVG 路径若使用受支持的填充和纯色描边,则保留为原生矢量。导入的径向渐变、渐变描边、图案、剪辑、蒙版、滤镜、嵌套图像和不受支持的绘制变换,会在页面像素分辨率下将其完整封闭作用域栅格化。SVG 组不透明度和放置不透明度也使用相同的回退方式。 - **本地历史记录** — 每份文档都有独立身份(文件中写入 ULID doc-id,渲染器会忽略该字段)、用于撤销/重做的临时会话 DAG,以及持久化的内容寻址版本存储(SHA-256 + DEFLATE),支持命名版本和恢复,完全不影响渲染流程。 - **工作区临时候选项** — 与历史记录一同存储内容寻址的 `.zen` 快照,以供设计探索:`scratch new` 记录候选项,`scratch list` / `show` 用于查看,`candidate` 用于转换其生命周期状态(草稿 → 已选定 | 已拒绝),`promote --into ` 将已选定的候选项合并到交付文档中,`finalize` 则移除已拒绝的候选项。`bundle` / `unbundle` 可将每份文档的完整存储(历史记录 + 临时候选项)打包为可移植且确定性的 `.zenithbundle`。 - **资源库子系统** — 内置预设包(`@zenith/flowchart`、`@zenith/filters`、`@zenith/masks`、`@zenith/brand-kit`);`library add` 会将资源项实例化为独立完整的文档,并通过 `libraries` + `provenance` 追踪来源。使用 `zenith library show #` 检查任意资源项。 - **AI 资源溯源** — 将图像模型生成的图像/插画作为 `asset` 合成到文档中时,Zenith 会记录其生成方式:`ai-prompt`、`ai-model`、`ai-provider`、`ai-seed`、`ai-license`、`ai-source-rights`、`ai-safety-status`、`ai-reuse-policy`(以及 `sha256` 内容锁定信息)。运行 `zenith schema asset` 查看完整字段列表。 - **可变数据合并** — `role="data."` 绑定可驱动文本和图像列以及多页模板的 CSV 邮件合并,并生成逐行 JSON 报告和可按字节复现的清单。 - **自描述 CLI** — `zenith schema` 会以人类可读文本或 `--json` 的形式输出可创作内容(所有节点类型及其属性、事务操作集、令牌类型,以及 `page` / `asset` / `document` / `variant` / `diagnostics` / `brand` 接口),让 Agent 能直接通过 CLI 了解可创作的内容,而无需猜测;同时可结合 `zenith validate` 提供的可操作诊断,完成修复闭环。

验证 — 安全网

70 多项检查(错误 / 警告 / 提示),可在渲染或打印之前发现问题、风险或不符合品牌规范之处。

zenith validate file.zen 是确保设计文件可安全编辑、值得放心交付的步骤。它就像编译器的类型检查器,不过针对的是文档:它会读取源文件,并在渲染或打印之前报告所有问题、风险或不符合品牌规范之处,这样 Agent(或你)就不用再靠“渲染出来仔细检查”来发现问题。

它会运行 70 多项检查,每项检查都会生成一条诊断信息,其中包含稳定的代码(例如 text.overflow)、易读的说明、出问题的节点 ID 和源文件位置。每条诊断信息都有以下三种严重级别之一:

严重级别含义影响
错误确定存在问题,会导致输出错误阻止渲染 — render 会拒绝执行,且 validate 会以非零状态退出,直到问题修复
警告可能存在问题或有风险的结构仍会生成输出;建议检查
提示信息性说明不会阻止操作;仅供参考

具体来说,它会检查:

  • 结构和引用有效 — 每个节点 ID 都唯一,且每个引用都指向实际存在的对象:令牌引用、图像资源、连接器目标、字段、母版/版块(id.duplicate、token.unknown_reference、asset.unknown_reference、connector.missing_target)。没有悬空链接,也没有导致内容悄无声息地无法渲染的拼写错误。
  • 遵循设计系统规范 — 视觉属性必须来自令牌,而不是原始十六进制值(token.raw_visual_literal),这样修改品牌风格只需改一处;它还会标记循环引用、类型错误或未使用的令牌(token.cyclic_reference、token.type_mismatch、token.unused)。
  • 没有内容溢出或超出画布 — 几何信息齐全且位于画布内,文本能放入文本框,子元素不会超出其框架,内容也符合页面边距和安全区要求(node.missing_geometry、text.overflow、text.fit_failed、frame.child_overflow、margin.violation、safe_zone.violation)。锚点必须能解析到实际的参考框架(anchor.unresolved_sibling、anchor.cycle)。
  • 易读且适合打印 — 文本与背景的对比度会依据 WCAG 3 (APCA) 检查(contrast.low);同时会验证色彩空间、出血和页面单双面设置,确保 PDF 确实适合打印(document.invalid_colorspace、page.invalid_bleed)。
  • 模型完整性 — 也会检查较新的 variants、recipes 和 provenance 区块,确保生成或派生的作品保持一致(variant.unknown_source、recipe.unknown_palette_token)。

这为何重要:

  • 对人来说 — 你可以在导出之前发现“标题跑出页面了”“灰字灰底看不清”“这个颜色不是品牌令牌”或“打印文件的色彩空间不对”等问题,而不是事后才发现。
  • 对 Agent 来说 — zenith validate --json 提供精确、机器可读的契约。Agent 编辑源文件后进行验证,就能_确认_修改是否可靠 — 这张安全网让无需人工介入的编辑值得信赖。

Agent 工作循环:编写 → 验证 → 渲染 → 检查 → 编辑

由 Zenith 渲染 — 源文件:assets/showcase/loop.zen。

### 感知
从渲染结果中测得的确定性信号。它们是信号,不是品味判断:不评审美,也不使用视觉模型。

zenith perceive page file.zen [--page N | --all-pages] [--json] 会以与 zenith render --png 相同的 1 倍比例渲染每一页,然后测量裁切框(出血部分会被裁掉)。zenith perceive vector 则直接从源文件测量路径几何形状。

输出描述像素和声明的几何信息,并非对设计质量的评判。请将其视为依据,再自行判断。

指标测量内容
histogramRec.709 亮度直方图,分为 10 档,并提供最小值、最大值和平均值。
value_zones各区域的像素数、平均值和分布范围:阴影区低于 1/3,中间调低于 2/3,高光区高于 2/3。
density_map最多 4 × 4 个单元格中的亮度对比能量、能量最强的单元格,以及 70/20/10 的能量分布。
edge_map相邻像素间的亮度变化。0.25 及以上为强边缘,低于 0.03 则会消失。
optical_balance墨迹中心相对于页面中心的偏移,以 px 和页面比例表示。
clearspace墨迹到各页面边缘的距离,并与声明的最小页面边距进行比较。
grid_conformance顶层节点框角点(以及并集的角点和中心)到最近构造辅助线的最大距离。

墨迹指与页面上最常见像素不同的所有像素。

如何读取 --json:

  • schema 为 1。如果结构发生不兼容变更,该值会递增。信封中不包含工具版本,因此发布新版本不会改变其字节内容。
  • pages[].metrics.<name>.status 的值为 measured 或 not_applicable。not_applicable 指标会附带 reason。
  • clearspace 需要提供全部四个边距:margin-top、margin-bottom、margin-inner 和 margin-outer(页面或文档级)。grid_conformance 需要包含 segment 或 circle 辅助线的 construction 块。指标不会自行设定阈值,也不会虚构输入。
  • 每个已测量指标都有一个 diagnostics 数组,其中包含 code、severity(info 或 warning)和 message。
  • 每个非整数数值都会按远离零的方向四舍五入,保留 decimals(4)位小数。
  • 页面测量成功时退出码为 0。感知诊断只是信号,永远不会导致命令失败。硬性验证错误会阻止该命令执行,就像它们会阻止 render 一样。

确定性:相同文档在所有目标平台上都会产生相同的字节内容。zenith-cli/tests/perceive_hashes.json 固定了每个示例在 Linux x64 和 arm64、macOS arm64 和 x64,以及 Windows x64 上的输出。MCP 通过 zenith_perceive 暴露相同的信封(doc、page、all_pages)。

变体

根据一个设计生成多种输出的两种方式:zenith variant(尺寸)和 zenith merge(数据)。

根据一个设计生成多种输出的两种互补方式——一种改变尺寸,另一种改变内容。

将一个标准设计分别渲染为方形、故事和横幅尺寸

由 Zenith 渲染——源文件:assets/showcase/variants.zen。

尺寸/格式变体(zenith variant)

variants 块可将一个规范页面扩展为多个命名的目标尺寸。每个目标都会生成一个 .zen 配套文件和 PNG 或 SVG 图像。每个目标的 override 可更改可见性、文本和视觉属性。源令牌的编辑会传播到所有变体。锚定节点会根据每种尺寸重新布局。

variants {
  variant id="square" source="page.main" w=(px)1080 h=(px)1080 {
    override node="qr" visible=#false
  }
  variant id="story" source="page.main" w=(px)1080 h=(px)1920 { }
}
zenith variant poster.zen --out-dir out/ --manifest manifest.json
zenith variant poster.zen --out-dir svg/ --format svg --raster-scale 2
批处理标志说明
--format png|svg选择 PNG 或 SVG。默认为 PNG。SVG 变体会保留 .zen 配套文件。
--raster-scale F仅适用于 SVG。取值有限,且满足 0 < F <= 4;默认为 1。
--manifest PATH记录已提交的输出,包括状态为失败的不完整条目。

批处理命令没有 --deny 标志。文档、本地和全局策略决定回退诊断行为。禁止回退时,该变体不会写入文件。I/O 错误可能导致先前的输出保留。批处理不支持回滚。

生成过程具有确定性(相同源文件 → 字节完全一致的输出和清单,schema: zenith-variant-manifest-v1)。

数据邮件合并(zenith merge)

一个模板加一个 CSV,每行生成一个渲染设计——适用于本地化帖子、个性化图形、证书或营销活动变体。为变量文本/图像节点标记 role="data.<column>"(列名即 CSV 表头),然后合并:

# in poster.zen — bind the headline to the CSV "name" column:
text id="hero.name" role="data.name" x=(px)60 y=(px)160 w=(px)680 h=(px)90 fill=(token)"color.ink" font-family=(token)"font.body" font-size=(token)"size.heading" { span "Name" }
zenith merge poster.zen people.csv --out-dir out/ --name-by name --manifest manifest.json
zenith merge poster.zen people.csv --out-dir svg/ --name-by name --format svg --raster-scale 2

合并格式默认为 PNG。多页文件名会在 .png 或 .svg 前添加 -page-N。SVG 回退诊断遵循文档、本地和全局策略。禁止回退时,该行不会写入文件。I/O 错误可能导致先前已提交的输出保留。报告会保留这些路径。

每行都会独立且确定性地渲染。--name-by 可按列名命名文件(Alice.png、Bob.png);--manifest 会为 CI 写入字节可复现的批处理记录(包含模板和数据哈希,以及每行的来源信息)。图像列同样适用——role="data.logo" 图像节点会按行替换其资源路径。

## 连接器
语义箭头,其端点根据 from/to 节点推导而来 — 自动路由、箭头、回环和线条跨越。

connector 是连接两个节点的语义箭头。它没有手动指定的几何信息 — 只需提供 from 和 to 节点 ID,引擎便会在编译时根据目标节点解析后的边界框推导出两个端点。移动任一边界框后,连接器会自动重新路由;相同的源始终生成相同的路径。它是仅描边的叶节点(无填充、无子节点);要渲染它,必须指定 stroke 颜色。

  • 端点锚定 — from-anchor / to-anchor 用于选择每一端的连接位置。简单流程图可使用命名网格锚点(top-left、bottom、center-right);需要在同一形状周围布置多个不同连线的精致图表,则可使用 35/60 之类的轮廓划分锚点。划分锚点从顶部中心开始,按顺时针方向排列;椭圆沿其周长取点,矩形则按边长沿轮廓取点。默认值 auto 会选择朝向另一个边界框的边。
  • 端口 — 页面可通过 ports { port node="agent" id="memory.vector" anchor="38/60" } 声明语义连接点;连接器随后可使用 from="agent#memory.vector" 或 to="store#in"。组件端口会透传到实例,因此 connector from="agent.instance#out" 无需复制坐标,也能保持与组件内部几何位置的关联。
  • 路由模式(route=)— straight(默认值)绘制直线;orthogonal 绘制直角折线;avoid 使用避障正交路由器,使路径绕开其他节点的边界框(找不到清晰路径时,则回退为普通折线)。
  • 回环 — 当 from 和 to 指向同一个节点时,连接器会在该节点一侧形成一个小回环(由锚点决定所在侧,默认是 top)。
  • 箭头 — marker-start / marker-end = arrow 会添加与描边同色的实心箭头(默认值为 none);箭头方向会沿实际路由线段确定,因此会与水平或垂直方向对齐。
  • 线条跨越 — 页面级设置 line-jumps="arc" 或 line-jumps="gap" 后,连接器在交叉处会进行跨越:交叉线会出现小半圆凸起(arc),或形成断开的间隙(gap),使重叠箭头清晰可辨。跨越方式是确定性的 — 水平线会跨过垂直线 — 且嵌套连接器也适用。不设置(none / 默认值)时,渲染结果逐字节保持一致。
  • 样式 — 支持 stroke(必填)、stroke-width、opacity、rotate 和 style 引用,遵循与其他基本图元相同的属性/样式级联规则。
page id="pg" w=(px)640 h=(px)360 line-jumps="arc" {
  ports {
    port node="n.start" id="out" anchor="1/4"
    port node="n.end" id="in" anchor="3/4"
  }
  shape id="n.start"  kind="process" x=(px)40  y=(px)150 w=(px)130 h=(px)60 fill=(token)"c.node" stroke=(token)"c.line" { span "Start" }
  shape id="n.end"    kind="process" x=(px)470 y=(px)150 w=(px)130 h=(px)60 fill=(token)"c.node" stroke=(token)"c.line" { span "Finish" }
  shape id="n.block"  kind="process" x=(px)290 y=(px)130 w=(px)70  h=(px)100 fill=(token)"c.block" stroke=(token)"c.blockline" { span "Block" }

  // Auto-routed flow bends around the Block instead of crossing it…
  connector id="e.flow"  from="n.start#out" to="n.end#in" route="avoid" marker-end="arrow" stroke=(token)"c.flow"  stroke-width=(token)"cw"
  // …and where a second connector crosses it, the page's line-jumps hops it.
  connector id="e.cross" from="n.top"   to="n.bottom" marker-end="arrow"               stroke=(token)"c.cross" stroke-width=(token)"cw"
}

完整的可运行文档请参阅 examples/connector-routing.zen。

## 图标与库
可复用资源包有两种格式:.zen 文件,或普通的 *.svg 目录。完整的 Lucide 图标集(1745 个图标)已随附内置。

资源包会导出以 <package>#<item> 形式寻址的条目,通过 zenith library add 将其实例化到文档中。条目分为三种类型:component(节点组,以 instance 形式放置)、token(滤镜/蒙版令牌)和 action(预设事务)。

资源包采用以下两种格式之一:

  • .zen 文件 — 功能丰富的格式:直接编写令牌、组件和操作。它通过 library 自身条目声明其身份。
  • *.svg 目录 — 即插即用格式,适用于图标集。每个 *.svg 都是一个图标,其 ID 为文件名(不含扩展名)。无需编写任何内容:将文件夹放入 <project>/libraries/,它就会成为一个资源包,地址为 @local/<dirname>#<stem>。

SVG 图标在添加时会转换为原生、可编辑的 path 节点,而不是作为不透明的光栅图嵌入,也不会使用 <image> 引用。可以像处理其他几何图形一样,使用实例覆盖样式(override ref="icon.0" stroke=(token)"brand" …)。转换是确定性的,且范围明确:添加一个图标,就只转换一个图标。

内置的 @zenith/icons-lucide 资源包包含完整的 Lucide 图标集(1745 个图标,ISC AND MIT)。图标数量太多,无法逐一列出,因此采用搜索优先的发现方式:

zenith library search sync                       # → refresh-cw (matched on its alias)
zenith library search arrow --category navigation
zenith library search cloud --kind component --limit 5
zenith library show  @zenith/icons-lucide#house  # format, license, aliases, tags, geometry
zenith library add   @zenith/icons-lucide#house --into poster.zen --page pg --at 40,40

搜索结果经过排序,而非进行子串扫描:名称与查询匹配的条目优先于别名与查询匹配的条目,后者又优先于仅有标签与查询匹配的条目——因此,搜索 home 会返回 house,而不是 lamp。查询中的每个词都必须匹配,categories 用于筛选,而非排序。

图标旁边可选放置 library.kdl,以提供身份信息和搜索元数据;如果没有该文件,仍可通过文件名找到图标:

library id="@acme/icons" version="1.0.0" {
  license "CC0-1.0"
  icon "rocket-launch" aliases="liftoff" tags="spaceship booster" categories="space"
}

无论采用哪种格式,项目资源包都会覆盖具有相同 ID 的内置资源包。

命令概览

创作 · 渲染 · 编辑 · 变体 · 库 · 主题 · 历史记录 · Agent — 每个命令都支持 --json。

运行 zenith <command> --help 查看标志(每个命令都会打印说明和示例)。每个命令都支持 --json,以输出机器可读内容。

组别命令
创作new · validate · fmt · tokens · inspect
渲染render(--png · --svg · --pdf · --scene · --all-pages · --all-pages-svg · --spread · --page)
感知perceive page(测量页面信号,参见感知) · perceive vector(路径几何信号)
编辑tx(类型化事务,默认试运行) · fix(用于诊断的机器修复,默认试运行) · edit(浏览器编辑器和 Agent HTTP API,参见浏览器编辑器)
变体variant(一个设计 → 多种尺寸/格式) · merge(CSV 数据邮件合并)
库library list · library search · library show · library add
主题theme new(根据品牌颜色合成令牌资源包)
历史记录history · undo · redo · version · restore · sync
工作区scratch new/list/show · candidate <status> · promote --into <page> · finalize · bundle/unbundle
Agentplugin install · plugin uninstall · plugin list · mcp
## 浏览器编辑器
在浏览器中编辑 .zen 文件:一侧显示源文本,另一侧显示渲染后的页面。可使用本地服务器或静态站点。

源文本窗格是内容的权威来源。画布显示引擎对该文本的渲染结果。在画布中进行的编辑(移动、调整大小、旋转、检查器字段)会转化为修改文本的事务。

Zenith 浏览器编辑器:源文本窗格、选中文本节点的画布、图层、检查器和诊断面板

Zenith 浏览器编辑器:画布处于全屏状态,选中的文本节点带有调整大小和旋转控制柄

Zenith 浏览器编辑器:诊断面板将未知令牌引用列为错误,源文本中对应的行带有下划线

### `zenith edit`
zenith edit poster.zen

此命令会在本地端口上提供一个文档,打印包含本次运行专属令牌的 URL,并打开浏览器。运行 zenith edit --help 可查看路由。

标志含义
--port <N>端口。默认:可用端口。
--host <ADDR>绑定地址:IP 地址或 localhost。默认值为 127.0.0.1。
--allow-remote允许使用非环回的 --host。流量使用纯 HTTP,因此令牌会以明文形式通过网络传输。建议使用 SSH 隧道(ssh -L PORT:127.0.0.1:PORT host)或 TLS 反向代理。
--root <DIR>编辑器可读取项目文件的目录。默认:文档所在目录。
--no-open不打开浏览器。
--json以 JSON 格式打印启动行:{schema, url, host, port, token, path}。

安全模型:

  • 绑定。 默认绑定到环回地址。使用非环回的 --host 需要加上 --allow-remote,并会打印警告:流量使用纯 HTTP。
  • 令牌。 从 OS RNG 生成的 64 位十六进制字符,每次运行都会更新。每个 /api 路由都需要 Authorization: Bearer <token>。服务器不会在其他任何地方接受令牌。Cookie 会发送到 127.0.0.1 上的每个服务,因为 Cookie 不区分端口。
  • 页面 URL。 http://127.0.0.1:PORT/#token=<token>。浏览器绝不会将片段发送给服务器或包含在 Referer 中。页面会读取令牌,将其从地址栏和历史记录中移除,并将其保存在内存和此标签页的 sessionStorage 中(因此重新加载页面也能正常工作)。页面文件本身是公开的,无需令牌。
  • 启动浏览器。 令牌不会出现在启动命令行中,其他本地用户可能会读取命令行。服务器会在 $XDG_RUNTIME_DIR(或临时目录)中写入一个带随机名称的 0600 重定向文件,打开该文件,并在首次经过身份验证的请求后将其删除。如果沙盒浏览器无法读取该文件,请打开打印出的 URL。
  • Host 和 Origin。 Host 必须是 localhost、IP 地址或 --host 名称,并且端口必须与绑定端口相同。否则服务器会返回 403 edit.bad_host。DNS 重绑定页面会在此处失败。请求包含 Origin 时,其值必须为 http://<Host>。跨站 fetch 会收到 403 edit.bad_origin。服务器不发送 CORS 标头。POST 请求体必须是 application/json。
  • 限制。 读取请求体前会检查请求头和令牌。请求头必须在 5 秒内到达。每个连接由一个线程处理,同时最多处理 64 个连接(同一远程对端最多 16 个)。空闲客户端无法阻塞实际请求。
  • 文件。 服务器只提供内嵌的页面文件。引擎只会读取文档所在目录(或 --root)下的文档、导入项、资源、数据和文本源。越出该目录的 .. 和符号链接都会报错。两次读取不会受此限制。配置文件(最近的 .zenith.kdl 和 $HOME/.config/zenith/config.kdl)及系统字体的读取方式与其他 CLI 命令相同。
  • 写入。 保存时会保留注释、记录历史、像 tx --apply 一样写入 doc-id 时间戳、将字节同步到磁盘,并以原子方式替换文件。只读文档打开时会显示警告。页面会禁用 Save,并说明如何使文件可写。

服务器会持续运行,直到收到 Ctrl-C 或 POST /api/shutdown。存在未保存的编辑时,关机请求会返回 409,除非请求体为 {"force": true}。对于干净会话,Ctrl-C、SIGTERM 和 SIGHUP 会立即停止服务并以退出代码 0 退出。存在未保存的编辑时,第一个信号不会停止服务:终端会显示文件名,页面会显示带有 Save 的横幅。第二个信号会丢弃编辑并以退出代码 130 退出。

使用编辑器
  • 布局。 源码和画布并排显示(窄屏上则上下排列)。拖动分隔线,或聚焦分隔线后使用方向键,可调整大小。全屏按钮可展开任一面板。按 Escape 恢复原状。工具栏按钮可隐藏页面与图层面板、检查器和诊断面板。布局和主题(系统、浅色、深色)会按浏览器保存。
  • 画布视图。 + 和 - 缩放,0 显示 100%,1 适应页面大小。按住 Ctrl 或 Cmd 滚动滚轮,或使用捏合手势,可围绕指针缩放。使用滚轮、双指、按住 Space 并拖动,或中键可平移。画布仅以设备分辨率渲染可见区域。
  • 选择。 单击节点即可选中。按住 Shift 单击可将其添加到选区。在空白画布上拖动可框选(Alt:仅选择完全位于框内的节点;Shift:添加到选区)。图层、源码光标和画布共享同一选区。
  • 移动、调整大小和旋转。 拖动节点或其控制柄。按住 Shift 可锁定一个轴、保持纵横比,或以 15 度为步进旋转。按住 Ctrl 或 Cmd 可围绕中心调整大小,并在移动时跳过吸附。按住 Alt 可分离受令牌绑定的值或锚点。松开时应用编辑结果。幽灵轮廓和实时预览会跟随指针。
  • 吸附。 磁铁按钮可切换是否吸附到其他节点和页面。
  • 选中时的键盘操作。 画布获得焦点时这些按键才有效:先单击画布。方向键每次移动 1 px(Shift:10 px)。按住 Ctrl 或 Cmd 并使用方向键可调整大小。[ 和 ] 按 15 度为步进旋转。Delete 或 Backspace 可删除。Escape 可取消拖动或清除选区。未选中内容时,方向键可平移画布。
  • 检查器。 显示选中的节点并编辑其字段,包括使用颜色令牌设置填充和描边。
  • 快捷键。 按住 Ctrl 或 Cmd 并使用:S 保存,Z 撤销,Shift+Z 或 Y 重做,D 复制选中内容,O 打开文件(静态站点)。撤销和重做会将输入和画布编辑纳入同一历史记录。
  • 诊断。 底部面板会列出错误、警告和提示。带有位置的行可跳转到源码中的对应位置。
  • 保存和冲突。 保存会将文本写入磁盘。如果磁盘上的文件发生更改,未编辑的会话会重新加载该文件。存在未保存编辑的会话会显示冲突提示:重新加载将采用磁盘上的文本(撤销可恢复你的文本),覆盖则会写入编辑器中的文本。关闭含有未保存编辑的标签页前,浏览器会询问是否确认。
事实来源
  • 源码面板中的输入绝不会被覆盖。引擎会将其他更改(画布、Agent、磁盘)合并到面板中,同时保留已输入的按键内容。
  • 画布和检查器中的编辑会就地修改文本。注释和布局会保留。如果无法准确应用补丁,引擎会以规范形式重写文档,显示一条注释已移除的警告,撤销操作可恢复注释。当编辑位置的布局无法准确应用补丁时,就会发生这种情况,例如节点与其他文本位于同一行、内联的 { ... } 子块,或新建的顶层节点。移除节点时,也会删除其正上方的 // 注释行,页面会对此进行说明。
  • 源码存在错误时,画布会保留最后一次有效渲染,并标注“正在显示上次有效预览”,诊断面板则会列出错误。
静态站点

编辑器也可以作为静态站点运行。引擎以 WebAssembly 模块的形式在 Worker 中运行。整个过程不涉及服务器。文档从用户的磁盘打开,并保存回磁盘。

构建站点:

cargo build --target wasm32-wasip1 -p zenith-editor-wasm --profile release-wasm
node zenith-cli/scripts/build-static-editor.mjs --out dist/editor

脚本从 target/wasm32-wasip1/release-wasm/(或 $CARGO_TARGET_DIR)读取模块。传入 --wasm <file> 可指定其他文件。它会将页面、模块、打包的字体和 samples/(示例)复制到 --out。所有 URL 都是相对路径,因此站点可以放在子目录中。可使用任意文件服务器在本地测试,例如 python3 -m http.server -d dist/editor。

主机要求:

  • 通过 https:// 或 http://localhost 提供服务。File System Access 选择器和 crypto.subtle 需要安全上下文。
  • 将 .wasm 作为 application/wasm 提供。类型不正确仍可加载,但无法使用流式编译。
  • 在 script-src 中允许 'wasm-unsafe-eval'。浏览器会在该源下编译模块。
  • 允许来自同一源的 Worker:worker-src 'self'。Worker 脚本为 js/engine/wasm/worker.js。
  • 在 img-src 中允许 blob: 和 data:。页面会从 blob 绘制 PNG。
  • 将 connect-src 'self' 保持不变。页面会从同一源获取模块、字体和示例。
  • build-static-editor.mjs 会写入一个 _headers 文件(适用于 Netlify 和 Cloudflare Pages),其中包含以下策略:default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; worker-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' blob: data:; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'。其他主机需要手动设置相同的标头。

运行方式:

  • 页面会在启动时选择主机。<meta name="zenith-host" content="wasm">(由构建过程写入)会选择 wasm 引擎。如果没有该 meta 标签,页面会请求一次 /api/state。zenith edit 会响应,页面随后使用它。
  • 使用工具栏按钮打开 .zen 文件或项目文件夹。文件夹会为文档提供其导入项和资源。Chromium 会将保存内容写回文件。其他浏览器通过 <input type=file> 读取,并通过下载保存。
  • 除 Noto Sans Regular 和 Bold 之外的打包字体会按需从 fonts/ 加载。
  • ?doc=samples/<name>.zen 可打开示例。默认值为 samples/stack.zen。
  • 每次引擎调用都会将会话和项目文件发送到模块。请勿将大型图片放入项目文件夹。
  • 在静态站点上保存文件不会将 doc-id 写入文件。
Agent 和 MCP

Agent 驱动的会话与页面上显示的会话相同。通过 HTTP,POST /api/cmd 会运行编辑器命令({"command":"commands.list"} 可列出命令)。Agent 所做的编辑会实时显示在页面上。通过 MCP,六个工具可调用引擎。它们仅打开和保存 .zen 文件。读取根目录为文档所在目录(或 root)。除非服务器以 zenith mcp --root / 运行,否则拒绝将 / 作为读取根目录。服务器最多保留 16 个会话:新会话会逐出最近最少使用且没有未保存编辑的会话。

工具用途
zenith_editor_open在编辑器会话中打开 .zen 文件。返回会话 ID。脏会话需要传入 discard=true 才能重新打开。
zenith_editor_command在会话上运行一条编辑器命令(select.hit、gesture.commit、tx.apply、history.undo、file.save 等)。文本编辑需要会话的 version。
zenith_editor_render将会话页面渲染为 PNG。文本有错误时,会渲染最后一份有效文本(stale: true)。
zenith_editor_sessions列出会话:ID、类型(本地或已附加)、路径、版本、脏状态、有效状态、冲突状态。
zenith_editor_close关闭会话。未保存的编辑需要传入 discard=true。关闭已附加的会话只会将其移除。
zenith_editor_attach附加到此计算机上运行的 zenith edit,让查看页面的人看到 Agent 的编辑。传入它打印出的 URL。
## 历史记录与版本
本地的单文档编辑历史(快照、撤销/重做、持久化的命名版本)——完全不影响渲染流程。

Zenith 会为每个文档保留本地编辑历史,完全不影响渲染流程——它绝不会改变像素。首次编辑时,文档会获得一个稳定身份:一个写入文件且渲染器会忽略的 ULID doc-id。此后,每次引擎编辑(tx --apply、 library add、undo/redo/restore)都会记录为一个完整的快照(保存状态,而非操作日志),因此即使手动编辑,历史记录也能保留。

zenith tx poster.zen recolor.json --apply   # an edit — recorded automatically
zenith undo poster.zen                       # step back, rewriting the file in place
zenith redo poster.zen                       # step forward again
zenith history poster.zen                    # list the timeline (--json for tooling)

zenith version poster.zen "launch-v1"        # save a NAMED version, kept indefinitely
zenith restore poster.zen launch-v1          # rewrite the doc to that version
zenith restore poster.zen @head~1            # …or to a revspec: v2, @head~1, @latest:named, a name

zenith sync poster.zen                        # capture an out-of-band change (GUI / hand-edit / git checkout)

历史记录分为两个层级。撤销/重做会在临时会话时间线上移动——快速、本地,适用于进行中的工作。命名版本是持久化的内容寻址检查点(SHA-256 + DEFLATE),会一直保留,直到你将其删除;restore 可跳转到任意版本。sync 用于将引擎外部所做的编辑纳入历史记录,确保历史完整。历史记录尽力写入:如果无法写入,文件仍会保存——编辑绝不会因此受阻。

与编码 Agent 搭配使用

使用 zenith plugin install 为 Claude Code / Codex / OpenCode / Cursor / … 安装技能,并为远程服务/CI 安装 MCP 服务。

Zenith 附带一项技能,用于教会 AI 编码 Agent 如何使用 CLI——Agent 驱动的创作 → 验证 → 渲染 → 编辑循环、设计方案,以及 --help 无法涵盖的令牌/品牌规范。为你使用的 Agent 安装该技能:

zenith plugin install                  # auto-detect installed agents, install for your user
zenith plugin install --claude --codex # choose specific agents
zenith plugin install --all            # every supported agent
zenith plugin install --claude --scope project   # into ./ for one repo
zenith plugin list                     # see what's installed where

Claude Code、Codex 和 OpenCode 会获得完整的文件夹技能(参考资料包、模板和主题);其他 Agent(Cursor、Windsurf、Aider、Zed、Gemini、Copilot、Continue、Kiro、 Antigravity)会获得一个独立的规则文件,其中链接回自文档化的 CLI。匹配的文件会保持不变。使用以下命令升级已安装的资源:

zenith plugin install --force

--force 会覆盖存在差异的已安装文件,包括用户所做的更改。不加此参数时,存在差异的文件会保持不变。使用 zenith plugin uninstall 移除安装内容。

MCP 服务(远程 / CI / 托管 Agent)

对于通过模型上下文协议发现功能的 Agent,以及 CI 和托管/SaaS 流水线,Zenith 可作为一流的 MCP 服务运行。它并非对 CLI 的简单封装:工具结果经过精简,为结构化 JSON;通过单个 zenith_schema 工具按需获取架构详情(因此模型无需携带每种节点/操作的架构);大型或二进制产物(渲染结果、大型树、差异)会以指向内容寻址存储的资源链接形式返回,而非内联;文档可通过 doc-id 寻址,Agent 无需再管理路径。完整的创作循环均已开放——zenith_schema、zenith_validate、 zenith_inspect、zenith_tokens、zenith_tx、zenith_fix、zenith_render、zenith_perceive、zenith_fmt、zenith_merge、 zenith_theme_new,以及 scratch/candidate/promote/finalize 工作区工具。指针式编辑(命中测试、拖动、撤销、实时渲染)使用 zenith_editor_* 工具,详见浏览器编辑器。

MCP 渲染参数约定
format必填:png、svg、pdf 或 scene。
page从 1 开始。默认为所有 PDF 页面;其他格式默认为第 1 页。
raster_scaleSVG/PDF 的回退分辨率。有限值 0 < F <= 4,默认值为 1。
scale / contact_sheet仅适用于 PNG。
out可选的受保护文件写入,与产物资源链接并列。
diagnostics包含软诊断信息。设为 false 时,回退报告仍会显示。

MCP zenith_merge 支持 format: png|svg,默认使用 PNG。SVG 接受有限的 raster_scale 值,范围为 0 < F <= 4,默认值为 1。文档、本地和全局批处理策略均适用。结构化响应会保留已提交的路径和部分行。清单写入错误会保留行数,并将工具结果标记为错误。没有 MCP 变体工具。

通过 stdio(默认传输方式)运行:

zenith mcp

将任何支持 MCP 的客户端指向它:

{
  "mcpServers": {
    "zenith": { "command": "zenith", "args": ["mcp"] }
  }
}

……或者,对于 Claude Code:claude mcp add zenith -- zenith mcp。

远程 / 托管式服务。 使用可选的 http 功能构建,并在单个 /mcp 端点上提供原生 Streamable-HTTP 服务。传输层运行在与 zenith edit 相同的受限 std::net HTTP 层上,且不会增加依赖:

cargo install --path zenith-cli --features http --locked
zenith mcp --http 127.0.0.1:8080     # prints the token to stderr
# test it:
curl -s -XPOST http://127.0.0.1:8080/mcp \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

这些工具会读取和写入文件,因此 HTTP 传输层会在读取请求正文前检查每个请求:

  • 绑定。 仅限回环地址。--allow-remote 允许使用其他地址。流量是纯 HTTP:请在前面部署 TLS 反向代理。
  • 令牌。 Authorization: Bearer <token>。令牌为 ZENITH_MCP_TOKEN(至少 32 个字符);否则,启动时会生成一个随机令牌并打印到 stderr。
  • Host 和 Origin。 Host 必须是 localhost、IP 地址、--http 主机或 --allow-host 名称。浏览器的 Origin 必须指定同一主机。
  • 正文。 Content-Type: application/json,最大 8 MiB。
  • 根目录。 每个工具路径(文档、输出、数据、捆绑包)都必须位于 --root 之下,默认为工作目录。通过 stdio 使用时,--root 可选。在指定根目录后,文档读取的所有文件(导入项、资源、数据、本地 .zenith.kdl)都必须位于该根目录内。用户级全局配置($HOME/.config/zenith/config.kdl)和系统字体不受此限制。

工作区存储(临时候选项、版本历史、渲染后的资源制品)位于 $XDG_DATA_HOME/zenith(默认为 ~/.local/share/zenith)下;设置 ZENITH_DATA_DIR 可在隔离式 / 托管式部署中更改其位置。

本地 Agent 应优先使用 CLI + 技能,而不是 MCP。如果环境可以运行二进制文件,直接运行 zenith(通过 zenith plugin install 安装)是最快的方式。只有在无法运行二进制文件时才使用 MCP 服务——例如远程主机、CI、沙盒或托管式 / 生产服务,在这些场景中,你需要通过协议提供完整的读写能力。MCP 服务在这些场景中是首选方案。

此代码仓库提供了 server.json(MCP 注册表清单)。手动触发 Publish MCP 工作流,可为选定的稳定标签发布相应的 npm 启动器和注册表条目(通过 GitHub OIDC——无需注册表令牌),让 Zenith 能在 MCP 目录中保持可发现,并可由客户端通过 npx -y @zenitheditor/zenith-mcp 启动。

  • MCP 注册表名称:mcp-name: io.github.zenitheditor/zenith
## 工作区
由各司其职的 Rust crate 组成的工作区;zenith-geometry 不依赖其他 Zenith crate。

每个 crate 负责一项工作,并提供稳定的契约。zenith-geometry 不依赖其他 Zenith crate。zenith-core 在这些 crate 中只依赖 zenith-geometry。

Crate职责
zenith-geometry纯几何:路径、轮廓、布尔运算
zenith-coreKDL 解析器适配器、语义 AST、规范化格式化器、保留注释的源文件补丁器、令牌、验证、诊断
zenith-layout文本整形与字体度量(rustybuzz + ttf-parser);第三方类型仅限在此使用
zenith-raster光栅表面、混合模式、调整
zenith-perception针对几何和光栅的视觉 QA 报告
zenith-scene与后端无关的场景 IR + 编译(几何、文本换行、锚点、不透明度/裁剪、命中数据)
zenith-renderCPU PNG 后端(tiny-skia)、SVG 导出和矢量 PDF 后端;强制确定性
zenith-tx事务操作集、应用/试运行引擎、差异和审计记录契约
zenith-session本地机器上的文档身份、会话 DAG、持久化版本(内容寻址存储)
zenith-zpx打包设计导出(清单 + 烘焙)
zenith-producers更高层级的生成/导出辅助工具(原生 SVG、ZPX 烘焙)
zenith-pipeline配置策略、导入、字体、资源、验证、编译,以及通过主机 I/O trait 执行渲染;由 CLI 和 wasm 编辑器共用
zenith-editor编辑器引擎:在可序列化会话上运行的无状态命令注册表;由浏览器、zenith edit 和 MCP 共用
zenith-editor-wasm作为 wasm32-wasip1 命令模块的编辑器引擎,用于静态网站(不发布)
zenith-clizenith 命令行工具(crate zenith-tool):分发、参数解析、JSON/人类可读输出、MCP

在你的代码库中使用

`.zen` 文件只是文本——提交它,在 PR 中审查它,在 CI 中渲染它,并回滚它。

Zenith 文件只是文本,因此可以和代码放在一起。将它提交到 git。在 pull request 中并排查看差异,审查设计变更。在 CI 中渲染,及时发现上线前的布局问题。在工作流中生成多个变体。像回滚其他文件一样回滚它。设计不再是一个需要导入导出的独立世界,而是构建流程的一部分。

适用对象

AI/Agent 构建者、工程团队、大批量内容制作方和工具构建者。
  • AI 和 Agent 构建者:需要可靠地生成和编辑视觉内容,而不是靠截图碰运气。
  • 工程团队:希望将设计资源放入代码库,在 PR 中审查,并在 CI 中构建。
  • 大批量内容制作方——营销、出版、本地化:需要大量正确的变体。
  • 工具构建者:更愿意基于开放格式构建,而不是依赖封闭的云 API。
## 展示
可重复使用的 Zenith 示例位于 zenith-showcase 子模块中。

公开展示库位于 zenitheditor/zenith-showcase,并在此作为 zenith-showcase 子模块链接。

这里汇集了可重复使用的 Zenith 示例:.zen 源文件、渲染输出、视觉方案、动作、滤镜、背景、海报、传单、书籍、杂志、广告、图表、演示文稿以及其他生成式设计作品。

只有在你拥有分享文件的权利,并且允许他人依据声明的许可证重复使用所提交的源文件、输出和资源时,才将文件放入展示库。私人作品、客户作品、仅用于作品集的作品或采用自定义许可证的作品,应改为链接到展示库的外部作品集;外部作品的许可仍由所有者决定。

状态

Zenith 正处于首个公开发布系列。作者 → 验证 → 编辑 → 渲染的流程已端到端打通:解析、诊断集、事务引擎、PNG/SVG/PDF 渲染、本地历史记录、库子系统和变量数据合并均已实现并通过测试。随着项目逐步成熟,格式、线缆类型和命令接口仍可能演变。

贡献

有关如何参与引擎开发,请参阅 CONTRIBUTING.md;有关具有约束力的仓库约定(人类贡献者和 Agent 贡献者均以此为准),请参阅 AGENTS.md。CHANGELOG.md 列出了各版本的变更。

许可证

Apache-2.0。请参阅 LICENSE。随附字体采用 SIL Open Font License 1.1(请参阅 zenith-core/assets/fonts/LICENSE.txt 和 zenith-fonts-fallback/OFL.txt)。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。