GEML — a plain-text document format built to be edited in place, one section at a time

io.github.geml-spec由 GitHub 帳號 geml-spec 發布v1.13.0更新於 Oct 29, 2026

One section in, one section out — on Markdown/GEML files, bad writes refused.

發布方自己的服務:Section Store

已驗證Streamable HTTP可網頁執行檔案與儲存開發者工具

概覽

AI 產生的概覽

以區塊為單位編輯 GEML 與 Markdown 文件:列出、尋找、讀取、驗證、轉換、插入、取代、刪除與重新命名章節,不必重寫整份檔案。

可以做什麼
  • 列出文件中所有可定址的區塊,包含位址、類型與標題文字
  • 搜尋區塊內容,回傳可直接使用的位址而非行號
  • 讀取單一區塊或章節,並驗證文件、給出穩定的診斷代碼
  • 在 GEML、Markdown 與 JSON 之間轉換整份文件
  • 寫入:取代單一區塊、在錨點前後插入新區塊、依 id 或篩選條件刪除區塊、重新命名 id 及其參照
  • 每次寫入都先驗證再寫入磁碟,未更動的位元組維持原樣
適用情境
適合讓助理編輯較長的 Markdown 或 GEML 文件時,只改動其中一節而不重新輸出整份檔案,節省上下文並避免內容漂移。也適合在回報完成前確認文件結構無誤。
執行需求
使用遠端端點,或在本機以 stdio 執行 npm 套件 @geml/geml,後者需要 Node.js 22 以上版本。未宣告任何帳號、API 金鑰或請求標頭。本機使用時路徑被限制在啟動時指定的根目錄內。
安裝前請注意
這些工具會寫入檔案:set、add、delete 與 rename 會更動磁碟上的文件,delete 還可能刪除所有符合篩選條件的區塊。寫入前會驗證並記錄修訂以便回退單一區塊,但仍應在接受前檢查變更。轉換為 Markdown 是有損的。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 GEML — a plain-text document format built to be edited in place, one section at a time,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Web executable,透過 Streamable HTTP。 遠端服務在工作區中設定後即可從網頁執行環境執行。

交給代理程式安裝

把這段提示詞貼上到 Claude Code、Codex、Cursor 等代理程式,或 SourceWeft 對話中。代理程式會讀取該伺服器的安裝指南,先向你展示發布者、端點和登入方式,經你同意後再把它新增到你的客戶端。金鑰不會寫進任何命令。

閱讀 https://sourceweft.com/mcp/io.github.geml-spec%2Fgeml/install.md,並按其中說明把這個 MCP 伺服器接入我的客戶端。修改任何設定之前,先告訴我它的發布者、端點和登入方式,等我確認。不要把 API 金鑰寫進命令或我會提交的檔案;問我金鑰應從哪裡取得。

檢視代理程式所依據的安裝指南

其他 MCP 客戶端

把它新增到你客戶端的 mcpServers 設定中。

{
  "mcpServers": {
    "geml-a-plain-text-document-format-built": {
      "type": "http",
      "url": "https://geml-mcp.supermarket.workers.dev/mcp"
    }
  }
}

README

[MCP Toplist] [Glama MCP server score] [Mentioned in Awesome MCP Servers] [Mentioned in Awesome AI Plugins] [Mentioned in Awesome Markdown]

[GEML]

GEML — General Expressive Markup Language

[npm] [MCP] [CI] [GEML check] [spec: 1.0] [code: MIT] [spec license: CC BY 4.0]

English | 中文

GEML is a lightweight markup language with uniform, addressable blocks and standard verbs.
Easy for humans to read, safe for agents to mutate. In agent-driven development and knowledge work, plain text and Markdown have no deterministic block boundaries: a program and a model trade the whole file in and the whole file back out — at best probing for it with line windows, and restating the original verbatim to rewrite it. Token cost grows with the length of the document, and the operation turns bloated. After a few rounds of rewriting, the copies excerpted elsewhere start to drift.

Contents: What it solves · What an LLM needs · What's different · The format in 1 minute · Profiles · Get hands-on · With an LLM · Maturity & versions · The design · Roadmap · Take part · License

You can start without changing a thing. geml list, geml find and geml get address the Markdown you already have — nothing is converted, no new files, your .md stays .md:

sh
geml list    README.md                          # every section, as an addressgeml get     README.md '#key-features'          # read ONE section, not the filegeml set     README.md '#key-features' --body   # write one section backgeml replace README.md 'old text' 'new text'    # swap a string, told which block held itgeml history save README.md -m 'tighten intro'  # a revision into README.md.gemlhistory, beside the file

