| *English | 中文* |
一种格式,两类读者。
人与 AI 智能体可共同书写同一篇章。
对人,清晰可读;对机器,可寻址、可校验、可带版本。
GEML 是纯文本——由一种类型块承载一切,由一个 .gemlhistory 伴生文件记忆。
▶ 到 Playground 试写 GEML——左边编辑、右边实时渲染,引用一断,构建判定当场翻红。无需安装。
GEML 是一种面向结构化文档的标记语言。.geml 文件本身就是纯文本,读它不需要任何渲染器。它也不为每种内容单独设一套迷你语法,而是把所有内容都放在一个构造上:类型块(typed block)。
=== code {#hello lang=python}
print("hi")
===
代码是块,表格、图形、公式、提示框、乃至文档元数据,也都是块。形态每次都一样,所以这门格式好学,也难写错。
Markdown 是为人类手写、人类阅读的文档设计的。而今天,同一批文档还要由 AI 智能体和 CI 流水线来书写、编辑、评审与查询——这一转变,对格式提出了三件 Markdown 从未需要提供的事:
GEML 就是围绕这三点做出来的。目标不是给某种文档格式”加上 AI 功能”,而是选一种对人更简单、对机器也更可靠的格式。
很多格式能做到其中一两件。GEML 的特别之处在于,一种纯文本格式三点都满足:
=== type {…} 类型块。一套语法要学、一套语法去正确生成:没有按特性各设的语法,也没有 HTML 兜底。#id、在任何地方引用它;悬空引用或断掉的跨文档链接是构建错误,而非静默的 404。自动编辑不会悄悄腐烂。.gemlhistory 伴生文件即可重建任意历史修订、把文档回滚——离线、无需 git、无需服务——而且它是纯文本,智能体能读懂文档的演变。跨 Markdown、HTML、CommonMark、AsciiDoc、Org-mode 的完整对照,见格式比较。
一种形态,通吃所有类型。 每个块永远是 === type {#id .class key=val} … ===——变的只有 type(以及正文怎么读):
=== code {lang=python}
print("hi")
===
=== note {.intro}
解析过的散文,可用 *强调* 与 [[#budget]] 引用。
===
=== meta
title = "Budget plan"
===
连续的 =(≥3 个)开块,等长的一串闭块;更长的围栏可嵌套更短的。带 #id 的块还可以用带标签围栏 === #id 闭合——不必数围栏长度,长块、嵌套块因此更难写错。类型决定正文如何解读——raw(原样:code、diagram、math、table)、flow(带内联标记的散文:note)、或 data(每行一个 key=val:meta);每个块都可携带属性对象 {#id .class key=val},其中 .class 是语义标签,绝不作样式钩子。完整的内联语法(强调、链接、[[#id]] 自动引用、媒体、脚注、行内 $公式$)见规范。
可视化写法:
=== table {#budget caption="年度成本"}
| Plan | Months | Rate |
|-------|-------:|-----:|
| Basic | 1 | 30 |
| Pro | 2 | 30 |
===
……或写成数据,带计算列与汇总行:
=== table {#fy25 format=csv header=1 compute="FY [%.1f] = Q1 + Q2 + Q3 + Q4" summary="Segment = 'Total'; FY [%.1f] = sum(FY)"}
Segment, Q1, Q2, Q3, Q4
Cloud, 8, 10, 12, 14
Platform, 5, 6, 7, 9
Services, 3, 4, 4, 5
===
两种形态描述同一个模型。FY 列与 Total 行在构建期算出:
| Segment | Q1 | Q2 | Q3 | Q4 | FY |
|---|---|---|---|---|---|
| Cloud | 8 | 10 | 12 | 14 | 44.0 |
| Platform | 5 | 6 | 7 | 9 | 27.0 |
| Services | 3 | 4 | 4 | 5 | 16.0 |
| Total | 87.0 |
compute 对各列逐行做 + - * / ( ) 运算;summary 用聚合 sum / avg / min / max / count(并可对聚合结果再做算术,如加权比率)生成表尾一行;列名后的 [printf] 控制数字显示。
表格还支持用 src="regions.csv" 引入外部 CSV。
=== math {#gauss caption="高斯积分"}
\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}
===
GEML 从不解释图形正文,而是把它交给可插拔渲染器(未知 format 仅告警、正文原样保留):
=== diagram {#flow format=mermaid caption="评审流程"}
graph LR
A[Draft] --> B{Review} -->|ok| C[Publish]
===
graph LR
A[Draft] --> B{Review} -->|ok| C[Publish]
图形还能为一张表作图——单一真相,列引用在构建期受校验,数据零拷贝:
=== diagram {format=geml-chart data=#fy25 type=bar x=Segment y=FY}
===
取自上面的 #fy25 表:
xychart-beta
title "FY by segment"
x-axis [Cloud, Platform, Services]
y-axis "FY"
bar [44, 27, 16]
为了更好地体会 GEML 格式的强大与灵活,我们拿程序员最熟悉、也最有挑战性的场景之一——代码图——来试一试。
把整个代码库的调用图,写成 GEML。 geml codemap build 把调用图落成一棵 GEML 文档树——每个方法一个 #id 块,#calls / #called-by 正反向边。正向调用的下游链做问题排查、反向被调用的上游链查看影响面,全都秒速得见;

npm i -g @geml/geml # 需要 Node 22+
geml codemap build # --root 默认当前目录:识别语言 → 索引 → 合并成一张图,落在 ./.geml-code-graph/
geml codemap serve # 自动打开浏览器看图
[!TIP] TS/JS——零前置,
build会自己拉取 scip 索引器。 Java / C / Python / Go / Kotlin——多下载一个 Joern:release 包解压后把目录传给 build,例如--joern C:\joern\joern-cli(放进 PATH 也行,可省掉这个参数)。 前端 + 后端混合仓库——会并进同一张图。
geml-code-graph 本身就是一个 diagram 格式——一行就能把它嵌进任何 GEML 文档(=== diagram {format=geml-code-graph src=.geml-code-graph/index.geml} ===),且每次代码变更都会自动触发重建,代码图永不脱节。规模不是问题:图是纯文本数据表——上万源文件、几十万条边仍秒开秒查(去感受下全局密如蛛网的对称美感带来的震撼吧),随意搜方法名可以定位调用链路。
.geml 链接看它渲染——GEML 规范本身(dogfood——规范本身就是一份 GEML,规模化渲染)、showcase(计算表、四张图、一条 Mermaid 流程、公式),或把 playground/sample.geml 打开看交互式代码图。让 GEML 肉眼读起来舒服的那套形态,也正是它在自动化下可靠的原因:
.geml,它看到的就是文档本身。diagnostics 数组的文档模型 JSON,智能体和 CI 由此拿到结构化的通过/失败信号。GEML 的设计目标是让模型来写、也来改——而且改得精确。要改一处,agent 不必重读、
重发整篇文档,而是按 id 定位到单个块,改完再校验。命令集只对着一条标尺打磨——
一个 agent 能否单靠命令行跑完一篇文档的全生命周期?——所以动词力求够全(每个
环节都有对应动词)、够顺手(参数少、默认合理、I/O 可管道化)、够一致(指定
目标 #id,内容便归到它名下,每次写入都有守卫):
npm i -g @geml/geml # 安装 geml 命令
geml doc.geml # 文档模型 JSON(默认 --to json)
geml doc.geml --to md|html|geml # 转换(geml notes.md -> GEML;-o 写文件)
geml get doc.geml ['#id'] # 列出全部 id,或打印单个块(标题 id = 整节)
geml set doc.geml '#license' --in template.geml#mit # 替换一个块,fork 另一文件(id 归一到 #license)
geml add doc.geml --after '#intro' --in snippet.geml # 在某位置插入片段(保留其自身 id)
geml delete doc.geml '#draft' '#tmp' # 删除一个或多个块
geml rename doc.geml '#old' '#new' # 重命名一个 id 及其全部引用
geml revert doc.geml '#plan' --rev -1 # 把单个块回退到某历史修订
转换只有一个入口 geml <file> [--to <fmt>]:输入格式自动判定(--from 覆盖 >
扩展名 > GEML),目标由 --to 决定(默认:GEML 输入 → JSON、Markdown 输入 →
GEML)。编辑则由四个动词覆盖整块生命周期:set 替换一个块(从文件或 stdin fork
内容,并把 id 归一到目标)、add 在某位置插入片段、delete 删除一个或多个块、
rename 改写一个 id 及其全部引用。每个变更都写出整篇更新后的文档——输入是文件
就地改、输入是 - 走 stdout、-o 重定向——因此编辑天然可管道化,且都有守卫:
写前重新解析,若会破坏文档则拒写。按 id 读取与修补,让每次编辑又小又准——只花整篇
文档零头的 token。
.claude/skills/ 下的技能——geml/ 管写作、
geml-code-graph/ 管调用图——
拷到 ~/.claude/skills/。之后 Claude 会自动加载:一碰 .geml 文件就跑
geml check,而你说「看下 code-graph」或「谁调用了 X」时它会自动构建并打开
调用图,无需记 CLI、也无需额外提示。geml check 拿硬性通过/失败信号。GEML primer。 把文档写成 GEML。每个块都是
=== type {#id .class key=val}…===;闭合围栏是与开围栏等长的一串=,更长的围栏可嵌套更短的——块若带#id,也可以用带标签围栏=== #id闭合(不必数长度,长块或嵌套块优先用它)。 块类型:code/diagram/math/table(原样正文)、note(带内联标记的散文)、meta(每行一个key=val)。标题只用 ATX#——没有---frontmatter(用=== meta)。每个#id唯一,且每个引用([[#id]]、[text](#id)、[^id]、 图表data=#id)都必须能解析。不允许 raw HTML。内联:*强调*、**加粗**、`代码`、$公式$、[文本](url)。规范见GEML-spec_CN.md。
geml 命令行 —— 一条命令管完文档全生命周期(npm 包 @geml/geml;源码在 geml-parser/):
npm i -g @geml/geml
geml check doc.geml # 校验:断引用即错误、非零退出——可直接进 CI
geml doc.geml --to html -o doc.html # 渲染成单个自包含、可交互的页面
geml notes.md # 从 Markdown 迁入;`--to md` 可迁出
一切都解析为带 diagnostics 数组的文档模型 JSON,脚本和智能体拿到结构化的通过/失败信号——下面的按块编辑(get/set/add/delete/rename)、版本历史、格式化器、代码图,都是同一条命令。
integrations/geml-viewer/,在本地(file://)与网络上渲染 .geml:带计算列的表格、作为内联 SVG 的 geml-chart、Mermaid 图、KaTeX 公式,以及作为横幅显示的构建期诊断。安装:构建后在 chrome://extensions 里 Load unpacked(步骤)。一键即看: 装好扩展后,打开一个 raw .geml URL(原始文件,而非 GitHub 的 blob 页面——那是 HTML),它便就地渲染——试试 showcase(一张计算表、四张图、一条 Mermaid 流程与公式)或 GEML 规范本身——一整篇规模化渲染的文档。想看可交互的 geml-code-graph,下载 playground/sample.geml 连同它的 codemap/ 文件夹,用 file:// 打开。geml get <file.geml> #id 按 id 打印单个块;set、add、delete、rename 每次改动一个块、一段片段或一个 id——都会重新解析,并拒绝任何会破坏文档的写入。标题的 #id 寻址它的整个小节(直到下一个同级或更高级标题),因此智能体改动一节——标题、散文、嵌套块——无需重读或重发整篇。.gemlhistory 伴生文件执行 geml history <commit | verify | show | restore | log> <file.geml>;再用 geml revert <file.geml> #id [--rev -1] 把单个块回退到某历史修订(按 -N 偏移、0 取最新一版,或 id 前缀;--rev changed 则跳到该块上一次真正变化的那一版)。可寻址 + 有版本——正是「智能体逐步改文档、并能回退任意一节」的底座。revert 就是块级 undo:把改动过的内容 splice 回去、复活已删的块、或删掉在目标修订版里根本不存在的块——正好是 set/delete/add 的逆(rename 用 rename #new #old 自我撤销)。geml <file.geml> --to geml [-o out.geml] 把文档模型重新序列化回规范 GEML(解析器的逆运算)。parse(serialize(parse(x))) 是同一个模型——一个由测试集校验的往返性质——且输出幂等。geml <file.md> [-o out.geml](Markdown 输入默认 --to geml)。映射:frontmatter → meta、围栏代码 → code、 ``mermaid/graphviz/… ` → diagram、$$ → math、引用块 → note、GFM 表格 → table、脚注、自动链接、setext → ATX。geml <file.geml> --to md [-o out.md] 把文档投影为 GFM:meta→frontmatter、计算表→GFM 表、note→引用块、脚注、围栏代码/mermaid、$$ 公式。本质有损——Markdown 没有类型块原语——故每个无法映射的构造(geml-chart、{hidden}、块 id)都会以 note 形式报告。geml <file.geml> --to html -o out.html 把文档变成单个自包含、可交互的 HTML 文件:可排序/可筛选的表格、从其表格绘制为内联 SVG 的 geml-chart、渲染好的图形,以及贯穿到非零退出码的构建期检查。见 docs/examples/ 里的 showcase.geml 源文件。GEML 已发布 1.0——稳定,可用来写真实文档(本仓库的规范本身就是一例)。
成熟度信号。 完整的核心规范(§1–§8)外加历史扩展规范,均有中英两版;可用的参考实现、渲染器 + CLI;一套一致性测试集(输入 → 投影出的文档模型),还要由第二个、独立编写的解析器逐用例复刻出完全相同的结果——两个各自独立的实现在每个用例上都一致,才能保证强调、列表这类微妙规则不会各写各的、跑偏——另有 600+ 项单元与一致性检查兜底(参考实现约 99% 行覆盖,CI 门槛:行/语句/函数/分支均 ≥95%);以及自举——GEML-spec.geml 是用 GEML 写成的规范本身,每次测试都被干净解析。
设计边界(非目标)。 GEML 刻意保持小:
--- frontmatter、无分隔线的歧义。贡献。 各种贡献都欢迎——报 bug、工具与集成、更广的一致性覆盖,以及规范本身讨论。GEML 已是 1.0,但仍可演进:实质性的规范改动通过 GEP 讨论并落地,每项都附带对应的一致性用例。参考实现的测试套件就是契约——代码改动应保持 npm test 通过、且 dogfood 规范解析无误。最有价值的贡献是用另一种语言写一个独立实现——可移植的一致性测试集让它成为一个周末的活儿,见 docs/WRITING-A-PARSER.md。
| 文档 | English | 中文 |
|---|---|---|
| 核心规范 | GEML-spec.md |
GEML-spec_CN.md |
| 历史扩展 | GEML-history-spec.md |
GEML-history-spec_CN.md |
spec/ 核心规范 + .gemlhistory 扩展(英 / 中)、dogfood 的
GEML-spec.geml、CC-BY 规范许可证、proposals/(GEP)
geml-parser/ 参考实现、渲染器、CLI + codemap 工具集(TypeScript, Node 22)
integrations/ GEML 接入的所有地方:geml-viewer(浏览器扩展)、
geml-check-action(CI)、vscode、obsidian、tree-sitter(简报)
playground/ 浏览器内 playground(含本仓库的实时 geml-code-graph)
docs/ 指南、设计笔记、格式 COMPARISON(英 / 中)、图片资产,
以及一个可自行渲染的示例 .geml 文档
代码(geml-parser/、integrations/geml-viewer/、integrations/geml-check-action/)为 MIT(LICENSE)。规范文档为 CC-BY-4.0(LICENSE-spec.md)——规范不是软件,任何人都可以构建一个兼容实现。决策方式见 GOVERNANCE.md,参与方式见 CONTRIBUTING.md