scored-review-loop:AI Agent 工具实践指南
2026-09-30 3467261
2026-09-30 0
工作中遇到相关需求时,geml值得先读说明,因为它主要用于一种格式,两种读者,人们和 AI 代理现在共同编写相同的文档,人们清晰易读;机器可寻址、可验证和版本化, geml 是纯文本 — 由一个类型块组织所有内容。从文档与演示交付的使用方式看,内容结构和版式在转换后容易走样是采用前必须回答的问题。落地前可以拿一份结构复杂的真实文档完成转换,用标题层级、表格图片、字体版式和可编辑性判断它是否真的省事。我的判断是,它更适合经常交付正式文档或演示稿的团队;若眼下没有这类需求,先保留观察即可。

geml — 通用表达标记语言
英语 | 中文
geml 是一种 Agent-Native 基本标记格式和协议,专为人和 AI 代理读写相同的 document. 而设计 一种格式,两种阅读器。 在代理驱动的开发和知识工作中,纯文本和 Markdown 没有确定性的块边界:程序和模型将整个文件换入,然后将整个文件换出——最多用行窗口探测它,然后逐字重述原始内容以重写它。令牌成本随着文档的长度而增加,并且操作变得臃肿。经过几轮重写后,其他地方摘录的副本开始出现偏差。
您无需更改任何内容即可开始。 geml list、geml find 和 geml get 解决您已有的 Markdown — 没有任何内容被转换,没有新文件,您的 .md 仍然是 .md:
geml list README.md # every section, as an address
geml get README.md '#key-features' # read ONE section, not the file
geml set README.md '#key-features' --body # write one section back
geml replace README.md 'old text' 'new text' # swap a string, told which block held it
只有该部分进入代理的上下文 - 几个 KB,而不是整个 ~48 KB 文件。
需要比一个部分更精细的内容——一个块、一张图表、一张表格?让 .geml 站在中间立场:在该颗粒上进行编辑,您发布的 --to md 永远不会偏离它。
一个区块有一个名字;它里面的东西有一个坐标。 一个表格的单元格,一个
data 块的叶子,meta 中的一个键 — 每个结构都有一个坐标
给出它,get 和 set 恰好落在该值上。
geml get doc.geml '#fy[2]["Q1"]' # one cell
geml set doc.geml '#intake["fields"][1]["name"]' # one leaf in the JSON
对于人们来说,纯文本读起来干净;对于代理来说,它是可寻址、可验证、可追踪、可恢复的 “Doc-as-a-Base”。
geml 是最小的。 它是纯文本——仍然干净,看不到渲染器; 整个语言的一个块语法; 本身是可寻址、可验证、可引用的结构。
geml 不是为每种内容使用单独的迷你语法,而是在一个容器中携带每种内容:类型化块。代码是一个块。表格、图表、数学、标注、甚至元数据也是如此,只要您希望它可寻址,一系列散文也可以是这样的(=== text)。稍后扩展它也同样简单。每次的形状都是相同的,这使得该语言很容易学习,并且很难出错。
=== code {#hello lang=python}
print("hi")
===
geml get doc.geml '#hello' # by name, just this block
块有名称,因此动词有地方可以放置 - 完整的语法位于 1 分钟内的格式为。
内容: 它解决了什么 · 为什么现在 · 有什么不同 · 1 分钟格式 · 配置文件 · 送给程序员的礼物 · 亲身体验 · 使用 LLM · 成熟度和版本 · 设计 · 路线图 · 参与 · 许可证
它解决什么问题
问题已解决
上下文加载和令牌膨胀
AST-级别精度和解析确定性
文档副本碎片
主要特点
1. AST-级别结构化操作
2.低令牌读写
#id 命中一个语义完整的块,其余部分永远不会进入上下文。3.单一事实来源、模块化参考
4. 稳健的双向读写
5. 基于配置文件的域可扩展性
profile 元数据扩展领域词汇(e.g.设计风格、交互表单、代码图、媒体时间线),无需发明新语法或破坏解析器。比较
| 尺寸 | 降价 | JSON / YAML | geml |
|---|---|---|---|
| 上下文成本(逐块I/O) | 高(整个文件输入和输出) | 高(整个文件+语法噪音) | 最小(仅目标块) |
| 精确的AST操作 | 弱(没有严格的语义节点) | 强 | 强大(专为代理读写而构建) |
| 人类可读性 | 高 | 中等 | 高 |
| 单一来源参考 | 不支持 | 需要协议扩展 | 本机(模块化嵌入) |
| 域可扩展性 | 破碎(专有语法黑客) | 依赖于模式 | 本机配置文件(零新语法+经过验证) |
| 写入安全 | 弱 | 中等 | 强(登陆前拒绝错误写入+单块恢复) |
为什么LLM时代需要全新的文本格式
因为文档的生产者和消费者都发生了变化。
在传统的软件工程中,文档要么是供人们阅读的静态解释,要么是程序的序列化数据文件。
如今,人们和 AI 代理频繁地就同一文档进行协作。当代理人成为文档的“第二读者和共同作者”时,旧的平衡就永远打破了:
然而,我们现有的文本基础设施都不是为这个场景设计的:
这三个失败的根源在于每个工具自身的优点:Markdown 的“从不出错,写任何东西”赋予了人们写作的自由——这正是机器不能信任它读回的结构的原因; JSON/XML 严格的模式赋予了机器确定性——这也正是为什么没有人用它来写散文的原因。 优点就是缺陷,这就是为什么补丁无法修复这个问题:将“损坏的引用必须使构建失败”附加到 Markdown 上背叛了它的契约,并且从 JSON 中剥离包装器语法否认了它的本质。当人们和代理开始高频度地共同编写相同的文本时,需要的不是两个极点之间的妥协,而是一种将“人可读”和“机器可操作”视为从第一天开始的一个设计约束的格式。
答案: “文档作为基础”
geml 没有发明任何沉重的新运行时。借用 Roy Fielding 博士论文的 REST 架构风格,它为纯文本文档提供了一组标准的操作语义:
| 老痛 | 匹配能力(四大定律) | 它购买了什么开发商和代理商 |
|---|---|---|
| 改变一个地方意味着重写整个文本 | 寻址法则 | 每个区块都带有一个#id; get/set 单独读取和写入该块。 从未加载的内容无法被破坏 - 上下文窗口仍属于您。 |
| 到处都是副本,都在漂流 | 投影定律 | === embed 动态计算而不是复制粘贴;源头的一个定义结束了同步副本的工作。 |
| 错误的格式/损坏的引用会污染下游 | 验证法则 | 在构建时检查引用和语法; 错误的写入在落地之前就会被停止,无需等待人工审核。 |
| 一次错误的编辑会强制整个文件回滚 | 回滚法则 | 同伴 .gemlhistory 原子地恢复单个块 - 不拆除页面;代理的轻量级安全网。 |
文档不再只需要一种格式 - 它需要一组动词。 geml 保持纯文本可读性并添加确定性块级操作。
深入研究: 如果您对 LLM 时代工程文档的困境以及为什么我们需要从头开始重新设计纯文本格式感兴趣,请阅读我们博客上的全文:“为什么在 LLMs 时代我们需要新的文本格式?”
geml 有什么不同
geml 有意保持小型化——我们对设计 的思考方式、它拒绝的内容以及仍然开放的内容都在 [中。
这四种功能是在前一章中建立的——寻址、投影、验证、回滚。本章是每种格式的对抗之处,也是 geml 划定其界限的地方。
其他格式如何比较
四者各自在自己的领域都有成熟的解决方案;不同寻常的是以一种纯文本格式满足所有四个要求:
| 家庭 | 国家到底是什么 | 可寻址/可引用 | 可投影/可嵌入 | 可验证 | 历史/可追溯性 |
|---|---|---|---|---|---|
| 文字/文档 | 不透明状态 | ❌ 无块级密钥;通过平台APIs访问 | ❌ 仅限复制粘贴 | ❌根本不检查 | ⚠平台服务器端,不在文件中 |
| 降价/AsciiDoc | 一串字符 | ⚠ 标题锚点或方言 ID;没有 read/write 动词 | ⚠ 方言嵌入(黑曜石 ![[…]]、include::)— 默默地打破 |
❌ 损坏的链接会默默失效 | ❌ 无格式 — 需要外部 git |
| JSON / XML | 数据序列化 | ✔(ID /架构) | ⚠ 仅 XML(XInclude,外部) | ✔ 通过外部工具链 | ❌ 无格式 — 需要外部 git |
| geml | 纯文本+块结构 | ✔ 每个块都有一个唯一的 #id(可本地引用) |
✔ === embed:引用就是查找(本机) |
✔ 构建时错误 | ✔ 文件旁边的 .gemlhistory(本机可追踪) |
Item by item: vs. CommonMark · vs. XML and JSON · a 7-format capability matrix.
与 Markdown 共存:geml 是编辑真相来源,Markdown 是交付的神器。使用 geml and ship .md or .html 和以前一样。 协作,而不是锁定。 (投影是有损的:块 id 和表格绑定图表无法幸存。)
不要相信表格中的说法 - 重新运行它。 这是我向模型提出的问题:
根据您自己刚才编辑 READMEs 的经验,描述一下您在文档上执行的命令步骤(我看到您使用 grep 等),以及是否缓存文档以保存令牌 - 让我们进行比较,从中看看 geml 的哪些部分实际上会赢得它们的位置。
返回的结果:一次编辑花费了 和 真实一天重播的。将问题粘贴到您自己的模型中,看看它会告诉您什么。
PS:我仍在尝试弄清楚 codemap 产生的上游链(谁称之为)和下游链(它称之为什么)是否可以以相同的方式固定函数和调用站点 - 并更改项目代码。当我有报告时,我会发布一份报告。
1分钟内的格式
类型块
一种形状,每种类型。 块的基本语法是 === type [attributes] … === (其中 {#id .class key=val} 等属性是可选的) - 只有 type (以及其主体的读取方式)发生变化:
=== code {lang=python}
print("hi")
===
=== note {.intro}
Parsed prose with *emphasis* and a [[#budget]] reference.
===
=== meta
title = "Budget plan"
===
运行 =(三个或更多)打开一个区块;等长运行将其关闭;较长的栅栏嵌套在较短的栅栏内。带有 #id 的块也可以用标记的栅栏 === #id 关闭 - 没有栅栏长度计数,这使得长块更难出错(嵌套仍然需要更长的外栅栏:体内相同长度的裸 === 会提前关闭块,无论是否标记)。类型决定正文的读取方式 - raw(逐字:code、diagram、math、table)、flow(带有内联标记的解析散文: note、text) 或 data(每行一个 key=val:meta); embed 根本不携带任何主体——它的 src= 命名了它所代表的块——并且每个块都可以携带一个属性对象 {#id .class key=val},其中 .class 是一个“语义”标签,而不是一个样式挂钩。完整的内联语法(强调、链接、[[#id]] 自动引用、媒体、脚注、内联 $math$)位于 规范 中。
桌子——两个主体,一个模型
直观地写一个表格:
=== table {#budget caption="Annual cost"}
Plan
Months
Rate
Basic
1
30
Pro
2
30
===
...或作为数据。一张桌子保存着事实;其上的 view 得出
计算列和摘要行:
=== table {#fy25 format=csv header=1}
Segment, Q1, Q2, Q3, Q4
Cloud, 8, 10, 12, 14
Platform, 5, 6, 7, 9
Services, 3, 4, 4, 5
===
=== view {#fy25-report src=#fy25 compute="FY [%.1f] = Q1 + Q2 + Q3 + Q4; n = 1" summary="Segment = 'Total'; FY [%.1f] = sum(FY); n = sum(n)"}
===
两种表格描述的是同一型号。 FY 列和 Total 行是在构建时通过视图计算的:
| 段 | Q1 | Q2 | 第三季度 | 第四季度 | FY | n |
|---|---|---|---|---|---|---|
| 云 | 8 | 10 | 12 | 14 | 44.0 | 1 |
| 平台 | 5 | 6 | 7 | 9 | 27.0 | 1 |
| 服务 | 3 | 4 | 4 | 5 | 16.0 | 1 |
| 总计 | 87.0 | 3 |
compute 在列上每行运行 + - * / ( ); summary 从聚合 sum / avg / min / max / count 中添加一英尺行(对其进行算术,e.g。加权比率);尾随的 [printf] 设置数字显示。上面的 n 是行计数习惯用法 - count 计算一列中的非空单元格,因此求和的常量列就是对行进行计数。
表还可以通过 src="regions.csv" 从外部 CSV 提取数据。
❓ 供讨论: 计算列和摘要行是否应该保留? 保留、冻结或丢弃 — 说出哪个。
数学
=== math {#gauss caption="Gaussian integral"}
\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}
===
$$\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}$$
图表 — 托管 DSL,或绘制表格
geml 从不解释图体;它将其路由到可插入渲染器(未知的 format 是一个警告,主体被保留):
=== diagram {#flow format=mermaid caption="Review flow"}
graph LR
A[Draft] --> B{Review} -->|ok| C[Publish]
===
graph LR
A[Draft] --> B{Review} -->|ok| C[Publish]
图表还可以绘制表格 - 单一事实来源,在构建时检查列引用并且不复制数据:
=== diagram {format=geml-chart data=#fy25-report type=bar x=Segment y=FY}
===
取自上面的 #fy25-report 视图 — FY 是计算列,因此
图表绑定到派生它的视图,而不是基表:
xychart-beta
title "FY by segment"
x-axis [Cloud, Platform, Services]
y-axis "FY"
bar [44, 27, 16]
数据——一种值,而不仅仅是文本
每个块类型都会对其所包含的内容进行命名:code 代码区域,table 网格,math 公式。 data 保存一个数据值,它是数据格式所在的位置 - json(默认)、jsonl 和 yaml 用于声明的子集; toml 保留。键入意味着读取正文,而不仅仅是显示:缺少逗号会使构建失败,geml get --json 返回值本身,图表可以直接读取它。
=== data {#log format=jsonl}
{"ts":"09:00","p95":41}
{"ts":"09:10","p95":58}
===
jsonl 正文每行保存一个记录,程序可以将其盲追加到文件末尾。记录也可以保留在自己的文件中:src=ops/latency.jsonl#L900-999 命名文件,并且可以选择使用行窗口 - 因此日志会像以前一样继续附加和尾部,而文档是其经过验证的、可寻址的、可绘制图表的视图。
嵌入——动态引用,而不是副本
一个块可以代表另一个块:在同一文档中由 src=#id 表示,跨文档由 src=other.geml#id 表示。嵌入是在渲染时对源进行的动态查找 - 更改源一次,然后每个嵌入都会随之而来;删除它,geml check 当场构建失败。
=== embed {src=#fy25}
===
身体保持空虚;目标位于 src=。
Markdown 无法向您显示投影。要实时查看:安装 浏览器扩展,打开 到 sample.geml 的原始链接,然后滚动到 Transclusion 部分 - 同一文档投影 (src=#roadmap)、跨文档投影,甚至链接的分辨率(嵌入拉出一个图表,它本身绑定到另一个文件中的表格)都在适当的位置渲染:那里没有写入任何内容,但编辑源一次,投影就会随之而来。
配置文件——领域词汇,像乐高积木一样组装
想要创作交互式表单、定义设计令牌系统或在文档中映射整个代码库的调用图?
在传统的 Markdown 中,这需要专有插件(:::note、自定义 JSX 标签),不可避免地会分裂成不兼容的方言孤岛。
geml 通过 配置文件(应用程序层词汇表,规范 §8.6) 解决了这个问题:单行声明,可按需解锁特定于域的结构化超级能力。
=== meta
profile = "geml-style/v1 geml-form/v1"
===
=== form-field {#email label="Work email" type=email required pattern="[^@]+@acme\\.com"}
===
=== style-rule {#cta match="button.cta" bg="{{brand}}" radius="6px"}
===
无碎片扩展
• 像乐高积木一样混合搭配
核心语法保持最小和冻结,而领域功能无限扩展。调用图、设计令牌、表单验证、版本历史记录...用一行 profile = "..." 组成多个领域词汇表。
• ⚡ 零插件开销和即时工具支持
添加新的域块需要零解析器分支或自定义插件。自定义块立即继承整个基础设施:确定性 #id 寻址、geml get/set 块式突变、CLI 动词、MCP 协议和自主 AI 代理控制。
• 自然便携,永不锁定 在不破坏互操作性的情况下扩展功能。在任何第三方或不熟悉的处理器中,文档都保持 100% 的结构完整性和块级可寻址性,结束了切换工具时格式损坏的噩梦。
标准发布的配置文件
| 公司简介 | 状态 | 领域和角色 | 承认超能力 | CLI | 现场演示/示例 |
|---|---|---|---|---|---|
geml-codemap/v1 |
稳定 | 代码库架构和调用图 | code 块:anchor、name、entry-via |
`geml 代码映射构建\ | 验证\ | 服务 | 交互式调用图 · sample.geml` |
geml-media/v1 |
草案 | 媒体时间线、资产轨道和剪辑 | media, media-asset, media-clip, media-text |
`geml 媒体构建\ | export\ | 躺着\ | 待办事项` | 文档到视频(通过 ffmpeg 文档到 MP4) |
geml-style/v1 |
草案 | 设计令牌和响应式样式 | style-rule, style-state, style-screen, style-frame |
geml style check |
GitHub Blob 页面 1:1 副本 |
geml-history/v1 |
稳定 | 块级版本快照和回滚 | history-revision, history-keyframe, history-blob |
`geml历史保存\ | 得到\ | 恢复` | 原子块回滚工作流程 |
geml-form/v1 |
草案 | 声明形式和输入约束 | form、form-field、form-group + 验证规则 |
— | 交互式复杂表单示例 |
geml-translator/v1 |
草案 | 多语言环境翻译和嵌入 | embed 和 meta 属性 translate-to |
— | — |
想要查看配置文件的实际效果吗? •
geml-media现场演示:一剪文档一命令(geml media build ep01-cut.geml --out ep01.mp4 --burn-subs)协调 ffmpeg 对齐 audio/video、混合音轨并将字幕刻录到成品视频中(详细信息见playground/geml-media-demo))。 •geml-style现场演示:内容在page.geml中保持纯文本,而样式和布局则在github.style.geml中 — 渲染 GitHub 的 blob 页面的 1:1 像素精确副本,无需 CSS 锁定(详细信息请参阅playground/style-demo)。 • 下一节中的代码图本身就是一个Profile:.geml-code-graph/中的每个文档都声明profile = "geml-codemap/v1"。您还可以轻松地 创建您自己的自定义域配置文件。
给程序员的礼物——geml-code-graph
为了测试 geml 的表达能力和灵活性 - 最重要的是看看块级双向链接是否成立 - 让我们在代码图上尝试一下,这是程序员熟悉但要求很高的情况:
整个代码库的调用图,写为 geml。 geml codemap build 将调用图布置为 geml 文档树 - 每个方法都是 #id 块,#calls / #called-by 双向边缘。 下游链(方法的称呼)用于故障排除,上游链(谁称呼它)用于爆炸半径 - 所有这些都在一秒钟内可见;
npm i -g @geml/geml
geml codemap build # --root defaults to . : detect languages -> index -> one merged graph in ./.geml-code-graph/
geml codemap serve # opens your browser on the graph
[!NOTE] 要求。 CLI (
npm i -g @geml/geml) 的节点 22+。一切 下面是可选的,仅在注明的情况下使用:Joern 对于代码图中的 non-TS/JS 语言,以及 Chrome 查看器扩展。
[!TIP] TS/JS — 零设置:
build自行获取 scip 索引器。 Java / C / Python / Go / Kotlin — 额外下载一个,Joern:解压缩其发布包并将该文件夹传递给构建,e.g。--joern ~/joern/joern-cli(Windows 上为--joern C:\joern\joern-cli),或将其放在 PATH 上并跳过该标志。 混合前端 + 后端存储库 - 一切都合并到一个图表中。
geml-code-graph 本身就是一种图表格式 - 一行将其嵌入到任何 geml 文档 (=== diagram {format=geml-code-graph src=.geml-code-graph/index.geml} ===) 中,并且可选的每次提交挂钩(与 Claude 技能捆绑在一起)会在代码移动时重建它,因此图表不会漂移。
规模是经过衡量的,而不是承诺的:在 Apache Flink 的代码库上 — 13,585 个 Java 源代码
文件、~81,000 个方法、266,821 个调用边缘 — 纯文本数据表仍然
立即打开并查询,并且可以 grep 任何方法名称来跟踪其调用链。
自己复制:克隆 apache/flink 并运行 geml codemap build --joern …
它的根。
下一步——立即动手
▶ 尝试在 Playground 中编写 geml - 在左侧编辑,在右侧实时渲染,一旦引用中断,构建判决就会变成红色。无需安装,无需先阅读任何内容。
然后,按照适合您的顺序:
.geml 链接 (原始文件,而不是 GitHub blob 页面 - 那个是 HTML):geml 规范本身(dogfood — 规范是按比例渲染的 geml 文档),展示(一个计算表、四个图表、一个 Mermaid 流程和数学),或者playground/sample.geml 用于交互式代码图。playground/style-demo/ 是 GitHub Blob 页面的 1:1 副本 — 顶部栏、文件树、面包屑、Preview/Code/Blame、下拉菜单 — 其中page.geml 保存每个字符串,而 github.style.geml 保存每个颜色和长度,而观看者两者都不知道。它需要扩展和本地服务器(为什么是,以及两个命令):页面获取其样式表和图标,这是raw.githubusercontent.com所禁止的。npm i -g @geml/geml(节点 22+),然后 geml check 文档,或使用 geml codemap build 将其指向您自己的存储库。npx -y @geml/geml skill install 将创作技能、CLI 和 MCP 服务器放置在用户全局的每个项目中。它不编辑任何设置,也不安装任何挂钩。 详情。geml check 诊断、geml list 地址、--to html 标记),每个规则都标有其源和状态。将 geml 与 LLM 结合使用
目标是一件事:你的模型一次编辑一个块,并验证 - 永远不会重新读取并重新发出整个文件来更改一个段落。到达那里 一步走,哪一步取决于你用的是什么。
使用克劳德代码——运行这个
npx -y @geml/geml skill install
它安装创作技能、geml CLI 和 MCP 服务器、用户全局、
对于每个项目。没有 settings.json 编辑,没有钩子;升级后重新运行。
(更喜欢插件?claude plugin marketplace add geml-spec/geml,然后
/plugin install geml@geml — 相同技能,捆绑 MCP 服务器。)
使用 DeepSeek 线束 — 添加此捆绑包
相同的设置,打包为 dsh 捆绑包 — geml MCP 服务器加上创作和代码图技能:
dsh plugin --profile web add @geml/dsh-plugin # web = the profile dsh boots by default; use your own profile name if you run another
上线 dshmarket 和 Awesome-dsh-plugin;源在integrations/dsh-plugin/。
使用 Codex — 安装插件
再次为 Codex 打包相同的有效负载:两种技能、MCP 服务器和
SessionStart 挂钩。在签出此存储库时启动 Codex,它会显示在
/plugins(市场来源致力于
.agents/plugins/marketplace.json);要添加它而不克隆,则 git-subdir
条目位于 integrations/codex-plugin/ 中。
然后在一个会话中说一次,项目就切换了:
本项目使用geml作为其基础文档格式;生成其他格式 根据需要从中获取。
使用其他任何东西 - 粘贴此内容,然后检查输出
没有阅读能力的模型需要一次规则。粘贴下面的提示,然后
将 geml check 作为它写回的任何内容的门 - CLI 是
npm i -g @geml/geml(节点 22+)。
将文档写为 geml:每个块都是
=== type [attributes]…===(格式为 1 分钟 列出类型)。四个规则是 一些模型出错:关闭栅栏是精确开口的=运行 长度,包含===的主体需要更长的栏;标题是 仅 ATX#,无---frontmatter(元数据为=== meta);每个#id都是独一无二的,并且每个参考号([[#id]]、[text](#id)、[^id]、data=#id) 必须解决;没有原始的 HTML。规范规格是GEML-spec.md.
它将用它做什么
geml list doc.geml # CALL FIRST: every block, its address, kind, lines
geml find "words" doc.geml # search block content -> an address, not a line number
geml get doc.geml '#hello' # read ONE block (a heading id = its whole section)
geml get doc.geml '#hello' --intro # a section cuts three ways: --head | --intro | --body
geml set doc.geml '#license' --in template.geml#mit # replace that block, forking another
geml add doc.geml --after '#intro' --in snippet.geml # insert a fragment (keeps its own ids)
geml revert doc.geml '#plan' --rev -1 # roll ONE block back
geml check doc.geml # validate only: diagnostics + exit code
任何部分都可以分为三种方式,在 get 和 set 上都是如此:--head 是标题
行,--intro 第一个副标题 --body 之前所说的一切
在它下面 - 所以 --body 总是包含 --intro,并且当没有时等于它
副标题。可以编辑部分的开头,而无需拉动其子部分
进入上下文。
每个突变在写入之前都会被重新解析,如果它会破坏
文档——这使得无人值守编辑变得安全。其余动词
(delete, rename, history, --至 md|html|geml 转换,寻址
按类型或内容哈希块)位于
解析器 README。
MCP 服务器
标准模型上下文协议服务器随程序包一起提供,因此您的代理
编辑一次一个块,而不是重写整个文件 - 在 Markdown 和
geml 类似。它可以在 Windows、macOS 和 Linux 上本地运行; --root 是
服务器限制的目录(使用 . 或 ${workspaceFolder} 绑定到
活动项目)。
Claude Code — 一条命令设置(安装技能、CLI 和 MCP 服务器):
npx -y @geml/geml skill install
(或通过CLI手动注册:claude mcp add --scope user geml -- npx -y @geml/geml mcp --root .)
光标 — 将 .cursor/mcp.json 添加到您的项目中:
{
"mcpServers": {
"geml": {
"command": "npx",
"args": ["-y", "@geml/geml", "mcp", "--root", "${workspaceFolder}"]
}
}
}
(或在光标设置→功能→MCP:名称geml,命令npx -y @geml/geml mcp --root .)
Claude Desktop — 添加到 claude_desktop_config.json:
{
"mcpServers": {
"geml": {
"command": "npx",
"args": [
"-y",
"@geml/geml",
"mcp",
"--root",
"/absolute/path/to/your/docs"
]
}
}
}
然后只需请求您想要的更改 - “修复 FY26 表中的 Q3 行” - 并且
代理处理该块。你永远不会知道工具名称:每个工具都反映一个
CLI 动词 (geml set → geml_set),因此一个词汇涵盖了终端和
代理。
有两个保证比让模型重写文件更好:写入是
在到达磁盘之前进行解析,并拒绝其诊断(如果需要)
破坏文档,每次写入首先都会记录 .gemlhistory 修订版 - 所以
错误的编辑既可以防止又可撤销(geml_revert 恢复一个块,
文件的其余部分字节相同)。路径仍然局限于 --root,这是客户端
不能扩大。
将 --root 指向具有代码图 (geml codemap build) 的存储库,并且
同一台服务器还回答“谁调用了这个”——四个只读 geml_codemap_* 工具,
一个客户端条目而不是两个。每个工具和选项:
docs/mcp-guide.md.
生态系统和成熟度
geml 是一个小型的、年轻的规范——但是一个稳定的规范:1.0 已发布并可用于真实文档(此存储库自己的规范就是其中之一),具有严格的一致性套件、通过它的参考实现(独立于规范的版本)以及开放的提案流程。
有一个规范,并且是双语的。 .gemlhistory 边车
由 geml-history/v1 配置文件 定义 - 之上的应用程序层
规范而不是它的一部分,这也是为什么它是 MIT 并且规范是
CC-BY(LICENSE-spec.md 说明原因):
| 文件 | 英语 | 中文 |
|---|---|---|
| 规格 | GEML-spec.md |
GEML-spec_CN.md |
geml-history/v1简介 |
geml-history-profile.md |
geml-history-profile_CN.md |
该项目发布的每个配置文件:spec/profiles/。
版本和兼容性
GEML-spec.geml 是在 geml 中编写的规范,需要在每次测试运行时解析干净。acme-invoice),将无连字符的名称留给规范的未来版本(§8.5)。.geml(版本 sidecar .gemlhistory)、媒体类型 text/geml 或需要注册类型的 text/vnd.geml — text/geml 尚未向 IANA 注册。.geml URL 上的片段标识符命名带有该 id 的块(§0.6)——这不是 #tag 在 HTML 页面上的含义。我们是如何思考设计的
设计遵循什么
人类-智能体同构,而不是妥协 geml 没有将人类可读的 Markdown 和机器可读的 JSON 之间的差异分开,而是将人类可读性和机器确定性视为单一的、不妥协的约束。人类获得干净、不受干扰的散文;代理获得强类型 AST — 消除两种不同格式之间的转换损失。
文档作为基础,而不是字符流
传统文档是脆弱的字符流,编辑一个句子通常会强制重写整个文件。 geml 将文档视为具有稳定主键的结构化记录的可寻址数据库 (#id)。每个块都有独立的生命周期、空间坐标和适合 O(1) 代理读写的原子 CRUD 接口。
一种语法原始,无限领域词汇
拒绝为每种新内容发明语法补丁。 geml 使用单个 类型块原语 (=== type) 来承载代码、数据、表格、数学和布局。领域功能通过配置文件 (profile = "...") 无限扩展:语法保持 100% 冻结,而词汇保持开放——从根源上结束方言碎片。
嵌入优于复制:扼杀复制的动力
传统的超链接是指向其他地方的路标,鼓励复制粘贴,这不可避免地导致副本不同步。 geml 引用是动态视口 (=== embed):在源处定义一次,然后在任何地方进行实时投影。通过消除复制动机来维护单一事实来源。
编译器级完整性:像对待代码一样对待文档
Markdown 的精神是“永不失败,渲染一些东西”——这是代理幻觉和无声文档腐烂的主要滋生地。 geml 强制执行严格的构建时静态验证。损坏的 #ids、无效属性和循环引用会导致构建失败并出现非零退出代码。在错误污染下游系统之前捕获它们。
本地优先历史,而不是云锁定或 Git 开销
数据属于本地文件系统,版本控制属于块粒度。 geml 拒绝将版本历史记录锁定在专有云平台(如 Notion 或 Google Docs)后面,同时避免了 Git 进行微编辑时沉重的整个存储库提交开销。配套产品 .gemlhistory 提供纯文本 本地优先原子快照和外科手术回滚 (geml revert #id),确保真正的数据主权和安全。
因此它拒绝什么
| 拒绝 | 为什么 |
|---|---|
| 自己的图表语言 | 托管外部 DSLs(Mermaid、Graphviz、D2,...);该格式仅定义托管协议 |
| 原始-HTML 逃生舱口 | 语义保持可移植性,不依赖于后端或渲染器 |
设置文本标题 / --- frontmatter |
仅 ATX #,因此不会与主题中断发生冲突 |
| 完整的电子表格引擎 | 每行公式和汇总聚合就足够了;没有单元格寻址、查找或宏 |
路线图
1.0 规范(英文和中文)以及一致性套件 — 以及定义 .gemlhistory sidecar 的 geml-history/v1 配置文件@geml/geml:解析器,CLI,块级.gemlhistory跟踪geml mcp)geml)xai-org/plugin-marketplace 中列出的 Grok 插件参加
geml 是 1.0,但“稳定”意味着已有的规则不会在你的控制下改变,
并不是说设计已经确定了。到目前为止,确实有一个实现,并且
规范背后的一组意见。您的想法仍然可以改变规范本身。
如果你想参与其中:
来争论这些:
.gemlhistory边车真正值得拥有?geml get 没有选择器列表块。应该是geml list吗?--view 读取嵌入内容。标志,还是它自己的动词?或者领取一块:
| 间隙 | 它的立场 | 需要什么 |
|---|---|---|
| 更多代理工具的技能安装 | Gemini CLI、Qwen Code、AGENTS.md 已检测安装; MCP 服务器可与任何客户端配合使用 | 以同样的方式添加其余部分:Cursor、GitHub Copilot、Cline - 它们的规则文件约定变化很快,因此在写入之前请检查当前文档 |
| 底漆在其他型号上的保持力如何 | 只对克劳德进行过锻炼 | 让 GPT / Gemini / 本地模型分别从底漆中写入一批 geml,计算有多少个第一次通过 geml check,并报告他们不断出错的规则 - 这些是底漆应该命名的规则 |
| 更深入的黑曜石集成 | 已渲染,但尚未在社区商店中出现 | 在 CodeMirror 层进行编辑和无缝双向渲染,加上商店提交本身。想要了解黑曜石 API 的人。 |
| 其他浏览器上的查看器 | Chrome 作品 | Firefox / Safari 端口。 |
| 打包 RAG 集成 | LangChain / LlamaIndex 是参考实现 | 发布到PyPI;并连接其他框架(Haystack、DSPy,...)。 |
或者提出新的建议:
或者使用它:
| 场景 | 哪里 | 状态 |
|---|---|---|
| 从命令行 — 验证、转换、按块编辑、版本历史记录,全部在一个命令中 | @geml/geml(来源geml-parser/) |
可用 |
在浏览器中阅读 — 打开任何原始 .geml 链接,它会就地呈现:计算表、图表、美人鱼、数学,并以诊断作为横幅 |
Chrome 网上应用店 · 源 | 可用 |
| 让代理按块进行编辑 — MCP 服务器;代理更改一个块而不是重写文件,并且每次写入在到达磁盘之前都会经过验证 | docs/mcp-guide.md |
可用 |
| 从 DeepSeek Harness 使用它 — geml MCP 服务器加上创作和代码图技能,一个可安装的捆绑包 | @geml/dsh-plugin · dshmarket · 源 |
可用 |
从 Codex 使用它 — 再次使用相同的有效负载:两种技能、MCP 服务器和 SessionStart 挂钩,可从 /plugins 安装 |
integrations/codex-plugin/ |
可从此存储库获取;尚未在公共插件目录中 |
| 从 Grok 使用它 — 再次使用相同的有效负载:技能和 MCP 服务器 | integrations/grok-plugin/ |
可从此存储库获取; xai-org/plugin-marketplace PR 尚未开通 |
将 Logseq 图表同步到纯文本 — Logseq 2.0 DB 图表作为连续同步的 geml 文件,可寻址且 git 友好,以 restore 作为返回方式 |
@geml/logseq-sync · 源 |
npm 上的观察者;该插件从发布 zip 安装 - 市场列表 (PR #893) 尚未合并 |
| 将代码库变成文档 — 整个调用图作为 geml 文档的树,可浏览 | geml codemap build(设计) |
可用 |
| 在编辑器中编写 - 语法突出显示 + 构建时参考检查 | Visual Studio Marketplace · 源 | 可用 |
| 在 Obsidian 中渲染它 — 参考解析器 + 查看器的渲染器,与 Web 相同的代码路径 | integrations/obsidian/ |
建造,不在社区商店 |
提供RAG /代理框架 - 块级加载器(每个块一个块,携带block_id)+代理编辑工具 |
integrations/langchain+llamaindex/ |
参考实现 |
| 无需安装任何东西即可尝试 - 左侧编辑,右侧实时渲染 | 游乐场 | 可用 |
首先要阅读的三个文件: GOVERNANCE.md 了解如何做出决策
制作, CONTRIBUTING.md 了解如何发送作品,以及
CODE_OF_CONDUCT.md 关于人的一条规则 —
不同意设计就可以了,而不是反对人。
存储库布局
spec/ The specification as .md (EN / 中文) and the CC-BY spec
license, with profiles/ (application layers — geml-history,
geml-codemap, geml-style, geml-form) and proposals/ (GEPs),
both MIT
spec/in_geml_format/ The dogfood: the specification written in GEML, with its
.gemlhistory sidecar
geml-parser/ Reference parser, renderer, CLI + codemap toolkit (TypeScript, Node 22)
integrations/ Everywhere GEML plugs in: geml-viewer (browser extension),
geml-check-action (CI), vscode, obsidian, logseq (two-way
vault sync + the watcher), tree-sitter (brief),
langchain+llamaindex (RAG loaders), windows-icon
(Explorer file icons), and the agent-harness plugins —
claude-plugin, codex-plugin, grok-plugin, dsh-plugin
.agents/, .claude-plugin/ Plugin marketplace manifests, so the plugins show up
from a checkout (Codex `/plugins`, Claude Code `/plugin`)
playground/ In-browser playground (+ a live geml-code-graph of this repo)
docs/ Guides, design notes, comparisons/ (COMPARISON + vs-CommonMark +
vs-XML-and-JSON), assets (logos, used by the Pages site below),
and an example .geml to render
.claude/skills/ Claude skills: GEML authoring, and the code graph
.github/ CI + geml-check workflows, MCP registry publish, and issue
templates (bug, GEP, new implementation)
site/ The geml-spec.github.io/geml Pages site: a project homepage
(index.md) plus a Jekyll blog (blog/, posts in _posts/) —
the long-form "why a new format" article (EN / 中文) lives
there as its first post. `cd site && bundle exec jekyll
serve` builds it locally; the pages jobs in
.github/workflows/ci.yml build and deploy it on push to
main, grafting in playground/ as static output — with
playground.js built there rather than committed.