Only that section enters the agent’s context — a couple of KB, not the whole file, however long it grows. And every save is a revision you can read back or roll back, one block or the whole file.

▶ Try it in the Playground — no install, nothing to read first.

Need finer than a section — one block, one chart, one table? Let .geml stand in the middle ground: edit at that grain, and the --to md you ship never drifts from it.

A block has a name; the things inside it have a coordinate. A table's cell, a data block's leaf, a key in meta — each has a coordinate the structure already gives it, and get and set land on exactly that value.

sh
geml get doc.geml '#fy[2]["Q1"]'                     # one cellgeml set doc.geml '#intake["fields"][1]["name"]'     # one leaf in the JSON

For people, it is plain text that reads clean; for agents, it is an addressable, verifiable, traceable, revertible "Doc-as-a-Base".


GEML is minimal. It is plain text — still clean with no renderer in sight; one block syntax for the whole language; addressable, verifiable, referenceable structure, natively.

Instead of a separate mini-syntax for each kind of content, GEML carries every kind in one container: the typed block. Code is a block. So are tables, diagrams, math, callouts, even metadata — and a run of prose can be one too (=== text), whenever you want it addressable. Extending it later is just as plain. The shape is the same every time, which makes the language easy enough to learn that it's hard to get wrong.

Blocks have names so the verbs have somewhere to land — the full syntax is in the format in 1 minute.

What it solves

Problems solved

  1. Context load and token bloat: JSON/XML carry heavy wrapper syntax, and Markdown lacks structural metadata and references; GEML reads and writes only the target block, so context cost stops growing with document length.
  2. AST-level precision and parsing determinism: unstructured text degrades over rounds of LLM reads and writes — broken formatting, semantic drift; GEML's deterministic grammar maps to an AST, so programs and LLMs create, read, update and delete one block at a time.
  3. Document copy fragmentation: multi-agent work and shared pipelines pass content around by copy-paste, leaving copies that drift apart; GEML is built around a single source of truth, with standard references and data binding in place of copies.

Key features

  • AST-level structured operations: a document parses into a typed tree; an agent pinpoints its target and patches it in place, idempotently. Writes land as byte splices with whole-document re-validation, and every untouched byte stays as it was.
  • Low-token reads and writes: what is saved is not markup characters but the part never read — #id hits one semantically complete block, and the rest never enters the context.
  • Single source of truth, modular references: native cross-document, cross-fragment references; change the source once and every reference follows.
  • Robust two-way reads and writes: one block shape for the whole language, easy to generate and hard to get wrong; a strict validator with precise error locations and repair feedback.
  • Profile-based domain extensibility: declare a profile in === meta to add a domain vocabulary (design styles, forms, code graphs, media timelines) without new syntax; a declared vocabulary is checked by its own checker, with safe fallback to standard blocks in unknown environments.

What kind of text format does an LLM need?

Text in the AI era is "produced by models, read by people and models together".

Reading together means readability cannot be traded away; and when models settled on Markdown, it was a compromise made for want of anything better, not the final answer.

A text format built for people and models working together should change what reading and writing feel like for the machine:

  • Fine-grained: address precisely by block, and by coordinate inside it — no more scanning the whole file;
  • Structured: better organized, more flexible in what it holds;
  • Consistent: one standard read/write interface, with other modalities extending it naturally;
  • Zero barrier: minimal mental load, and a smooth, near-zero-cost migration.

Yet none of our existing text infrastructure was designed for this scene:

  • Markdown (typeset for people): no stable structural blocks, no machine keys. To change one parameter, an agent must read and write the whole text — wasting context budget across multi-turn loops, and inviting drift in both format and meaning.
  • JSON / XML (serialized for machines): full of wrapper syntax and structural noise — blocking natural human reading, while quietly eating expensive tokens in long contexts.
  • Scratch memory and scattered files (no single source of truth): context is torn across chat history and Markdown copies everywhere; a copy is drift from the moment it is made, and version skew and hallucinated distortion follow.

The root of all three failures is each tool's own virtue: Markdown's "never error, write anything" is what gives people their freedom to write — and exactly why a machine cannot trust the structure it reads back; JSON/XML's strict schema is what gives machines their certainty — and exactly why nobody writes prose in it. The virtue is the defect, which is why patches cannot fix this: bolting "a broken reference must fail the build" onto Markdown betrays its contract, and stripping the wrapper syntax from JSON denies its nature. When people and agents start co-writing the same text at high frequency, what is needed is not a compromise between the two poles, but a format that treats "readable by people" and "operable by machines" as one design constraint from day one.

The answer: "Doc-as-a-Base"

GEML is a new format, but the wine is old: enhancing and unifying Markdown-style expression, stripping away HTML-style presentational syntax, and the idea of fenced blocks come from Markdown, #ids and embeds from XML and AsciiDoc, inline projection from Obsidian, and the verbs from the REST architectural style of Dr. Roy Fielding's dissertation. What is new is one block container for all of them. It is a little like TypeScript to JavaScript — the syntax can't be compatible, but list, get, set, add and delete already work on the Markdown you have. That container gives plain-text documents one standard set of operational semantics:

Old painThe matching capability (the four laws)What it buys developers and agents
Changing one spot means rewriting the whole textThe Law of AddressingEvery block carries an #id; get/set reads and writes that block alone. What is never loaded cannot be broken — the context window stays yours.
Copies everywhere, all driftingThe Law of Projection=== embed evaluates dynamically instead of copy-pasting; one definition at the source ends the labor of syncing copies.
Bad formats / broken references pollute downstreamThe Law of ValidationReferences and syntax are checked at build time; a bad write is stopped before it lands, with no waiting for human review.
One bad edit forces a whole-file rollbackThe Law of RollbackThe companion .gemlhistory reverts a single block atomically — no tearing down the page; a lightweight version safety net for agents.

A document no longer needs just a format — it needs a set of verbs. GEML keeps plain-text readability and adds deterministic block-level operations. The dilemma of engineering documents in the LLM era, and why these old practices belong in one new block container, is argued in full on the blog: "Why Do We Need a New Text Format in the Era of LLMs?"


What's different about GEML

Where each format lands on the four capabilities of the last chapter — addressing, projection, validation, rollback — is the table below; GEML stays small on purpose, and what it refuses is in how we thought about the design.

How other formats compare

Each of the four has mature solutions in its own field; what's unusual is meeting all four in one plain-text format:

FamilyWhat the state really isAddressable / referenceableProjectable / embeddableVerifiableHistory / traceability
Word / DocsOpaque state❌ No block-level keys; access via platform APIs❌ Copy-paste only❌ No checking at all⚠️ Platform server-side, not in the file
Markdown / AsciiDocA stream of characters⚠️ Heading anchors or dialect ids; no read/write verbs⚠️ Dialect embeds (Obsidian ![[…]], include::) — break silently❌ Broken links fail silently❌ None in-format — external git required
JSON / XMLData serialization✔️ (id / schema)⚠️ XML only (XInclude, external)✔️ Via an external toolchain❌ None in-format — external git required
GEMLPlain text + block structure✔️ A unique #id per block (referenceable natively)✔️ === embed: a reference is a lookup (native)✔️ A build-time error✔️ .gemlhistory next to the file (traceable natively)

Item by item: vs. CommonMark · vs. XML and JSON · a 7-format capability matrix · the Markdown variants and tools in awesome-markdown (Chinese, an HTML page).

Coexisting with Markdown: GEML is the editing source of truth, Markdown is the delivered artifact. Project one way with geml <file> --to md|html and ship .md or .html as before. Collaboration, not lock-in. (Projection is lossy: block ids and table-bound charts don't survive it.)

Don't take the table's word for it — re-run it. This is what I asked the model:

Based on your own experience editing the READMEs just now, describe the command steps you go through on a document (I saw you using grep and such), and whether you cache documents to save tokens — let's compare, and from that see which parts of GEML would actually earn their place.

What came back: what one edit costs and a real day replayed. Paste the question to your own model and see what it tells you. PS: I am still trying to work out whether the upstream chain (who calls this) and the downstream chain (what it calls) that codemap produces can pin down functions and call sites — and change project code — the same way. I will post a report when I have one.

The format in 1 minute

Typed blocks

One shape, every type. A block's basic syntax is === type [attributes] … === (where attributes like {#id .class key=val} are optional) — only the type (and how its body is read) changes:

=== code {lang=python}print("hi")===
=== note {.intro}Parsed prose with *emphasis* and a [[#budget]] reference.===
=== metatitle = "Budget plan"===

A run of = (three or more) opens a block; an equal-length run closes it; longer fences nest inside shorter ones. A block that carries an #id can also close with the labeled fence === #id — no fence-length counting, which makes long blocks much harder to get wrong (nesting still requires a longer outer fence: a same-length bare === in the body closes the block early, labeled or not). The type decides how the body is read — raw (verbatim: code, diagram, math, table), flow (parsed prose with inline markup: note, text), or data (one key=val per line: meta); embed carries no body at all — its src= names the block it stands for — and every block may carry an attribute object {#id .class key=val}, where a .class is a semantic label, never a styling hook. The full inline grammar (emphasis, links, [[#id]] auto-references, media, footnotes, inline $math$) is in the spec.

Tables — two bodies, one model

Write a table visually:

=== table {#budget caption="Annual cost"}| Plan  | Months | Rate ||-------|-------:|-----:|| Basic |      1 |   30 || Pro   |      2 |   30 |===

…or as data. A table holds the facts; a view over it derives the computed columns and the summary row:

=== table {#fy25 format=csv header=1}Segment,  Q1, Q2, Q3, Q4Cloud,     8, 10, 12, 14Platform,  5,  6,  7,  9Services,  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)"}===

Both table forms describe the same model. The FY column and Total row are computed at build time, by the view:

SegmentQ1Q2Q3Q4FYn
Cloud810121444.01
Platform567927.01
Services344516.01
Total87.03

compute runs + - * / ( ) per row over columns; summary adds a foot row from the aggregates sum / avg / min / max / count (with arithmetic over them, e.g. weighted ratios); a trailing [printf] sets numeric display. n above is the row-count idiom — count tallies non-empty cells in one column, so a constant column summed is what counts rows.

Tables can also pull their data from an external CSV via src="regions.csv".

Math

=== math {#gauss caption="Gaussian integral"}\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}===

$$\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}$$

Diagrams & charts — host a DSL, or chart a table

GEML never interprets a diagram body; it routes it to a pluggable renderer (an unknown format is a warning, body preserved):

=== diagram {#flow format=mermaid caption="Review flow"}graph LR  A[Draft] --> B{Review} -->|ok| C[Publish]===
mermaid
graph LR  A[Draft] --> B{Review} -->|ok| C[Publish]

A diagram can also chart a table — single source of truth, with the column references checked at build time and no data copied:

=== diagram {format=geml-chart data=#fy25-report type=bar x=Segment y=FY}===

Drawn from the #fy25-report view above — FY is a computed column, so the chart binds to the view that derives it, not to the base table:

mermaid
xychart-beta  title "FY by segment"  x-axis [Cloud, Platform, Services]  y-axis "FY"  bar [44, 27, 16]

Data — a value, not just text

Every block type names what it holds: code a region of code, table a grid, math a formula. data holds a data value, and it is where the data formats live — json (the default), jsonl, and yaml for a declared subset; toml reserved. Being typed means the body is read, not just displayed: a missing comma fails the build, geml get --json returns the value itself, and a chart can read it directly.

=== data {#log format=jsonl}{"ts":"09:00","p95":41}{"ts":"09:10","p95":58}===

A jsonl body holds one record per line, which a program can blind-append at end-of-file. Records can also stay in their own file: src=ops/latency.jsonl#L900-999 names the file and, optionally, a line window — so the log keeps being appended and tailed as before, while the document is its verified, addressable, chartable view of it.

Embeds — a dynamic reference, not a copy

One block can stand for another: in the same document by src=#id, across documents by src=other.geml#id. An embed is a dynamic lookup of the source at render time — change the source once and every embed follows; delete it and geml check fails the build on the spot.

=== embed {src=#fy25}===

The body stays empty; the target lives in src=.

Markdown can't show you the projection. To see it live: install the browser extension, open the raw link to sample.geml, and scroll to the Transclusion section — a same-document projection (src=#roadmap), cross-document projections, and even chained resolution (an embed pulls a chart, which itself binds to a table in another file) all render in place: nothing is written there, yet edit the source once and the projection follows.

Profiles — domain vocabularies, assembled like Lego bricks

Want to author interactive forms, define a design token system, or map an entire codebase's call graph inside your documents? In traditional Markdown, this requires proprietary plugins (:::note, custom JSX tags), inevitably fracturing into incompatible dialect silos.

GEML solves this with Profiles (Application-layer vocabularies, spec §8.6): A single-line declaration that unlocks domain-specific structured superpowers on demand.

geml
=== metaprofile = "geml-style/v1 geml-form/v1"===
==== form {#signup handler=subscribe}=== form-field {name=email label="Work email" type=text required pattern="[^@]+@acme\\.com"}=======
=== style-rule {#cta match="button.cta" bg="{{brand}}" radius="6px"}===

Extension without fragmentation

  • 🧩 Mix & match like Lego bricks: the core syntax stays minimal and frozen, while domain vocabularies grow beside it; call graphs, design tokens, form validation, version history... compose several of them with one profile = "..." line.
  • ⚡ No plugin to write, the tooling already there: adding a new domain block requires no parser fork and no custom plugin; it gets the same infrastructure as every other block — deterministic #id addressing, geml get/set blockwise mutation, CLI verbs, MCP protocol, and autonomous AI Agent control.
  • 🛡️ Naturally portable, never locked in: extend capabilities without breaking interoperability; a processor that doesn't know a profile still reads every block and addresses it by its #id, so a document keeps its structure when it moves to another tool.

Standard Published Profiles

Profile (guide)StatusWhat it's forCLILive Demo / Example
geml-codemap/v1stableGenerates your codebase's call graph as GEML documents: one block per method, so you can see who calls it and what it calls; front-end and back-end merge into one graphgeml codemap build|verify|serveInteractive Call Graph
geml-media/v1draftDescribes a video timeline in one document: assets, clips, subtitle and voice tracks; export it as a web player, or render an MP4 with ffmpeggeml media build|export|lay|todoDoc-to-Video (Doc to MP4 via ffmpeg)
geml-style/v1draftColours, spacing and layout live in a separate stylesheet document whose rules apply to your content; the content document itself stays unchangedgeml style checkGitHub Blob Page 1:1 Replica
geml-history/v1stableKeeps past versions in a .gemlhistory file beside the document: read any old version, put back a single block, or roll back the whole filegeml history save|get|restoreAtomic Block Rollback Workflow
geml-form/v1draftDescribes a form in a document: its fields, their types, which are required, allowed ranges; the browser extension and the playground draw a preview—Interactive Complex Form Example
geml-translator/v1draftA translation document holds no translated text: it embeds the source and names the target language, and the browser extension machine-translates it on open, so it follows every change to the source—Translated on Open
geml-statechart/v1draftWrites a state machine as one diagram block: states, transitions with their guards and actions, and the variables the guards read; geml check finds states nothing reaches and dead ends, --to html draws it, --to md turns it into Mermaid——

💡 Want to see Profiles in action? • geml-media live demo: One cut document and one command (geml media build ep01-cut.geml --out ep01.mp4 --burn-subs) orchestrates ffmpeg to align audio/video, mix tracks, and burn subtitles into a finished video (see it). • geml-style live demo: Content stays pure text in page.geml, while styles and layout live in github.style.geml — rendering a 1:1 pixel-accurate replica of GitHub's blob page without CSS lock-in (see it). • Every profile name in the table opens its one-page guide — what it does, the first command, everyday use. If you write code, start with geml-codemap. You can also easily create your own custom domain profile.

Next — get hands-on now

▶ Try writing GEML in the Playground — edit on the left, rendered live on the right; seven chapters walk from typed blocks and #ids to coordinates, data, charts and projection, and a bad edit is flagged on the spot. No install, nothing to read first.

Then, in the order that suits you:

  1. See it render in your browser. Install the extension and open a raw .geml link (the raw file, not the GitHub blob page — that one is HTML): the GEML spec itself (dogfood — the spec is a GEML document, rendered at scale), the showcase (a computed table, four charts, a Mermaid flow, and math), or playground/sample.geml for the interactive code-graph.
  2. See a whole page laid out from a document. The style demo is a 1:1 replica of a GitHub blob page — top bar, file tree, breadcrumb, Preview/Code/Blame, dropdown menus — where page.geml holds every string and github.style.geml holds every colour and length, and the viewer knows about neither. It opens in any browser — the viewer's own code draws it — with the GEML that makes it right below.
  3. Run it locally. npm i -g @geml/geml (Node 22+), then geml check a document, or point it at your own repo with geml codemap build; on Claude Code, npx -y @geml/geml skill install puts the authoring skill, the CLI and the MCP server in place, user-global, with no settings edited and no hooks installed (details).
  4. Read the grammar, or see it worked through rule by rule. The full spec (EN / 中文) is normative and short enough to read in a sitting; GEML, illustrated (EN and 中文) is eleven self-contained pages, one per block type, per profile, and for the CLI: GEML on the left, what the processor actually does on the right (geml check diagnostics, geml list addresses, --to html markup), each rule tagged with its source and status.

Using GEML with an LLM

The goal is one thing: your model edits a block at a time, and verifies — never re-reads and re-emits a whole file to change one paragraph. One step gets you there:

You useRun
Claude Code, Gemini, Qwennpx -y @geml/geml skill install — the authoring skill, the CLI and the MCP server, user-global; no settings.json edits, no hooks (or claude plugin marketplace add geml-spec/geml, then /plugin install geml@geml)
Codexstart it in a checkout of this repo and the plugin is in /plugins; without cloning, see integrations/codex-plugin/
DeepSeek Harnessdsh plugin --profile web add @geml/dsh-plugin (source)
Any MCP clientnpx -y @geml/geml mcp --root ., or nothing to install at https://geml-mcp.supermarket.workers.dev/mcp — Cursor, VS Code and Claude Desktop setup in docs/mcp-guide.md

Anything else — a model with no skill to read needs the rules once. Paste the prompt below, and keep geml check as the gate on whatever it writes back (the CLI is npm i -g @geml/geml, Node 22+):

Write the document as GEML: every block is === type [attributes] … === (the format in 1 minute lists the types). Four rules are the ones models get wrong: the closing fence is a = run of the exact opening length, and a body containing === needs a longer outer fence; headings are ATX # only, with no --- frontmatter (metadata is === meta); every #id is unique and every reference ([[#id]], [text](#id), [^id], data=#id) must resolve; there is no raw HTML. The normative spec is GEML-spec.md.

What it will do with it

sh
geml list   doc.geml                                     # CALL FIRST: every block, its address, kind, linesgeml find   "words" doc.geml                             # search block content -> an address, not a line numbergeml 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 | --bodygeml set    doc.geml '#license' --in template.geml#mit   # replace that block, forking anothergeml 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 backgeml check  doc.geml                                     # validate only: diagnostics + exit code

Over MCP the same verbs are tools (geml set → geml_set), and two guarantees make it better than letting a model rewrite the file: a write is parsed before it reaches disk and refused if it would break the document, and every write first records a .gemlhistory revision, so geml_revert can undo one block. Paths stay confined to --root; a root that holds a code graph also answers "who calls this". Every verb: the parser README; every tool: docs/mcp-guide.md.

Ecosystem and maturity

How we thought about the design

What the design follows

  1. Human–Agent Isomorphism, Not a Compromise: rather than splitting the difference between Markdown for people and JSON for machines, GEML treats "readable at a glance" and "operable with certainty" as one constraint — people get clean prose, agents get a strongly typed AST.
  2. Doc-as-a-Base, Not a Stream of Characters: a document is a base of structured records with stable primary keys (#id); every block has its own lifecycle, coordinate and atomic CRUD interface, so an agent edits one block instead of rewriting the file.
  3. One Syntax Primitive, Open Domain Vocabularies: a single typed-block primitive (=== type) carries code, data, tables, math and layout; domain vocabularies extend it through Profiles (profile = "..."), the grammar frozen and the vocabularies open, which keeps dialects from splintering it at the root.
  4. Transclusion over Duplication: Kill the Incentive to Copy: a hyperlink is a signpost that invites copy-paste and drift; a GEML reference is a live viewport (=== embed) — define once at the source, project everywhere.
  5. Compiler-Grade Integrity: Treat Documentation Like Code: where Markdown never fails and renders something, GEML validates at build time — a broken #id or a reference cycle fails with a non-zero exit, before bad data reaches anything downstream.
  6. Local-First History, Not Cloud Lock-in or Git Overhead: versions live at block granularity in a .gemlhistory beside the document, with no cloud service and no whole-repo commit for a micro-edit; geml revert doc.geml '#id' rolls one block back.

What it therefore refuses

RefusedWhy
A diagram language of its ownExternal DSLs are hosted (Mermaid, Graphviz, D2, …); the format defines only the hosting protocol
A raw-HTML escape hatchSemantics stay portable, tied to no backend or renderer
Setext headings / --- frontmatterATX # only, so nothing collides with a thematic break
A full spreadsheet enginePer-row formulas and summary aggregates are enough; no cell addressing, lookups, or macros

Roadmap

  • Spec and implementations: the GEML 1.0 specification, in English and Chinese, with a conformance suite and the geml-history/v1 profile that defines the .gemlhistory sidecar; the reference implementation @geml/geml (parser, CLI, block-level .gemlhistory tracking); a second implementation, geml-parser-rs/ — Rust, compiled to WebAssembly, written from the spec and the conformance suite alone, without reading the reference parser
  • The MIME media type text/vnd.geml registered with IANA (2026-10-26), with the spec as its published specification and the project as change controller
  • Tools: the official MCP server (geml mcp) for Claude Code, Cursor, Codex and other MCP hosts; codemap, a whole codebase's call graph written as GEML; the VS Code extension on the Visual Studio Marketplace (publisher geml)
  • Ecosystem integrations: VS Code highlighting and reference checking, tree-sitter, Obsidian, Logseq (two-way sync against a live DB graph), the browser viewer, a GitHub Action, LangChain / LlamaIndex, and the agent-harness plugins — Claude Code, Codex, Grok, DeepSeek Harness, plus root manifests for Gemini CLI and Kimi Code
  • The Logseq plugin listed in the Logseq marketplace (PR #893) and the Grok plugin listed in xai-org/plugin-marketplace
  • Implementations by other hands — in whatever language you write; the spec and the conformance suite are public, and we are glad to help line them up

Where it runs

The CLI @geml/geml · the browser Chrome extension · VS Code · IntelliJ / Android Studio (build from source) · a GitHub Action · LangChain / LlamaIndex (reference implementation) · the Playground, with nothing to install.

Take part

1.0 means the rules already there won't shift under you — not that the design is settled, and there is one author behind both implementations so far.

  • Write a parser in your language — how; finding where the spec is ambiguous is itself the contribution.
  • Argue with the drafts — GEP-0008 and GEP-0010, or start a discussion.
  • Claim a piece — the open gaps, and the repository layout, are in CONTRIBUTING.md.

License & governance

Code is MIT (LICENSE); the specification documents are CC-BY-4.0 (spec/LICENSE-spec.md lists them). Anyone may build a conformant implementation without permission; how decisions are made and how to use the name: GOVERNANCE.md.

來源:README.md,提交 f387552

工具

9

geml_list

List the blocks of a document

List every addressable block in a GEML document — its address, kind and heading text — in one call, with no paging. Call this FIRST: what it returns is what every other tool here addresses, and it is cheaper and more reliable than reading the file to see what is in it. Rows marked `anon` have no `#id`; geml_get and geml_set take their `address` as `id`, while the other write tools need a real id, so give such a block one first. A file that is not under the server root is an error. This server is STATELESS: the document travels in `source` and a write comes back as `document` for you to save; it holds no other documents, so a cross-document reference such as `[[other.geml#id]]` cannot be resolved here and is reported as `unresolvable-document`.

輸入參數namesource必填within

geml_find

Find the blocks that hold some text

Search block CONTENT in the document; each hit is one `<name>\t<address>` row. geml_list says what a document contains, this says which block holds the words — as an address that pastes straight into geml_get or geml_set, not a line number the next edit invalidates. The address is the innermost block holding the match, and a block matching on many lines is reported once. Substring, case-insensitive unless `case` is true. No match is an empty result, not an error. This server is STATELESS: the document travels in `source` and a write comes back as `document` for you to save; it holds no other documents, so a cross-document reference such as `[[other.geml#id]]` cannot be resolved here and is reported as `unresolvable-document`.

輸入參數caseheadnamesource必填withinpattern必填

geml_get

Read one block

Read ONE block from a GEML document instead of the whole file: only that block comes back, typically a few percent of the document. Pass the `address` geml_list prints as `id` — it also reaches blocks with no `#id`; to locate a block by its words instead, use geml_find first. An `id` that matches nothing, or a file that is not under the server root, is an error naming it. This server is STATELESS: the document travels in `source` and a write comes back as `document` for you to save; it holds no other documents, so a cross-document reference such as `[[other.geml#id]]` cannot be resolved here and is reported as `unresolvable-document`.

輸入參數id必填namepartviewsource必填within

geml_check

Validate a document

Validate a GEML document without changing it: returns every diagnostic with a stable `code`, a severity and a line, and an empty list means the document is valid. Use it to confirm a document is sound before reporting work as finished. Every write through this server runs the same check before it lands, so a refused write already carries this information. This server is STATELESS: the document travels in `source` and a write comes back as `document` for you to save; it holds no other documents, so a cross-document reference such as `[[other.geml#id]]` cannot be resolved here and is reported as `unresolvable-document`.

輸入參數namesource必填

geml_to

Convert a whole document

Convert a WHOLE document and get the result back as text — the read half of the CLI's `geml <file> --to <fmt>`. `to: "geml"` on a Markdown file is the importer, the one thing the block tools cannot do; `to: "md"` projects a GEML document out (lossy); `to: "json"` returns the full document model, for when geml_list plus geml_get is not enough. Nothing is written — pass the result to geml_add or geml_set to land it. `to: "html"` also works but returns a whole self-contained page, usually tens of kilobytes this server cannot save: prefer the CLI (`geml <file> --to html -o out.html`) unless you want the markup in the conversation. A document with errors returns its diagnostics instead of a conversion, and a file that is not under the server root is an error. This server is STATELESS: the document travels in `source` and a write comes back as `document` for you to save; it holds no other documents, so a cross-document reference such as `[[other.geml#id]]` cannot be resolved here and is reported as `unresolvable-document`.

輸入參數tofromnamesource必填

geml_set

Replace one block

Replace ONE block and leave every other byte untouched — prefer this to rewriting a file. For content that does not exist yet use geml_add; to remove a block, geml_delete. The replacement is validated before it is written: if it would break the document, nothing is written and the diagnostics come back — fix the body rather than resending it. Removing content is not refused: if the replacement drops blocks, the write goes through and the result names each one, so check it after shortening a section; geml_revert puts one back. `part` replaces the whole block (default), its head line, a section's `intro`, or its body. In a Markdown file a heading's anchor is its text, as on GitHub: new heading text gives the heading a new address, and the document's links to the old one follow in the same write. GEML content written over a Markdown heading or prose is converted to Markdown, as in geml_add; a GEML block already in the file stays GEML. An `id` that matches no block, or several, is refused. Returns `{ok, file, diagnostics, revision}`, with `notes` when the write did something to say out loud (a block it dropped, an address it changed); a refusal is `ok: false` with a `hint`, and the file is unchanged. This server is STATELESS: the document travels in `source` and a write comes back as `document` for you to save; it holds no other documents, so a cross-document reference such as `[[other.geml#id]]` cannot be resolved here and is reported as `unresolvable-document`.

輸入參數id必填body必填namepartsource必填

geml_add

Insert new content

Insert new content — one or more blocks, or prose — at the end of the document (`position: append`) or before/after the block named by `anchor`. Use this for content that does not exist yet; to change a block that does, use geml_set. Ids inside the content are kept. In a `.md` file Markdown lands as written, and GEML content is converted to Markdown as `to: "md"` converts it, the result's `notes` saying so; content Markdown cannot hold, such as a view without its source, is refused. Like every write here it is validated first: a missing anchor, an id that clashes with an existing one, or content that would break the document is refused. Returns `{ok, file, diagnostics, revision}`, with `notes` when the write did something to say out loud (a block it dropped, an address it changed); a refusal is `ok: false` with a `hint`, and the file is unchanged. This server is STATELESS: the document travels in `source` and a write comes back as `document` for you to save; it holds no other documents, so a cross-document reference such as `[[other.geml#id]]` cannot be resolved here and is reported as `unresolvable-document`.

輸入參數nameanchorsource必填content必填position必填

geml_delete

Delete blocks

Remove one or more blocks, each named by an id or any address geml_list prints; a filter (`=== type`, `{key=value}`) removes every block it matches. Each block takes the blank line that separated it from its neighbours, so deleting what geml_add inserted leaves the file as it was. To undo a deletion, geml_revert the removed id; to change a block rather than remove it, use geml_set. References left pointing at a removed block come back as diagnostics but do NOT block the deletion — read them, then repair the references or revert. A selector that names nothing is skipped, so repeating a call changes nothing. Returns `{ok, file, diagnostics, revision}`, with `notes` when the write did something to say out loud (a block it dropped, an address it changed); a refusal is `ok: false` with a `hint`, and the file is unchanged. This server is STATELESS: the document travels in `source` and a write comes back as `document` for you to save; it holds no other documents, so a cross-document reference such as `[[other.geml#id]]` cannot be resolved here and is reported as `unresolvable-document`.

輸入參數ids必填namesource必填

geml_rename

Rename a block id

Rename a block id AND every reference to it in the same document, in one id-boundary-safe write. Use this rather than geml_set or a text search-and-replace, which would also hit ids that merely share a prefix. A Markdown heading's anchor is its text, so it is renamed by changing the heading with geml_set (`part: head`), not here. An `old` id that does not exist, or a `new` one already taken, is refused. Returns `{ok, file, diagnostics, revision}`, with `notes` when the write did something to say out loud (a block it dropped, an address it changed); a refusal is `ok: false` with a `hint`, and the file is unchanged. This server is STATELESS: the document travels in `source` and a write comes back as `document` for you to save; it holds no other documents, so a cross-document reference such as `[[other.geml#id]]` cannot be resolved here and is reported as `unresolvable-document`.

輸入參數new必填old必填namesource必填

版本歷史

15
  1. v1.13.0最新Oct 29, 2026
  2. v1.12.6Oct 16, 2026
  3. v1.12.5Oct 9, 2026
  4. v1.12.4Oct 8, 2026
  5. v1.12.3Oct 4, 2026
  6. v1.12.2Oct 4, 2026
  7. v1.12.0Oct 2, 2026
  8. v1.11.6Oct 2, 2026
  9. v1.11.5Oct 1, 2026
  10. v1.11.4Sep 30, 2026
  11. v1.11.3Sep 29, 2026
  12. v1.11.2Sep 27, 2026
  13. v1.11.1Sep 18, 2026
  14. v1.11.0Sep 17, 2026
  15. v1.10.3Sep 16, 2026

評分

已滿足適用檢查項的 100%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通必需25 分
  • 已宣告認證方式必需10 分
  • 已列出工具必需15 分
  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分

其他 Section 整合